browser/devtools/shared/FloatingScrollbars.jsm

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:2305a8cf44e1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
8
9 this.EXPORTED_SYMBOLS = [ "switchToFloatingScrollbars", "switchToNativeScrollbars" ];
10
11 Cu.import("resource://gre/modules/Services.jsm");
12
13 let URL = Services.io.newURI("chrome://browser/skin/devtools/floating-scrollbars.css", null, null);
14
15 let trackedTabs = new WeakMap();
16
17 /**
18 * Switch to floating scrollbars, à la mobile.
19 *
20 * @param aTab the targeted tab.
21 *
22 */
23 this.switchToFloatingScrollbars = function switchToFloatingScrollbars(aTab) {
24 let mgr = trackedTabs.get(aTab);
25 if (!mgr) {
26 mgr = new ScrollbarManager(aTab);
27 }
28 mgr.switchToFloating();
29 }
30
31 /**
32 * Switch to original native scrollbars.
33 *
34 * @param aTab the targeted tab.
35 *
36 */
37 this.switchToNativeScrollbars = function switchToNativeScrollbars(aTab) {
38 let mgr = trackedTabs.get(aTab);
39 if (mgr) {
40 mgr.reset();
41 }
42 }
43
44 function ScrollbarManager(aTab) {
45 trackedTabs.set(aTab, this);
46
47 this.attachedTab = aTab;
48 this.attachedBrowser = aTab.linkedBrowser;
49
50 this.reset = this.reset.bind(this);
51 this.switchToFloating = this.switchToFloating.bind(this);
52
53 this.attachedTab.addEventListener("TabClose", this.reset, true);
54 this.attachedBrowser.addEventListener("DOMContentLoaded", this.switchToFloating, true);
55 }
56
57 ScrollbarManager.prototype = {
58 get win() {
59 return this.attachedBrowser.contentWindow;
60 },
61
62 /*
63 * Change the look of the scrollbars.
64 */
65 switchToFloating: function() {
66 let windows = this.getInnerWindows(this.win);
67 windows.forEach(this.injectStyleSheet);
68 this.forceStyle();
69 },
70
71
72 /*
73 * Reset the look of the scrollbars.
74 */
75 reset: function() {
76 let windows = this.getInnerWindows(this.win);
77 windows.forEach(this.removeStyleSheet);
78 this.forceStyle(this.attachedBrowser);
79 this.attachedBrowser.removeEventListener("DOMContentLoaded", this.switchToFloating, true);
80 this.attachedTab.removeEventListener("TabClose", this.reset, true);
81 trackedTabs.delete(this.attachedTab);
82 },
83
84 /*
85 * Toggle the display property of the window to force the style to be applied.
86 */
87 forceStyle: function() {
88 let parentWindow = this.attachedBrowser.ownerDocument.defaultView;
89 let display = parentWindow.getComputedStyle(this.attachedBrowser).display; // Save display value
90 this.attachedBrowser.style.display = "none";
91 parentWindow.getComputedStyle(this.attachedBrowser).display; // Flush
92 this.attachedBrowser.style.display = display; // Restore
93 },
94
95 /*
96 * return all the window objects present in the hiearchy of a window.
97 */
98 getInnerWindows: function(win) {
99 let iframes = win.document.querySelectorAll("iframe");
100 let innerWindows = [];
101 for (let iframe of iframes) {
102 innerWindows = innerWindows.concat(this.getInnerWindows(iframe.contentWindow));
103 }
104 return [win].concat(innerWindows);
105 },
106
107 /*
108 * Append the new scrollbar style.
109 */
110 injectStyleSheet: function(win) {
111 let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
112 try {
113 winUtils.loadSheet(URL, win.AGENT_SHEET);
114 }catch(e) {}
115 },
116
117 /*
118 * Remove the injected stylesheet.
119 */
120 removeStyleSheet: function(win) {
121 let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
122 try {
123 winUtils.removeSheet(URL, win.AGENT_SHEET);
124 }catch(e) {}
125 },
126 }

mercurial