--- a/browser/devtools/responsivedesign/responsivedesign.jsm
+++ b/browser/devtools/responsivedesign/responsivedesign.jsm
@@ -10,16 +10,17 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource:///modules/devtools/FloatingScrollbars.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
var require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
+let {TouchEventHandler} = require("devtools/shared/touch-events");
this.EXPORTED_SYMBOLS = ["ResponsiveUIManager"];
const MIN_WIDTH = 50;
const MIN_HEIGHT = 50;
const MAX_WIDTH = 10000;
const MAX_HEIGHT = 10000;
@@ -111,16 +112,17 @@ function ResponsiveUI(aWindow, aTab)
this.tab = aTab;
this.tabContainer = aWindow.gBrowser.tabContainer;
this.browser = aTab.linkedBrowser;
this.chromeDoc = aWindow.document;
this.container = aWindow.gBrowser.getBrowserContainer(this.browser);
this.stack = this.container.querySelector(".browserStack");
this._telemetry = new Telemetry();
+
// Try to load presets from prefs
if (Services.prefs.prefHasUserValue("devtools.responsiveUI.presets")) {
try {
presets = JSON.parse(Services.prefs.getCharPref("devtools.responsiveUI.presets"));
} catch(e) {
// User pref is malformated.
Cu.reportError("Could not parse pref `devtools.responsiveUI.presets`: " + e);
}
@@ -151,21 +153,24 @@ function ResponsiveUI(aWindow, aTab)
this.currentPresetKey = this.presets[1].key; // most common preset
}
this.container.setAttribute("responsivemode", "true");
this.stack.setAttribute("responsivemode", "true");
// Let's bind some callbacks.
+ this.bound_onPageLoad = this.onPageLoad.bind(this);
+ this.bound_onPageUnload = this.onPageUnload.bind(this);
this.bound_presetSelected = this.presetSelected.bind(this);
this.bound_addPreset = this.addPreset.bind(this);
this.bound_removePreset = this.removePreset.bind(this);
this.bound_rotate = this.rotate.bind(this);
this.bound_screenshot = () => this.screenshot();
+ this.bound_touch = this.toggleTouch.bind(this);
this.bound_close = this.close.bind(this);
this.bound_startResizing = this.startResizing.bind(this);
this.bound_stopResizing = this.stopResizing.bind(this);
this.bound_onDrag = this.onDrag.bind(this);
this.bound_onKeypress = this.onKeypress.bind(this);
// Events
this.tab.addEventListener("TabClose", this);
@@ -183,16 +188,28 @@ function ResponsiveUI(aWindow, aTab)
if (this._floatingScrollbars)
switchToFloatingScrollbars(this.tab);
this.tab.__responsiveUI = this;
this._telemetry.toolOpened("responsive");
+ // Touch events support
+ this.touchEnableBefore = false;
+ this.touchEventHandler = new TouchEventHandler(this.browser.contentWindow);
+
+ this.browser.addEventListener("load", this.bound_onPageLoad, true);
+ this.browser.addEventListener("unload", this.bound_onPageUnload, true);
+
+ if (this.browser.contentWindow.document &&
+ this.browser.contentWindow.document.readyState == "complete") {
+ this.onPageLoad();
+ }
+
ResponsiveUIManager.emit("on", this.tab, this);
}
ResponsiveUI.prototype = {
_transitionsEnabled: true,
_floatingScrollbars: Services.appinfo.OS != "Darwin",
get transitionsEnabled() this._transitionsEnabled,
set transitionsEnabled(aValue) {
@@ -200,23 +217,44 @@ ResponsiveUI.prototype = {
if (aValue && !this._resizing && this.stack.hasAttribute("responsivemode")) {
this.stack.removeAttribute("notransition");
} else if (!aValue) {
this.stack.setAttribute("notransition", "true");
}
},
/**
+ * Window onload / onunload
+ */
+ onPageLoad: function() {
+ this.touchEventHandler = new TouchEventHandler(this.browser.contentWindow);
+ if (this.touchEnableBefore) {
+ this.enableTouch();
+ }
+ },
+
+ onPageUnload: function() {
+ if (this.closing)
+ return;
+ this.touchEnableBefore = this.touchEventHandler.enabled;
+ this.disableTouch();
+ delete this.touchEventHandler;
+ },
+
+ /**
* Destroy the nodes. Remove listeners. Reset the style.
*/
close: function RUI_unload() {
if (this.closing)
return;
this.closing = true;
+ this.browser.removeEventListener("load", this.bound_onPageLoad, true);
+ this.browser.removeEventListener("unload", this.bound_onPageUnload, true);
+
if (this._floatingScrollbars)
switchToNativeScrollbars(this.tab);
this.unCheckMenus();
// Reset style of the stack.
let style = "max-width: none;" +
"min-width: 0;" +
"max-height: none;" +
@@ -228,31 +266,34 @@ ResponsiveUI.prototype = {
// Remove listeners.
this.mainWindow.document.removeEventListener("keypress", this.bound_onKeypress, false);
this.menulist.removeEventListener("select", this.bound_presetSelected, true);
this.tab.removeEventListener("TabClose", this);
this.tabContainer.removeEventListener("TabSelect", this);
this.rotatebutton.removeEventListener("command", this.bound_rotate, true);
this.screenshotbutton.removeEventListener("command", this.bound_screenshot, true);
+ this.touchbutton.removeEventListener("command", this.bound_touch, true);
this.closebutton.removeEventListener("command", this.bound_close, true);
this.addbutton.removeEventListener("command", this.bound_addPreset, true);
this.removebutton.removeEventListener("command", this.bound_removePreset, true);
// Removed elements.
this.container.removeChild(this.toolbar);
this.stack.removeChild(this.resizer);
this.stack.removeChild(this.resizeBarV);
this.stack.removeChild(this.resizeBarH);
// Unset the responsive mode.
this.container.removeAttribute("responsivemode");
this.stack.removeAttribute("responsivemode");
delete this.tab.__responsiveUI;
+ if (this.touchEventHandler)
+ this.touchEventHandler.stop();
this._telemetry.toolClosed("responsive");
ResponsiveUIManager.emit("off", this.tab, this);
},
/**
* Handle keypressed.
*
* @param aEvent
@@ -352,25 +393,32 @@ ResponsiveUI.prototype = {
this.rotatebutton.addEventListener("command", this.bound_rotate, true);
this.screenshotbutton = this.chromeDoc.createElement("toolbarbutton");
this.screenshotbutton.setAttribute("tabindex", "0");
this.screenshotbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.screenshot"));
this.screenshotbutton.className = "devtools-toolbarbutton devtools-responsiveui-screenshot";
this.screenshotbutton.addEventListener("command", this.bound_screenshot, true);
+ this.touchbutton = this.chromeDoc.createElement("toolbarbutton");
+ this.touchbutton.setAttribute("tabindex", "0");
+ this.touchbutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.touch"));
+ this.touchbutton.className = "devtools-toolbarbutton devtools-responsiveui-touch";
+ this.touchbutton.addEventListener("command", this.bound_touch, true);
+
this.closebutton = this.chromeDoc.createElement("toolbarbutton");
this.closebutton.setAttribute("tabindex", "0");
this.closebutton.className = "devtools-toolbarbutton devtools-responsiveui-close";
this.closebutton.setAttribute("tooltiptext", this.strings.GetStringFromName("responsiveUI.close"));
this.closebutton.addEventListener("command", this.bound_close, true);
this.toolbar.appendChild(this.closebutton);
this.toolbar.appendChild(this.menulist);
this.toolbar.appendChild(this.rotatebutton);
+ this.toolbar.appendChild(this.touchbutton);
this.toolbar.appendChild(this.screenshotbutton);
// Resizers
let resizerTooltip = this.strings.GetStringFromName("responsiveUI.resizerTooltip");
this.resizer = this.chromeDoc.createElement("box");
this.resizer.className = "devtools-responsiveui-resizehandle";
this.resizer.setAttribute("right", "0");
this.resizer.setAttribute("bottom", "0");
@@ -618,16 +666,47 @@ ResponsiveUI.prototype = {
canvas.toBlob(blob => {
let chromeWindow = this.chromeDoc.defaultView;
let url = chromeWindow.URL.createObjectURL(blob);
chromeWindow.saveURL(url, filename + ".png", null, true, true, document.documentURIObject, document);
});
},
/**
+ * Enable/Disable mouse -> touch events translation.
+ */
+ enableTouch: function RUI_enableTouch() {
+ if (!this.touchEventHandler.enabled) {
+ let isReloadNeeded = this.touchEventHandler.start();
+ this.touchbutton.setAttribute("checked", "true");
+ return isReloadNeeded;
+ }
+ return false;
+ },
+
+ disableTouch: function RUI_disableTouch() {
+ if (this.touchEventHandler.enabled) {
+ this.touchEventHandler.stop();
+ this.touchbutton.removeAttribute("checked");
+ }
+ },
+
+ toggleTouch: function RUI_toggleTouch() {
+ if (this.touchEventHandler.enabled) {
+ this.disableTouch();
+ } else {
+ let isReloadNeeded = this.enableTouch();
+ if (isReloadNeeded) {
+ // Lightest way to reload I found:
+ this.browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
+ }
+ }
+ },
+
+ /**
* Change the size of the browser.
*
* @param aWidth width of the browser.
* @param aHeight height of the browser.
*/
setSize: function RUI_setSize(aWidth, aHeight) {
aWidth = Math.min(Math.max(aWidth, MIN_WIDTH), MAX_WIDTH);
aHeight = Math.min(Math.max(aHeight, MIN_HEIGHT), MAX_HEIGHT);
--- a/browser/devtools/responsivedesign/test/Makefile.in
+++ b/browser/devtools/responsivedesign/test/Makefile.in
@@ -11,12 +11,14 @@ relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_FILES := \
browser_responsiveui.js \
browser_responsiveuiaddcustompreset.js \
browser_responsiveruleview.js \
browser_responsive_cmd.js \
browser_responsivecomputedview.js \
+ browser_responsiveui_touch.js \
+ touch.html \
head.js \
$(NULL)
include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/browser/devtools/responsivedesign/test/browser_responsiveui_touch.js
@@ -0,0 +1,66 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+ let url = "http://mochi.test:8888/browser/browser/devtools/responsivedesign/test/touch.html";
+
+ let mgr = ResponsiveUI.ResponsiveUIManager;
+
+ waitForExplicitFinish();
+
+ gBrowser.selectedTab = gBrowser.addTab();
+ gBrowser.selectedBrowser.addEventListener("load", function onload() {
+ gBrowser.selectedBrowser.removeEventListener("load", onload, true);
+ waitForFocus(startTest, content);
+ }, true);
+
+ content.location = url;
+
+ function startTest() {
+ mgr.once("on", function() {executeSoon(testWithNoTouch)});
+ mgr.once("off", function() {executeSoon(finishUp)});
+ mgr.toggle(window, gBrowser.selectedTab);
+ }
+
+ function testWithNoTouch() {
+ let div = content.document.querySelector("div");
+ let x = 2, y = 2;
+ EventUtils.synthesizeMouse(div, x, y, {type: "mousedown"}, content);
+ x += 20; y += 10;
+ EventUtils.synthesizeMouse(div, x, y, {type: "mousemove"}, content);
+ is(div.style.transform, "", "touch didn't work");
+ EventUtils.synthesizeMouse(div, x, y, {type: "mouseup"}, content);
+ testWithTouch();
+ }
+
+ function testWithTouch() {
+ gBrowser.selectedTab.__responsiveUI.enableTouch();
+ let div = content.document.querySelector("div");
+ let x = 2, y = 2;
+ EventUtils.synthesizeMouse(div, x, y, {type: "mousedown"}, content);
+ x += 20; y += 10;
+ EventUtils.synthesizeMouse(div, x, y, {type: "mousemove"}, content);
+ is(div.style.transform, "translate(20px, 10px)", "touch worked");
+ EventUtils.synthesizeMouse(div, x, y, {type: "mouseup"}, content);
+ is(div.style.transform, "none", "end event worked");
+ mgr.toggle(window, gBrowser.selectedTab);
+ }
+
+ function testWithTouchAgain() {
+ gBrowser.selectedTab.__responsiveUI.disableTouch();
+ let div = content.document.querySelector("div");
+ let x = 2, y = 2;
+ EventUtils.synthesizeMouse(div, x, y, {type: "mousedown"}, content);
+ x += 20; y += 10;
+ EventUtils.synthesizeMouse(div, x, y, {type: "mousemove"}, content);
+ is(div.style.transform, "", "touch didn't work");
+ EventUtils.synthesizeMouse(div, x, y, {type: "mouseup"}, content);
+ finishUp();
+ }
+
+
+ function finishUp() {
+ gBrowser.removeCurrentTab();
+ finish();
+ }
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/responsivedesign/test/touch.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+
+<meta charset=utf-8 />
+<title>test</title>
+
+
+<style>
+ div {
+ border:1px solid red;
+ width: 100px; height: 100px;
+ }
+</style>
+
+<div></div>
+
+<script>
+ var div = document.querySelector("div");
+ var initX, initY;
+
+
+ div.addEventListener("touchstart", function(evt) {
+ var touch = evt.changedTouches[0];
+ initX = touch.pageX;
+ initY = touch.pageY;
+ }, true);
+
+ div.addEventListener("touchmove", function(evt) {
+ var touch = evt.changedTouches[0];
+ var deltaX = touch.pageX - initX;
+ var deltaY = touch.pageY - initY;
+ div.style.transform = "translate(" + deltaX + "px, " + deltaY + "px)";
+ }, true);
+
+ div.addEventListener("touchend", function(evt) {
+ div.style.transform = "none";
+ }, true);
+</script>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/touch-events.js
@@ -0,0 +1,185 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+let {CC, Cc, Ci, Cu, Cr} = require('chrome');
+
+Cu.import('resource://gre/modules/Services.jsm');
+
+let handlerCount = 0;
+
+let orig_w3c_touch_events = Services.prefs.getIntPref('dom.w3c_touch_events.enabled');
+
+// =================== Touch ====================
+// Simulate touch events on desktop
+function TouchEventHandler (window) {
+ let contextMenuTimeout = 0;
+
+ // This guard is used to not re-enter the events processing loop for
+ // self dispatched events
+ let ignoreEvents = false;
+
+ let threshold = 25;
+ try {
+ threshold = Services.prefs.getIntPref('ui.dragThresholdX');
+ } catch(e) {}
+
+ let delay = 500;
+ try {
+ delay = Services.prefs.getIntPref('ui.click_hold_context_menus.delay');
+ } catch(e) {}
+
+ let TouchEventHandler = {
+ enabled: false,
+ events: ['mousedown', 'mousemove', 'mouseup', 'click'],
+ start: function teh_start() {
+ let isReloadNeeded = Services.prefs.getIntPref('dom.w3c_touch_events.enabled') != 1;
+ handlerCount++;
+ Services.prefs.setIntPref('dom.w3c_touch_events.enabled', 1);
+ this.enabled = true;
+ this.events.forEach((function(evt) {
+ window.addEventListener(evt, this, true);
+ }).bind(this));
+ return isReloadNeeded;
+ },
+ stop: function teh_stop() {
+ handlerCount--;
+ if (handlerCount == 0)
+ Services.prefs.setIntPref('dom.w3c_touch_events.enabled', orig_w3c_touch_events);
+ this.enabled = false;
+ this.events.forEach((function(evt) {
+ window.removeEventListener(evt, this, true);
+ }).bind(this));
+ },
+ handleEvent: function teh_handleEvent(evt) {
+ if (evt.button || ignoreEvents ||
+ evt.mozInputSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_UNKNOWN)
+ return;
+
+ // The gaia system window use an hybrid system even on the device which is
+ // a mix of mouse/touch events. So let's not cancel *all* mouse events
+ // if it is the current target.
+ let content = evt.target.ownerDocument.defaultView;
+ let isSystemWindow = content.location.toString().indexOf("system.gaiamobile.org") != -1;
+
+ let eventTarget = this.target;
+ let type = '';
+ switch (evt.type) {
+ case 'mousedown':
+ this.target = evt.target;
+
+ contextMenuTimeout =
+ this.sendContextMenu(evt.target, evt.pageX, evt.pageY, delay);
+
+ this.cancelClick = false;
+ this.startX = evt.pageX;
+ this.startY = evt.pageY;
+
+ // Capture events so if a different window show up the events
+ // won't be dispatched to something else.
+ evt.target.setCapture(false);
+
+ type = 'touchstart';
+ break;
+
+ case 'mousemove':
+ if (!eventTarget)
+ return;
+
+ if (!this.cancelClick) {
+ if (Math.abs(this.startX - evt.pageX) > threshold ||
+ Math.abs(this.startY - evt.pageY) > threshold) {
+ this.cancelClick = true;
+ content.clearTimeout(contextMenuTimeout);
+ }
+ }
+
+ type = 'touchmove';
+ break;
+
+ case 'mouseup':
+ if (!eventTarget)
+ return;
+ this.target = null;
+
+ content.clearTimeout(contextMenuTimeout);
+ type = 'touchend';
+ break;
+
+ case 'click':
+ // Mouse events has been cancelled so dispatch a sequence
+ // of events to where touchend has been fired
+ evt.preventDefault();
+ evt.stopImmediatePropagation();
+
+ if (this.cancelClick)
+ return;
+
+ ignoreEvents = true;
+ content.setTimeout(function dispatchMouseEvents(self) {
+ self.fireMouseEvent('mousedown', evt);
+ self.fireMouseEvent('mousemove', evt);
+ self.fireMouseEvent('mouseup', evt);
+ ignoreEvents = false;
+ }, 0, this);
+
+ return;
+ }
+
+ let target = eventTarget || this.target;
+ if (target && type) {
+ this.sendTouchEvent(evt, target, type);
+ }
+
+ if (!isSystemWindow) {
+ evt.preventDefault();
+ evt.stopImmediatePropagation();
+ }
+ },
+ fireMouseEvent: function teh_fireMouseEvent(type, evt) {
+ let content = evt.target.ownerDocument.defaultView;
+ var utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ utils.sendMouseEvent(type, evt.clientX, evt.clientY, 0, 1, 0, true);
+ },
+ sendContextMenu: function teh_sendContextMenu(target, x, y, delay) {
+ let doc = target.ownerDocument;
+ let evt = doc.createEvent('MouseEvent');
+ evt.initMouseEvent('contextmenu', true, true, doc.defaultView,
+ 0, x, y, x, y, false, false, false, false,
+ 0, null);
+
+ let content = target.ownerDocument.defaultView;
+ let timeout = content.setTimeout((function contextMenu() {
+ target.dispatchEvent(evt);
+ this.cancelClick = true;
+ }).bind(this), delay);
+
+ return timeout;
+ },
+ sendTouchEvent: function teh_sendTouchEvent(evt, target, name) {
+ let document = target.ownerDocument;
+ let content = document.defaultView;
+
+ let touchEvent = document.createEvent('touchevent');
+ let point = document.createTouch(content, target, 0,
+ evt.pageX, evt.pageY,
+ evt.screenX, evt.screenY,
+ evt.clientX, evt.clientY,
+ 1, 1, 0, 0);
+ let touches = document.createTouchList(point);
+ let targetTouches = touches;
+ let changedTouches = touches;
+ touchEvent.initTouchEvent(name, true, true, content, 0,
+ false, false, false, false,
+ touches, targetTouches, changedTouches);
+ target.dispatchEvent(touchEvent);
+ return touchEvent;
+ }
+ };
+
+ return TouchEventHandler;
+}
+
+exports.TouchEventHandler = TouchEventHandler;
--- a/browser/locales/en-US/chrome/browser/devtools/responsiveUI.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/responsiveUI.properties
@@ -18,16 +18,19 @@ responsiveUI.rotate2=Rotate
# LOCALIZATION NOTE (responsiveUI.screenshot): tooltip of the screenshot button.
responsiveUI.screenshot=Screenshot
# LOCALIZATION NOTE (responsiveUI.screenshotGeneratedFilename): The auto generated filename.
# The first argument (%1$S) is the date string in yyyy-mm-dd format and the second
# argument (%2$S) is the time string in HH.MM.SS format.
responsiveUI.screenshotGeneratedFilename=Screen Shot %1$S at %2$S
+# LOCALIZATION NOTE (responsiveUI.touch): tooltip of the touch button.
+responsiveUI.touch=Simulate touch events (might trigger a reload)
+
# LOCALIZATION NOTE (responsiveUI.addPreset): label of the add preset button.
responsiveUI.addPreset=Add Preset
# LOCALIZATION NOTE (responsiveUI.removePreset): label of the remove preset button.
responsiveUI.removePreset=Remove Preset
# LOCALIZATION NOTE (responsiveUI.customResolution): label of the first item
# in the menulist at the beginning of the toolbar. For %S is replace with the
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -218,16 +218,17 @@ browser.jar:
skin/classic/browser/devtools/close.png (devtools/close.png)
skin/classic/browser/devtools/vview-delete.png (devtools/vview-delete.png)
skin/classic/browser/devtools/vview-edit.png (devtools/vview-edit.png)
skin/classic/browser/devtools/undock.png (devtools/undock.png)
skin/classic/browser/devtools/font-inspector.css (devtools/font-inspector.css)
skin/classic/browser/devtools/computedview.css (devtools/computedview.css)
skin/classic/browser/devtools/arrow-e.png (devtools/arrow-e.png)
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png)
+ skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/responsiveui-touch.png)
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-16-throbber.png
skin/classic/browser/sync-16.png
skin/classic/browser/sync-24-throbber.png
skin/classic/browser/sync-32.png
skin/classic/browser/sync-bg.png
skin/classic/browser/sync-128.png
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -308,16 +308,17 @@ browser.jar:
skin/classic/browser/devtools/close.png (devtools/close.png)
skin/classic/browser/devtools/vview-delete.png (devtools/vview-delete.png)
skin/classic/browser/devtools/vview-edit.png (devtools/vview-edit.png)
skin/classic/browser/devtools/undock.png (devtools/undock.png)
skin/classic/browser/devtools/font-inspector.css (devtools/font-inspector.css)
skin/classic/browser/devtools/computedview.css (devtools/computedview.css)
skin/classic/browser/devtools/arrow-e.png (devtools/arrow-e.png)
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png)
+ skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/responsiveui-touch.png)
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-throbber.png
skin/classic/browser/sync-16.png
skin/classic/browser/sync-32.png
skin/classic/browser/sync-bg.png
skin/classic/browser/sync-128.png
skin/classic/browser/sync-desktopIcon.png
--- a/browser/themes/shared/devtools/responsivedesign.inc.css
+++ b/browser/themes/shared/devtools/responsivedesign.inc.css
@@ -37,16 +37,25 @@
.devtools-responsiveui-close {
list-style-image: url("chrome://browser/skin/devtools/close.png");
}
.devtools-responsiveui-rotate {
list-style-image: url("chrome://browser/skin/devtools/responsiveui-rotate.png");
}
+.devtools-responsiveui-touch {
+ list-style-image: url("chrome://browser/skin/devtools/responsiveui-touch.png");
+ -moz-image-region: rect(0px,16px,16px,0px);
+}
+
+.devtools-responsiveui-touch[checked] {
+ -moz-image-region: rect(0px,32px,16px,16px);
+}
+
.devtools-responsiveui-screenshot {
list-style-image: url("chrome://browser/skin/devtools/responsiveui-screenshot.png");
}
.devtools-responsiveui-resizebarV {
width: 7px;
height: 24px;
cursor: ew-resize;
new file mode 100644
index 0000000000000000000000000000000000000000..c25b44d04402adadda813d70c849c1c19507e161
GIT binary patch
literal 834
zc$@)31HJr-P)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^0009CNkl<ZNXL!T
zdq`7Z6aet~K#IuTKIVLtZKkE@Qr3J6si=WvVE*AFshL`tkUhvInDl^XS&f<IWAlk-
zlrqhc{$Ut}5ENOWD=Q5%+aDTj(-~jqtUDRv&2R8y=R5bFd(L*hdpVqCA3}&7H~^%e
zl!@&)l%MpM#2#b-1*l|Vd)j)=;^JcR*vIiae&D_|gt5tFN}#Pz9hlG9-#$_98ZF6l
zjgsVJ47nrJ1L*aJ;s8->-0a+31H#y7oG+%WkMEt6^Wut*B|e&(K^Vtte#xl^fTo32
zbq!nLZy!P!V~)07)G>9}FS{-$Y2Xh*ep$6Sn4=y*+0=HF8Q=v{HMei6u5Zkyt><6u
zF7nN)$&KruCkSKym9Ep&18n9A_S!je*Fy8>2xG_v)7GzX4-ojI$TDIzdV+io-jTV4
z<)-itD>hMG02<mdPeVUL0UNWDb^xr0X6X^?S%P9(zUpF{KkFb@0EE<oKw}N#8RH(J
zx(zUZ=!uRXapymgP2)O5JqR>YFVn-QK&uTPeE6MM3+<RT6D!AbVx@Kl&JnLRz+)Dj
z4124F>%kt70K!3jK+6PKNl@#gnIOHo2<t4(Y=8vRfkw>znE8ouI~&*+*-Uc>e%k%W
zz?-i|gvv3!ut95t+-*VSJA<$46JZm0eNc--n+I4}Fa^U!+dwPAoWWpJLfpazYE+hA
z?_b(i?pv=VKDDD}kW=lf`e52oGfLR(dN8s8=OtQpuB*3SNanecvNOZ)M`W1$t=HE;
zBNZDwZutjz(Pu+=iBg$YUgMDGjlpTim3hhEm^>?o2^&1VGypS%1K_Q5@{YxIkETz`
z+>#Y_s(VYU_J9pH;?xFi_{pGcp_zwZ9p!Q9=_FVFmay@-*!^Yc7A$*?ZSdR4%Ri*6
zTO);Es(^;o7P!W|v-fTx%X`2EF6`(YfBA&l1@$+VTSF%2ir2&f*N~rdPmoHMHX+*!
z1qeYZNVk&8<Zb`=6m3tsw$Vj&JeeC-aNaGVunb(mZ(L&@kK=iN0i$xzr-V<Uk^lez
M07*qoM6N<$g7?gkw*UYD
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -245,16 +245,17 @@ browser.jar:
skin/classic/browser/devtools/close.png (devtools/close.png)
skin/classic/browser/devtools/vview-delete.png (devtools/vview-delete.png)
skin/classic/browser/devtools/vview-edit.png (devtools/vview-edit.png)
skin/classic/browser/devtools/undock.png (devtools/undock.png)
skin/classic/browser/devtools/font-inspector.css (devtools/font-inspector.css)
skin/classic/browser/devtools/computedview.css (devtools/computedview.css)
skin/classic/browser/devtools/arrow-e.png (devtools/arrow-e.png)
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png)
+ skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/responsiveui-touch.png)
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/sync-throbber.png
skin/classic/browser/sync-16.png
skin/classic/browser/sync-32.png
skin/classic/browser/sync-128.png
skin/classic/browser/sync-bg.png
skin/classic/browser/sync-desktopIcon.png
@@ -506,16 +507,17 @@ browser.jar:
skin/classic/aero/browser/devtools/close.png (devtools/close.png)
skin/classic/aero/browser/devtools/vview-delete.png (devtools/vview-delete.png)
skin/classic/aero/browser/devtools/vview-edit.png (devtools/vview-edit.png)
skin/classic/aero/browser/devtools/undock.png (devtools/undock.png)
skin/classic/aero/browser/devtools/font-inspector.css (devtools/font-inspector.css)
skin/classic/aero/browser/devtools/computedview.css (devtools/computedview.css)
skin/classic/aero/browser/devtools/arrow-e.png (devtools/arrow-e.png)
skin/classic/aero/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png)
+ skin/classic/aero/browser/devtools/responsiveui-touch.png (../shared/devtools/responsiveui-touch.png)
skin/classic/aero/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/aero/browser/sync-throbber.png
skin/classic/aero/browser/sync-16.png
skin/classic/aero/browser/sync-32.png
skin/classic/aero/browser/sync-128.png
skin/classic/aero/browser/sync-bg.png
skin/classic/aero/browser/sync-desktopIcon.png