From c737bad66e861292bfd52a60d360c4086b223448 Mon Sep 17 00:00:00 2001 From: Philip Giuliani Date: Fri, 19 Dec 2014 15:17:15 +0100 Subject: [PATCH 1/6] Fix the jobLimit of the imageLoader Fixes #490 --- src/imageLoader.js | 7 ++++--- src/viewer.js | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/imageLoader.js b/src/imageLoader.js index f1d5265d..0fa658a2 100644 --- a/src/imageLoader.js +++ b/src/imageLoader.js @@ -94,14 +94,16 @@ ImageJob.prototype = { * @memberof OpenSeadragon * @classdesc Handles downloading of a set of images using asynchronous queue pattern. * You generally won't have to interact with the ImageLoader directly. + * @param {Object} options - Options for this ImageLoader. + * @param {Number} options.jobLimit - The number of concurrent image requests. */ -$.ImageLoader = function() { +$.ImageLoader = function( options ) { $.extend( true, this, { jobLimit: $.DEFAULT_SETTINGS.imageLoaderLimit, jobQueue: [], jobsInProgress: 0 - }); + }, options ); }; @@ -166,4 +168,3 @@ function completeJob( loader, job, callback ) { } }( OpenSeadragon )); - diff --git a/src/viewer.js b/src/viewer.js index 00108538..f6650203 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -436,7 +436,9 @@ $.Viewer = function( options ) { this.viewport.setHomeBounds(this.world.getHomeBounds(), this.world.getContentFactor()); // Create the image loader - this.imageLoader = new $.ImageLoader(); + this.imageLoader = new $.ImageLoader({ + jobLimit: this.imageLoaderLimit + }); // Create the tile cache this.tileCache = new $.TileCache({ From b82f5cea768cecf45e72fc23cf0f452e708ef858 Mon Sep 17 00:00:00 2001 From: Philip Giuliani Date: Fri, 19 Dec 2014 15:50:19 +0100 Subject: [PATCH 2/6] Fixed imageLoaderLimit Currently jobsInProgress was not incremented after adding a job. So it has gone into the - range and was like unlimited jobs. --- src/imageLoader.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/imageLoader.js b/src/imageLoader.js index 0fa658a2..3cab4cdd 100644 --- a/src/imageLoader.js +++ b/src/imageLoader.js @@ -133,7 +133,7 @@ $.ImageLoader.prototype = /** @lends OpenSeadragon.ImageLoader.prototype */{ this.jobsInProgress++; } else { - this.jobQueue.push( newJob ); + this.jobQueue.push( newJob ); } }, @@ -162,6 +162,7 @@ function completeJob( loader, job, callback ) { if ( (!loader.jobLimit || loader.jobsInProgress < loader.jobLimit) && loader.jobQueue.length > 0) { nextJob = loader.jobQueue.shift(); nextJob.start(); + loader.jobsInProgress++; } callback( job.image ); From 71cbd848798865000b7a129d065f2f74d458a2a8 Mon Sep 17 00:00:00 2001 From: Philip Giuliani Date: Fri, 19 Dec 2014 16:06:21 +0100 Subject: [PATCH 3/6] Fix case of filename All files are downcased so far. --- Gruntfile.js | 2 +- src/{imageLoader.js => imageloader.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{imageLoader.js => imageloader.js} (100%) diff --git a/Gruntfile.js b/Gruntfile.js index f774df6f..828f37a1 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -46,7 +46,7 @@ module.exports = function(grunt) { "src/referencestrip.js", "src/displayrectangle.js", "src/spring.js", - "src/imageLoader.js", + "src/imageloader.js", "src/tile.js", "src/overlay.js", "src/drawer.js", diff --git a/src/imageLoader.js b/src/imageloader.js similarity index 100% rename from src/imageLoader.js rename to src/imageloader.js From b8a7d33ebbbb961043cfad411acb35834b2e1f23 Mon Sep 17 00:00:00 2001 From: Philip Giuliani Date: Mon, 22 Dec 2014 08:51:57 +0100 Subject: [PATCH 4/6] Fix documentation of jobLimit --- src/imageloader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imageloader.js b/src/imageloader.js index 3cab4cdd..d1f9e785 100644 --- a/src/imageloader.js +++ b/src/imageloader.js @@ -95,7 +95,7 @@ ImageJob.prototype = { * @classdesc Handles downloading of a set of images using asynchronous queue pattern. * You generally won't have to interact with the ImageLoader directly. * @param {Object} options - Options for this ImageLoader. - * @param {Number} options.jobLimit - The number of concurrent image requests. + * @param {Number} [options.jobLimit] - The number of concurrent image requests. See imageLoaderLimit in {@link OpenSeadragon.Options} for details. */ $.ImageLoader = function( options ) { From 8d4c776cd0003382214dc1b189db74c7cf6eb1af Mon Sep 17 00:00:00 2001 From: Mark Salsbery Date: Tue, 30 Dec 2014 12:57:17 -0800 Subject: [PATCH 5/6] MouseTracker fixes for #502, #518, #527, #539 --- src/mousetracker.js | 136 +++++++++++++++++--------------------------- test/events.js | 64 ++++++++++----------- 2 files changed, 85 insertions(+), 115 deletions(-) diff --git a/src/mousetracker.js b/src/mousetracker.js index 0c865c74..3485c84d 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -193,8 +193,6 @@ mousemove: function ( event ) { onMouseMove( _this, event ); }, mousemovecaptured: function ( event ) { onMouseMoveCaptured( _this, event ); }, - mouseoutdocument: function ( event ) { onMouseOutDocument( _this, event ); }, - touchenter: function ( event ) { onTouchEnter( _this, event ); }, touchleave: function ( event ) { onTouchLeave( _this, event ); }, touchstart: function ( event ) { onTouchStart( _this, event ); }, @@ -210,9 +208,6 @@ pointerout: function ( event ) { onPointerOut( _this, event ); }, MSPointerOut: function ( event ) { onPointerOut( _this, event ); }, - pointeroutdocument: function ( event ) { onPointerOutDocument( _this, event ); }, - MSPointerOutdocument: function ( event ) { onPointerOutDocument( _this, event ); }, - pointerdown: function ( event ) { onPointerDown( _this, event ); }, MSPointerDown: function ( event ) { onPointerDown( _this, event ); }, pointerup: function ( event ) { onPointerUp( _this, event ); }, @@ -797,6 +792,8 @@ // Pointer event model and feature detection /////////////////////////////////////////////////////////////////////////////// + $.MouseTracker.captureElement = document; + /** * Detect available mouse wheel event name. */ @@ -1035,6 +1032,50 @@ // Utility functions /////////////////////////////////////////////////////////////////////////////// + /** + * Removes all tracked pointers. + * @private + * @inner + */ + function clearTrackedPointers( tracker ) { + var delegate = THIS[ tracker.hash ], + i, + pointerListCount = delegate.activePointersLists.length; + + if ( delegate.pointerCaptureCount > 0 ) { + $.removeEvent( + $.MouseTracker.captureElement, + 'mousemove', + delegate.mousemovecaptured, + true + ); + $.removeEvent( + $.MouseTracker.captureElement, + 'mouseup', + delegate.mouseupcaptured, + true + ); + $.removeEvent( + $.MouseTracker.captureElement, + $.MouseTracker.unprefixedPointerEvents ? 'pointermove' : 'MSPointerMove', + delegate.pointermovecaptured, + true + ); + $.removeEvent( + $.MouseTracker.captureElement, + $.MouseTracker.unprefixedPointerEvents ? 'pointerup' : 'MSPointerUp', + delegate.pointerupcaptured, + true + ); + + delegate.pointerCaptureCount = 0; + } + + for ( i = 0; i < pointerListCount; i++ ) { + delegate.activePointersLists.pop(); + } + } + /** * Starts tracking pointer events on the tracked element. * @private @@ -1056,14 +1097,7 @@ ); } - // handle pointer/mouse out of document body - if ( window.PointerEvent ) { - $.addEvent(document.body, "pointerout", delegate.pointeroutdocument); - } else if ( window.MSPointerEvent ) { - $.addEvent(document.body, "pointerout", delegate.MSPointerOutdocument); - } else { - $.addEvent(document.body, "mouseout", delegate.mouseoutdocument); - } + clearTrackedPointers( tracker ); delegate.tracking = true; } @@ -1090,14 +1124,7 @@ ); } - // handle pointer/mouse out of document body - if ( window.PointerEvent ) { - $.removeEvent(document.body, "pointerout", delegate.pointeroutdocument); - } else if ( window.MSPointerEvent ) { - $.removeEvent(document.body, "MSPointerOut", delegate.MSPointerOutdocument); - } else { - $.removeEvent(document.body, "mouseout", delegate.mouseoutdocument); - } + clearTrackedPointers( tracker ); delegate.tracking = false; } @@ -1112,19 +1139,18 @@ var delegate = THIS[ tracker.hash ]; delegate.pointerCaptureCount++; - //$.console.log('pointerCaptureCount++ ', delegate.pointerCaptureCount); if ( delegate.pointerCaptureCount === 1 ) { // We emulate mouse capture by hanging listeners on the window object. // (Note we listen on the capture phase so the captured handlers will get called first) $.addEvent( - window, + $.MouseTracker.captureElement, isLegacyMouse ? 'mouseup' : ($.MouseTracker.unprefixedPointerEvents ? 'pointerup' : 'MSPointerUp'), isLegacyMouse ? delegate.mouseupcaptured : delegate.pointerupcaptured, true ); $.addEvent( - window, + $.MouseTracker.captureElement, isLegacyMouse ? 'mousemove' : ($.MouseTracker.unprefixedPointerEvents ? 'pointermove' : 'MSPointerMove'), isLegacyMouse ? delegate.mousemovecaptured : delegate.pointermovecaptured, true @@ -1142,19 +1168,18 @@ var delegate = THIS[ tracker.hash ]; delegate.pointerCaptureCount--; - //$.console.log('pointerCaptureCount-- ', delegate.pointerCaptureCount); if ( delegate.pointerCaptureCount === 0 ) { // We emulate mouse capture by hanging listeners on the window object. // (Note we listen on the capture phase so the captured handlers will get called first) $.removeEvent( - window, + $.MouseTracker.captureElement, isLegacyMouse ? 'mousemove' : ($.MouseTracker.unprefixedPointerEvents ? 'pointermove' : 'MSPointerMove'), isLegacyMouse ? delegate.mousemovecaptured : delegate.pointermovecaptured, true ); $.removeEvent( - window, + $.MouseTracker.captureElement, isLegacyMouse ? 'mouseup' : ($.MouseTracker.unprefixedPointerEvents ? 'pointerup' : 'MSPointerUp'), isLegacyMouse ? delegate.mouseupcaptured : delegate.pointerupcaptured, true @@ -1481,35 +1506,6 @@ updatePointersExit( tracker, event, [ gPoint ] ); } - /** - * This handler is used to handle the case where the mouse is dragged out of the window, it should cause the drag to be properly released. - * - * @private - * @inner - */ - function onMouseOutDocument( tracker, event ) { - event = $.getEvent( event ); - - var html = document.getElementsByTagName("html")[0]; - var target = event.target || event.srcElement; - if ((event.relatedTarget!==html && event.relatedTarget!==null) || event.currentTarget !== document.body) { - return; // not a mouseout of the iframe - } - - var gPoint = { - id: $.MouseTracker.mousePointerId, - type: 'mouse', - isPrimary: true, - currentPos: getMouseAbsolute( event ), - currentTime: $.now() - }; - - event.buttons = undefined; - - if ( updatePointersUp( tracker, event, [ gPoint ], 0 ) ) { - releasePointer( tracker, true ); - } - } /** * @private @@ -1700,6 +1696,7 @@ if ( updatePointersDown( tracker, event, gPoints, 0 ) ) { // 0 means primary button press/release or touch contact // Touch event model start, end, and move events are always captured so we don't need to capture explicitly + $.stopEvent( event ); } $.cancelEvent( event ); @@ -1853,33 +1850,6 @@ updatePointersExit( tracker, event, [ gPoint ] ); } - /** - * This handler is used to handle the case where the pointer is dragged out of the window, it should cause the drag to be properly released. - * - * @private - * @inner - */ - function onPointerOutDocument( tracker, event ) { - event = $.getEvent( event ); - - var html = document.getElementsByTagName("html")[0]; - if ((event.relatedTarget!==html && event.relatedTarget!==null) || event.currentTarget !== document.body) { - return; // not a mouseout of the iframe - } - - var gPoint = { - id: event.pointerId, - type: getPointerType( event ), - isPrimary: event.isPrimary, - currentPos: getMouseAbsolute( event ), - currentTime: $.now() - }; - - if ( updatePointersUp( tracker, event, [ gPoint ], 0 ) ) { - releasePointer( tracker, false ); - } - } - /** * @private * @inner diff --git a/test/events.js b/test/events.js index ba1a36e2..07c14ea6 100644 --- a/test/events.js +++ b/test/events.js @@ -165,13 +165,13 @@ var simulateLeave = function (x, y) { simEvent.clientX = offset.left + x; simEvent.clientY = offset.top + y; - simEvent.relatedTarget = document.body; - $canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', simEvent ); - }; - var simulateLeaveFrame = function (x, y) { - simEvent.clientX = offset.left + x; - simEvent.clientY = offset.top + y; - simEvent.relatedTarget = document.getElementsByTagName("html")[0]; + // simEvent.relatedTarget = document.body; + // $canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', simEvent ); + //}; + //var simulateLeaveFrame = function (x, y) { + // simEvent.clientX = offset.left + x; + // simEvent.clientY = offset.top + y; + // simEvent.relatedTarget = document.getElementsByTagName("html")[0]; $canvas.simulate( OpenSeadragon.MouseTracker.haveMouseEnter ? 'mouseleave' : 'mouseout', simEvent ); }; @@ -454,31 +454,31 @@ }); - // enter-press-move-exit-move-release-outside (drag, release outside iframe) - resetForAssessment(); - simulateEnter(0, 0); - simulateDown(0, 0); - simulateMove(1, 1, 5); - simulateMove(-1, -1, 5); - simulateLeaveFrame(-1, -1); - // you don't actually receive the mouseup if you mouseup outside of the document - assessGestureExpectations({ - description: 'enter-press-move-exit-move-release-outside (drag, release outside iframe): ', - enterCount: 1, - exitCount: 1, - pressCount: 1, - releaseCount: 1, - moveCount: 10, - clickCount: 0, - dblClickCount: 0, - dragCount: 10, - dragEndCount: 1, - insideElementPressed: true, - insideElementReleased: false, - contacts: 0, - trackedPointers: 0, - quickClick: false - }); + //// enter-press-move-exit-move-release-outside (drag, release outside iframe) + //resetForAssessment(); + //simulateEnter(0, 0); + //simulateDown(0, 0); + //simulateMove(1, 1, 5); + //simulateMove(-1, -1, 5); + //simulateLeaveFrame(-1, -1); + //// you don't actually receive the mouseup if you mouseup outside of the document + //assessGestureExpectations({ + // description: 'enter-press-move-exit-move-release-outside (drag, release outside iframe): ', + // enterCount: 1, + // exitCount: 1, + // pressCount: 1, + // releaseCount: 1, + // moveCount: 10, + // clickCount: 0, + // dblClickCount: 0, + // dragCount: 10, + // dragEndCount: 1, + // insideElementPressed: true, + // insideElementReleased: false, + // contacts: 0, + // trackedPointers: 0, + // quickClick: false + //}); unhookViewerHandlers(); viewer.close(); From 3e76bfdd9eae24a212d4dc34a66871faa7290722 Mon Sep 17 00:00:00 2001 From: Ian Gilman Date: Wed, 31 Dec 2014 11:08:06 -0800 Subject: [PATCH 6/6] Changelog for #518 --- changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index e77bb84d..4ae3667e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -18,8 +18,8 @@ OPENSEADRAGON CHANGELOG * Viewport.setRotation now allows all rotation angles (#466) * Pinch rotate is now available (defaults to off) (#468) * Added option for home button to fill viewer (#474) -* Now handling iframe/frame mouseouts properly (#481) * Better handling of mid-update image loaded callbacks (#409) +* Tracked pointers are now cleaned up when Viewer.setMouseNavEnabled(false) is called (#518) 1.1.1: