Permalink
Browse files

Add Oxide WebView port for Shell

  • Loading branch information...
penk committed Mar 16, 2014
1 parent 15e4537 commit a2b757bd6de462117030239585d6974a847c0029
Showing with 206 additions and 58 deletions.
  1. +41 −58 Shell/qml/Shell.qml
  2. +147 −0 Shell/qml/js/selection.js
  3. +18 −0 Shell/qml/userscript.js
View
@@ -3,8 +3,7 @@ import QtQuick.LocalStorage 2.0
import QtGraphicalEffects 1.0
import QtQuick.Window 2.0
-import QtWebKit 3.0
-import QtWebKit.experimental 1.0
+import com.canonical.Oxide 0.1
import "js/script.js" as Tab
Window {
@@ -217,6 +216,7 @@ Window {
MouseArea {
id: contextOverlay;
+ z: 3
anchors.fill: parent;
enabled: contextMenu.visible
onClicked: contextMenu.visible = false
@@ -228,6 +228,7 @@ Window {
width: 250; height: 230
color: "gray"
radius: 5
+ z: 3
Text {
id: contextUrl
color: "white"
@@ -255,69 +256,51 @@ Window {
ContextButton { label: "Copy"; onClicked: { console.log('Copy: ' + contextUrl.text); contextMenu.visible = false } }
}
}
-
- // FIXME: calculate scale, and position of screen
- function updateContextMenu(X, Y, url) {
- contextMenu.x = X; contextMenu.y = Y
- if (X + contextMenu.width/2 > root.width) {
- contextMenu.x = root.width - contextMenu.width - 30
- } else if (X - contextMenu.width/2 < 0) {
- contextMenu.x = 30
- } else {
- contextMenu.x = X - contextMenu.width/2 - 10;
- }
- if (Y - contextMenu.height - 40 < 0) {
- contextMenu.y = Y + 5
- } else {
- contextMenu.y = Y - contextMenu.height - 20
- }
- contextMenu.visible = true
- contextUrl.text = url
- }
-
- //property real scale: experimental.test.contentsScale
- //experimental.devicePixelRatio: 2.0;
-
- experimental.itemSelector: PopOver {}
- experimental.preferences.fullScreenEnabled: true;
- experimental.preferences.developerExtrasEnabled: true;
-
- experimental.userScripts: [Qt.resolvedUrl("js/userscript.js")];
- experimental.preferences.navigatorQtObjectEnabled: true;
- experimental.onMessageReceived: {
- console.log('onMessageReceived: ' + message.data );
- var data = null
- try {
- data = JSON.parse(message.data)
- } catch (error) {
- console.log('onMessageReceived: ' + message.data );
- return
- }
- switch (data.type) {
- case 'link': {
- updateContextMenu(data.pageX, data.pageY, data.href)
- if (data.target === '_blank') { // open link in new tab
- bounce.start()
- openNewTab('page-'+salt(), data.href)
- }
- break;
- }
- case 'longpress': {
- updateContextMenu(data.pageX, data.pageY, fixUrl(data.href));
+ popupMenu: PopOver {}
+
+ context: WebContext {
+ userScripts: [
+ UserScript {
+ context: "oxide://osk/"
+ url: Qt.resolvedUrl("userscript.js")
+ incognitoEnabled: true
+ matchAllFrames: true
+ },
+ UserScript {
+ context: "oxide://selection/"
+ url: Qt.resolvedUrl("js/selection.js")
+ incognitoEnabled: true
+ matchAllFrames: true
}
- case 'input': {
- keyboard.state = data.state;
- break;
+ ]
+ }
+ messageHandlers: [
+ ScriptMessageHandler {
+ msgId: 'inputmethod'
+ contexts: ["oxide://osk/"]
+ callback: function(msg, frame) {
+ if (msg.args.type == 'input')
+ keyboard.state = msg.args.state
+ }
+ },
+ ScriptMessageHandler {
+ msgId: "contextmenu"
+ contexts: ["oxide://selection/"]
+ callback: function(msg, frame) {
+ if (('href' in msg.args)) {
+ contextUrl.text = msg.args.href
+ contextMenu.x = msg.args.left * msg.args.scaleX
+ contextMenu.y = msg.args.top * msg.args.scaleY
+ contextMenu.visible = true
+ }
}
}
- }
- //experimental.userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3"
-
+ ]
onLoadingChanged: {
contextMenu.visible = false;
readerMode = false;
urlText.text = Tab.itemMap[currentTab].url;
- if (loadRequest.status == WebView.LoadSucceededStatus) {
+ if (loadEvent.type === LoadEvent.TypeSucceeded) {
updateHistory(Tab.itemMap[currentTab].url, Tab.itemMap[currentTab].title, Tab.itemMap[currentTab].icon)
}
}
View
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2013-2014 Canonical Ltd.
+ *
+ * This file is part of webbrowser-app.
+ *
+ * webbrowser-app is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * webbrowser-app is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+function elementContainedInBox(element, box) {
+ var rect = element.getBoundingClientRect();
+ return ((box.left <= rect.left) && (box.right >= rect.right) &&
+ (box.top <= rect.top) && (box.bottom >= rect.bottom));
+}
+
+function getImgFullUri(uri) {
+ if ((uri.slice(0, 7) === 'http://') ||
+ (uri.slice(0, 8) === 'https://') ||
+ (uri.slice(0, 7) === 'file://')) {
+ return uri;
+ } else if (uri.slice(0, 1) === '/') {
+ var docuri = document.documentURI;
+ var firstcolon = docuri.indexOf('://');
+ var protocol = 'http://';
+ if (firstcolon !== -1) {
+ protocol = docuri.slice(0, firstcolon + 3);
+ }
+ return protocol + document.domain + uri;
+ } else {
+ var base = document.baseURI;
+ var lastslash = base.lastIndexOf('/');
+ if (lastslash === -1) {
+ return base + '/' + uri;
+ } else {
+ return base.slice(0, lastslash + 1) + uri;
+ }
+ }
+}
+
+function getSelectedData(element) {
+ var node = element;
+ var data = new Object;
+
+ var nodeName = node.nodeName.toLowerCase();
+ if (nodeName === 'img') {
+ data.img = getImgFullUri(node.getAttribute('src'));
+ } else if (nodeName === 'a') {
+ data.href = node.href;
+ data.title = node.title;
+ }
+
+ // If the parent tag is a hyperlink, we want it too.
+ var parent = node.parentNode;
+ if ((nodeName !== 'a') && parent && (parent.nodeName.toLowerCase() === 'a')) {
+ data.href = parent.href;
+ data.title = parent.title;
+ node = parent;
+ }
+
+ var boundingRect = node.getBoundingClientRect();
+ data.left = boundingRect.left;
+ data.top = boundingRect.top;
+ data.width = boundingRect.width;
+ data.height = boundingRect.height;
+
+ node = node.cloneNode(true);
+ // filter out script nodes
+ var scripts = node.getElementsByTagName('script');
+ while (scripts.length > 0) {
+ var scriptNode = scripts[0];
+ if (scriptNode.parentNode) {
+ scriptNode.parentNode.removeChild(scriptNode);
+ }
+ }
+ data.html = node.outerHTML;
+ data.nodeName = node.nodeName.toLowerCase();
+ // FIXME: extract the text and images in the order they appear in the block,
+ // so that this order is respected when the data is pushed to the clipboard.
+ data.text = node.textContent;
+ var images = [];
+ var imgs = node.getElementsByTagName('img');
+ for (var i = 0; i < imgs.length; i++) {
+ images.push(getImgFullUri(imgs[i].getAttribute('src')));
+ }
+ if (images.length > 0) {
+ data.images = images;
+ }
+
+ return data;
+}
+
+function adjustSelection(selection) {
+ // FIXME: allow selecting two consecutive blocks, instead of
+ // interpolating to the containing block.
+ var centerX = (selection.left + selection.right) / 2;
+ var centerY = (selection.top + selection.bottom) / 2;
+ var element = document.elementFromPoint(centerX, centerY);
+ var parent = element;
+ while (elementContainedInBox(parent, selection)) {
+ parent = parent.parentNode;
+ }
+ element = parent;
+ return getSelectedData(element);
+}
+
+function distance(touch1, touch2) {
+ return Math.sqrt(Math.pow(touch2.clientX - touch1.clientX, 2) +
+ Math.pow(touch2.clientY - touch1.clientY, 2));
+}
+
+/*navigator.qt.onmessage = function(message) {
+ var data = null;
+ try {
+ data = JSON.parse(message.data);
+ } catch (error) {
+ return;
+ }
+ if ('query' in data) {
+ if (data.query === 'adjustselection') {
+ var selection = adjustSelection(data);
+ selection.event = 'selectionadjusted';
+ navigator.qt.postMessage(JSON.stringify(selection));
+ }
+ }
+}*/
+
+document.documentElement.addEventListener('contextmenu', function(event) {
+ var element = document.elementFromPoint(event.clientX, event.clientY);
+ var data = getSelectedData(element);
+ var w = document.defaultView;
+ data['scaleX'] = w.outerWidth / w.innerWidth * w.devicePixelRatio;
+ data['scaleY'] = w.outerHeight / w.innerHeight * w.devicePixelRatio;
+ oxide.sendMessage('contextmenu', data);
+});
+
+document.defaultView.addEventListener('scroll', function(event) {
+ oxide.sendMessage('scroll', {});
+});
View
@@ -0,0 +1,18 @@
+window.document.addEventListener('click', (function(e) {
+ if (e.srcElement.tagName === ('INPUT'||'TEXTAREA')) {
+ var inputContext = new Object({'type': 'input', 'state': 'show'})
+ oxide.sendMessage('inputmethod', inputContext)
+ }
+}), true);
+
+window.document.addEventListener('focus', (function(e) {
+ if (e.srcElement.tagName === ('INPUT'||'TEXTAREA')) {
+ var inputContext = new Object({'type': 'input', 'state': 'show'})
+ oxide.sendMessage('inputmethod', inputContext)
+ }
+}), true);
+
+window.document.addEventListener('blur', (function(e) {
+ var inputContext = new Object({'type': 'input', 'state': 'hide'})
+ oxide.sendMessage('inputmethod', inputContext)
+}), true);

0 comments on commit a2b757b

Please sign in to comment.