Back out c6371662e21e (bug 765372), a3bbd67b9528 (bug 695173), ed90d02fd908 and 639edd2b32d4 (bug 764535) for widespread orange

This commit is contained in:
Phil Ringnalda 2012-06-15 19:37:22 -07:00
parent 82639a6888
commit 2f4ecd39c0
11 changed files with 414 additions and 450 deletions

View File

@ -0,0 +1,241 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<bindings
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="richlistbox-batch" extends="chrome://global/content/bindings/richlistbox.xml#richlistbox">
<handlers>
<handler event="scroll">
<![CDATA[
// if there no more items to insert, just return early
if (this._items.length == 0)
return;
if (this._contentScrollHeight == -1) {
let scrollheight = {};
this.scrollBoxObject.getScrolledSize({}, scrollheight);
this._contentScrollHeight = scrollheight.value;
}
let y = {};
this.scrollBoxObject.getPosition({}, y);
let scrollRatio = (y.value + this._childrenHeight) / this._contentScrollHeight;
// If we're scrolled 80% to the bottom of the list, append the next
// set of items
if (scrollRatio > 0.8)
this._insertItems();
]]>
</handler>
</handlers>
<implementation>
<!-- Number of elements to add to the list initially. If there are more
than this many elements to display, only add them to the list once
the user has scrolled towards them. This is a performance
optimization to avoid locking up while attempting to append hundreds
of nodes to our richlistbox.
-->
<property name="batchSize" readonly="true" onget="return this.getAttribute('batch')"/>
<field name="_childrenHeight">this.scrollBoxObject.height;</field>
<field name="_items">[]</field>
<method name="setItems">
<parameter name="aItems"/>
<body><![CDATA[
this._items = aItems;
this._insertItems();
]]></body>
</method>
<method name="_insertItems">
<body><![CDATA[
let items = this._items.splice(0, this.batchSize);
if (!items.length)
return; // no items to insert
let count = items.length;
for (let i = 0; i<count; i++)
this.appendChild(items[i]);
// make sure we recalculate the scrollHeight of the content
this._contentScrollHeight = -1;
]]></body>
</method>
</implementation>
</binding>
<binding id="richlistitem" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<handlers>
<handler event="mousedown" phase="capturing">
<![CDATA[
event.stopPropagation();
]]>
</handler>
</handlers>
</binding>
<binding id="menulist" display="xul:box" extends="chrome://global/content/bindings/menulist.xml#menulist">
<handlers>
<handler event="mousedown" phase="capturing">
<![CDATA[
// Stop the normal menupopup from appearing
event.stopPropagation();
]]>
</handler>
<handler event="click" button="0">
<![CDATA[
if (this.disabled || this.itemCount == 0)
return;
this.focus();
SelectHelper.handleClick(this);
]]>
</handler>
<handler event="command" phase="capturing">
<![CDATA[
// The dropmark (button) fires a command event too. Don't forward that.
// Just forward the menuitem command events, which the toolkit version does.
if (event.target.parentNode.parentNode != this)
event.stopPropagation();
]]>
</handler>
</handlers>
</binding>
<binding id="textbox" extends="chrome://global/content/bindings/textbox.xml#textbox">
<handlers>
<handler event="TapLong" phase="capturing">
<![CDATA[
let box = this.inputField.parentNode;
box.showContextMenu(this, false);
]]>
</handler>
</handlers>
</binding>
<binding id="textarea" extends="chrome://global/content/bindings/textbox.xml#textarea">
<handlers>
<handler event="TapLong" phase="capturing">
<![CDATA[
let box = this.inputField.parentNode;
box.showContextMenu(this, false);
]]>
</handler>
</handlers>
</binding>
<binding id="timed-textbox" extends="chrome://global/content/bindings/textbox.xml#timed-textbox">
<handlers>
<handler event="TapLong" phase="capturing">
<![CDATA[
let box = this.inputField.parentNode;
box.showContextMenu(this, false);
]]>
</handler>
</handlers>
</binding>
<binding id="search-textbox" extends="chrome://global/content/bindings/textbox.xml#search-textbox">
<implementation>
<field name="_searchClear">
<![CDATA[
document.getAnonymousElementByAttribute(this, "class", "textbox-search-clear");
]]>
</field>
</implementation>
<handlers>
<handler event="TapLong" phase="capturing">
<![CDATA[
let box = this.inputField.parentNode;
box.showContextMenu(this, false);
]]>
</handler>
<handler event="text" phase="bubbling"><![CDATA[
// Listen for composition update, some VKB that does suggestions does not
// update directly the content of the field but in this case we want to
// search as soon as something is entered in the field
let evt = document.createEvent("Event");
evt.initEvent("input", true, false);
this.dispatchEvent(evt);
]]></handler>
<handler event="click" phase="bubbling"><![CDATA[
// bug 629661. To reset the autosuggestions mechanism of Android, the
// textfield need to reset the IME state
if (event.originalTarget == this._searchClear) {
setTimeout(function(self) {
try {
let imeEditor = self.inputField.QueryInterface(Ci.nsIDOMNSEditableElement)
.editor
.QueryInterface(Ci.nsIEditorIMESupport);
if (imeEditor.composing)
imeEditor.forceCompositionEnd();
} catch(e) {}
}, 0, this);
}
]]></handler>
</handlers>
</binding>
<binding id="numberbox" extends="chrome://global/content/bindings/numberbox.xml#numberbox">
<handlers>
<handler event="TapLong" phase="capturing">
<![CDATA[
let box = this.inputField.parentNode;
box.showContextMenu(this, false);
]]>
</handler>
</handlers>
</binding>
<binding id="input-box" extends="xul:box">
<implementation>
<method name="showContextMenu">
<parameter name="aTextbox"/>
<parameter name="aIgnoreReadOnly"/>
<body><![CDATA[
let selectionStart = aTextbox.selectionStart;
let selectionEnd = aTextbox.selectionEnd;
let json = { types: ["input-text"], string: "" };
if (selectionStart != selectionEnd) {
json.types.push("copy");
json.string = aTextbox.value.slice(selectionStart, selectionEnd);
} else if (aTextbox.value) {
json.types.push("copy-all");
json.string = aTextbox.value;
}
if (selectionStart > 0 || selectionEnd < aTextbox.textLength)
json.types.push("select-all");
let clipboard = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
let flavors = ["text/unicode"];
let hasData = clipboard.hasDataMatchingFlavors(flavors, flavors.length, Ci.nsIClipboard.kGlobalClipboard);
if (hasData && (!aTextbox.readOnly || aIgnoreReadOnly)) {
json.types.push("paste");
if (aTextbox.type == "url") {
json.types.push("paste-url");
}
}
ContextHelper.showPopup({ target: aTextbox, json: json });
]]></body>
</method>
</implementation>
</binding>
</bindings>

View File

@ -1,15 +0,0 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="selection-handles" inheritstyle="false">
<content>
<html:div class="moz-fennec-selection-handle" anonid="selection-handle-start"/>
<html:div class="moz-fennec-selection-handle" anonid="selection-handle-end"/>
<children/>
</content>
</binding>
</bindings>

View File

@ -0,0 +1,109 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<bindings
xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="dialog">
<content orient="vertical" xbl:inherits="orient, closebutton" flex="1">
<children/>
</content>
<implementation implements="nsIDOMEventListener">
<field name="arguments"/>
<field name="parent"/>
<property name="_scrollbox" readonly="true" onget="return this.getElementsByTagName('scrollbox')[0];"/>
<constructor><![CDATA[
this._closed = false;
if (this.hasAttribute("script")) {
try {
Services.scriptloader.loadSubScript(this.getAttribute("script"), this);
} catch(e) {
throw("Dialog : Unable to load script : " + this.getAttribute("script") + "\n");
}
}
window.addEventListener("unload", this, true);
let scrollbox = this._scrollbox;
if (scrollbox) {
window.addEventListener("resize", this, true);
scrollbox.addEventListener("overflow", this, true);
}
setTimeout(this.load.bind(this), 0);
]]></constructor>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
switch(aEvent.type) {
case "unload":
if (aEvent.originalTarget == document)
this._removeDialog();
break;
case "resize":
case "overflow":
let scrollbox = this._scrollbox;
let style = document.defaultView.getComputedStyle(scrollbox, null);
let newHeight = Math.ceil(scrollbox.firstChild.getBoundingClientRect().height) +
parseInt(style.marginTop) +
parseInt(style.marginBottom);
scrollbox.style.minHeight = Math.min(window.innerHeight / 2, newHeight) + "px";
break;
}
]]></body>
</method>
<method name="load">
<body><![CDATA[
if (this.hasAttribute("onload")) {
let func = new Function(this.getAttribute("onload"));
func.call(this);
}
]]></body>
</method>
<method name="close">
<body><![CDATA[
if (this.hasAttribute("onclose")) {
let func = new Function(this.getAttribute("onclose"));
func.call(this);
}
this._removeDialog();
]]></body>
</method>
<method name="_removeDialog">
<body><![CDATA[
window.removeEventListener("unload", this, true);
let scrollbox = this._scrollbox;
if (scrollbox) {
window.removeEventListener("resize", this, true);
scrollbox.removeEventListener("overflow", this, true);
}
this.parentNode.parentNode.removeChild(this.parentNode);
this._closed = true;
// emit DOMModalDialogClosed event
let event = document.createEvent("Events");
event.initEvent("DOMModalDialogClosed", true, false);
let dispatcher = this.parent || getBrowser();
dispatcher.dispatchEvent(event);
]]></body>
</method>
<method name="waitForClose">
<body><![CDATA[
while (!this._closed)
Services.tm.currentThread.processNextEvent(true);
]]></body>
</method>
</implementation>
</binding>
</bindings>

View File

@ -1,40 +0,0 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<bindings
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="menulist" display="xul:box" extends="chrome://global/content/bindings/menulist.xml#menulist">
<handlers>
<handler event="mousedown" phase="capturing">
<![CDATA[
// Stop the normal menupopup from appearing
event.stopPropagation();
]]>
</handler>
<handler event="click" button="0">
<![CDATA[
if (this.disabled || this.itemCount == 0)
return;
this.focus();
SelectHelper.handleClick(this);
]]>
</handler>
<handler event="command" phase="capturing">
<![CDATA[
// The dropmark (button) fires a command event too. Don't forward that.
// Just forward the menuitem command events, which the toolkit version does.
if (event.target.parentNode.parentNode != this)
event.stopPropagation();
]]>
</handler>
</handlers>
</binding>
</bindings>

View File

@ -0,0 +1,59 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
radio {
-moz-binding: url("chrome://global/content/bindings/radio.xml#radio");
}
checkbox {
-moz-binding: url("chrome://browser/content/bindings/checkbox.xml#checkbox-radio");
}
menulist {
-moz-binding: url("chrome://browser/content/bindings.xml#menulist");
}
/* richlist defaults ------------------------------------------------------- */
richlistbox[batch] {
-moz-binding: url("chrome://browser/content/bindings.xml#richlistbox-batch");
}
richlistitem {
-moz-binding: url("chrome://browser/content/bindings.xml#richlistitem");
}
dialog {
-moz-binding: url("chrome://browser/content/bindings/dialog.xml#dialog");
}
/* Do not allow these to inherit from the toolkit binding */
dialog.content-dialog {
-moz-binding: none;
}
/* Disable context menus in textboxes */
.textbox-input-box,
.textbox-input-box[spellcheck="true"] {
-moz-binding: url("chrome://browser/content/bindings.xml#input-box");
}
textbox {
-moz-binding: url("chrome://browser/content/bindings.xml#textbox");
}
textbox[multiline="true"] {
-moz-binding: url("chrome://browser/content/bindings.xml#textarea");
}
textbox[type="timed"] {
-moz-binding: url("chrome://browser/content/bindings.xml#timed-textbox");
}
textbox[type="search"] {
-moz-binding: url("chrome://browser/content/bindings.xml#search-textbox");
}
textbox[type="number"] {
-moz-binding: url("chrome://browser/content/bindings.xml#numberbox");
}

View File

@ -192,7 +192,6 @@ var BrowserApp = {
window.addEventListener("MozShowFullScreenWarning", showFullScreenWarning, true);
NativeWindow.init();
SelectionHandler.init();
Downloads.init();
FindHelper.init();
FormAssistant.init();
@ -346,7 +345,6 @@ var BrowserApp = {
shutdown: function shutdown() {
NativeWindow.uninit();
SelectionHandler.uninit();
FormAssistant.uninit();
FindHelper.uninit();
OfflineApps.uninit();
@ -1247,9 +1245,6 @@ var NativeWindow = {
0, null);
rootElement.ownerDocument.defaultView.addEventListener("contextmenu", this, false);
rootElement.dispatchEvent(event);
} else {
// Otherwise, let the selection handler take over
SelectionHandler.startSelection(rootElement, aX, aY);
}
},
@ -1352,356 +1347,6 @@ var NativeWindow = {
}
};
var SelectionHandler = {
// Keeps track of data about the dimensions of the selection
cache: null,
selectedText: "",
// The window that holds the selection (can be a sub-frame)
get _view() {
if (this._viewRef)
return this._viewRef.get();
return null;
},
set _view(aView) {
this._viewRef = Cu.getWeakReference(aView);
},
// The DIV elements for the start/end handles
get _start() {
if (this._startRef)
return this._startRef.get();
return null;
},
set _start(aElement) {
this._startRef = Cu.getWeakReference(aElement);
},
get _end() {
if (this._endRef)
return this._endRef.get();
return null;
},
set _end(aElement) {
this._endRef = Cu.getWeakReference(aElement);
},
// Units in pixels
HANDLE_WIDTH: 35,
HANDLE_HEIGHT: 64,
HANDLE_VERTICAL_MARGIN: 4,
HANDLE_PADDING: 20,
init: function sh_init() {
Services.obs.addObserver(this, "Gesture:SingleTap", false);
},
uninit: function sh_uninit() {
Services.obs.removeObserver(this, "Gesture:SingleTap", false);
},
observe: function sh_observe(aSubject, aTopic, aData) {
let data = JSON.parse(aData);
if (this._view)
this.endSelection(data.x, data.y);
},
// aX/aY are in top-level window browser coordinates
startSelection: function sh_startSelection(aElement, aX, aY) {
// Clear out any existing selection
if (this._view)
this.endSelection(0, 0);
// Get the element's view
this._view = aElement.ownerDocument.defaultView;
// Clear out the text cache
this.selectedText = "";
// Remove any previous selected or created ranges. Tapping anywhere on a
// page will create an empty range.
let selection = this._view.getSelection();
selection.removeAllRanges();
// Position the caret using a fake mouse click
let cwu = BrowserApp.selectedBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
cwu.sendMouseEventToWindow("mousedown", aX, aY, 0, 0, 0, true);
cwu.sendMouseEventToWindow("mouseup", aX, aY, 0, 0, 0, true);
try {
let selectionController = this._view.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsISelectionDisplay).
QueryInterface(Ci.nsISelectionController);
// Select the word nearest the caret
selectionController.wordMove(false, false);
selectionController.wordMove(true, true);
} catch(e) {
// If we couldn't select the word at the given point, bail
Cu.reportError("Error selecting word: " + e);
return;
}
// Find the selected text rect and send it back so the handles can position correctly
if (selection.rangeCount == 0)
return;
let range = selection.getRangeAt(0);
if (!range)
return;
// Initialize the cache
this.cache = {};
this.updateCacheFromRange(range);
this.updateCacheOffset();
// Cache the selected text since the selection might be gone by the time we get the "end" message
this.selectedText = selection.toString().trim();
// If the range didn't have any text, let's bail
if (!this.selectedText.length) {
selection.collapseToStart();
return;
}
this.showHandles();
},
// aX/aY are in top-level window browser coordinates
moveSelection: function sh_moveSelection(aIsStartHandle, aX, aY) {
let contentWindow = BrowserApp.selectedBrowser.contentWindow;
/* XXX bug 765367: Because the handles are in the document, the element
will always be the handle the user touched. These checks are disabled
until we can figure out a way to get the element under the handle.
let element = ElementTouchHelper.elementFromPoint(contentWindow, aX, aY);
if (!element)
element = ElementTouchHelper.anyElementFromPoint(contentWindow, aX, aY);
// The element can be null if it's outside the viewport. We also want
// to avoid setting focus in a textbox [Bugs 654352 & 667243] and limit
// the selection to the initial content window (don't leave or enter iframes).
if (!element || element instanceof Ci.nsIDOMHTMLInputElement ||
element instanceof Ci.nsIDOMHTMLTextAreaElement ||
element.ownerDocument.defaultView != this._view)
return;
*/
// Update the handle position as it's dragged
if (aIsStartHandle) {
this._start.style.left = aX + this.cache.offset.x + "px";
this._start.style.top = aY + this.cache.offset.y + "px";
} else {
this._end.style.left = aX + this.cache.offset.x + "px";
this._end.style.top = aY + this.cache.offset.y + "px";
}
//XXX bug 765057: Reverse text selection handles if necessary
// Send mouse events to the top-level window
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
if (aIsStartHandle) {
// If we're moving the start handle, we need to re-position the caret using a fake mouse click
let start = this._start.getBoundingClientRect();
cwu.sendMouseEventToWindow("mousedown", start.right - this.HANDLE_PADDING, start.top - this.HANDLE_VERTICAL_MARGIN, 0, 0, 0, true);
cwu.sendMouseEventToWindow("mouseup", start.right - this.HANDLE_PADDING, start.top - this.HANDLE_VERTICAL_MARGIN, 0, 0, 0, true);
}
// Send a shift+click to select text between the carat at the start and an end point
let end = this._end.getBoundingClientRect();
cwu.sendMouseEventToWindow("mousedown", end.left + this.HANDLE_PADDING, end.top - this.HANDLE_VERTICAL_MARGIN, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
cwu.sendMouseEventToWindow("mouseup", end.left + this.HANDLE_PADDING, end.top - this.HANDLE_VERTICAL_MARGIN, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
},
finishMoveSelection: function sh_finishMoveSelection(aIsStartHandle) {
// Cache the selected text since the selection might be gone by the time we get the "end" message
let selection = this._view.getSelection();
this.selectedText = selection.toString().trim();
// Update the cache to match the new selection range
let range = selection.getRangeAt(0);
this.updateCacheFromRange(range);
this.updateCacheOffset();
// Adjust the handles to be in the correct spot relative to the text selection
this.positionHandles();
},
// aX/aY are in top-level window browser coordinates
endSelection: function sh_endSelection(aX, aY) {
this.hideHandles();
this._view.getSelection().removeAllRanges();
let contentWindow = BrowserApp.selectedBrowser.contentWindow;
let element = ElementTouchHelper.elementFromPoint(contentWindow, aX, aY);
if (!element)
element = ElementTouchHelper.anyElementFromPoint(contentWindow, aX, aY);
// Only try copying text if the tap happens in the same view
if (element.ownerDocument.defaultView == this._view) {
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
let scrollX = {}, scrollY = {};
cwu.getScrollXY(false, scrollX, scrollY);
// aX/aY already accounts for the top-level scroll, add that back from the cache.offset values
let pointInSelection = (aX - this.cache.offset.x + scrollX.value > this.cache.rect.left &&
aX - this.cache.offset.x + scrollX.value < this.cache.rect.right) &&
(aY - this.cache.offset.y + scrollY.value > this.cache.rect.top &&
aY - this.cache.offset.y + scrollY.value < this.cache.rect.bottom);
if (pointInSelection && this.selectedText.length) {
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
clipboard.copyString(this.selectedText);
NativeWindow.toast.show(Strings.browser.GetStringFromName("selectionHelper.textCopied"), "short");
}
}
this._view = null;
this.cache = null;
},
updateCacheFromRange: function sh_updateCacheFromRange(aRange) {
let rects = aRange.getClientRects();
this.cache.start = { x: rects[0].left, y: rects[0].bottom };
this.cache.end = { x: rects[rects.length - 1].right, y: rects[rects.length - 1].bottom };
this.cache.rect = aRange.getBoundingClientRect();
},
updateCacheOffset: function sh_updateCacheOffset() {
let offset = { x: 0, y: 0 };
let cwu = null, scrollX = {}, scrollY = {};
let win = this._view;
// Recursively look through frames to compute the total scroll offset. This is
// necessary for positioning the handles correctly.
while (win) {
cwu = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
cwu.getScrollXY(false, scrollX, scrollY);
offset.x += scrollX.value;
offset.y += scrollY.value;
// Break if there are no more frames to process
if (!win.frameElement)
break;
win = win.frameElement.contentWindow;
}
this.cache.offset = offset;
},
// Adjust start/end positions to account for scroll, and account for the dimensions of the
// handle elements to ensure the handles point exactly at the ends of the selection.
positionHandles: function sh_positionHandles() {
this._start.style.left = (this.cache.start.x + this.cache.offset.x - this.HANDLE_WIDTH - this.HANDLE_PADDING) + "px";
this._start.style.top = (this.cache.start.y + this.cache.offset.y - this.HANDLE_VERTICAL_MARGIN - this.HANDLE_PADDING) + "px";
this._end.style.left = (this.cache.end.x + this.cache.offset.x - this.HANDLE_PADDING) + "px";
this._end.style.top = (this.cache.end.y + this.cache.offset.y - this.HANDLE_VERTICAL_MARGIN - this.HANDLE_PADDING) + "px";
},
showHandles: function sh_showHandles() {
let doc = this._view.document;
//XXX bug 765076: Add the binding dynamically
//doc.loadBindingDocument("chrome://browser-content/content/content.xml");
//doc.documentElement.style.MozBinding = "url(chrome://browser-content/content/content.xml#selection-handles)";
this._start = doc.getAnonymousElementByAttribute(doc.documentElement, "anonid", "selection-handle-start");
this._end = doc.getAnonymousElementByAttribute(doc.documentElement, "anonid", "selection-handle-end");
if (!this._start || !this._end) {
Cu.reportError("SelectionHandler.showHandles: Couldn't find anonymous handle elements");
this.endSelection(0, 0);
return;
}
this.positionHandles();
this._start.setAttribute("showing", "true");
this._end.setAttribute("showing", "true");
this._start.addEventListener("touchend", this, true);
this._end.addEventListener("touchend", this, true);
this._start.addEventListener("touchstart", this, true);
this._end.addEventListener("touchstart", this, true);
},
hideHandles: function sh_hideHandles() {
if (!this._start || !this._end)
return;
this._start.removeAttribute("showing");
this._end.removeAttribute("showing");
this._start.removeEventListener("touchstart", this, true);
this._end.removeEventListener("touchstart", this, true);
this._start.removeEventListener("touchend", this, true);
this._end.removeEventListener("touchend", this, true);
this._start = null;
this._end = null;
//XXX bug 765076: Remove the binding dynamically
//this._view.document.documentElement.style.MozBinding = "";
},
_touchId: null,
_touchDelta: null,
handleEvent: function sh_handleEvent(aEvent) {
let isStartHandle = (aEvent.target == this._start);
switch (aEvent.type) {
case "touchstart":
aEvent.preventDefault();
// Update the offset in case we scrolled between touches
this.updateCacheOffset();
let touch = aEvent.changedTouches[0];
this._touchId = touch.identifier;
// Keep track of what part of the handle the user touched
let rect = aEvent.target.getBoundingClientRect();
this._touchDelta = { x: touch.clientX - rect.left,
y: touch.clientY - rect.top };
aEvent.target.addEventListener("touchmove", this, false);
break;
case "touchend":
aEvent.target.removeEventListener("touchmove", this, false);
this._touchId = null;
this._touchDelta = null;
// Update the cached values after the dragging action is over
this.finishMoveSelection(isStartHandle);
break;
case "touchmove":
touch = aEvent.changedTouches.identifiedTouch(this.touchId);
// Adjust the touch to account for what part of the handle the user first touched
this.moveSelection(isStartHandle, touch.clientX - this._touchDelta.x,
touch.clientY - this._touchDelta.y);
break;
}
}
};
function nsBrowserAccess() {
}
@ -3342,7 +2987,7 @@ const ElementTouchHelper = {
if (!aAllowBodyListeners && aElement && aElement.ownerDocument)
stopNode = aElement.ownerDocument.body;
for (let elem = aElement; elem && elem != stopNode; elem = elem.parentNode) {
for (let elem = aElement; elem != stopNode; elem = elem.parentNode) {
if (aUnclickableCache && aUnclickableCache.indexOf(elem) != -1)
continue;
if (this._hasMouseListener(elem))

View File

@ -25,9 +25,11 @@ chrome.jar:
content/languages.properties (content/languages.properties)
* content/browser.xul (content/browser.xul)
* content/browser.js (content/browser.js)
* content/bindings.xml (content/bindings.xml)
content/bindings/checkbox.xml (content/bindings/checkbox.xml)
content/bindings/menulist.xml (content/bindings/menulist.xml)
content/bindings/settings.xml (content/bindings/settings.xml)
content/bindings/dialog.xml (content/bindings/dialog.xml)
content/browser.css (content/browser.css)
content/cursor.css (content/cursor.css)
% content branding %content/branding/
content/sanitize.js (content/sanitize.js)
@ -37,9 +39,6 @@ chrome.jar:
content/SelectHelper.js (content/SelectHelper.js)
content/dbg-browser-actors.js (content/dbg-browser-actors.js)
% content browser-content %content/ contentaccessible=yes
browser-content/content.xml (content/bindings/content.xml)
% override chrome://global/content/config.xul chrome://browser/content/config.xhtml
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
% override chrome://mozapps/content/extensions/extensions.xul chrome://browser/content/aboutAddons.xhtml

View File

@ -338,37 +338,5 @@ video {
}
xul|menulist {
-moz-binding: url("chrome://browser/content/bindings/menulist.xml#menulist");
}
/* Text Selection Handles */
/*XXX bug 765076: Add the binding dynamically using style.MozBinding */
:root {
-moz-binding: url("chrome://browser-content/content/content.xml#selection-handles");
}
.moz-fennec-selection-handle {
position: absolute;
z-index: 999999;
min-width: 35px;
min-height: 64px;
width: 35px;
height: 64px;
padding: 20px; /* Add padding to make touch target larger */
margin: 0;
background-repeat: no-repeat;
background-position: center;
}
.moz-fennec-selection-handle:not([showing]) {
display: none;
}
.moz-fennec-selection-handle[anonid="selection-handle-start"] {
background-image: url("chrome://browser/skin/images/handle-start.png");
}
.moz-fennec-selection-handle[anonid="selection-handle-end"] {
background-image: url("chrome://browser/skin/images/handle-end.png");
-moz-binding: url("chrome://browser/content/bindings.xml#menulist");
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -51,5 +51,3 @@ chrome.jar:
skin/images/row-bg-light.png (images/row-bg-light.png)
skin/images/row-bg-normal.png (images/row-bg-normal.png)
skin/images/addons-amo-hdpi.png (images/addons-amo-hdpi.png)
skin/images/handle-start.png (images/handle-start.png)
skin/images/handle-end.png (images/handle-end.png)