mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Back out c6371662e21e (bug 765372), a3bbd67b9528 (bug 695173), ed90d02fd908 and 639edd2b32d4 (bug 764535) for widespread orange
This commit is contained in:
parent
82639a6888
commit
2f4ecd39c0
241
mobile/android/chrome/content/bindings.xml
Normal file
241
mobile/android/chrome/content/bindings.xml
Normal 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>
|
@ -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>
|
109
mobile/android/chrome/content/bindings/dialog.xml
Normal file
109
mobile/android/chrome/content/bindings/dialog.xml
Normal 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>
|
@ -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>
|
59
mobile/android/chrome/content/browser.css
Normal file
59
mobile/android/chrome/content/browser.css
Normal 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");
|
||||
}
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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 |
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user