1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/devtools/shared/FloatingScrollbars.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,126 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; 1.11 + 1.12 +this.EXPORTED_SYMBOLS = [ "switchToFloatingScrollbars", "switchToNativeScrollbars" ]; 1.13 + 1.14 +Cu.import("resource://gre/modules/Services.jsm"); 1.15 + 1.16 +let URL = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null); 1.17 + 1.18 +let trackedTabs = new WeakMap(); 1.19 + 1.20 +/** 1.21 + * Switch to floating scrollbars, à la mobile. 1.22 + * 1.23 + * @param aTab the targeted tab. 1.24 + * 1.25 + */ 1.26 +this.switchToFloatingScrollbars = function switchToFloatingScrollbars(aTab) { 1.27 + let mgr = trackedTabs.get(aTab); 1.28 + if (!mgr) { 1.29 + mgr = new ScrollbarManager(aTab); 1.30 + } 1.31 + mgr.switchToFloating(); 1.32 +} 1.33 + 1.34 +/** 1.35 + * Switch to original native scrollbars. 1.36 + * 1.37 + * @param aTab the targeted tab. 1.38 + * 1.39 + */ 1.40 +this.switchToNativeScrollbars = function switchToNativeScrollbars(aTab) { 1.41 + let mgr = trackedTabs.get(aTab); 1.42 + if (mgr) { 1.43 + mgr.reset(); 1.44 + } 1.45 +} 1.46 + 1.47 +function ScrollbarManager(aTab) { 1.48 + trackedTabs.set(aTab, this); 1.49 + 1.50 + this.attachedTab = aTab; 1.51 + this.attachedBrowser = aTab.linkedBrowser; 1.52 + 1.53 + this.reset = this.reset.bind(this); 1.54 + this.switchToFloating = this.switchToFloating.bind(this); 1.55 + 1.56 + this.attachedTab.addEventListener("TabClose", this.reset, true); 1.57 + this.attachedBrowser.addEventListener("DOMContentLoaded", this.switchToFloating, true); 1.58 +} 1.59 + 1.60 +ScrollbarManager.prototype = { 1.61 + get win() { 1.62 + return this.attachedBrowser.contentWindow; 1.63 + }, 1.64 + 1.65 + /* 1.66 + * Change the look of the scrollbars. 1.67 + */ 1.68 + switchToFloating: function() { 1.69 + let windows = this.getInnerWindows(this.win); 1.70 + windows.forEach(this.injectStyleSheet); 1.71 + this.forceStyle(); 1.72 + }, 1.73 + 1.74 + 1.75 + /* 1.76 + * Reset the look of the scrollbars. 1.77 + */ 1.78 + reset: function() { 1.79 + let windows = this.getInnerWindows(this.win); 1.80 + windows.forEach(this.removeStyleSheet); 1.81 + this.forceStyle(this.attachedBrowser); 1.82 + this.attachedBrowser.removeEventListener("DOMContentLoaded", this.switchToFloating, true); 1.83 + this.attachedTab.removeEventListener("TabClose", this.reset, true); 1.84 + trackedTabs.delete(this.attachedTab); 1.85 + }, 1.86 + 1.87 + /* 1.88 + * Toggle the display property of the window to force the style to be applied. 1.89 + */ 1.90 + forceStyle: function() { 1.91 + let parentWindow = this.attachedBrowser.ownerDocument.defaultView; 1.92 + let display = parentWindow.getComputedStyle(this.attachedBrowser).display; // Save display value 1.93 + this.attachedBrowser.style.display = "none"; 1.94 + parentWindow.getComputedStyle(this.attachedBrowser).display; // Flush 1.95 + this.attachedBrowser.style.display = display; // Restore 1.96 + }, 1.97 + 1.98 + /* 1.99 + * return all the window objects present in the hiearchy of a window. 1.100 + */ 1.101 + getInnerWindows: function(win) { 1.102 + let iframes = win.document.querySelectorAll("iframe"); 1.103 + let innerWindows = []; 1.104 + for (let iframe of iframes) { 1.105 + innerWindows = innerWindows.concat(this.getInnerWindows(iframe.contentWindow)); 1.106 + } 1.107 + return [win].concat(innerWindows); 1.108 + }, 1.109 + 1.110 + /* 1.111 + * Append the new scrollbar style. 1.112 + */ 1.113 + injectStyleSheet: function(win) { 1.114 + let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); 1.115 + try { 1.116 + winUtils.loadSheet(URL, win.AGENT_SHEET); 1.117 + }catch(e) {} 1.118 + }, 1.119 + 1.120 + /* 1.121 + * Remove the injected stylesheet. 1.122 + */ 1.123 + removeStyleSheet: function(win) { 1.124 + let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); 1.125 + try { 1.126 + winUtils.removeSheet(URL, win.AGENT_SHEET); 1.127 + }catch(e) {} 1.128 + }, 1.129 +}