mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 22:55:23 +00:00
Changes to KineticController to stop it from painting as it scrolls.
Added sidebar snapping. More debug dumps for the content click redispatch bug.
This commit is contained in:
parent
0874fc97b3
commit
19e225ec8f
@ -95,6 +95,43 @@ function InputHandler() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The input handler is an arbiter between the Fennec chrome window inputs and any
|
||||
* registered input modules. It keeps an array of input module objects. Incoming
|
||||
* input events are wrapped in an EventInfo object and passed down to the input modules
|
||||
* in the order of the modules array.
|
||||
*
|
||||
* Input modules must provide the following interface:
|
||||
*
|
||||
* handleEvent(evInfo)
|
||||
* Entry point by which InputHandler passes wrapped Fennec chrome window events
|
||||
* to the module.
|
||||
*
|
||||
* cancelPending()
|
||||
* Called by the InputHandler as a hint to the module that it may wish to reset
|
||||
* whatever state it might have entered by processing events thus far. For
|
||||
* instance, a module may have grabbed (cf grab()) focus, in which case the
|
||||
* InputHandler will call cancelPending() on all remaining modules.
|
||||
*
|
||||
*
|
||||
*
|
||||
* An input module may wish to grab event focus of the InputHandler, which means that it
|
||||
* wants to process all incoming events for a while. When the InputHandler is grabbed
|
||||
* by one of its modules, only that module will receive incoming events until it ungrabs
|
||||
* the InputHandler. No other modules' handleEvent() function will be called while the
|
||||
* InputHandler is grabbed. Grabs and ungrabs of the InputHandler require an object reference
|
||||
* corresponding to the grabbing object. That is, a module must call inputHandler.grab(this)
|
||||
* and .ungrab(this) in order for the calls to succeed. The object given as the argument
|
||||
* will be that which is given event focus. grab/ungrab may be nested (that is, a module can
|
||||
* grab as many times as it wants to) provided that they are one-to-one. That is, if a
|
||||
* module grabs four times, it should be sure to ungrab that many times as well. Lastly,
|
||||
* an input module may, in ungrabbing, provide an array of queued EventInfo objects, each of
|
||||
* which will be passed by the InputHandler to each of the subsequent modules ("subsequent"
|
||||
* as in "next in the ordering within the modules array") via handleEvent(). This can be
|
||||
* thought of as the module's way of saying "sorry for grabbing focus, here's everything I
|
||||
* kept you from processing this whole time" to the modules of lower priority. To prevent
|
||||
* infinite loops, this event queue is only passed to lower-priority modules.
|
||||
*/
|
||||
InputHandler.prototype = {
|
||||
|
||||
/**
|
||||
@ -110,7 +147,7 @@ InputHandler.prototype = {
|
||||
*/
|
||||
// XXX froystig: grab(null) is supported because the old grab() supported
|
||||
// it, but I'm not sure why. The comment on that was "grab(null) is
|
||||
// allowed because of mouseout handling. Feel free to remove if that
|
||||
// allowed because of mouseout handling". Feel free to remove if that
|
||||
// is no longer relevant, or remove this comment if it still is.
|
||||
grab: function grab(grabber) {
|
||||
if (grabber == null) {
|
||||
@ -148,7 +185,7 @@ InputHandler.prototype = {
|
||||
* events all along.
|
||||
*/
|
||||
// XXX froystig: ungrab(null) is supported here too because the old ungrab()
|
||||
// happened to support it (not sure if intentionally --- there was no
|
||||
// happened to support it (not sure if intentionally; there was no
|
||||
// comment it), so cf the corresponding comment on grab().
|
||||
ungrab: function ungrab(grabber, restoreEventInfos) {
|
||||
if (this._grabber == null && grabber == null) {
|
||||
@ -242,7 +279,7 @@ function MouseModule(owner) {
|
||||
this._owner = owner;
|
||||
this._dragData = new DragData(this, 50, 200);
|
||||
|
||||
this._dragger = this._defaultDragger;
|
||||
this._dragger = null;
|
||||
this._clicker = null;
|
||||
|
||||
this._downUpEvents = [];
|
||||
@ -253,7 +290,10 @@ function MouseModule(owner) {
|
||||
this._fastPath = false;
|
||||
|
||||
var self = this;
|
||||
this._kinetic = new KineticController( function (dx, dy) { return self._dragBy(dx, dy); } );
|
||||
this._kinetic = new KineticController(
|
||||
function _dragByBound(dx, dy) { return self._dragBy(dx, dy); },
|
||||
function _dragStopBound() { return self._doDragStop(0, 0, true); }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -284,6 +324,8 @@ MouseModule.prototype = {
|
||||
|
||||
_onMouseDown: function _onMouseDown(evInfo) {
|
||||
this._owner.allowClicks();
|
||||
if (this._kinetic.isActive())
|
||||
this._kinetic.end();
|
||||
|
||||
// walk up the DOM tree in search of nearest scrollable ancestor. nulls are
|
||||
// returned if none found.
|
||||
@ -294,13 +336,8 @@ MouseModule.prototype = {
|
||||
|
||||
this._targetScrollInterface = targetScrollInterface;
|
||||
|
||||
// fast path: we have no scrollable element nor any element with custom clicker, so
|
||||
// just let the event bubble on through
|
||||
//this._fastPath = !targetScrollInterface && !targetClicker;
|
||||
//if (this._fastPath)
|
||||
// return;
|
||||
|
||||
this._dragger = (targetScrollInterface && targetScrollbox.customDragger) || this._defaultDragger;
|
||||
this._dragger = (targetScrollInterface) ? (targetScrollbox.customDragger || this._defaultDragger)
|
||||
: null;
|
||||
this._clicker = (targetClicker) ? targetClicker.customClicker : null;
|
||||
|
||||
evInfo.event.stopPropagation();
|
||||
@ -309,7 +346,6 @@ MouseModule.prototype = {
|
||||
this._owner.grab(this);
|
||||
|
||||
if (targetScrollInterface) {
|
||||
this._kinetic.end();
|
||||
this._doDragStart(evInfo.event.screenX, evInfo.event.screenY);
|
||||
}
|
||||
|
||||
@ -396,18 +432,22 @@ MouseModule.prototype = {
|
||||
this._dragger.dragStart(this._targetScrollInterface);
|
||||
},
|
||||
|
||||
_doDragStop: function _doDragStop(sX, sY) {
|
||||
let dragData = this._dragData;
|
||||
_doDragStop: function _doDragStop(sX, sY, kineticStop) {
|
||||
if (!kineticStop) { // we're not really done, since now it is
|
||||
// kinetic's turn to scroll about
|
||||
let dragData = this._dragData;
|
||||
|
||||
let dx = dragData.sX - sX;
|
||||
let dy = dragData.sY - sY;
|
||||
let dx = dragData.sX - sX;
|
||||
let dy = dragData.sY - sY;
|
||||
|
||||
dragData.setDragPosition(sX, sY);
|
||||
this._kinetic.addData(sX, sY);
|
||||
dragData.reset();
|
||||
this._kinetic.addData(sX, sY);
|
||||
|
||||
this._dragger.dragStop(dx, dy, this._targetScrollInterface);
|
||||
this._kinetic.start();
|
||||
|
||||
this._kinetic.start();
|
||||
} else { // now we're done, says our secret 3rd argument
|
||||
this._dragger.dragStop(0, 0, this._targetScrollInterface);
|
||||
}
|
||||
},
|
||||
|
||||
_doDragMove: function _doDragMove(sX, sY) {
|
||||
@ -447,12 +487,14 @@ MouseModule.prototype = {
|
||||
*
|
||||
*/
|
||||
_commitAnotherClick: function _commitAnotherClick() {
|
||||
this._doSingleClick();
|
||||
/*
|
||||
if (this._clickTimeout) { // we're waiting for a second click for double
|
||||
window.clearTimeout(this._clickTimeout);
|
||||
this._doDoubleClick();
|
||||
} else {
|
||||
this._clickTimeout = window.setTimeout(function _clickTimeout(self) { self._doSingleClick(); }, 400, this);
|
||||
}
|
||||
}*/
|
||||
},
|
||||
|
||||
/**
|
||||
@ -667,9 +709,10 @@ DragData.prototype = {
|
||||
* generated by the kinetic algorithm. It should return true if the
|
||||
* object was panned, false if there was no movement.
|
||||
*/
|
||||
function KineticController(aPanBy) {
|
||||
function KineticController(aPanBy, aEndCallback) {
|
||||
this._panBy = aPanBy;
|
||||
this._timer = null;
|
||||
this._beforeEnd = aEndCallback;
|
||||
|
||||
try {
|
||||
this._updateInterval = gPrefService.getIntPref("browser.ui.kinetic.updateInterval");
|
||||
@ -782,6 +825,7 @@ KineticController.prototype = {
|
||||
},
|
||||
|
||||
end: function end() {
|
||||
this._beforeEnd();
|
||||
this._reset();
|
||||
},
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
* Johnathan Nightingale <johnath@mozilla.com>
|
||||
* Stuart Parmenter <stuart@mozilla.com>
|
||||
* Taras Glek <tglek@mozilla.com>
|
||||
* Roy Frostig <rfrostig@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -89,6 +90,7 @@ function debug() {
|
||||
dump('visibleRect from foo: ' + getVisibleRect().toString() + endl);
|
||||
|
||||
dump('batch depth: ' + bv._batchOps.length + endl);
|
||||
dump('renderpause depth: ' + bv._renderMode + endl);
|
||||
|
||||
dump(endl);
|
||||
|
||||
@ -233,12 +235,12 @@ function screenToBrowserView(x, y) {
|
||||
}
|
||||
|
||||
// Return the visible rect in terms of the tile container
|
||||
function getVisibleRect() {
|
||||
function getVisibleRect(noTranslate) {
|
||||
let container = document.getElementById("tile-container");
|
||||
let containerBCR = container.getBoundingClientRect();
|
||||
|
||||
let x = Math.round(-containerBCR.left);
|
||||
let y = Math.round(-containerBCR.top);
|
||||
let x = Math.round(noTranslate ? 0 : -containerBCR.left);
|
||||
let y = Math.round(noTranslate ? 0 : -containerBCR.top);
|
||||
let w = window.innerWidth;
|
||||
let h = window.innerHeight;
|
||||
|
||||
@ -279,12 +281,17 @@ var Browser = {
|
||||
},
|
||||
|
||||
dragStop: function dragStop(dx, dy, scroller) {
|
||||
let ret = this.dragMove(dx, dy, scroller);
|
||||
let dx = this.dragMove(dx, dy, scroller, true);
|
||||
|
||||
let snapdx = Browser.snapSidebars(scroller);
|
||||
bv.onAfterVisibleMove(snapdx, 0);
|
||||
|
||||
bv.resumeRendering();
|
||||
return ret;
|
||||
|
||||
return (dy != 0) || ((dx + snapdx) != 0);
|
||||
},
|
||||
|
||||
dragMove: function dragMove(dx, dy, scroller) {
|
||||
dragMove: function dragMove(dx, dy, scroller, doReturnDX) {
|
||||
bv.onBeforeVisibleMove(dx, dy);
|
||||
|
||||
let [x0, y0] = getScrollboxPosition(scroller);
|
||||
@ -302,7 +309,7 @@ var Browser = {
|
||||
dump('--> scroll asked for ' + dx + ',' + dy + ' and got ' + realdx + ',' + realdy + '\n');
|
||||
}
|
||||
|
||||
return !(realdx == 0 && realdy == 0);
|
||||
return (doReturnDX) ? realdx : !(realdx == 0 && realdy == 0);
|
||||
}
|
||||
};
|
||||
|
||||
@ -378,12 +385,12 @@ var Browser = {
|
||||
bv.commitBatchOperation();
|
||||
}
|
||||
window.addEventListener("resize", resizeHandler, false);
|
||||
|
||||
|
||||
function fullscreenHandler() {
|
||||
if (!window.fullScreen)
|
||||
document.getElementById("toolbar-main").setAttribute("fullscreen", "true");
|
||||
else
|
||||
document.getElementById("toolbar-main").removeAttribute("fullscreen");
|
||||
document.getElementById("toolbar-main").removeAttribute("fullscreen");
|
||||
}
|
||||
window.addEventListener("fullscreen", fullscreenHandler, false);
|
||||
|
||||
@ -837,9 +844,9 @@ var Browser = {
|
||||
singleClick: function singleClick(cX, cY) {
|
||||
let browser = browserView.getBrowser();
|
||||
if (browser) {
|
||||
dump('singleClick was invoked with ' + cX + ', ' + cY + '\n');
|
||||
dump('singleClick was invoked with ' + cX + ', ' + cY + '\n');
|
||||
let [x, y] = transformScreenToBrowser(cX, cY);
|
||||
dump('dispatching in browser ' + x + ', ' + y + '\n');
|
||||
dump('dispatching in browser ' + x + ', ' + y + '\n');
|
||||
dispatchContentClick(browser, x, y);
|
||||
}
|
||||
},
|
||||
@ -850,10 +857,10 @@ var Browser = {
|
||||
let zoomElement = elementFromPoint(browser, cX2, cY2);
|
||||
|
||||
if (zoomElement) {
|
||||
// TODO actually zoom to and from element
|
||||
// TODO actually zoom to and from element
|
||||
//browserView.zoom(this.zoomDir);
|
||||
//this.zoomDir *= -1;
|
||||
dump('zooming to/from element: ' + zoomElement + '\n');
|
||||
//this.zoomDir *= -1;
|
||||
dump('zooming to/from element: ' + zoomElement + '\n');
|
||||
}
|
||||
|
||||
//let [x, y] = transformScreenToBrowser(cX1, cY1);
|
||||
@ -863,6 +870,57 @@ var Browser = {
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns dx of snap
|
||||
*/
|
||||
snapSidebars: function snapSidebars(scroller) {
|
||||
function visibility(bar, visrect) {
|
||||
try {
|
||||
let w = bar.width;
|
||||
let h = bar.height;
|
||||
bar.restrictTo(visrect); // throws exception if intersection of rects is empty
|
||||
return [bar.width / w, bar.height / h];
|
||||
} catch (e) {
|
||||
return [0, 0];
|
||||
}
|
||||
}
|
||||
|
||||
let visrect = getVisibleRect(true);
|
||||
let leftbarCBR = document.getElementById('tabs-container').getBoundingClientRect();
|
||||
let ritebarCBR = document.getElementById('browser-controls').getBoundingClientRect();
|
||||
|
||||
let leftbar = new wsRect(leftbarCBR.left, leftbarCBR.top, leftbarCBR.width, leftbarCBR.height);
|
||||
let ritebar = new wsRect(ritebarCBR.left, ritebarCBR.top, ritebarCBR.width, ritebarCBR.height);
|
||||
let leftw = leftbar.width;
|
||||
let ritew = ritebar.width;
|
||||
|
||||
let [leftvis, ] = visibility(leftbar, visrect);
|
||||
let [ritevis, ] = visibility(ritebar, visrect);
|
||||
|
||||
let snappedX = 0;
|
||||
|
||||
if (leftvis != 0 && leftvis != 1) {
|
||||
if (leftvis >= 0.6666)
|
||||
snappedX = -((1 - leftvis) * leftw);
|
||||
else
|
||||
snappedX = leftvis * leftw;
|
||||
|
||||
snappedX = Math.round(snappedX);
|
||||
scroller.scrollBy(snappedX, 0);
|
||||
}
|
||||
else if (ritevis != 0 && ritevis != 1) {
|
||||
if (ritevis >= 0.6666)
|
||||
snappedX = (1 - ritevis) * ritew;
|
||||
else
|
||||
snappedX = -ritevis * ritew;
|
||||
|
||||
snappedX = Math.round(snappedX);
|
||||
scroller.scrollBy(snappedX, 0);
|
||||
}
|
||||
|
||||
return snappedX;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1677,9 +1735,16 @@ Tab.prototype = {
|
||||
},
|
||||
|
||||
load: function(uri) {
|
||||
dump('browser 3: ' + this._browser.contentWindow + '\n');
|
||||
dump("cb set src\n");
|
||||
this._browser.setAttribute("src", uri);
|
||||
dump("cb end src\n");
|
||||
dump('browser 4: ' + this._browser.contentWindow + '\n');
|
||||
try {
|
||||
dump('QIs to: ' + this._browser.contentWindow.QueryInterface(Ci.nsIDOMChromeWindow) + '\n');
|
||||
} catch (e) {
|
||||
dump('failed to QI\n');
|
||||
}
|
||||
},
|
||||
|
||||
create: function() {
|
||||
@ -1697,6 +1762,7 @@ Tab.prototype = {
|
||||
},
|
||||
|
||||
_createBrowser: function() {
|
||||
dump('for the break\n');
|
||||
if (this._browser)
|
||||
throw "Browser already exists";
|
||||
|
||||
@ -1704,6 +1770,8 @@ Tab.prototype = {
|
||||
let scaledHeight = kDefaultBrowserWidth * (window.innerHeight / window.innerWidth);
|
||||
let browser = this._browser = document.createElement("browser");
|
||||
|
||||
dump('browser 1: ' + browser.contentWindow + '\n');
|
||||
|
||||
browser.setAttribute("style", "overflow: -moz-hidden-unscrollable; visibility: hidden; width: " + kDefaultBrowserWidth + "px; height: " + scaledHeight + "px;");
|
||||
browser.setAttribute("type", "content");
|
||||
|
||||
@ -1720,6 +1788,8 @@ Tab.prototype = {
|
||||
// stop about:blank from loading
|
||||
browser.stop();
|
||||
|
||||
dump('browser 2: ' + browser.contentWindow + '\n');
|
||||
|
||||
// Attach a separate progress listener to the browser
|
||||
this._listener = new ProgressController(this);
|
||||
browser.addProgressListener(this._listener);
|
||||
|
Loading…
Reference in New Issue
Block a user