зеркало из https://github.com/mozilla/gecko-dev.git
Merge of iframe scrolling patch to tiles. r=stuart
This commit is contained in:
Родитель
3037d574d0
Коммит
a1da836547
|
@ -378,7 +378,14 @@ BrowserView.prototype = {
|
|||
this._renderMode--;
|
||||
|
||||
if (renderNow || this._renderMode == 0)
|
||||
this._tileManager.criticalRectPaint();
|
||||
this.renderNow();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called while rendering is paused to allow update of critical area
|
||||
*/
|
||||
renderNow: function renderNow() {
|
||||
this._tileManager.criticalRectPaint();
|
||||
},
|
||||
|
||||
isRendering: function isRendering() {
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/**
|
||||
* InputHandler
|
||||
*
|
||||
|
@ -56,7 +55,6 @@
|
|||
* On the Fennec global chrome window:
|
||||
* URLChanged
|
||||
* TabSelect
|
||||
* mouseout
|
||||
* mousedown
|
||||
* mouseup
|
||||
* mousemove
|
||||
|
@ -122,9 +120,6 @@ function InputHandler(browserViewContainer) {
|
|||
this.listenFor(window, "URLChanged");
|
||||
this.listenFor(window, "TabSelect");
|
||||
|
||||
/* used to stop everything if mouse leaves window on desktop */
|
||||
this.listenFor(window, "mouseout");
|
||||
|
||||
/* these handle dragging of both chrome elements and content */
|
||||
this.listenFor(window, "mousedown");
|
||||
this.listenFor(window, "mouseup");
|
||||
|
@ -140,8 +135,6 @@ function InputHandler(browserViewContainer) {
|
|||
|
||||
this.addModule(new MouseModule(this));
|
||||
this.addModule(new ScrollwheelModule(this, Browser._browserView, browserViewContainer));
|
||||
//this.addModule(new ContentPanningModule(this, browserViewContainer, useEarlyMouseMoves));
|
||||
//this.addModule(new ContentClickingModule(this));
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,20 +170,21 @@ InputHandler.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* A module calls grab(this) to grab event focus from the input handler.
|
||||
* In grabbed state, the input handler forwards all events directly to
|
||||
* the grabber module, and not to any other modules. The this reference
|
||||
* passed is essentially a ceritificate to the input handler --- collateral
|
||||
* for the grab. A grabber module may make nested calls to grab() but
|
||||
* should symmetrically ungrab(). Other modules cannot grab a grabbed input
|
||||
* handler, and only the grabber module can ungrab the input handler.
|
||||
* A module calls grab(this) to grab event focus from the input
|
||||
* handler. In grabbed state, the input handler forwards all events
|
||||
* directly to the grabber module, and not to any other modules.
|
||||
* The this reference passed is essentially a ceritificate to the
|
||||
* input handler --- collateral for the grab. A grabber module may
|
||||
* make nested calls to grab() but should symmetrically ungrab().
|
||||
* Other modules cannot grab a grabbed input handler, and only the
|
||||
* grabber module can ungrab the input handler.
|
||||
*
|
||||
* grab(null) aborts all input handlers. This is used in situations
|
||||
* like the page changing to a different URL where you want to abort
|
||||
* drags in progress or kinetic movement.
|
||||
*
|
||||
* Returns true if the grab succeeded, false otherwise.
|
||||
*/
|
||||
// XXX 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 is no longer
|
||||
// relevant, or remove this comment if it still is.
|
||||
grab: function grab(grabber) {
|
||||
if (grabber == null) {
|
||||
this._grabber = null;
|
||||
|
@ -369,8 +363,9 @@ InputHandler.EventInfo.prototype = {
|
|||
* following interface: (The `scroller' argument is given for convenience, and
|
||||
* is the object reference to the element's scrollbox object).
|
||||
*
|
||||
* dragStart(scroller)
|
||||
* Signals the beginning of a drag.
|
||||
* dragStart(cX, cY, target, scroller)
|
||||
* Signals the beginning of a drag. Coordinates are passed as
|
||||
* client coordinates. target is copied from the event.
|
||||
*
|
||||
* dragStop(dx, dy, scroller)
|
||||
* Signals the end of a drag. The dx, dy parameters may be non-zero to
|
||||
|
@ -479,7 +474,7 @@ MouseModule.prototype = {
|
|||
this._owner.grab(this);
|
||||
|
||||
if (targetScrollInterface) {
|
||||
this._doDragStart(evInfo.event.screenX, evInfo.event.screenY);
|
||||
this._doDragStart(evInfo.event);
|
||||
}
|
||||
|
||||
this._recordEvent(evInfo);
|
||||
|
@ -587,13 +582,13 @@ MouseModule.prototype = {
|
|||
/**
|
||||
* Inform our dragger of a dragStart and update kinetic with new data.
|
||||
*/
|
||||
_doDragStart: function _doDragStart(sX, sY) {
|
||||
_doDragStart: function _doDragStart(event) {
|
||||
let dragData = this._dragData;
|
||||
|
||||
dragData.setDragStart(sX, sY);
|
||||
this._kinetic.addData(sX, sY);
|
||||
dragData.setDragStart(event.screenX, event.screenY);
|
||||
this._kinetic.addData(event.screenX, event.screenY);
|
||||
|
||||
this._dragger.dragStart(this._targetScrollInterface);
|
||||
this._dragger.dragStart(event.clientX, event.clientY, event.target, this._targetScrollInterface);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -738,7 +733,7 @@ MouseModule.prototype = {
|
|||
* regular scrollBy calls on the scroller.
|
||||
*/
|
||||
_defaultDragger: {
|
||||
dragStart: function dragStart(scroller) {},
|
||||
dragStart: function dragStart(cx, cy, target, scroller) {},
|
||||
|
||||
dragStop : function dragStop(dx, dy, scroller)
|
||||
{ return this.dragMove(dx, dy, scroller); },
|
||||
|
@ -903,7 +898,7 @@ DragData.prototype = {
|
|||
},
|
||||
|
||||
isPointOutsideRadius: function isPointOutsideRadius(sX, sY) {
|
||||
if (this._originX == undefined)
|
||||
if (this._originX === null)
|
||||
return false;
|
||||
return (Math.pow(sX - this._originX, 2) + Math.pow(sY - this._originY, 2)) >
|
||||
(2 * Math.pow(this._dragRadius, 2));
|
||||
|
@ -1043,7 +1038,8 @@ KineticController.prototype = {
|
|||
},
|
||||
|
||||
end: function end() {
|
||||
this._beforeEnd();
|
||||
if (this._beforeEnd)
|
||||
this._beforeEnd();
|
||||
this._reset();
|
||||
},
|
||||
|
||||
|
@ -1062,253 +1058,11 @@ KineticController.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Util.dumpLn("adding t:", now, ", sx: ", sx, ", sy: ", sy);
|
||||
this.momentumBuffer.push({'t': now, 'sx' : sx, 'sy' : sy});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function ContentPanningModule(owner, browserCanvas, useEarlyMouseMoves) {
|
||||
this._owner = owner;
|
||||
this._browserCanvas = browserCanvas;
|
||||
this._dragData = new DragData(this, 50, 200);
|
||||
this._useEarlyMouseMoves = useEarlyMouseMoves;
|
||||
|
||||
var self = this;
|
||||
this._kinetic = new KineticController( function (dx, dy) { return self._dragBy(dx, dy); } );
|
||||
}
|
||||
|
||||
ContentPanningModule.prototype = {
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
// exit early for events outside displayed content area
|
||||
if (aEvent.target !== this._browserCanvas)
|
||||
return;
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "mousedown":
|
||||
this._onMouseDown(aEvent);
|
||||
break;
|
||||
case "mousemove":
|
||||
this._onMouseMove(aEvent);
|
||||
break;
|
||||
case "mouseout":
|
||||
case "mouseup":
|
||||
this._onMouseUp(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/* If someone else grabs events ahead of us, cancel any pending
|
||||
* timeouts we may have.
|
||||
*/
|
||||
cancelPending: function cancelPending() {
|
||||
this._kinetic.end();
|
||||
this._dragData.reset();
|
||||
},
|
||||
|
||||
_dragStart: function _dragStart(sX, sY) {
|
||||
let dragData = this._dragData;
|
||||
|
||||
dragData.setDragStart(sX, sY);
|
||||
|
||||
[sX, sY] = dragData.lockAxis(sX, sY);
|
||||
|
||||
//ws.dragStart(sX, sY);
|
||||
|
||||
//Browser.canvasBrowser.startPanning();
|
||||
},
|
||||
|
||||
_dragStop: function _dragStop(sX, sY) {
|
||||
let dragData = this._dragData;
|
||||
|
||||
this._owner.ungrab(this);
|
||||
|
||||
[sX, sY] = dragData.lockMouseMove(sX, sY);
|
||||
|
||||
// start kinetic scrolling here for canvas only
|
||||
this._kinetic.start(sX, sY);
|
||||
|
||||
dragData.reset();
|
||||
},
|
||||
|
||||
_dragBy: function _dragBy(dx, dy) {
|
||||
/* XXX
|
||||
let panned = ws.dragBy(dx, dy);
|
||||
return panned;
|
||||
*/
|
||||
return false;
|
||||
},
|
||||
|
||||
_dragMove: function _dragMove(sX, sY) {
|
||||
let dragData = this._dragData;
|
||||
[sX, sY] = dragData.lockMouseMove(sX, sY);
|
||||
//XXX let panned = ws.dragMove(sX, sY);
|
||||
let panned = false;
|
||||
dragData.setDragPosition(sX, sY);
|
||||
return panned;
|
||||
},
|
||||
|
||||
_onMouseDown: function _onMouseDown(aEvent) {
|
||||
let dragData = this._dragData;
|
||||
// if we're in the process of kineticly scrolling, stop and start over
|
||||
if (this._kinetic.isActive()) {
|
||||
this._kinetic.end();
|
||||
this._owner.ungrab(this);
|
||||
dragData.reset();
|
||||
}
|
||||
|
||||
this._dragStart(aEvent.screenX, aEvent.screenY);
|
||||
this._onMouseMove(aEvent); // treat this as a mouse move too
|
||||
},
|
||||
|
||||
_onMouseUp: function _onMouseUp(aEvent) {
|
||||
let dragData = this._dragData;
|
||||
|
||||
if (dragData.dragging) {
|
||||
this._onMouseMove(aEvent); // treat this as a mouse move, incase our x/y are different
|
||||
this._dragStop(aEvent.screenX, aEvent.screenY);
|
||||
}
|
||||
|
||||
dragData.reset(); // be sure to reset the timer
|
||||
},
|
||||
|
||||
_onMouseMove: function _onMouseMove(aEvent) {
|
||||
// don't do anything if we're in the process of kineticly scrolling
|
||||
if (this._kinetic.isActive())
|
||||
return;
|
||||
|
||||
let dragData = this._dragData;
|
||||
|
||||
// if we move enough, start a grab to prevent click from getting events
|
||||
if (dragData.isPointOutsideRadius(aEvent.screenX, aEvent.screenY))
|
||||
this._owner.grab(this);
|
||||
|
||||
// if we never received a mouseDown, we need to go ahead and set this data
|
||||
if (!dragData.sX)
|
||||
dragData.setDragPosition(aEvent.screenX, aEvent.screenY);
|
||||
|
||||
let [sX, sY] = dragData.lockMouseMove(aEvent.screenX, aEvent.screenY);
|
||||
|
||||
// even if we haven't started dragging yet, we should queue up the
|
||||
// mousemoves in case we do start
|
||||
if (this._useEarlyMouseMoves || dragData.dragging)
|
||||
this._kinetic.addData(sX, sY);
|
||||
|
||||
if (dragData.dragging)
|
||||
this._dragMove(sX, sY);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Mouse click handlers
|
||||
*/
|
||||
function ContentClickingModule(owner) {
|
||||
this._owner = owner;
|
||||
this._clickTimeout = -1;
|
||||
this._events = [];
|
||||
this._zoomedTo = null;
|
||||
}
|
||||
|
||||
ContentClickingModule.prototype = {
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
// UI panning events
|
||||
case "mousedown":
|
||||
this._events.push({event: aEvent, time: Date.now()});
|
||||
|
||||
|
||||
case "mouseup":
|
||||
// keep an eye out for mouseups that didn't start with a mousedown
|
||||
if (!(this._events.length % 2)) {
|
||||
this._reset();
|
||||
break;
|
||||
}
|
||||
|
||||
this._events.push({event: aEvent, time: Date.now()});
|
||||
|
||||
if (this._clickTimeout == -1) {
|
||||
this._clickTimeout = window.setTimeout(function _clickTimeout(self) { self._sendSingleClick(); }, 400, this);
|
||||
} else {
|
||||
window.clearTimeout(this._clickTimeout);
|
||||
this._clickTimeout = -1;
|
||||
this._sendDoubleClick();
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/* If someone else grabs events ahead of us, cancel any pending
|
||||
* timeouts we may have.
|
||||
*/
|
||||
cancelPending: function cancelPending() {
|
||||
this._reset();
|
||||
},
|
||||
|
||||
_reset: function _reset() {
|
||||
if (this._clickTimeout != -1)
|
||||
window.clearTimeout(this._clickTimeout);
|
||||
this._clickTimeout = -1;
|
||||
|
||||
this._events = [];
|
||||
},
|
||||
|
||||
_sendSingleClick: function _sendSingleClick() {
|
||||
this._owner.grab(this);
|
||||
this._dispatchContentMouseEvent(this._events[0].event);
|
||||
this._dispatchContentMouseEvent(this._events[1].event);
|
||||
this._owner.ungrab(this);
|
||||
|
||||
this._reset();
|
||||
},
|
||||
|
||||
_sendDoubleClick: function _sendDoubleClick() {
|
||||
this._owner.grab(this);
|
||||
|
||||
function optimalElementForPoint(cX, cY) {
|
||||
var element = Browser.canvasBrowser.elementFromPoint(cX, cY);
|
||||
return element;
|
||||
}
|
||||
|
||||
let firstEvent = this._events[0].event;
|
||||
let zoomElement = optimalElementForPoint(firstEvent.clientX, firstEvent.clientY);
|
||||
|
||||
if (zoomElement) {
|
||||
if (zoomElement != this._zoomedTo) {
|
||||
this._zoomedTo = zoomElement;
|
||||
Browser.canvasBrowser.zoomToElement(zoomElement);
|
||||
} else {
|
||||
this._zoomedTo = null;
|
||||
Browser.canvasBrowser.zoomFromElement(zoomElement);
|
||||
}
|
||||
}
|
||||
|
||||
this._owner.ungrab(this);
|
||||
|
||||
this._reset();
|
||||
},
|
||||
|
||||
|
||||
_dispatchContentMouseEvent: function _dispatchContentMouseEvent(aEvent, aType) {
|
||||
if (!(aEvent instanceof MouseEvent)) {
|
||||
Cu.reportError("_dispatchContentMouseEvent called with a non-mouse event");
|
||||
return;
|
||||
}
|
||||
|
||||
let cb = Browser.canvasBrowser;
|
||||
var [x, y] = cb._clientToContentCoords(aEvent.clientX, aEvent.clientY);
|
||||
var cwu = cb.contentDOMWindowUtils;
|
||||
|
||||
// Redispatch the mouse event, ignoring the root scroll frame
|
||||
cwu.sendMouseEvent(aType || aEvent.type,
|
||||
x, y,
|
||||
aEvent.button || 0,
|
||||
aEvent.detail || 1,
|
||||
0, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Input module for basic scrollwheel input. Currently just zooms the browser
|
||||
* view accordingly.
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Roy Frostig <rfrostig@mozilla.com>
|
||||
* Ben Combee <bcombee@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
|
||||
|
@ -56,8 +57,13 @@ let Util = {
|
|||
for (let key in instance)
|
||||
if (instance[key] instanceof Function)
|
||||
instance[key] = bind(instance[key], instance);
|
||||
}
|
||||
},
|
||||
|
||||
dumpLn: function dumpLn() {
|
||||
// like dump, but each arg is handled and there's an automatic newline
|
||||
for (var i = 0; i < arguments.length; i++) { dump(arguments[i]); }
|
||||
dump("\n");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -554,4 +560,3 @@ wsRect.prototype = {
|
|||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
* Stuart Parmenter <stuart@mozilla.com>
|
||||
* Taras Glek <tglek@mozilla.com>
|
||||
* Roy Frostig <rfrostig@mozilla.com>
|
||||
*
|
||||
* Ben Combee <bcombee@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
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
|
@ -339,18 +340,19 @@ var Browser = {
|
|||
let container = document.getElementById("tile-container");
|
||||
let bv = this._browserView = new BrowserView(container, Browser.getVisibleRect());
|
||||
|
||||
/* handles dispatching clicks on tiles into clicks in content or zooms */
|
||||
container.customClicker = this._createContentCustomClicker(bv);
|
||||
|
||||
/* vertically scrolling box that contains tiles and the urlbar */
|
||||
let contentScrollbox = this.contentScrollbox = document.getElementById("tile-container-container");
|
||||
this.contentScrollboxScroller = contentScrollbox.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||
|
||||
let controlsScrollbox = this.controlsScrollbox = document.getElementById("scrollbox");
|
||||
this.controlsScrollboxScroller = controlsScrollbox.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||
|
||||
contentScrollbox.customDragger = new Browser.MainDragger(bv);
|
||||
|
||||
/* horizontally scrolling box that holds the sidebars as well as the contentScrollbox */
|
||||
let controlsScrollbox = this.controlsScrollbox = document.getElementById("scrollbox");
|
||||
this.controlsScrollboxScroller = controlsScrollbox.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||
controlsScrollbox.customDragger = {
|
||||
dragStart: function dragStart(scroller) {},
|
||||
dragStart: function dragStart(cx, cy, target, scroller) {},
|
||||
dragStop: function dragStop(dx, dy, scroller) { return false; },
|
||||
dragMove: function dragMove(dx, dy, scroller) { return false; }
|
||||
};
|
||||
|
@ -848,24 +850,6 @@ var Browser = {
|
|||
// XXX we probably shouldn't generate this dynamically like this, but
|
||||
// actually make it a prototype somewhere and instantiate it and such...
|
||||
|
||||
function transformClientToBrowser(cX, cY) {
|
||||
return Browser.clientToBrowserView(cX, cY).map(browserView.viewportToBrowser);
|
||||
}
|
||||
|
||||
function elementFromPoint(browser, x, y) {
|
||||
let cwu = BrowserView.Util.getBrowserDOMWindowUtils(browser);
|
||||
let scrollX = { value: 0 };
|
||||
let scrollY = { value: 0 };
|
||||
cwu.getScrollXY(false, scrollX, scrollY);
|
||||
|
||||
dump('elementFromPoint: ' + x + ', ' + y + '\n');
|
||||
|
||||
return cwu.elementFromPoint(x - scrollX.value,
|
||||
y - scrollY.value,
|
||||
true, // ignore root scroll frame
|
||||
false); // don't flush layout
|
||||
}
|
||||
|
||||
function dispatchContentClick(browser, x, y) {
|
||||
let cwu = BrowserView.Util.getBrowserDOMWindowUtils(browser);
|
||||
let scrollX = { value: 0 };
|
||||
|
@ -885,26 +869,23 @@ var Browser = {
|
|||
singleClick: function singleClick(cX, cY) {
|
||||
let browser = browserView.getBrowser();
|
||||
if (browser) {
|
||||
let [x, y] = transformClientToBrowser(cX, cY);
|
||||
let [x, y] = Browser.transformClientToBrowser(cX, cY);
|
||||
dispatchContentClick(browser, x, y);
|
||||
}
|
||||
},
|
||||
|
||||
doubleClick: function doubleClick(cX1, cY1, cX2, cY2) {
|
||||
let browser = browserView.getBrowser();
|
||||
if (browser) {
|
||||
let [x, y] = transformClientToBrowser(cX2, cY2);
|
||||
let zoomElement = elementFromPoint(browser, x, y);
|
||||
let [x, y] = Browser.transformClientToBrowser(cX2, cY2);
|
||||
let zoomElement = Browser.elementFromPoint(x, y);
|
||||
|
||||
if (zoomElement) {
|
||||
dump('@@@ zoomElement is ' + zoomElement + ' :: ' + zoomElement.id + ' :: ' + zoomElement.name + '\n');
|
||||
this.zoomIn = !this.zoomIn;
|
||||
|
||||
if (zoomElement) {
|
||||
this.zoomIn = !this.zoomIn;
|
||||
|
||||
if (this.zoomIn)
|
||||
Browser.zoomToElement(zoomElement);
|
||||
else
|
||||
Browser.zoomFromElement(zoomElement);
|
||||
}
|
||||
if (this.zoomIn)
|
||||
Browser.zoomToElement(zoomElement);
|
||||
else
|
||||
Browser.zoomFromElement(zoomElement);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1153,6 +1134,49 @@ var Browser = {
|
|||
return (arguments.length > 1) ? [x - x0, y - y0] : (x - x0);
|
||||
},
|
||||
|
||||
/**
|
||||
* turn client coordinates into page-relative ones (adjusted for
|
||||
* zoom and page position)
|
||||
*/
|
||||
transformClientToBrowser: function transformClientToBrowser(cX, cY) {
|
||||
return this.clientToBrowserView(cX, cY).map(this._browserView.viewportToBrowser);
|
||||
},
|
||||
|
||||
/**
|
||||
* return element at client coordinates of browser, returns null if
|
||||
* there's no active browser or if no element can be found
|
||||
*/
|
||||
elementFromPoint: function elementFromPoint(x, y) {
|
||||
Util.dumpLn("*** elementFromPoint: page ", x, ",", y);
|
||||
|
||||
let browser = this._browserView.getBrowser();
|
||||
if (!browser) return null;
|
||||
|
||||
let cwu = BrowserView.Util.getBrowserDOMWindowUtils(browser);
|
||||
|
||||
let scrollX = { value: 0 }, scrollY = { value: 0 };
|
||||
cwu.getScrollXY(false, scrollX, scrollY);
|
||||
x = x - scrollX.value;
|
||||
y = y - scrollY.value;
|
||||
|
||||
let elem = cwu.elementFromPoint(x, y,
|
||||
true, /* ignore root scroll frame*/
|
||||
false); /* don't flush layout */
|
||||
|
||||
// step through layers of IFRAMEs and FRAMES to find innermost element
|
||||
while (elem && (elem instanceof HTMLIFrameElement || elem instanceof HTMLFrameElement)) {
|
||||
let frameWin = elem.ownerDocument.defaultView;
|
||||
let frameUtils = frameWin.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
frameUtils.getScrollXY(false, scrollX, scrollY);
|
||||
|
||||
x = x - elem.offsetLeft + scrollX.value;
|
||||
y = y - elem.offsetTop + scrollY.value;
|
||||
elem = elem.contentDocument.elementFromPoint(x, y);
|
||||
}
|
||||
|
||||
return elem;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the visible rect in coordinates with origin at the (left, top) of
|
||||
* the tile container, i.e. BrowserView coordinates.
|
||||
|
@ -1193,19 +1217,86 @@ Browser.MainDragger = function MainDragger(browserView) {
|
|||
this.scrollingOuterX = true;
|
||||
this.bv = browserView;
|
||||
this.floatedWhileDragging = false;
|
||||
this.draggedFrame = null;
|
||||
};
|
||||
|
||||
Browser.MainDragger.prototype = {
|
||||
dragStart: function dragStart(scroller) {
|
||||
_targetIsContent: function _targetIsContent(target) {
|
||||
let tileBox = document.getElementById("tile-container");
|
||||
while (target) {
|
||||
if (target === window)
|
||||
return false;
|
||||
if (target === tileBox)
|
||||
return true;
|
||||
|
||||
target = target.parentNode;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
dragStart: function dragStart(clientX, clientY, target, scroller) {
|
||||
this.draggedFrame = null;
|
||||
|
||||
if (this._targetIsContent(target)) {
|
||||
// since we're dealing with content, look to see if user has started
|
||||
// a drag while over a IFRAME/FRAME element
|
||||
let [x, y] = Browser.transformClientToBrowser(clientX, clientY);
|
||||
let element = Browser.elementFromPoint(x, y);
|
||||
if (element && element.ownerDocument != Browser.selectedBrowser.contentDocument) {
|
||||
Util.dumpLn("*** dragStart got element ", element, " ownerDoc ", element.ownerDocument,
|
||||
" selectedBrowser.contentDoc ", Browser.selectedBrowser.contentDocument);
|
||||
this.draggedFrame = element.ownerDocument.defaultView;
|
||||
}
|
||||
}
|
||||
|
||||
this.bv.pauseRendering();
|
||||
this.floatedWhileDragging = false;
|
||||
},
|
||||
|
||||
|
||||
_panFrame: function _panFrame(dx, dy) {
|
||||
if (this.draggedFrame === null)
|
||||
return false;
|
||||
|
||||
if (dx == 0 && dy == 0)
|
||||
return true;
|
||||
|
||||
let panned = false;
|
||||
let elem = this.draggedFrame;
|
||||
|
||||
// top-level window will have itself as its parent, so stop
|
||||
// there to allow canvasbrowser/widgetstack to pan instead
|
||||
// of doing scrolling
|
||||
while (elem && elem !== elem.parent.document.defaultView) {
|
||||
let windowUtils = elem.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let origX = {}, origY = {};
|
||||
windowUtils.getScrollXY(false, origX, origY);
|
||||
|
||||
elem.scrollBy(dx, dy);
|
||||
|
||||
let newX = {}, newY = {};
|
||||
windowUtils.getScrollXY(false, newX, newY);
|
||||
|
||||
panned = (origX.value != newX.value) || (origY.value != newY.value);
|
||||
|
||||
if (panned) {
|
||||
// get critical area to redraw after we move frame
|
||||
// NOTE: may need to rate limit these for performance
|
||||
this.bv.renderNow();
|
||||
break;
|
||||
}
|
||||
|
||||
elem = elem.parent.document.defaultView;
|
||||
}
|
||||
|
||||
return panned;
|
||||
},
|
||||
|
||||
dragStop: function dragStop(dx, dy, scroller) {
|
||||
let dx = this.dragMove(dx, dy, scroller, true);
|
||||
|
||||
|
||||
dx += this.dragMove(Browser.snapSidebars(), 0, scroller, true);
|
||||
|
||||
|
||||
Browser.tryUnfloatToolbar();
|
||||
|
||||
this.bv.resumeRendering();
|
||||
|
@ -1217,6 +1308,10 @@ Browser.MainDragger.prototype = {
|
|||
dragMove: function dragMove(dx, dy, scroller, doReturnDX) {
|
||||
let outrv = 0;
|
||||
|
||||
// first see if we need to adjust internal IFRAME/FRAME
|
||||
if (this._panFrame(dx, dy))
|
||||
return true;
|
||||
|
||||
if (this.scrollingOuterX) {
|
||||
let odx = 0;
|
||||
let ody = 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче