Merge fx-team to m-c.
@ -1274,15 +1274,20 @@ pref("devtools.hud.loglimit.cssparser", 200);
|
||||
pref("devtools.hud.loglimit.exception", 200);
|
||||
pref("devtools.hud.loglimit.console", 200);
|
||||
|
||||
// By how many times eyedropper will magnify pixels
|
||||
pref("devtools.eyedropper.zoom", 6);
|
||||
|
||||
// The developer tools editor configuration:
|
||||
// - tabsize: how many spaces to use when a Tab character is displayed.
|
||||
// - expandtab: expand Tab characters to spaces.
|
||||
// - keymap: which keymap to use (can be 'default', 'emacs' or 'vim')
|
||||
// - autoclosebrackets: whether to permit automatic bracket/quote closing.
|
||||
// - detectindentation: whether to detect the indentation from the file
|
||||
pref("devtools.editor.tabsize", 4);
|
||||
pref("devtools.editor.expandtab", true);
|
||||
pref("devtools.editor.keymap", "default");
|
||||
pref("devtools.editor.autoclosebrackets", true);
|
||||
pref("devtools.editor.detectindentation", true);
|
||||
|
||||
// Enable the Font Inspector
|
||||
pref("devtools.fontinspector.enabled", true);
|
||||
|
@ -177,7 +177,7 @@ let gFxAccounts = {
|
||||
|
||||
// If the user is signed into their Firefox account and we are not
|
||||
// currently in customization mode, show their email address.
|
||||
fxAccounts.getSignedInUser().then(userData => {
|
||||
let doUpdate = userData => {
|
||||
// Reset the button to its original state.
|
||||
this.button.setAttribute("label", defaultLabel);
|
||||
this.button.removeAttribute("tooltiptext");
|
||||
@ -194,6 +194,15 @@ let gFxAccounts = {
|
||||
this.button.setAttribute("tooltiptext", userData.email);
|
||||
}
|
||||
}
|
||||
}
|
||||
fxAccounts.getSignedInUser().then(userData => {
|
||||
doUpdate(userData);
|
||||
}).then(null, error => {
|
||||
// This is most likely in tests, were we quickly log users in and out.
|
||||
// The most likely scenario is a user logged out, so reflect that.
|
||||
// Bug 995134 calls for better errors so we could retry if we were
|
||||
// sure this was the failure reason.
|
||||
doUpdate(null);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -504,6 +504,9 @@
|
||||
<menuitem id="menu_responsiveUI"
|
||||
observes="devtoolsMenuBroadcaster_ResponsiveUI"
|
||||
accesskey="&responsiveDesignTool.accesskey;"/>
|
||||
<menuitem id="menu_eyedropper"
|
||||
observes="devtoolsMenuBroadcaster_Eyedropper"
|
||||
accesskey="&eyedropper.accesskey;"/>
|
||||
<menuitem id="menu_scratchpad"
|
||||
observes="devtoolsMenuBroadcaster_Scratchpad"
|
||||
accesskey="&scratchpad.accesskey;"/>
|
||||
|
@ -102,6 +102,7 @@
|
||||
<command id="Tools:BrowserConsole" oncommand="HUDService.toggleBrowserConsole();"/>
|
||||
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();"/>
|
||||
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();"/>
|
||||
<command id="Tools:Eyedropper" oncommand="openEyedropper();"/>
|
||||
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
|
||||
<command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
|
||||
<command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)" disabled="true" hidden="true"/>
|
||||
@ -211,6 +212,10 @@
|
||||
type="checkbox" autocheck="false"
|
||||
command="Tools:ResponsiveUI"
|
||||
key="key_responsiveUI"/>
|
||||
<broadcaster id="devtoolsMenuBroadcaster_Eyedropper"
|
||||
label="&eyedropper.label;"
|
||||
type="checkbox" autocheck="false"
|
||||
command="Tools:Eyedropper"/>
|
||||
<broadcaster id="devtoolsMenuBroadcaster_PageSource"
|
||||
label="&pageSourceCmd.label;"
|
||||
key="key_viewSource"
|
||||
|
@ -216,14 +216,14 @@ toolbar[customizing] > .overflow-button {
|
||||
}
|
||||
|
||||
/* Fullscreen and caption buttons don't move with RTL on OS X so override the automatic ordering. */
|
||||
#titlebar-fullscreen-button:-moz-locale-dir(ltr),
|
||||
#titlebar-secondary-buttonbox:-moz-locale-dir(ltr),
|
||||
#titlebar-buttonbox-container:-moz-locale-dir(rtl),
|
||||
.titlebar-placeholder[type="fullscreen-button"]:-moz-locale-dir(ltr),
|
||||
.titlebar-placeholder[type="caption-buttons"]:-moz-locale-dir(rtl) {
|
||||
-moz-box-ordinal-group: 1000;
|
||||
}
|
||||
|
||||
#titlebar-fullscreen-button:-moz-locale-dir(rtl),
|
||||
#titlebar-secondary-buttonbox:-moz-locale-dir(rtl),
|
||||
#titlebar-buttonbox-container:-moz-locale-dir(ltr),
|
||||
.titlebar-placeholder[type="caption-buttons"]:-moz-locale-dir(ltr),
|
||||
.titlebar-placeholder[type="fullscreen-button"]:-moz-locale-dir(rtl) {
|
||||
@ -236,6 +236,12 @@ toolbar[customizing] > .overflow-button {
|
||||
}
|
||||
%endif
|
||||
|
||||
%if !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_QT)
|
||||
#TabsToolbar > .private-browsing-indicator {
|
||||
-moz-box-ordinal-group: 1000;
|
||||
}
|
||||
%endif
|
||||
|
||||
%ifdef XP_WIN
|
||||
#main-window[sizemode="maximized"] #titlebar-buttonbox {
|
||||
-moz-appearance: -moz-window-button-box-maximized;
|
||||
|
@ -4481,7 +4481,7 @@ var TabsInTitlebar = {
|
||||
let captionButtonsBoxWidth = rect($("titlebar-buttonbox-container")).width;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
let fullscreenButtonWidth = rect($("titlebar-fullscreen-button")).width;
|
||||
let secondaryButtonsWidth = rect($("titlebar-secondary-buttonbox")).width;
|
||||
// No need to look up the menubar stuff on OS X:
|
||||
let menuHeight = 0;
|
||||
let fullMenuHeight = 0;
|
||||
@ -4557,7 +4557,7 @@ var TabsInTitlebar = {
|
||||
|
||||
// Finally, size the placeholders:
|
||||
#ifdef XP_MACOSX
|
||||
this._sizePlaceholder("fullscreen-button", fullscreenButtonWidth);
|
||||
this._sizePlaceholder("fullscreen-button", secondaryButtonsWidth);
|
||||
#endif
|
||||
this._sizePlaceholder("caption-buttons", captionButtonsBoxWidth);
|
||||
|
||||
@ -4624,7 +4624,8 @@ function updateTitlebarDisplay() {
|
||||
document.documentElement.setAttribute("chromemargin-nonlwtheme", "");
|
||||
let isCustomizing = document.documentElement.hasAttribute("customizing");
|
||||
let hasLWTheme = document.documentElement.hasAttribute("lwtheme");
|
||||
if (!hasLWTheme || isCustomizing) {
|
||||
let isPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
|
||||
if ((!hasLWTheme || isCustomizing) && !isPrivate) {
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
}
|
||||
document.documentElement.setAttribute("drawtitle", "true");
|
||||
@ -7122,6 +7123,20 @@ XPCOMUtils.defineLazyGetter(ResponsiveUI, "ResponsiveUIManager", function() {
|
||||
return tmp.ResponsiveUIManager;
|
||||
});
|
||||
|
||||
function openEyedropper() {
|
||||
var eyedropper = new this.Eyedropper(this);
|
||||
eyedropper.open();
|
||||
}
|
||||
|
||||
Object.defineProperty(this, "Eyedropper", {
|
||||
get: function() {
|
||||
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
return devtools.require("devtools/eyedropper/eyedropper").Eyedropper;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () {
|
||||
#ifdef XP_WIN
|
||||
// Only show resizers on Windows 2000 and XP
|
||||
|
@ -498,7 +498,12 @@
|
||||
</hbox>
|
||||
</hbox>
|
||||
#ifdef XP_MACOSX
|
||||
<hbox id="titlebar-fullscreen-button"/>
|
||||
<!-- OS X does not natively support RTL for its titlebar items, so we prevent this secondary
|
||||
buttonbox from reversing order in RTL by forcing an LTR direction. -->
|
||||
<hbox id="titlebar-secondary-buttonbox" dir="ltr">
|
||||
<hbox class="private-browsing-indicator"/>
|
||||
<hbox id="titlebar-fullscreen-button"/>
|
||||
</hbox>
|
||||
#endif
|
||||
</hbox>
|
||||
</vbox>
|
||||
@ -602,8 +607,8 @@
|
||||
cui-areatype="toolbar"
|
||||
tooltiptext="&closeTab.label;"/>
|
||||
|
||||
#ifdef XP_WIN
|
||||
<hbox class="private-browsing-indicator" skipintoolbarset="true" ordinal="1000"/>
|
||||
#if !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_QT)
|
||||
<hbox class="private-browsing-indicator" skipintoolbarset="true"/>
|
||||
#endif
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
<hbox class="titlebar-placeholder" type="caption-buttons"
|
||||
|
@ -3568,18 +3568,10 @@
|
||||
// 3 - close button at the end of the tabstrip
|
||||
switch (this.mCloseButtons) {
|
||||
case 0:
|
||||
if (numTabs == 1 && this._closeWindowWithLastTab)
|
||||
this.setAttribute("closebuttons", "hidden");
|
||||
else
|
||||
this.setAttribute("closebuttons", "activetab");
|
||||
this.setAttribute("closebuttons", "activetab");
|
||||
break;
|
||||
case 1:
|
||||
if (numTabs == 1) {
|
||||
if (this._closeWindowWithLastTab)
|
||||
this.setAttribute("closebuttons", "hidden");
|
||||
else
|
||||
this.setAttribute("closebuttons", "alltabs");
|
||||
} else if (numTabs == 2) {
|
||||
if (numTabs <= 2) {
|
||||
// This is an optimization to avoid layout flushes by calling
|
||||
// getBoundingClientRect() when we just opened a second tab. In
|
||||
// this case it's highly unlikely that the tab width is smaller
|
||||
|
@ -1857,12 +1857,17 @@ let CustomizableUIInternal = {
|
||||
|
||||
// Look through previously saved state to see if we're restoring a widget.
|
||||
let seenAreas = new Set();
|
||||
let widgetMightNeedAutoAdding = true;
|
||||
for (let [area, placements] of gPlacements) {
|
||||
seenAreas.add(area);
|
||||
let areaIsRegistered = gAreas.has(area);
|
||||
let index = gPlacements.get(area).indexOf(widget.id);
|
||||
if (index != -1) {
|
||||
widget.currentArea = area;
|
||||
widget.currentPosition = index;
|
||||
widgetMightNeedAutoAdding = false;
|
||||
if (areaIsRegistered) {
|
||||
widget.currentArea = area;
|
||||
widget.currentPosition = index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1870,16 +1875,20 @@ let CustomizableUIInternal = {
|
||||
// Also look at saved state data directly in areas that haven't yet been
|
||||
// restored. Can't rely on this for restored areas, as they may have
|
||||
// changed.
|
||||
if (!widget.currentArea && gSavedState) {
|
||||
if (widgetMightNeedAutoAdding && gSavedState) {
|
||||
for (let area of Object.keys(gSavedState.placements)) {
|
||||
if (seenAreas.has(area)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let areaIsRegistered = gAreas.has(area);
|
||||
let index = gSavedState.placements[area].indexOf(widget.id);
|
||||
if (index != -1) {
|
||||
widget.currentArea = area;
|
||||
widget.currentPosition = index;
|
||||
widgetMightNeedAutoAdding = false;
|
||||
if (areaIsRegistered) {
|
||||
widget.currentArea = area;
|
||||
widget.currentPosition = index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1891,7 +1900,7 @@ let CustomizableUIInternal = {
|
||||
if (widget.currentArea) {
|
||||
this.notifyListeners("onWidgetAdded", widget.id, widget.currentArea,
|
||||
widget.currentPosition);
|
||||
} else {
|
||||
} else if (widgetMightNeedAutoAdding) {
|
||||
let autoAdd = true;
|
||||
try {
|
||||
autoAdd = Services.prefs.getBoolPref(kPrefCustomizationAutoAdd);
|
||||
|
@ -104,4 +104,5 @@ skip-if = os == "linux"
|
||||
[browser_987177_xul_wrapper_updating.js]
|
||||
[browser_987492_window_api.js]
|
||||
[browser_992747_toggle_noncustomizable_toolbar.js]
|
||||
[browser_993322_widget_notoolbar.js]
|
||||
[browser_panel_toggle.js]
|
||||
|
@ -0,0 +1,34 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const BUTTONID = "test-API-created-widget-toolbar-gone";
|
||||
const TOOLBARID = "test-API-created-extra-toolbar";
|
||||
|
||||
add_task(function*() {
|
||||
let toolbar = createToolbarWithPlacements(TOOLBARID, []);
|
||||
CustomizableUI.addWidgetToArea(BUTTONID, TOOLBARID);
|
||||
is(CustomizableUI.getPlacementOfWidget(BUTTONID).area, TOOLBARID, "Should be on toolbar");
|
||||
is(toolbar.children.length, 0, "Toolbar has no kid");
|
||||
|
||||
CustomizableUI.unregisterArea(TOOLBARID);
|
||||
CustomizableUI.createWidget({id: BUTTONID, label: "Test widget toolbar gone"});
|
||||
|
||||
let currentWidget = CustomizableUI.getWidget(BUTTONID);
|
||||
|
||||
yield startCustomizing();
|
||||
let buttonNode = document.getElementById(BUTTONID);
|
||||
ok(buttonNode, "Should find button in window");
|
||||
if (buttonNode) {
|
||||
is(buttonNode.parentNode.localName, "toolbarpaletteitem", "Node should be wrapped");
|
||||
is(buttonNode.parentNode.getAttribute("place"), "palette", "Node should be in palette");
|
||||
is(buttonNode, gNavToolbox.palette.querySelector("#" + BUTTONID), "Node should really be in palette.");
|
||||
}
|
||||
is(currentWidget.forWindow(window).node, buttonNode, "Should have the same node for customize mode");
|
||||
yield endCustomizing();
|
||||
|
||||
CustomizableUI.destroyWidget(BUTTONID);
|
||||
CustomizableUI.unregisterArea(TOOLBARID, true);
|
||||
});
|
@ -456,7 +456,7 @@
|
||||
// If we have not moved to a valid new target clear the drop indicator
|
||||
// this happens when moving out of the popup.
|
||||
let target = event.relatedTarget;
|
||||
if (!target)
|
||||
if (!target || !this.contains(target))
|
||||
this._indicatorBar.hidden = true;
|
||||
|
||||
// Close any folder being hovered over
|
||||
|
@ -22,15 +22,15 @@ var gMainPane = {
|
||||
.getService(Components.interfaces.nsIObserverService)
|
||||
.notifyObservers(window, "main-pane-loaded", null);
|
||||
|
||||
//Functionality for "Show tabs in taskbar" on Win XP
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Functionality for "Show tabs in taskbar" on Windows 7 and up.
|
||||
|
||||
try {
|
||||
let sysInfo = Cc["@mozilla.org/system-info;1"].
|
||||
getService(Ci.nsIPropertyBag2);
|
||||
let ver = parseFloat(sysInfo.getProperty("version"));
|
||||
let showTabsInTaskbar = document.getElementById("showTabsInTaskbar");
|
||||
showTabsInTaskbar.hidden = ver < 6.1 || (ver >= 6.1 && history.state != "tabs");
|
||||
showTabsInTaskbar.hidden = ver < 6.1;
|
||||
} catch (ex) {}
|
||||
|
||||
#endif
|
||||
@ -443,8 +443,31 @@ var gMainPane = {
|
||||
startupPref.updateElements(); // select the correct index in the startup menulist
|
||||
}
|
||||
},
|
||||
|
||||
// TABS
|
||||
|
||||
/*
|
||||
* Preferences:
|
||||
*
|
||||
* browser.link.open_newwindow - int
|
||||
* Determines where links targeting new windows should open.
|
||||
* Values:
|
||||
* 1 - Open in the current window or tab.
|
||||
* 2 - Open in a new window.
|
||||
* 3 - Open in a new tab in the most recent window.
|
||||
* browser.tabs.loadInBackground - bool
|
||||
* True - Whether browser should switch to a new tab opened from a link.
|
||||
* browser.tabs.warnOnClose - bool
|
||||
* True - If when closing a window with multiple tabs the user is warned and
|
||||
* allowed to cancel the action, false to just close the window.
|
||||
* browser.tabs.warnOnOpen - bool
|
||||
* True - Whether the user should be warned when trying to open a lot of
|
||||
* tabs at once (e.g. a large folder of bookmarks), allowing to
|
||||
* cancel the action.
|
||||
* browser.taskbar.previews.enable - bool
|
||||
* True - Tabs are to be shown in Windows 7 taskbar.
|
||||
* False - Only the window is to be shown in Windows 7 taskbar.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determines where a link which opens a new window will open.
|
||||
|
@ -1,18 +0,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/. */
|
||||
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
|
||||
const Cu = Components.utils;
|
||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
||||
Cu.import("resource:///modules/devtools/BuiltinCommands.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdDebugger.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdEdit.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdInspect.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdResize.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdTilt.jsm");
|
||||
Cu.import("resource:///modules/devtools/CmdScratchpad.jsm");
|
||||
|
||||
require("devtools/profiler/commands.js");
|
@ -1,9 +0,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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
@ -17,15 +17,35 @@
|
||||
content: '\bb';
|
||||
}
|
||||
|
||||
.gcli-menu-option {
|
||||
overflow: hidden;
|
||||
.gcli-menu-template {
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
width: 290px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.gcli-menu-template {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
.gcli-menu-names {
|
||||
white-space: nowrap;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.gcli-menu-descs {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
.gcli-menu-name,
|
||||
.gcli-menu-desc {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.gcli-menu-name {
|
||||
-moz-padding-end: 10px;
|
||||
}
|
||||
|
||||
.gcli-menu-desc {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gcli-menu-name,
|
||||
|
37
browser/devtools/commandline/commands-index.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
const commandModules = [
|
||||
"devtools/tilt/tilt-commands",
|
||||
"gcli/commands/addon",
|
||||
"gcli/commands/appcache",
|
||||
"gcli/commands/calllog",
|
||||
"gcli/commands/cmd",
|
||||
"gcli/commands/cookie",
|
||||
"gcli/commands/jsb",
|
||||
"gcli/commands/listen",
|
||||
"gcli/commands/media",
|
||||
"gcli/commands/pagemod",
|
||||
"gcli/commands/paintflashing",
|
||||
"gcli/commands/restart",
|
||||
"gcli/commands/screenshot",
|
||||
"gcli/commands/tools",
|
||||
];
|
||||
|
||||
gcli.addItemsByModule(commandModules, { delayedLoad: true });
|
||||
|
||||
const defaultTools = require("main").defaultTools;
|
||||
for (let definition of defaultTools) {
|
||||
if (definition.commands) {
|
||||
gcli.addItemsByModule(definition.commands, { delayedLoad: true });
|
||||
}
|
||||
}
|
||||
|
||||
const { mozDirLoader } = require("gcli/commands/cmd");
|
||||
|
||||
gcli.addItemsByModule("mozcmd", { delayedLoad: true, loader: mozDirLoader });
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "gcli" ];
|
||||
Components.utils.import("resource://gre/modules/devtools/gcli.jsm");
|
@ -1,7 +1,11 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/commandline'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'commands-index.js'
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
@ -3,149 +3,132 @@
|
||||
|
||||
// Tests that the addon commands works as they should
|
||||
|
||||
let CmdAddonFlags = (Cu.import("resource:///modules/devtools/BuiltinCommands.jsm", {})).CmdAddonFlags;
|
||||
|
||||
let tests = {};
|
||||
|
||||
function test() {
|
||||
helpers.addTabWithToolbar("about:blank", function(options) {
|
||||
return helpers.runTests(options, tests);
|
||||
}).then(finish, helpers.handleError);
|
||||
return Task.spawn(spawnTest).then(finish, helpers.handleError);
|
||||
}
|
||||
|
||||
tests.gatTest = function(options) {
|
||||
let deferred = promise.defer();
|
||||
function spawnTest() {
|
||||
let options = yield helpers.openTab("about:blank");
|
||||
yield helpers.openToolbar(options);
|
||||
|
||||
let onGatReady = function() {
|
||||
Services.obs.removeObserver(onGatReady, "gcli_addon_commands_ready");
|
||||
info("gcli_addon_commands_ready notification received, running tests");
|
||||
|
||||
let auditDone = helpers.audit(options, [
|
||||
{
|
||||
setup: 'addon list dictionary',
|
||||
check: {
|
||||
input: 'addon list dictionary',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'There are no add-ons of that type installed.'
|
||||
}
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
setup: 'addon list dictionary',
|
||||
check: {
|
||||
input: 'addon list dictionary',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
{
|
||||
setup: 'addon list extension',
|
||||
check: {
|
||||
input: 'addon list extension',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/The following/, /Mochitest/, /Special Powers/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list locale',
|
||||
check: {
|
||||
input: 'addon list locale',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'There are no add-ons of that type installed.'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list plugin',
|
||||
check: {
|
||||
input: 'addon list plugin',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/Test Plug-in/, /Second Test Plug-in/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list theme',
|
||||
check: {
|
||||
input: 'addon list theme',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/following themes/, /Default/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list all',
|
||||
check: {
|
||||
input: 'addon list all',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/The following/, /Default/, /Mochitest/, /Test Plug-in/,
|
||||
/Second Test Plug-in/, /Special Powers/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon disable Test_Plug-in_1.0.0.0',
|
||||
check: {
|
||||
input: 'addon disable Test_Plug-in_1.0.0.0',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'Test Plug-in 1.0.0.0 disabled.'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon disable WRONG',
|
||||
check: {
|
||||
input: 'addon disable WRONG',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVEEEEE',
|
||||
status: 'ERROR'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon enable Test_Plug-in_1.0.0.0',
|
||||
check: {
|
||||
input: 'addon enable Test_Plug-in_1.0.0.0',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
command: { name: 'addon enable' },
|
||||
name: { value: 'Test Plug-in', status: 'VALID' },
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: 'Test Plug-in 1.0.0.0 enabled.'
|
||||
}
|
||||
exec: {
|
||||
output: 'There are no add-ons of that type installed.'
|
||||
}
|
||||
]);
|
||||
},
|
||||
{
|
||||
setup: 'addon list extension',
|
||||
check: {
|
||||
input: 'addon list extension',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/The following/, /Mochitest/, /Special Powers/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list locale',
|
||||
check: {
|
||||
input: 'addon list locale',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'There are no add-ons of that type installed.'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list plugin',
|
||||
check: {
|
||||
input: 'addon list plugin',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/Test Plug-in/, /Second Test Plug-in/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list theme',
|
||||
check: {
|
||||
input: 'addon list theme',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/following themes/, /Default/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon list all',
|
||||
check: {
|
||||
input: 'addon list all',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: [/The following/, /Default/, /Mochitest/, /Test Plug-in/,
|
||||
/Second Test Plug-in/, /Special Powers/]
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon disable Test_Plug-in_1.0.0.0',
|
||||
check: {
|
||||
input: 'addon disable Test_Plug-in_1.0.0.0',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
},
|
||||
exec: {
|
||||
output: 'Test Plug-in 1.0.0.0 disabled.'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon disable WRONG',
|
||||
check: {
|
||||
input: 'addon disable WRONG',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVEEEEE',
|
||||
status: 'ERROR'
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'addon enable Test_Plug-in_1.0.0.0',
|
||||
check: {
|
||||
input: 'addon enable Test_Plug-in_1.0.0.0',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
command: { name: 'addon enable' },
|
||||
addon: {
|
||||
value: function(addon) {
|
||||
is(addon.name, 'Test Plug-in', 'test plugin name');
|
||||
},
|
||||
status: 'VALID'
|
||||
}
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: 'Test Plug-in 1.0.0.0 enabled.'
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
auditDone.then(deferred.resolve, deferred.reject);
|
||||
};
|
||||
|
||||
Services.obs.addObserver(onGatReady, "gcli_addon_commands_ready", false);
|
||||
|
||||
if (CmdAddonFlags.addonsLoaded) {
|
||||
info("The call to AddonManager.getAllAddons in BuiltinCommands.jsm is done.");
|
||||
info("Send the gcli_addon_commands_ready notification ourselves.");
|
||||
|
||||
Services.obs.notifyObservers(null, "gcli_addon_commands_ready", null);
|
||||
} else {
|
||||
info("Waiting for gcli_addon_commands_ready notification.");
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
yield helpers.closeToolbar(options);
|
||||
yield helpers.closeTab(options);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ function spawnTest() {
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
setup: "console close",
|
||||
exec: { output: "" }
|
||||
exec: { output: true }
|
||||
}
|
||||
]);
|
||||
|
||||
|
@ -11,7 +11,6 @@ function test() {
|
||||
}
|
||||
|
||||
function spawnTest() {
|
||||
// Setup
|
||||
let options = yield helpers.openTab(TEST_URI);
|
||||
yield helpers.openToolbar(options);
|
||||
|
||||
@ -31,12 +30,13 @@ function spawnTest() {
|
||||
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
setup: 'export html',
|
||||
setup: 'export html',
|
||||
skipIf: true,
|
||||
check: {
|
||||
input: 'export html',
|
||||
hints: '',
|
||||
hints: ' [destination]',
|
||||
markup: 'VVVVVVVVVVV',
|
||||
status: 'VALID'
|
||||
status: 'VALID',
|
||||
},
|
||||
exec: {
|
||||
output: ''
|
||||
@ -45,12 +45,32 @@ function spawnTest() {
|
||||
isnot(openURL.indexOf('<html lang="en">'), -1, "export html works: <html>");
|
||||
isnot(openURL.indexOf("<title>GCLI"), -1, "export html works: <title>");
|
||||
isnot(openURL.indexOf('<p id="someid">#'), -1, "export html works: <p>");
|
||||
|
||||
options.window.open = oldOpen;
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'export html stdout',
|
||||
check: {
|
||||
input: 'export html stdout',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVV',
|
||||
status: 'VALID',
|
||||
args: {
|
||||
destination: { value: "stdout" }
|
||||
},
|
||||
},
|
||||
exec: {
|
||||
output: [
|
||||
/<html lang="en">/,
|
||||
/<title>GCLI/,
|
||||
/<p id="someid">#/
|
||||
]
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
options.window.open = oldOpen;
|
||||
oldOpen = undefined;
|
||||
|
||||
// Test 'pagemod replace'
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
|
@ -1,23 +1,18 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
var gcli = devtools.require('gcli/index');
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/devtools/Console.jsm");
|
||||
/**
|
||||
* The commands and converters that are exported to GCLI
|
||||
*/
|
||||
exports.items = [];
|
||||
|
||||
/**
|
||||
* Utility to get access to the current breakpoint list.
|
||||
@ -56,7 +51,7 @@ function getAllBreakpoints(dbg) {
|
||||
/**
|
||||
* 'break' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break",
|
||||
description: gcli.lookup("breakDesc"),
|
||||
manual: gcli.lookup("breakManual")
|
||||
@ -65,7 +60,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'break list' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break list",
|
||||
description: gcli.lookup("breaklistDesc"),
|
||||
returnType: "breakpoints",
|
||||
@ -75,7 +70,8 @@ gcli.addCommand({
|
||||
}
|
||||
});
|
||||
|
||||
gcli.addConverter({
|
||||
exports.items.push({
|
||||
item: "converter",
|
||||
from: "breakpoints",
|
||||
to: "view",
|
||||
exec: function(breakpoints, context) {
|
||||
@ -129,7 +125,7 @@ var MAX_LABEL_LENGTH = 20;
|
||||
/**
|
||||
* 'break add' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break add",
|
||||
description: gcli.lookup("breakaddDesc"),
|
||||
manual: gcli.lookup("breakaddManual")
|
||||
@ -138,7 +134,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'break add line' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break add line",
|
||||
description: gcli.lookup("breakaddlineDesc"),
|
||||
params: [
|
||||
@ -185,7 +181,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'break del' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "break del",
|
||||
description: gcli.lookup("breakdelDesc"),
|
||||
params: [
|
||||
@ -231,7 +227,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg",
|
||||
description: gcli.lookup("dbgDesc"),
|
||||
manual: gcli.lookup("dbgManual")
|
||||
@ -240,7 +236,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg open' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg open",
|
||||
description: gcli.lookup("dbgOpen"),
|
||||
params: [],
|
||||
@ -253,7 +249,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg close' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg close",
|
||||
description: gcli.lookup("dbgClose"),
|
||||
params: [],
|
||||
@ -269,7 +265,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg interrupt' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg interrupt",
|
||||
description: gcli.lookup("dbgInterrupt"),
|
||||
params: [],
|
||||
@ -290,7 +286,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg continue' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg continue",
|
||||
description: gcli.lookup("dbgContinue"),
|
||||
params: [],
|
||||
@ -311,7 +307,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg step' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg step",
|
||||
description: gcli.lookup("dbgStepDesc"),
|
||||
manual: gcli.lookup("dbgStepManual")
|
||||
@ -320,7 +316,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg step over' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg step over",
|
||||
description: gcli.lookup("dbgStepOverDesc"),
|
||||
params: [],
|
||||
@ -341,7 +337,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg step in' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: 'dbg step in',
|
||||
description: gcli.lookup("dbgStepInDesc"),
|
||||
params: [],
|
||||
@ -362,7 +358,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg step over' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: 'dbg step out',
|
||||
description: gcli.lookup("dbgStepOutDesc"),
|
||||
params: [],
|
||||
@ -383,7 +379,7 @@ gcli.addCommand({
|
||||
/**
|
||||
* 'dbg list' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg list",
|
||||
description: gcli.lookup("dbgListSourcesDesc"),
|
||||
params: [],
|
||||
@ -429,7 +425,7 @@ gcli.addCommand({
|
||||
return gcli.lookup(cmd.l10nPrefix + id);
|
||||
};
|
||||
|
||||
gcli.addCommand({
|
||||
exports.items.push({
|
||||
name: "dbg " + cmd.name,
|
||||
description: lookup("Desc"),
|
||||
params: [
|
@ -6,6 +6,7 @@
|
||||
JS_MODULES_PATH = 'modules/devtools/debugger'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'debugger-commands.js',
|
||||
'panel.js'
|
||||
]
|
||||
|
||||
|
3
browser/devtools/eyedropper/crosshairs.css
Normal file
@ -0,0 +1,3 @@
|
||||
* {
|
||||
cursor: crosshair !important;
|
||||
}
|
671
browser/devtools/eyedropper/eyedropper.js
Normal file
@ -0,0 +1,671 @@
|
||||
/* 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/. */
|
||||
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
const {rgbToHsl} = require("devtools/css-color").colorUtils;
|
||||
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
loader.lazyGetter(this, "clipboardHelper", function() {
|
||||
return Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Ci.nsIClipboardHelper);
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "ssService", function() {
|
||||
return Cc["@mozilla.org/content/style-sheet-service;1"]
|
||||
.getService(Ci.nsIStyleSheetService);
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "ioService", function() {
|
||||
return Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "DOMUtils", function () {
|
||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "XULRuntime", function() {
|
||||
return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "l10n", () => Services.strings
|
||||
.createBundle("chrome://browser/locale/devtools/eyedropper.properties"));
|
||||
|
||||
const EYEDROPPER_URL = "chrome://browser/content/devtools/eyedropper.xul";
|
||||
const CROSSHAIRS_URL = "chrome://browser/content/devtools/eyedropper/crosshairs.css";
|
||||
const NOCURSOR_URL = "chrome://browser/content/devtools/eyedropper/nocursor.css";
|
||||
|
||||
const ZOOM_PREF = "devtools.eyedropper.zoom";
|
||||
const FORMAT_PREF = "devtools.defaultColorUnit";
|
||||
|
||||
const CANVAS_WIDTH = 96;
|
||||
const CANVAS_OFFSET = 3; // equals the border width of the canvas.
|
||||
const CLOSE_DELAY = 750;
|
||||
|
||||
const HEX_BOX_WIDTH = CANVAS_WIDTH + CANVAS_OFFSET * 2;
|
||||
const HSL_BOX_WIDTH = 158;
|
||||
|
||||
/**
|
||||
* Eyedropper widget. Once opened, shows zoomed area above current pixel and
|
||||
* displays the color value of the center pixel. Clicking on the window will
|
||||
* close the widget and fire a 'select' event. If 'copyOnSelect' is true, the color
|
||||
* will also be copied to the clipboard.
|
||||
*
|
||||
* let eyedropper = new Eyedropper(window);
|
||||
* eyedropper.open();
|
||||
*
|
||||
* eyedropper.once("select", (ev, color) => {
|
||||
* console.log(color); // "rgb(20, 50, 230)"
|
||||
* })
|
||||
*
|
||||
* @param {DOMWindow} chromeWindow
|
||||
* window to inspect
|
||||
* @param {object} opts
|
||||
* optional options object, with 'copyOnSelect'
|
||||
*/
|
||||
function Eyedropper(chromeWindow, opts = { copyOnSelect: true }) {
|
||||
this.copyOnSelect = opts.copyOnSelect;
|
||||
|
||||
this._onFirstMouseMove = this._onFirstMouseMove.bind(this);
|
||||
this._onMouseMove = this._onMouseMove.bind(this);
|
||||
this._onMouseDown = this._onMouseDown.bind(this);
|
||||
this._onKeyDown = this._onKeyDown.bind(this);
|
||||
this._onFrameLoaded = this._onFrameLoaded.bind(this);
|
||||
|
||||
this._chromeWindow = chromeWindow;
|
||||
this._chromeDocument = chromeWindow.document;
|
||||
|
||||
this._dragging = true;
|
||||
this.loaded = false;
|
||||
|
||||
this.format = Services.prefs.getCharPref(FORMAT_PREF); // color value format
|
||||
this.zoom = Services.prefs.getIntPref(ZOOM_PREF); // zoom level - integer
|
||||
|
||||
this._zoomArea = {
|
||||
x: 0, // the left coordinate of the center of the inspected region
|
||||
y: 0, // the top coordinate of the center of the inspected region
|
||||
width: CANVAS_WIDTH, // width of canvas to draw zoomed area onto
|
||||
height: CANVAS_WIDTH // height of canvas
|
||||
};
|
||||
EventEmitter.decorate(this);
|
||||
}
|
||||
|
||||
exports.Eyedropper = Eyedropper;
|
||||
|
||||
Eyedropper.prototype = {
|
||||
/**
|
||||
* Get the number of cells (blown-up pixels) per direction in the grid.
|
||||
*/
|
||||
get cellsWide() {
|
||||
// Canvas will render whole "pixels" (cells) only, and an even
|
||||
// number at that. Round up to the nearest even number of pixels.
|
||||
let cellsWide = Math.ceil(this._zoomArea.width / this.zoom);
|
||||
cellsWide += cellsWide % 2;
|
||||
|
||||
return cellsWide;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the size of each cell (blown-up pixel) in the grid.
|
||||
*/
|
||||
get cellSize() {
|
||||
return this._zoomArea.width / this.cellsWide;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get index of cell in the center of the grid.
|
||||
*/
|
||||
get centerCell() {
|
||||
return Math.floor(this.cellsWide / 2);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get color of center cell in the grid.
|
||||
*/
|
||||
get centerColor() {
|
||||
let x = y = (this.centerCell * this.cellSize) + (this.cellSize / 2);
|
||||
let rgb = this._ctx.getImageData(x, y, 1, 1).data;
|
||||
return rgb;
|
||||
},
|
||||
|
||||
/**
|
||||
* Start the eyedropper. Add listeners for a mouse move in the window to
|
||||
* show the eyedropper.
|
||||
*/
|
||||
open: function() {
|
||||
if (this.isOpen) {
|
||||
// the eyedropper is aready open, don't create another panel.
|
||||
return;
|
||||
}
|
||||
this.isOpen = true;
|
||||
|
||||
this._OS = XULRuntime.OS;
|
||||
|
||||
this._chromeDocument.addEventListener("mousemove", this._onFirstMouseMove);
|
||||
|
||||
this._showCrosshairs();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called on the first mouse move over the window. Opens the eyedropper
|
||||
* panel where the mouse is.
|
||||
*/
|
||||
_onFirstMouseMove: function(event) {
|
||||
this._chromeDocument.removeEventListener("mousemove", this._onFirstMouseMove);
|
||||
|
||||
this._panel = this._buildPanel();
|
||||
|
||||
let popupSet = this._chromeDocument.querySelector("#mainPopupSet");
|
||||
popupSet.appendChild(this._panel);
|
||||
|
||||
let { panelX, panelY } = this._getPanelCoordinates(event);
|
||||
this._panel.openPopupAtScreen(panelX, panelY);
|
||||
|
||||
this._setCoordinates(event);
|
||||
|
||||
this._addListeners();
|
||||
|
||||
// hide cursor as we'll be showing the panel over the mouse instead.
|
||||
this._hideCrosshairs();
|
||||
this._hideCursor();
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the current coordinates to inspect from where a mousemove originated.
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* Event for the mouse move.
|
||||
*/
|
||||
_setCoordinates: function(event) {
|
||||
let win = this._chromeWindow;
|
||||
|
||||
let x, y;
|
||||
if (this._OS == "Linux") {
|
||||
// event.clientX is off on Linux, so calculate it by hand
|
||||
let windowX = win.screenX + (win.outerWidth - win.innerWidth);
|
||||
x = event.screenX - windowX;
|
||||
|
||||
let windowY = win.screenY + (win.outerHeight - win.innerHeight);
|
||||
y = event.screenY - windowY;
|
||||
}
|
||||
else {
|
||||
x = event.clientX;
|
||||
y = event.clientY;
|
||||
}
|
||||
|
||||
// don't let it inspect outside the browser window
|
||||
x = Math.max(0, Math.min(x, win.outerWidth - 1));
|
||||
y = Math.max(0, Math.min(y, win.outerHeight - 1));
|
||||
|
||||
this._zoomArea.x = x;
|
||||
this._zoomArea.y = y;
|
||||
},
|
||||
|
||||
/**
|
||||
* Build and add a new eyedropper panel to the window.
|
||||
*
|
||||
* @return {Panel}
|
||||
* The XUL panel holding the eyedropper UI.
|
||||
*/
|
||||
_buildPanel: function() {
|
||||
let panel = this._chromeDocument.createElement("panel");
|
||||
panel.setAttribute("noautofocus", true);
|
||||
panel.setAttribute("noautohide", true);
|
||||
panel.setAttribute("level", "floating");
|
||||
panel.setAttribute("class", "devtools-eyedropper-panel");
|
||||
|
||||
let iframe = this._iframe = this._chromeDocument.createElement("iframe");
|
||||
iframe.addEventListener("load", this._onFrameLoaded, true);
|
||||
iframe.setAttribute("flex", "1");
|
||||
iframe.setAttribute("transparent", "transparent");
|
||||
iframe.setAttribute("allowTransparency", true);
|
||||
iframe.setAttribute("class", "devtools-eyedropper-iframe");
|
||||
iframe.setAttribute("src", EYEDROPPER_URL);
|
||||
iframe.setAttribute("width", CANVAS_WIDTH);
|
||||
iframe.setAttribute("height", CANVAS_WIDTH);
|
||||
|
||||
panel.appendChild(iframe);
|
||||
|
||||
return panel;
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for the panel's iframe's load event. Emits
|
||||
* a "load" event from this eyedropper object.
|
||||
*/
|
||||
_onFrameLoaded: function() {
|
||||
this._iframe.removeEventListener("load", this._onFrameLoaded, true);
|
||||
|
||||
this._iframeDocument = this._iframe.contentDocument;
|
||||
this._colorPreview = this._iframeDocument.querySelector("#color-preview");
|
||||
this._colorValue = this._iframeDocument.querySelector("#color-value");
|
||||
|
||||
// value box will be too long for hex values and too short for hsl
|
||||
let valueBox = this._iframeDocument.querySelector("#color-value-box");
|
||||
if (this.format == "hex") {
|
||||
valueBox.style.width = HEX_BOX_WIDTH + "px";
|
||||
}
|
||||
else if (this.format == "hsl") {
|
||||
valueBox.style.width = HSL_BOX_WIDTH + "px";
|
||||
}
|
||||
|
||||
this._canvas = this._iframeDocument.querySelector("#canvas");
|
||||
this._ctx = this._canvas.getContext("2d");
|
||||
|
||||
// so we preserve the clear pixel boundaries
|
||||
this._ctx.mozImageSmoothingEnabled = false;
|
||||
|
||||
this._drawWindow();
|
||||
|
||||
this._addPanelListeners();
|
||||
this._iframe.focus();
|
||||
|
||||
this.loaded = true;
|
||||
this.emit("load");
|
||||
},
|
||||
|
||||
/**
|
||||
* Add key listeners to the panel.
|
||||
*/
|
||||
_addPanelListeners: function() {
|
||||
this._iframeDocument.addEventListener("keydown", this._onKeyDown);
|
||||
|
||||
let closeCmd = this._iframeDocument.getElementById("eyedropper-cmd-close");
|
||||
closeCmd.addEventListener("command", this.destroy.bind(this), true);
|
||||
|
||||
let copyCmd = this._iframeDocument.getElementById("eyedropper-cmd-copy");
|
||||
copyCmd.addEventListener("command", this.selectColor.bind(this), true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove listeners from the panel.
|
||||
*/
|
||||
_removePanelListeners: function() {
|
||||
this._iframeDocument.removeEventListener("keydown", this._onKeyDown);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add mouse event listeners to the document we're inspecting.
|
||||
*/
|
||||
_addListeners: function() {
|
||||
this._chromeDocument.addEventListener("mousemove", this._onMouseMove);
|
||||
this._chromeDocument.addEventListener("mousedown", this._onMouseDown);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove mouse event listeners from the document we're inspecting.
|
||||
*/
|
||||
_removeListeners: function() {
|
||||
this._chromeDocument.removeEventListener("mousemove", this._onFirstMouseMove);
|
||||
this._chromeDocument.removeEventListener("mousemove", this._onMouseMove);
|
||||
this._chromeDocument.removeEventListener("mousedown", this._onMouseDown);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the cursor.
|
||||
*/
|
||||
_hideCursor: function() {
|
||||
registerStyleSheet(NOCURSOR_URL);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset the cursor back to default.
|
||||
*/
|
||||
_resetCursor: function() {
|
||||
unregisterStyleSheet(NOCURSOR_URL);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a crosshairs as the mouse cursor
|
||||
*/
|
||||
_showCrosshairs: function() {
|
||||
registerStyleSheet(CROSSHAIRS_URL);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset cursor.
|
||||
*/
|
||||
_hideCrosshairs: function() {
|
||||
unregisterStyleSheet(CROSSHAIRS_URL);
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for a mouse move over the page we're inspecting.
|
||||
* Preview the area under the cursor, and move panel to be under the cursor.
|
||||
*
|
||||
* @param {DOMEvent} event
|
||||
* MouseEvent for the mouse moving
|
||||
*/
|
||||
_onMouseMove: function(event) {
|
||||
if (!this._dragging || !this._panel || !this._canvas) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._setCoordinates(event);
|
||||
this._drawWindow();
|
||||
|
||||
let { panelX, panelY } = this._getPanelCoordinates(event);
|
||||
this._movePanel(panelX, panelY);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get coordinates of where the eyedropper panel should go based on
|
||||
* the current coordinates of the mouse cursor.
|
||||
*
|
||||
* @param {MouseEvent} event
|
||||
* object with properties 'screenX' and 'screenY'
|
||||
*
|
||||
* @return {object}
|
||||
* object with properties 'panelX', 'panelY'
|
||||
*/
|
||||
_getPanelCoordinates: function({screenX, screenY}) {
|
||||
let win = this._chromeWindow;
|
||||
let offset = CANVAS_WIDTH / 2 + CANVAS_OFFSET;
|
||||
|
||||
let panelX = screenX - offset;
|
||||
let windowX = win.screenX + (win.outerWidth - win.innerWidth);
|
||||
let maxX = win.screenX + win.outerWidth - offset - 1;
|
||||
|
||||
let panelY = screenY - offset;
|
||||
let windowY = win.screenY + (win.outerHeight - win.innerHeight);
|
||||
let maxY = win.screenY + win.outerHeight - offset - 1;
|
||||
|
||||
// don't let the panel move outside the browser window
|
||||
panelX = Math.max(windowX - offset, Math.min(panelX, maxX));
|
||||
panelY = Math.max(windowY - offset, Math.min(panelY, maxY));
|
||||
|
||||
return { panelX: panelX, panelY: panelY };
|
||||
},
|
||||
|
||||
/**
|
||||
* Move the eyedropper panel to the given coordinates.
|
||||
*
|
||||
* @param {number} screenX
|
||||
* left coordinate on the screen
|
||||
* @param {number} screenY
|
||||
* top coordinate
|
||||
*/
|
||||
_movePanel: function(screenX, screenY) {
|
||||
this._panelX = screenX;
|
||||
this._panelY = screenY;
|
||||
|
||||
this._panel.moveTo(screenX, screenY);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the mouse down event on the inspected page. This means a
|
||||
* click, so we'll select the color that's currently hovered.
|
||||
*
|
||||
* @param {Event} event
|
||||
* DOM MouseEvent object
|
||||
*/
|
||||
_onMouseDown: function(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.selectColor();
|
||||
},
|
||||
|
||||
/**
|
||||
* Select the current color that's being previewed. Fire a
|
||||
* "select" event with the color as an rgb string.
|
||||
*/
|
||||
selectColor: function() {
|
||||
if (this._isSelecting) {
|
||||
return;
|
||||
}
|
||||
this._isSelecting = true;
|
||||
this._dragging = false;
|
||||
|
||||
this.emit("select", this._colorValue.value);
|
||||
|
||||
if (this.copyOnSelect) {
|
||||
this.copyColor(this.destroy.bind(this));
|
||||
}
|
||||
else {
|
||||
this.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the currently inspected color to the clipboard.
|
||||
*
|
||||
* @param {Function} callback
|
||||
* Callback to be called when the color is in the clipboard.
|
||||
*/
|
||||
copyColor: function(callback) {
|
||||
Services.appShell.hiddenDOMWindow.clearTimeout(this._copyTimeout);
|
||||
|
||||
let color = this._colorValue.value;
|
||||
clipboardHelper.copyString(color);
|
||||
|
||||
this._colorValue.classList.add("highlight");
|
||||
this._colorValue.value = "✓ " + l10n.GetStringFromName("colorValue.copied");
|
||||
|
||||
this._copyTimeout = Services.appShell.hiddenDOMWindow.setTimeout(() => {
|
||||
this._colorValue.classList.remove("highlight");
|
||||
this._colorValue.value = color;
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}, CLOSE_DELAY);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for the keydown event on the panel. Either copy the color
|
||||
* or move the panel in a direction depending on the key pressed.
|
||||
*
|
||||
* @param {Event} event
|
||||
* DOM KeyboardEvent object
|
||||
*/
|
||||
_onKeyDown: function(event) {
|
||||
if (event.metaKey && event.keyCode === event.DOM_VK_C) {
|
||||
this.copyColor();
|
||||
return;
|
||||
}
|
||||
|
||||
let offsetX = 0;
|
||||
let offsetY = 0;
|
||||
let modifier = 1;
|
||||
|
||||
if (event.keyCode === event.DOM_VK_LEFT) {
|
||||
offsetX = -1;
|
||||
}
|
||||
if (event.keyCode === event.DOM_VK_RIGHT) {
|
||||
offsetX = 1;
|
||||
}
|
||||
if (event.keyCode === event.DOM_VK_UP) {
|
||||
offsetY = -1;
|
||||
}
|
||||
if (event.keyCode === event.DOM_VK_DOWN) {
|
||||
offsetY = 1;
|
||||
}
|
||||
if (event.shiftKey) {
|
||||
modifier = 10;
|
||||
}
|
||||
|
||||
offsetY *= modifier;
|
||||
offsetX *= modifier;
|
||||
|
||||
if (offsetX !== 0 || offsetY !== 0) {
|
||||
this._zoomArea.x += offsetX;
|
||||
this._zoomArea.y += offsetY;
|
||||
|
||||
this._drawWindow();
|
||||
|
||||
this._movePanel(this._panelX + offsetX, this._panelY + offsetY);
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the inspected area onto the canvas using the zoom level.
|
||||
*/
|
||||
_drawWindow: function() {
|
||||
let { width, height, x, y } = this._zoomArea;
|
||||
|
||||
let zoomedWidth = width / this.zoom;
|
||||
let zoomedHeight = height / this.zoom;
|
||||
|
||||
let drawX = x - (zoomedWidth / 2);
|
||||
let drawY = y - (zoomedHeight / 2);
|
||||
|
||||
// draw the portion of the window we're inspecting
|
||||
this._ctx.drawWindow(this._chromeWindow, drawX, drawY, zoomedWidth,
|
||||
zoomedHeight, "white");
|
||||
|
||||
// now scale it
|
||||
let sx = 0;
|
||||
let sy = 0;
|
||||
let sw = zoomedWidth;
|
||||
let sh = zoomedHeight;
|
||||
let dx = 0;
|
||||
let dy = 0;
|
||||
let dw = width;
|
||||
let dh = height;
|
||||
|
||||
this._ctx.drawImage(this._canvas, sx, sy, sw, sh, dx, dy, dw, dh);
|
||||
|
||||
let rgb = this.centerColor;
|
||||
this._colorPreview.style.backgroundColor = toColorString(rgb, "rgb");
|
||||
this._colorValue.value = toColorString(rgb, this.format);
|
||||
|
||||
if (this.zoom > 2) {
|
||||
// grid at 2x is too busy
|
||||
this._drawGrid();
|
||||
}
|
||||
this._drawCrosshair();
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw a grid on the canvas representing pixel boundaries.
|
||||
*/
|
||||
_drawGrid: function() {
|
||||
let { width, height } = this._zoomArea;
|
||||
|
||||
this._ctx.lineWidth = 1;
|
||||
this._ctx.strokeStyle = "rgba(143, 143, 143, 0.2)";
|
||||
|
||||
for (let i = 0; i < width; i += this.cellSize) {
|
||||
this._ctx.beginPath();
|
||||
this._ctx.moveTo(i - .5, 0);
|
||||
this._ctx.lineTo(i - .5, height);
|
||||
this._ctx.stroke();
|
||||
|
||||
this._ctx.beginPath();
|
||||
this._ctx.moveTo(0, i - .5);
|
||||
this._ctx.lineTo(width, i - .5);
|
||||
this._ctx.stroke();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw a box on the canvas to highlight the center cell.
|
||||
*/
|
||||
_drawCrosshair: function() {
|
||||
let x = y = this.centerCell * this.cellSize;
|
||||
|
||||
this._ctx.lineWidth = 1;
|
||||
this._ctx.lineJoin = 'miter';
|
||||
this._ctx.strokeStyle = "rgba(0, 0, 0, 1)";
|
||||
this._ctx.strokeRect(x - 1.5, y - 1.5, this.cellSize + 2, this.cellSize + 2);
|
||||
|
||||
this._ctx.strokeStyle = "rgba(255, 255, 255, 1)";
|
||||
this._ctx.strokeRect(x - 0.5, y - 0.5, this.cellSize, this.cellSize);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the eyedropper and clean up. Emits a "destroy" event.
|
||||
*/
|
||||
destroy: function() {
|
||||
this._resetCursor();
|
||||
this._hideCrosshairs();
|
||||
|
||||
if (this._panel) {
|
||||
this._panel.hidePopup();
|
||||
this._panel.remove();
|
||||
this._panel = null;
|
||||
}
|
||||
this._removePanelListeners();
|
||||
this._removeListeners();
|
||||
|
||||
this.isOpen = false;
|
||||
this._isSelecting = false;
|
||||
|
||||
this.emit("destroy");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a user style sheet that applies to all documents.
|
||||
*/
|
||||
function registerStyleSheet(url) {
|
||||
var uri = ioService.newURI(url, null, null);
|
||||
if (!ssService.sheetRegistered(uri, ssService.AGENT_SHEET)) {
|
||||
ssService.loadAndRegisterSheet(uri, ssService.AGENT_SHEET);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a user style sheet.
|
||||
*/
|
||||
function unregisterStyleSheet(url) {
|
||||
var uri = ioService.newURI(url, null, null);
|
||||
if (ssService.sheetRegistered(uri, ssService.AGENT_SHEET)) {
|
||||
ssService.unregisterSheet(uri, ssService.AGENT_SHEET);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a formatted CSS color string from a color value.
|
||||
*
|
||||
* @param {array} rgb
|
||||
* Rgb values of a color to format
|
||||
* @param {string} format
|
||||
* Format of string. One of "hex", "rgb", "hsl", "name"
|
||||
*
|
||||
* @return {string}
|
||||
* Formatted color value, e.g. "#FFF" or "hsl(20, 10%, 10%)"
|
||||
*/
|
||||
function toColorString(rgb, format) {
|
||||
let [r,g,b] = rgb;
|
||||
|
||||
switch(format) {
|
||||
case "hex":
|
||||
return hexString(rgb);
|
||||
case "rgb":
|
||||
return "rgb(" + r + ", " + g + ", " + b + ")";
|
||||
case "hsl":
|
||||
let [h,s,l] = rgbToHsl(rgb);
|
||||
return "hsl(" + h + ", " + s + "%, " + l + "%)";
|
||||
case "name":
|
||||
let str;
|
||||
try {
|
||||
str = DOMUtils.rgbToColorName(r, g, b);
|
||||
} catch(e) {
|
||||
str = hexString(rgb);
|
||||
}
|
||||
return str;
|
||||
default:
|
||||
return hexString(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a hex-formatted color string from rgb values.
|
||||
*
|
||||
* @param {array} rgb
|
||||
* Rgb values of color to stringify
|
||||
*
|
||||
* @return {string}
|
||||
* Hex formatted string for color, e.g. "#FFEE00"
|
||||
*/
|
||||
function hexString([r,g,b]) {
|
||||
let val = (1 << 24) + (r << 16) + (g << 8) + (b << 0);
|
||||
return "#" + val.toString(16).substr(-6).toUpperCase();
|
||||
}
|
41
browser/devtools/eyedropper/eyedropper.xul
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE window []>
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/eyedropper.css" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<commandset id="eyedropper-commandset">
|
||||
<command id="eyedropper-cmd-close"
|
||||
oncommand="void(0);"/>
|
||||
<command id="eyedropper-cmd-copy"
|
||||
oncommand="void(0);"/>
|
||||
</commandset>
|
||||
|
||||
<keyset id="eyedropper-keyset">
|
||||
<key id="eyedropper-key-escape"
|
||||
keycode="VK_ESCAPE"
|
||||
command="eyedropper-cmd-close"/>
|
||||
<key id="eyedropper-key-enter"
|
||||
keycode="VK_RETURN"
|
||||
command="eyedropper-cmd-copy"/>
|
||||
</keyset>
|
||||
|
||||
<box id="canvas-overflow">
|
||||
<canvas id="canvas" xmlns="http://www.w3.org/1999/xhtml" width="96" height="96">
|
||||
</canvas>
|
||||
</box>
|
||||
<hbox id="color-value-container">
|
||||
<hbox id="color-value-box">
|
||||
<box id="color-preview">
|
||||
</box>
|
||||
<label id="color-value" class="devtools-monospace">
|
||||
</label>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</window>
|
13
browser/devtools/eyedropper/moz.build
Normal file
@ -0,0 +1,13 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/eyedropper'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'eyedropper.js'
|
||||
]
|
3
browser/devtools/eyedropper/nocursor.css
Normal file
@ -0,0 +1,3 @@
|
||||
* {
|
||||
cursor: none !important;
|
||||
}
|
8
browser/devtools/eyedropper/test/browser.ini
Normal file
@ -0,0 +1,8 @@
|
||||
[DEFAULT]
|
||||
skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
|
||||
support-files =
|
||||
color-block.html
|
||||
head.js
|
||||
|
||||
[browser_eyedropper_basic.js]
|
||||
skip-if = os == "win" && debug # bug 963492
|
75
browser/devtools/eyedropper/test/browser_eyedropper_basic.js
Normal file
@ -0,0 +1,75 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TESTCASE_URI = TEST_BASE + "color-block.html";
|
||||
const DIV_COLOR = "#0000FF";
|
||||
|
||||
/**
|
||||
* Test basic eyedropper widget functionality:
|
||||
* - Opening eyedropper and pressing ESC closes the eyedropper
|
||||
* - Opening eyedropper and clicking copies the center color
|
||||
*/
|
||||
function test() {
|
||||
addTab(TESTCASE_URI).then(testEscape);
|
||||
}
|
||||
|
||||
function testEscape() {
|
||||
let dropper = new Eyedropper(window);
|
||||
|
||||
dropper.once("destroy", (event) => {
|
||||
ok(true, "escape closed the eyedropper");
|
||||
|
||||
// now test selecting a color
|
||||
testSelect();
|
||||
});
|
||||
|
||||
inspectPage(dropper, false).then(pressESC);
|
||||
}
|
||||
|
||||
function testSelect() {
|
||||
let dropper = new Eyedropper(window);
|
||||
|
||||
dropper.once("select", (event, color) => {
|
||||
is(color, DIV_COLOR, "correct color selected");
|
||||
});
|
||||
|
||||
// wait for DIV_COLOR to be copied to the clipboard then finish the test.
|
||||
waitForClipboard(DIV_COLOR, () => {
|
||||
inspectPage(dropper); // setup: inspect the page
|
||||
}, finish, finish);
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
|
||||
function inspectPage(dropper, click=true) {
|
||||
dropper.open();
|
||||
|
||||
let target = content.document.getElementById("test");
|
||||
let win = content.window;
|
||||
|
||||
EventUtils.synthesizeMouse(target, 20, 20, { type: "mousemove" }, win);
|
||||
|
||||
return dropperLoaded(dropper).then(() => {
|
||||
EventUtils.synthesizeMouse(target, 30, 30, { type: "mousemove" }, win);
|
||||
|
||||
if (click) {
|
||||
EventUtils.synthesizeMouse(target, 30, 30, {}, win);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function pressESC() {
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", { });
|
||||
}
|
||||
|
||||
function dropperLoaded(dropper) {
|
||||
if (dropper.loaded) {
|
||||
return promise.resolve();
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
dropper.once("load", deferred.resolve);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
22
browser/devtools/eyedropper/test/color-block.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>basic eyedropper test case</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: #f99;
|
||||
}
|
||||
|
||||
#test {
|
||||
margin: 100px;
|
||||
background-color: blue;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="test">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
37
browser/devtools/eyedropper/test/head.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TEST_BASE = "chrome://mochitests/content/browser/browser/devtools/eyedropper/test/";
|
||||
const TEST_HOST = 'mochi.test:8888';
|
||||
|
||||
const promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
|
||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
const { Eyedropper } = require("devtools/eyedropper/eyedropper");
|
||||
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(cleanup);
|
||||
|
||||
function addTab(uri) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let tab = gBrowser.addTab();
|
||||
|
||||
gBrowser.selectedTab = tab;
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
deferred.resolve(tab);
|
||||
}, true);
|
||||
|
||||
content.location = uri;
|
||||
|
||||
return deferred.promise;
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
||||
BROWSER_CHROME_MANIFESTS += ['browser.ini']
|
@ -313,13 +313,18 @@ DevTools.prototype = {
|
||||
|
||||
/**
|
||||
* Close the toolbox for a given target
|
||||
*
|
||||
* @return promise
|
||||
* This promise will resolve to false if no toolbox was found
|
||||
* associated to the target. true, if the toolbox was successfuly
|
||||
* closed.
|
||||
*/
|
||||
closeToolbox: function DT_closeToolbox(target) {
|
||||
let toolbox = this._toolboxes.get(target);
|
||||
if (toolbox == null) {
|
||||
return promise.reject(null);
|
||||
return promise.resolve(false);
|
||||
}
|
||||
return toolbox.destroy();
|
||||
return toolbox.destroy().then(() => true);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -41,10 +41,6 @@ loader.lazyGetter(this, "toolboxStrings", () => {
|
||||
};
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "Requisition", () => {
|
||||
return require("gcli/cli").Requisition;
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "Selection", () => require("devtools/framework/selection").Selection);
|
||||
loader.lazyGetter(this, "InspectorFront", () => require("devtools/server/actors/inspector").InspectorFront);
|
||||
|
||||
@ -539,7 +535,7 @@ Toolbox.prototype = {
|
||||
|
||||
let spec = CommandUtils.getCommandbarSpec("devtools.toolbox.toolbarSpec");
|
||||
let environment = CommandUtils.createEnvironment(this, '_target');
|
||||
this._requisition = new Requisition({ environment: environment });
|
||||
this._requisition = CommandUtils.createRequisition(environment);
|
||||
let buttons = CommandUtils.createButtons(spec, this._target,
|
||||
this.doc, this._requisition);
|
||||
let container = this.doc.getElementById("toolbox-buttons");
|
||||
|
@ -1,38 +0,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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const gcli = devtools.require('gcli/index');
|
||||
|
||||
/**
|
||||
* 'inspect' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "inspect",
|
||||
description: gcli.lookup("inspectDesc"),
|
||||
manual: gcli.lookup("inspectManual"),
|
||||
params: [
|
||||
{
|
||||
name: "selector",
|
||||
type: "node",
|
||||
description: gcli.lookup("inspectNodeDesc"),
|
||||
manual: gcli.lookup("inspectNodeManual")
|
||||
}
|
||||
],
|
||||
exec: function Command_inspect(args, context) {
|
||||
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
|
||||
let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
return gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
|
||||
toolbox.getCurrentPanel().selection.setNode(args.selector, "gcli");
|
||||
}.bind(this));
|
||||
}
|
||||
});
|
@ -1,9 +0,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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools/
|
||||
$(NSINSTALL) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools/inspector
|
29
browser/devtools/inspector/inspector-commands.js
Normal file
@ -0,0 +1,29 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
exports.items = [{
|
||||
name: "inspect",
|
||||
description: gcli.lookup("inspectDesc"),
|
||||
manual: gcli.lookup("inspectManual"),
|
||||
params: [
|
||||
{
|
||||
name: "selector",
|
||||
type: "node",
|
||||
description: gcli.lookup("inspectNodeDesc"),
|
||||
manual: gcli.lookup("inspectNodeManual")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let target = context.environment.target;
|
||||
let gDevTools = require("resource:///modules/devtools/gDevTools.jsm").gDevTools;
|
||||
|
||||
return gDevTools.showToolbox(target, "inspector").then(toolbox => {
|
||||
toolbox.getCurrentPanel().selection.setNode(args.selector, "gcli");
|
||||
});
|
||||
}
|
||||
}];
|
@ -1,7 +1,14 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/inspector'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'breadcrumbs.js',
|
||||
'inspector-commands.js',
|
||||
'inspector-panel.js',
|
||||
'selector-search.js'
|
||||
]
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
@ -15,6 +15,7 @@ browser.jar:
|
||||
content/browser/devtools/webconsole.xul (webconsole/webconsole.xul)
|
||||
* content/browser/devtools/scratchpad.xul (scratchpad/scratchpad.xul)
|
||||
content/browser/devtools/scratchpad.js (scratchpad/scratchpad.js)
|
||||
content/browser/devtools/scratchpad-commands.js (scratchpad/scratchpad-commands.js)
|
||||
content/browser/devtools/splitview.css (shared/splitview.css)
|
||||
content/browser/devtools/theme-switching.js (shared/theme-switching.js)
|
||||
content/browser/devtools/styleeditor.xul (styleeditor/styleeditor.xul)
|
||||
@ -79,9 +80,11 @@ browser.jar:
|
||||
content/browser/devtools/profiler/cleopatra/images/noise.png (profiler/cleopatra/images/noise.png)
|
||||
content/browser/devtools/profiler/cleopatra/images/throbber.svg (profiler/cleopatra/images/throbber.svg)
|
||||
content/browser/devtools/profiler/cleopatra/images/treetwisty.svg (profiler/cleopatra/images/treetwisty.svg)
|
||||
content/browser/devtools/responsivedesign/resize-commands.js (responsivedesign/resize-commands.js)
|
||||
content/browser/devtools/commandline.css (commandline/commandline.css)
|
||||
content/browser/devtools/commandlineoutput.xhtml (commandline/commandlineoutput.xhtml)
|
||||
content/browser/devtools/commandlinetooltip.xhtml (commandline/commandlinetooltip.xhtml)
|
||||
content/browser/devtools/commandline/commands-index.js (commandline/commands-index.js)
|
||||
content/browser/devtools/framework/toolbox-window.xul (framework/toolbox-window.xul)
|
||||
content/browser/devtools/framework/toolbox-options.xul (framework/toolbox-options.xul)
|
||||
content/browser/devtools/framework/toolbox-options.js (framework/toolbox-options.js)
|
||||
@ -108,3 +111,7 @@ browser.jar:
|
||||
content/browser/devtools/app-manager/manifest-editor.js (app-manager/content/manifest-editor.js)
|
||||
content/browser/devtools/spectrum-frame.xhtml (shared/widgets/spectrum-frame.xhtml)
|
||||
content/browser/devtools/spectrum.css (shared/widgets/spectrum.css)
|
||||
content/browser/devtools/eyedropper.xul (eyedropper/eyedropper.xul)
|
||||
content/browser/devtools/eyedropper/crosshairs.css (eyedropper/crosshairs.css)
|
||||
content/browser/devtools/eyedropper/nocursor.css (eyedropper/nocursor.css)
|
||||
|
||||
|
@ -90,6 +90,7 @@ Tools.webConsole = {
|
||||
menuLabel: l10n("MenuWebconsole.label", webConsoleStrings),
|
||||
tooltip: l10n("ToolboxWebconsole.tooltip", webConsoleStrings),
|
||||
inMenu: true,
|
||||
commands: "devtools/webconsole/console-commands",
|
||||
|
||||
preventClosingOnKey: true,
|
||||
onkey: function(panel, toolbox) {
|
||||
@ -120,6 +121,10 @@ Tools.inspector = {
|
||||
label: l10n("inspector.label", inspectorStrings),
|
||||
tooltip: l10n("inspector.tooltip", inspectorStrings),
|
||||
inMenu: true,
|
||||
commands: [
|
||||
"devtools/resize-commands",
|
||||
"devtools/inspector/inspector-commands",
|
||||
],
|
||||
|
||||
preventClosingOnKey: true,
|
||||
onkey: function(panel) {
|
||||
@ -149,6 +154,7 @@ Tools.jsdebugger = {
|
||||
label: l10n("ToolboxDebugger.label", debuggerStrings),
|
||||
tooltip: l10n("ToolboxDebugger.tooltip", debuggerStrings),
|
||||
inMenu: true,
|
||||
commands: "devtools/debugger/debugger-commands",
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return true;
|
||||
@ -172,6 +178,7 @@ Tools.styleEditor = {
|
||||
label: l10n("ToolboxStyleEditor.label", styleEditorStrings),
|
||||
tooltip: l10n("ToolboxStyleEditor.tooltip2", styleEditorStrings),
|
||||
inMenu: true,
|
||||
commands: "devtools/styleeditor/styleeditor-commands",
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return !target.isAddon;
|
||||
@ -236,6 +243,7 @@ Tools.jsprofiler = {
|
||||
label: l10n("profiler.label", profilerStrings),
|
||||
tooltip: l10n("profiler.tooltip2", profilerStrings),
|
||||
inMenu: true,
|
||||
commands: "devtools/profiler/commands",
|
||||
|
||||
isTargetSupported: function (target) {
|
||||
return !target.isAddon;
|
||||
@ -282,6 +290,7 @@ Tools.scratchpad = {
|
||||
label: l10n("scratchpad.label", scratchpadStrings),
|
||||
tooltip: l10n("scratchpad.tooltip", scratchpadStrings),
|
||||
inMenu: false,
|
||||
commands: "devtools/scratchpad/scratchpad-commands",
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return !target.isAddon && target.isRemote;
|
||||
|
@ -9,6 +9,7 @@ DIRS += [
|
||||
'canvasdebugger',
|
||||
'commandline',
|
||||
'debugger',
|
||||
'eyedropper',
|
||||
'fontinspector',
|
||||
'framework',
|
||||
'inspector',
|
||||
|
@ -2,147 +2,115 @@
|
||||
* 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/. */
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
module.exports = [];
|
||||
"use strict";
|
||||
|
||||
var gcli = require('gcli/index');
|
||||
const gcli = require('gcli/index');
|
||||
|
||||
loader.lazyGetter(this, "gDevTools",
|
||||
() => Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools);
|
||||
|
||||
var { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
/*
|
||||
* 'profiler' command. Doesn't do anything.
|
||||
*/
|
||||
gcli.addCommand({
|
||||
module.exports.items = [
|
||||
{
|
||||
name: "profiler",
|
||||
description: gcli.lookup("profilerDesc"),
|
||||
manual: gcli.lookup("profilerManual")
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler open' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler open",
|
||||
description: gcli.lookup("profilerOpenDesc"),
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(function () null);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler close' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler close",
|
||||
description: gcli.lookup("profilerCloseDesc"),
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
if (!getPanel(context, "jsprofiler"))
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
let panel = (toolbox == null) ? null : toolbox.getPanel(id);
|
||||
if (panel == null)
|
||||
return;
|
||||
|
||||
return gDevTools.closeToolbox(context.environment.target)
|
||||
.then(function () null);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler start' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler start",
|
||||
description: gcli.lookup("profilerStartDesc"),
|
||||
returnType: "string",
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
function start() {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let target = context.environment.target
|
||||
return gDevTools.showToolbox(target, "jsprofiler").then(toolbox => {
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
|
||||
if (panel.recordingProfile)
|
||||
throw gcli.lookup("profilerAlreadyStarted2");
|
||||
|
||||
panel.toggleRecording();
|
||||
return gcli.lookup("profilerStarted2");
|
||||
}
|
||||
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(start);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler stop' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler stop",
|
||||
description: gcli.lookup("profilerStopDesc"),
|
||||
returnType: "string",
|
||||
params: [],
|
||||
|
||||
exec: function (args, context) {
|
||||
function stop() {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let target = context.environment.target
|
||||
return gDevTools.showToolbox(target, "jsprofiler").then(toolbox => {
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
|
||||
if (!panel.recordingProfile)
|
||||
throw gcli.lookup("profilerNotStarted3");
|
||||
|
||||
panel.toggleRecording();
|
||||
return gcli.lookup("profilerStopped");
|
||||
}
|
||||
|
||||
return gDevTools.showToolbox(context.environment.target, "jsprofiler")
|
||||
.then(stop);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler list' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "profiler list",
|
||||
description: gcli.lookup("profilerListDesc"),
|
||||
returnType: "dom",
|
||||
params: [],
|
||||
|
||||
returnType: "profileList",
|
||||
exec: function (args, context) {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
let panel = (toolbox == null) ? null : toolbox.getPanel("jsprofiler");
|
||||
|
||||
if (!panel) {
|
||||
if (panel == null) {
|
||||
throw gcli.lookup("profilerNotReady");
|
||||
}
|
||||
|
||||
let doc = panel.document;
|
||||
let div = createXHTMLElement(doc, "div");
|
||||
let ol = createXHTMLElement(doc, "ol");
|
||||
|
||||
for ([ uid, profile] of panel.profiles) {
|
||||
let li = createXHTMLElement(doc, "li");
|
||||
li.textContent = profile.name;
|
||||
if (profile.isStarted) {
|
||||
li.textContent += " *";
|
||||
}
|
||||
ol.appendChild(li);
|
||||
let profileList = [];
|
||||
for ([ uid, profile ] of panel.profiles) {
|
||||
profileList.push({ name: profile.name, started: profile.isStarted });
|
||||
}
|
||||
|
||||
div.appendChild(ol);
|
||||
return div;
|
||||
return profileList;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 'profiler show' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
item: "converter",
|
||||
from: "profileList",
|
||||
to: "view",
|
||||
exec: function(profileList, context) {
|
||||
return {
|
||||
html: "<div>" +
|
||||
" <ol>" +
|
||||
" <li forEach='profile of ${profiles}'>${profile.name}</li>" +
|
||||
" ${profile.name} ${profile.started ? '*' : ''}" +
|
||||
" </li>" +
|
||||
" </ol>" +
|
||||
"</div>",
|
||||
data: { profiles: profileList.profiles },
|
||||
options: { allowEval: true }
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "profiler show",
|
||||
description: gcli.lookup("profilerShowDesc"),
|
||||
|
||||
params: [
|
||||
{
|
||||
name: "name",
|
||||
@ -152,7 +120,8 @@ gcli.addCommand({
|
||||
],
|
||||
|
||||
exec: function (args, context) {
|
||||
let panel = getPanel(context, "jsprofiler");
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
let panel = (toolbox == null) ? null : toolbox.getPanel(id);
|
||||
|
||||
if (!panel) {
|
||||
throw gcli.lookup("profilerNotReady");
|
||||
@ -165,17 +134,4 @@ gcli.addCommand({
|
||||
|
||||
panel.sidebar.selectedItem = panel.sidebar.getItemByProfile(profile);
|
||||
}
|
||||
});
|
||||
|
||||
function getPanel(context, id) {
|
||||
if (context == null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
return toolbox == null ? undefined : toolbox.getPanel(id);
|
||||
}
|
||||
|
||||
function createXHTMLElement(document, tagname) {
|
||||
return document.createElementNS("http://www.w3.org/1999/xhtml", tagname);
|
||||
}
|
||||
}];
|
||||
|
@ -1,94 +0,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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle("chrome://branding/locale/brand.properties").
|
||||
GetStringFromName("brandShortName");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const gcli = devtools.require("gcli/index");
|
||||
|
||||
/* Responsive Mode commands */
|
||||
gcli.addCommand({
|
||||
name: 'resize',
|
||||
description: gcli.lookup('resizeModeDesc')
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize on',
|
||||
description: gcli.lookup('resizeModeOnDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize off',
|
||||
description: gcli.lookup('resizeModeOffDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize toggle',
|
||||
buttonId: "command-button-responsive",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
tooltipText: gcli.lookup("resizeModeToggleTooltip"),
|
||||
description: gcli.lookup('resizeModeToggleDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
state: {
|
||||
isChecked: function(aTarget) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
return mgr.isActiveForTab(aTarget.tab);
|
||||
},
|
||||
onChange: function(aTarget, aChangeHandler) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.on("on", aChangeHandler);
|
||||
mgr.on("off", aChangeHandler);
|
||||
},
|
||||
offChange: function(aTarget, aChangeHandler) {
|
||||
if (aTarget.tab) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.off("on", aChangeHandler);
|
||||
mgr.off("off", aChangeHandler);
|
||||
}
|
||||
},
|
||||
},
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: 'resize to',
|
||||
description: gcli.lookup('resizeModeToDesc'),
|
||||
params: [
|
||||
{
|
||||
name: 'width',
|
||||
type: 'number',
|
||||
description: gcli.lookup("resizePageArgWidthDesc"),
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'number',
|
||||
description: gcli.lookup("resizePageArgHeightDesc"),
|
||||
},
|
||||
],
|
||||
exec: gcli_cmd_resize
|
||||
});
|
||||
|
||||
function gcli_cmd_resize(args, context) {
|
||||
let browserDoc = context.environment.chromeDocument;
|
||||
let browserWindow = browserDoc.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.handleGcliCommand(browserWindow,
|
||||
browserWindow.gBrowser.selectedTab,
|
||||
this.name,
|
||||
args);
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
JS_MODULES_PATH = 'modules/devtools'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'resize-commands.js'
|
||||
]
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
89
browser/devtools/responsivedesign/resize-commands.js
Normal file
@ -0,0 +1,89 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
createBundle("chrome://branding/locale/brand.properties").
|
||||
GetStringFromName("brandShortName");
|
||||
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: 'resize',
|
||||
description: gcli.lookup('resizeModeDesc')
|
||||
},
|
||||
{
|
||||
name: 'resize on',
|
||||
description: gcli.lookup('resizeModeOnDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
},
|
||||
{
|
||||
name: 'resize off',
|
||||
description: gcli.lookup('resizeModeOffDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
exec: gcli_cmd_resize
|
||||
},
|
||||
{
|
||||
name: 'resize toggle',
|
||||
buttonId: "command-button-responsive",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
tooltipText: gcli.lookup("resizeModeToggleTooltip"),
|
||||
description: gcli.lookup('resizeModeToggleDesc'),
|
||||
manual: gcli.lookupFormat('resizeModeManual2', [BRAND_SHORT_NAME]),
|
||||
state: {
|
||||
isChecked: function(aTarget) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
return mgr.isActiveForTab(aTarget.tab);
|
||||
},
|
||||
onChange: function(aTarget, aChangeHandler) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.on("on", aChangeHandler);
|
||||
mgr.on("off", aChangeHandler);
|
||||
},
|
||||
offChange: function(aTarget, aChangeHandler) {
|
||||
if (aTarget.tab) {
|
||||
let browserWindow = aTarget.tab.ownerDocument.defaultView;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.off("on", aChangeHandler);
|
||||
mgr.off("off", aChangeHandler);
|
||||
}
|
||||
},
|
||||
},
|
||||
exec: gcli_cmd_resize
|
||||
},
|
||||
{
|
||||
name: 'resize to',
|
||||
description: gcli.lookup('resizeModeToDesc'),
|
||||
params: [
|
||||
{
|
||||
name: 'width',
|
||||
type: 'number',
|
||||
description: gcli.lookup("resizePageArgWidthDesc"),
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'number',
|
||||
description: gcli.lookup("resizePageArgHeightDesc"),
|
||||
},
|
||||
],
|
||||
exec: gcli_cmd_resize
|
||||
}
|
||||
];
|
||||
|
||||
function gcli_cmd_resize(args, context) {
|
||||
let browserWindow = context.environment.chromeWindow;
|
||||
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
|
||||
mgr.handleGcliCommand(browserWindow,
|
||||
browserWindow.gBrowser.selectedTab,
|
||||
this.name,
|
||||
args);
|
||||
}
|
@ -9,5 +9,6 @@ TEST_DIRS += ['test']
|
||||
JS_MODULES_PATH = 'modules/devtools/scratchpad'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'scratchpad-commands.js',
|
||||
'scratchpad-panel.js'
|
||||
]
|
||||
|
@ -2,22 +2,18 @@
|
||||
* 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/. */
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
"use strict";
|
||||
|
||||
const { devtools } = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const gcli = devtools.require("gcli/index");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
/**
|
||||
* 'scratchpad' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items = [{
|
||||
name: "scratchpad",
|
||||
buttonId: "command-button-scratchpad",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
tooltipText: gcli.lookup("scratchpadOpenTooltip"),
|
||||
hidden: true,
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
chromeWindow.Scratchpad.ScratchpadManager.openScratchpad();
|
||||
let Scratchpad = context.environment.chromeWindow.Scratchpad;
|
||||
Scratchpad.ScratchpadManager.openScratchpad();
|
||||
}
|
||||
});
|
||||
}];
|
@ -12,7 +12,6 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/Commands.jsm");
|
||||
|
||||
const { require, TargetFactory } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
|
||||
@ -21,9 +20,6 @@ const Node = Ci.nsIDOMNode;
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CmdCommands",
|
||||
"resource:///modules/devtools/BuiltinCommands.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
@ -43,7 +39,13 @@ XPCOMUtils.defineLazyGetter(this, "toolboxStrings", function () {
|
||||
|
||||
const Telemetry = require("devtools/shared/telemetry");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gcli", () => require("gcli/index"));
|
||||
// This lazy getter is needed to prevent a require loop
|
||||
XPCOMUtils.defineLazyGetter(this, "gcli", () => {
|
||||
let gcli = require("gcli/index");
|
||||
require("devtools/commandline/commands-index");
|
||||
gcli.load();
|
||||
return gcli;
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "ConsoleServiceListener", {
|
||||
get: function() {
|
||||
@ -59,6 +61,15 @@ const promise = Cu.import('resource://gre/modules/Promise.jsm', {}).Promise;
|
||||
* A collection of utilities to help working with commands
|
||||
*/
|
||||
let CommandUtils = {
|
||||
/**
|
||||
* Utility to ensure that things are loaded in the correct order
|
||||
*/
|
||||
createRequisition: function(environment) {
|
||||
let temp = gcli.createDisplay; // Ensure GCLI is loaded
|
||||
let Requisition = require("gcli/cli").Requisition
|
||||
return new Requisition({ environment: environment });
|
||||
},
|
||||
|
||||
/**
|
||||
* Read a toolbarSpec from preferences
|
||||
* @param pref The name of the preference to read
|
||||
@ -349,13 +360,6 @@ DeveloperToolbar.prototype.show = function(focus) {
|
||||
var waitPromise = this._hidePromise || promise.resolve();
|
||||
|
||||
this._showPromise = waitPromise.then(() => {
|
||||
try {
|
||||
CmdCommands.refreshAutoCommands(this._chromeWindow);
|
||||
}
|
||||
catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
|
||||
Services.prefs.setBoolPref("devtools.toolbar.visible", true);
|
||||
|
||||
this._telemetry.toolOpened("developertoolbar");
|
||||
|
@ -147,158 +147,158 @@ function finishUp() {
|
||||
function getTestData() {
|
||||
return [
|
||||
{authored: "aliceblue", name: "aliceblue", hex: "#F0F8FF", hsl: "hsl(208, 100%, 97%)", rgb: "rgb(240, 248, 255)"},
|
||||
{authored: "antiquewhite", name: "antiquewhite", hex: "#FAEBD7", hsl: "hsl(34.286, 78%, 91%)", rgb: "rgb(250, 235, 215)"},
|
||||
{authored: "antiquewhite", name: "antiquewhite", hex: "#FAEBD7", hsl: "hsl(34, 78%, 91%)", rgb: "rgb(250, 235, 215)"},
|
||||
{authored: "aqua", name: "aqua", hex: "#0FF", hsl: "hsl(180, 100%, 50%)", rgb: "rgb(0, 255, 255)"},
|
||||
{authored: "aquamarine", name: "aquamarine", hex: "#7FFFD4", hsl: "hsl(159.844, 100%, 75%)", rgb: "rgb(127, 255, 212)"},
|
||||
{authored: "aquamarine", name: "aquamarine", hex: "#7FFFD4", hsl: "hsl(160, 100%, 75%)", rgb: "rgb(127, 255, 212)"},
|
||||
{authored: "azure", name: "azure", hex: "#F0FFFF", hsl: "hsl(180, 100%, 97%)", rgb: "rgb(240, 255, 255)"},
|
||||
{authored: "beige", name: "beige", hex: "#F5F5DC", hsl: "hsl(60, 56%, 91%)", rgb: "rgb(245, 245, 220)"},
|
||||
{authored: "bisque", name: "bisque", hex: "#FFE4C4", hsl: "hsl(32.542, 100%, 88%)", rgb: "rgb(255, 228, 196)"},
|
||||
{authored: "bisque", name: "bisque", hex: "#FFE4C4", hsl: "hsl(33, 100%, 88%)", rgb: "rgb(255, 228, 196)"},
|
||||
{authored: "black", name: "black", hex: "#000", hsl: "hsl(0, 0%, 0%)", rgb: "rgb(0, 0, 0)"},
|
||||
{authored: "blanchedalmond", name: "blanchedalmond", hex: "#FFEBCD", hsl: "hsl(36, 100%, 90%)", rgb: "rgb(255, 235, 205)"},
|
||||
{authored: "blue", name: "blue", hex: "#00F", hsl: "hsl(240, 100%, 50%)", rgb: "rgb(0, 0, 255)"},
|
||||
{authored: "blueviolet", name: "blueviolet", hex: "#8A2BE2", hsl: "hsl(271.148, 76%, 53%)", rgb: "rgb(138, 43, 226)"},
|
||||
{authored: "blueviolet", name: "blueviolet", hex: "#8A2BE2", hsl: "hsl(271, 76%, 53%)", rgb: "rgb(138, 43, 226)"},
|
||||
{authored: "brown", name: "brown", hex: "#A52A2A", hsl: "hsl(0, 59%, 41%)", rgb: "rgb(165, 42, 42)"},
|
||||
{authored: "burlywood", name: "burlywood", hex: "#DEB887", hsl: "hsl(33.793, 57%, 70%)", rgb: "rgb(222, 184, 135)"},
|
||||
{authored: "cadetblue", name: "cadetblue", hex: "#5F9EA0", hsl: "hsl(181.846, 25%, 50%)", rgb: "rgb(95, 158, 160)"},
|
||||
{authored: "chartreuse", name: "chartreuse", hex: "#7FFF00", hsl: "hsl(90.118, 100%, 50%)", rgb: "rgb(127, 255, 0)"},
|
||||
{authored: "burlywood", name: "burlywood", hex: "#DEB887", hsl: "hsl(34, 57%, 70%)", rgb: "rgb(222, 184, 135)"},
|
||||
{authored: "cadetblue", name: "cadetblue", hex: "#5F9EA0", hsl: "hsl(182, 25%, 50%)", rgb: "rgb(95, 158, 160)"},
|
||||
{authored: "chartreuse", name: "chartreuse", hex: "#7FFF00", hsl: "hsl(90, 100%, 50%)", rgb: "rgb(127, 255, 0)"},
|
||||
{authored: "chocolate", name: "chocolate", hex: "#D2691E", hsl: "hsl(25, 75%, 47%)", rgb: "rgb(210, 105, 30)"},
|
||||
{authored: "coral", name: "coral", hex: "#FF7F50", hsl: "hsl(16.114, 100%, 66%)", rgb: "rgb(255, 127, 80)"},
|
||||
{authored: "cornflowerblue", name: "cornflowerblue", hex: "#6495ED", hsl: "hsl(218.54, 79%, 66%)", rgb: "rgb(100, 149, 237)"},
|
||||
{authored: "coral", name: "coral", hex: "#FF7F50", hsl: "hsl(16, 100%, 66%)", rgb: "rgb(255, 127, 80)"},
|
||||
{authored: "cornflowerblue", name: "cornflowerblue", hex: "#6495ED", hsl: "hsl(219, 79%, 66%)", rgb: "rgb(100, 149, 237)"},
|
||||
{authored: "cornsilk", name: "cornsilk", hex: "#FFF8DC", hsl: "hsl(48, 100%, 93%)", rgb: "rgb(255, 248, 220)"},
|
||||
{authored: "crimson", name: "crimson", hex: "#DC143C", hsl: "hsl(348, 83%, 47%)", rgb: "rgb(220, 20, 60)"},
|
||||
{authored: "cyan", name: "aqua", hex: "#0FF", hsl: "hsl(180, 100%, 50%)", rgb: "rgb(0, 255, 255)"},
|
||||
{authored: "darkblue", name: "darkblue", hex: "#00008B", hsl: "hsl(240, 100%, 27%)", rgb: "rgb(0, 0, 139)"},
|
||||
{authored: "darkcyan", name: "darkcyan", hex: "#008B8B", hsl: "hsl(180, 100%, 27%)", rgb: "rgb(0, 139, 139)"},
|
||||
{authored: "darkgoldenrod", name: "darkgoldenrod", hex: "#B8860B", hsl: "hsl(42.659, 89%, 38%)", rgb: "rgb(184, 134, 11)"},
|
||||
{authored: "darkgoldenrod", name: "darkgoldenrod", hex: "#B8860B", hsl: "hsl(43, 89%, 38%)", rgb: "rgb(184, 134, 11)"},
|
||||
{authored: "darkgray", name: "darkgray", hex: "#A9A9A9", hsl: "hsl(0, 0%, 66%)", rgb: "rgb(169, 169, 169)"},
|
||||
{authored: "darkgreen", name: "darkgreen", hex: "#006400", hsl: "hsl(120, 100%, 20%)", rgb: "rgb(0, 100, 0)"},
|
||||
{authored: "darkgrey", name: "darkgray", hex: "#A9A9A9", hsl: "hsl(0, 0%, 66%)", rgb: "rgb(169, 169, 169)"},
|
||||
{authored: "darkkhaki", name: "darkkhaki", hex: "#BDB76B", hsl: "hsl(55.61, 38%, 58%)", rgb: "rgb(189, 183, 107)"},
|
||||
{authored: "darkkhaki", name: "darkkhaki", hex: "#BDB76B", hsl: "hsl(56, 38%, 58%)", rgb: "rgb(189, 183, 107)"},
|
||||
{authored: "darkmagenta", name: "darkmagenta", hex: "#8B008B", hsl: "hsl(300, 100%, 27%)", rgb: "rgb(139, 0, 139)"},
|
||||
{authored: "darkolivegreen", name: "darkolivegreen", hex: "#556B2F", hsl: "hsl(82, 39%, 30%)", rgb: "rgb(85, 107, 47)"},
|
||||
{authored: "darkorange", name: "darkorange", hex: "#FF8C00", hsl: "hsl(32.941, 100%, 50%)", rgb: "rgb(255, 140, 0)"},
|
||||
{authored: "darkorchid", name: "darkorchid", hex: "#9932CC", hsl: "hsl(280.13, 61%, 50%)", rgb: "rgb(153, 50, 204)"},
|
||||
{authored: "darkorange", name: "darkorange", hex: "#FF8C00", hsl: "hsl(33, 100%, 50%)", rgb: "rgb(255, 140, 0)"},
|
||||
{authored: "darkorchid", name: "darkorchid", hex: "#9932CC", hsl: "hsl(280, 61%, 50%)", rgb: "rgb(153, 50, 204)"},
|
||||
{authored: "darkred", name: "darkred", hex: "#8B0000", hsl: "hsl(0, 100%, 27%)", rgb: "rgb(139, 0, 0)"},
|
||||
{authored: "darksalmon", name: "darksalmon", hex: "#E9967A", hsl: "hsl(15.135, 72%, 70%)", rgb: "rgb(233, 150, 122)"},
|
||||
{authored: "darksalmon", name: "darksalmon", hex: "#E9967A", hsl: "hsl(15, 72%, 70%)", rgb: "rgb(233, 150, 122)"},
|
||||
{authored: "darkseagreen", name: "darkseagreen", hex: "#8FBC8F", hsl: "hsl(120, 25%, 65%)", rgb: "rgb(143, 188, 143)"},
|
||||
{authored: "darkslateblue", name: "darkslateblue", hex: "#483D8B", hsl: "hsl(248.462, 39%, 39%)", rgb: "rgb(72, 61, 139)"},
|
||||
{authored: "darkslateblue", name: "darkslateblue", hex: "#483D8B", hsl: "hsl(248, 39%, 39%)", rgb: "rgb(72, 61, 139)"},
|
||||
{authored: "darkslategray", name: "darkslategray", hex: "#2F4F4F", hsl: "hsl(180, 25%, 25%)", rgb: "rgb(47, 79, 79)"},
|
||||
{authored: "darkslategrey", name: "darkslategray", hex: "#2F4F4F", hsl: "hsl(180, 25%, 25%)", rgb: "rgb(47, 79, 79)"},
|
||||
{authored: "darkturquoise", name: "darkturquoise", hex: "#00CED1", hsl: "hsl(180.861, 100%, 41%)", rgb: "rgb(0, 206, 209)"},
|
||||
{authored: "darkviolet", name: "darkviolet", hex: "#9400D3", hsl: "hsl(282.085, 100%, 41%)", rgb: "rgb(148, 0, 211)"},
|
||||
{authored: "deeppink", name: "deeppink", hex: "#FF1493", hsl: "hsl(327.574, 100%, 54%)", rgb: "rgb(255, 20, 147)"},
|
||||
{authored: "deepskyblue", name: "deepskyblue", hex: "#00BFFF", hsl: "hsl(195.059, 100%, 50%)", rgb: "rgb(0, 191, 255)"},
|
||||
{authored: "darkturquoise", name: "darkturquoise", hex: "#00CED1", hsl: "hsl(181, 100%, 41%)", rgb: "rgb(0, 206, 209)"},
|
||||
{authored: "darkviolet", name: "darkviolet", hex: "#9400D3", hsl: "hsl(282, 100%, 41%)", rgb: "rgb(148, 0, 211)"},
|
||||
{authored: "deeppink", name: "deeppink", hex: "#FF1493", hsl: "hsl(328, 100%, 54%)", rgb: "rgb(255, 20, 147)"},
|
||||
{authored: "deepskyblue", name: "deepskyblue", hex: "#00BFFF", hsl: "hsl(195, 100%, 50%)", rgb: "rgb(0, 191, 255)"},
|
||||
{authored: "dimgray", name: "dimgray", hex: "#696969", hsl: "hsl(0, 0%, 41%)", rgb: "rgb(105, 105, 105)"},
|
||||
{authored: "dodgerblue", name: "dodgerblue", hex: "#1E90FF", hsl: "hsl(209.6, 100%, 56%)", rgb: "rgb(30, 144, 255)"},
|
||||
{authored: "dodgerblue", name: "dodgerblue", hex: "#1E90FF", hsl: "hsl(210, 100%, 56%)", rgb: "rgb(30, 144, 255)"},
|
||||
{authored: "firebrick", name: "firebrick", hex: "#B22222", hsl: "hsl(0, 68%, 42%)", rgb: "rgb(178, 34, 34)"},
|
||||
{authored: "floralwhite", name: "floralwhite", hex: "#FFFAF0", hsl: "hsl(40, 100%, 97%)", rgb: "rgb(255, 250, 240)"},
|
||||
{authored: "forestgreen", name: "forestgreen", hex: "#228B22", hsl: "hsl(120, 61%, 34%)", rgb: "rgb(34, 139, 34)"},
|
||||
{authored: "fuchsia", name: "fuchsia", hex: "#F0F", hsl: "hsl(300, 100%, 50%)", rgb: "rgb(255, 0, 255)"},
|
||||
{authored: "gainsboro", name: "gainsboro", hex: "#DCDCDC", hsl: "hsl(0, 0%, 86%)", rgb: "rgb(220, 220, 220)"},
|
||||
{authored: "ghostwhite", name: "ghostwhite", hex: "#F8F8FF", hsl: "hsl(240, 100%, 99%)", rgb: "rgb(248, 248, 255)"},
|
||||
{authored: "gold", name: "gold", hex: "#FFD700", hsl: "hsl(50.588, 100%, 50%)", rgb: "rgb(255, 215, 0)"},
|
||||
{authored: "goldenrod", name: "goldenrod", hex: "#DAA520", hsl: "hsl(42.903, 74%, 49%)", rgb: "rgb(218, 165, 32)"},
|
||||
{authored: "gold", name: "gold", hex: "#FFD700", hsl: "hsl(51, 100%, 50%)", rgb: "rgb(255, 215, 0)"},
|
||||
{authored: "goldenrod", name: "goldenrod", hex: "#DAA520", hsl: "hsl(43, 74%, 49%)", rgb: "rgb(218, 165, 32)"},
|
||||
{authored: "gray", name: "gray", hex: "#808080", hsl: "hsl(0, 0%, 50%)", rgb: "rgb(128, 128, 128)"},
|
||||
{authored: "green", name: "green", hex: "#008000", hsl: "hsl(120, 100%, 25%)", rgb: "rgb(0, 128, 0)"},
|
||||
{authored: "greenyellow", name: "greenyellow", hex: "#ADFF2F", hsl: "hsl(83.654, 100%, 59%)", rgb: "rgb(173, 255, 47)"},
|
||||
{authored: "greenyellow", name: "greenyellow", hex: "#ADFF2F", hsl: "hsl(84, 100%, 59%)", rgb: "rgb(173, 255, 47)"},
|
||||
{authored: "grey", name: "gray", hex: "#808080", hsl: "hsl(0, 0%, 50%)", rgb: "rgb(128, 128, 128)"},
|
||||
{authored: "honeydew", name: "honeydew", hex: "#F0FFF0", hsl: "hsl(120, 100%, 97%)", rgb: "rgb(240, 255, 240)"},
|
||||
{authored: "hotpink", name: "hotpink", hex: "#FF69B4", hsl: "hsl(330, 100%, 71%)", rgb: "rgb(255, 105, 180)"},
|
||||
{authored: "indianred", name: "indianred", hex: "#CD5C5C", hsl: "hsl(0, 53%, 58%)", rgb: "rgb(205, 92, 92)"},
|
||||
{authored: "indigo", name: "indigo", hex: "#4B0082", hsl: "hsl(274.615, 100%, 25%)", rgb: "rgb(75, 0, 130)"},
|
||||
{authored: "indigo", name: "indigo", hex: "#4B0082", hsl: "hsl(275, 100%, 25%)", rgb: "rgb(75, 0, 130)"},
|
||||
{authored: "ivory", name: "ivory", hex: "#FFFFF0", hsl: "hsl(60, 100%, 97%)", rgb: "rgb(255, 255, 240)"},
|
||||
{authored: "khaki", name: "khaki", hex: "#F0E68C", hsl: "hsl(54, 77%, 75%)", rgb: "rgb(240, 230, 140)"},
|
||||
{authored: "lavender", name: "lavender", hex: "#E6E6FA", hsl: "hsl(240, 67%, 94%)", rgb: "rgb(230, 230, 250)"},
|
||||
{authored: "lavenderblush", name: "lavenderblush", hex: "#FFF0F5", hsl: "hsl(340, 100%, 97%)", rgb: "rgb(255, 240, 245)"},
|
||||
{authored: "lawngreen", name: "lawngreen", hex: "#7CFC00", hsl: "hsl(90.476, 100%, 49%)", rgb: "rgb(124, 252, 0)"},
|
||||
{authored: "lawngreen", name: "lawngreen", hex: "#7CFC00", hsl: "hsl(90, 100%, 49%)", rgb: "rgb(124, 252, 0)"},
|
||||
{authored: "lemonchiffon", name: "lemonchiffon", hex: "#FFFACD", hsl: "hsl(54, 100%, 90%)", rgb: "rgb(255, 250, 205)"},
|
||||
{authored: "lightblue", name: "lightblue", hex: "#ADD8E6", hsl: "hsl(194.737, 53%, 79%)", rgb: "rgb(173, 216, 230)"},
|
||||
{authored: "lightblue", name: "lightblue", hex: "#ADD8E6", hsl: "hsl(195, 53%, 79%)", rgb: "rgb(173, 216, 230)"},
|
||||
{authored: "lightcoral", name: "lightcoral", hex: "#F08080", hsl: "hsl(0, 79%, 72%)", rgb: "rgb(240, 128, 128)"},
|
||||
{authored: "lightcyan", name: "lightcyan", hex: "#E0FFFF", hsl: "hsl(180, 100%, 94%)", rgb: "rgb(224, 255, 255)"},
|
||||
{authored: "lightgoldenrodyellow", name: "lightgoldenrodyellow", hex: "#FAFAD2", hsl: "hsl(60, 80%, 90%)", rgb: "rgb(250, 250, 210)"},
|
||||
{authored: "lightgray", name: "lightgray", hex: "#D3D3D3", hsl: "hsl(0, 0%, 83%)", rgb: "rgb(211, 211, 211)"},
|
||||
{authored: "lightgreen", name: "lightgreen", hex: "#90EE90", hsl: "hsl(120, 73%, 75%)", rgb: "rgb(144, 238, 144)"},
|
||||
{authored: "lightgrey", name: "lightgray", hex: "#D3D3D3", hsl: "hsl(0, 0%, 83%)", rgb: "rgb(211, 211, 211)"},
|
||||
{authored: "lightpink", name: "lightpink", hex: "#FFB6C1", hsl: "hsl(350.959, 100%, 86%)", rgb: "rgb(255, 182, 193)"},
|
||||
{authored: "lightsalmon", name: "lightsalmon", hex: "#FFA07A", hsl: "hsl(17.143, 100%, 74%)", rgb: "rgb(255, 160, 122)"},
|
||||
{authored: "lightseagreen", name: "lightseagreen", hex: "#20B2AA", hsl: "hsl(176.712, 70%, 41%)", rgb: "rgb(32, 178, 170)"},
|
||||
{authored: "lightskyblue", name: "lightskyblue", hex: "#87CEFA", hsl: "hsl(202.957, 92%, 75%)", rgb: "rgb(135, 206, 250)"},
|
||||
{authored: "lightpink", name: "lightpink", hex: "#FFB6C1", hsl: "hsl(351, 100%, 86%)", rgb: "rgb(255, 182, 193)"},
|
||||
{authored: "lightsalmon", name: "lightsalmon", hex: "#FFA07A", hsl: "hsl(17, 100%, 74%)", rgb: "rgb(255, 160, 122)"},
|
||||
{authored: "lightseagreen", name: "lightseagreen", hex: "#20B2AA", hsl: "hsl(177, 70%, 41%)", rgb: "rgb(32, 178, 170)"},
|
||||
{authored: "lightskyblue", name: "lightskyblue", hex: "#87CEFA", hsl: "hsl(203, 92%, 75%)", rgb: "rgb(135, 206, 250)"},
|
||||
{authored: "lightslategray", name: "lightslategray", hex: "#789", hsl: "hsl(210, 14%, 53%)", rgb: "rgb(119, 136, 153)"},
|
||||
{authored: "lightslategrey", name: "lightslategray", hex: "#789", hsl: "hsl(210, 14%, 53%)", rgb: "rgb(119, 136, 153)"},
|
||||
{authored: "lightsteelblue", name: "lightsteelblue", hex: "#B0C4DE", hsl: "hsl(213.913, 41%, 78%)", rgb: "rgb(176, 196, 222)"},
|
||||
{authored: "lightsteelblue", name: "lightsteelblue", hex: "#B0C4DE", hsl: "hsl(214, 41%, 78%)", rgb: "rgb(176, 196, 222)"},
|
||||
{authored: "lightyellow", name: "lightyellow", hex: "#FFFFE0", hsl: "hsl(60, 100%, 94%)", rgb: "rgb(255, 255, 224)"},
|
||||
{authored: "lime", name: "lime", hex: "#0F0", hsl: "hsl(120, 100%, 50%)", rgb: "rgb(0, 255, 0)"},
|
||||
{authored: "limegreen", name: "limegreen", hex: "#32CD32", hsl: "hsl(120, 61%, 50%)", rgb: "rgb(50, 205, 50)"},
|
||||
{authored: "linen", name: "linen", hex: "#FAF0E6", hsl: "hsl(30, 67%, 94%)", rgb: "rgb(250, 240, 230)"},
|
||||
{authored: "magenta", name: "fuchsia", hex: "#F0F", hsl: "hsl(300, 100%, 50%)", rgb: "rgb(255, 0, 255)"},
|
||||
{authored: "maroon", name: "maroon", hex: "#800000", hsl: "hsl(0, 100%, 25%)", rgb: "rgb(128, 0, 0)"},
|
||||
{authored: "mediumaquamarine", name: "mediumaquamarine", hex: "#66CDAA", hsl: "hsl(159.612, 51%, 60%)", rgb: "rgb(102, 205, 170)"},
|
||||
{authored: "mediumaquamarine", name: "mediumaquamarine", hex: "#66CDAA", hsl: "hsl(160, 51%, 60%)", rgb: "rgb(102, 205, 170)"},
|
||||
{authored: "mediumblue", name: "mediumblue", hex: "#0000CD", hsl: "hsl(240, 100%, 40%)", rgb: "rgb(0, 0, 205)"},
|
||||
{authored: "mediumorchid", name: "mediumorchid", hex: "#BA55D3", hsl: "hsl(288.095, 59%, 58%)", rgb: "rgb(186, 85, 211)"},
|
||||
{authored: "mediumpurple", name: "mediumpurple", hex: "#9370DB", hsl: "hsl(259.626, 60%, 65%)", rgb: "rgb(147, 112, 219)"},
|
||||
{authored: "mediumseagreen", name: "mediumseagreen", hex: "#3CB371", hsl: "hsl(146.723, 50%, 47%)", rgb: "rgb(60, 179, 113)"},
|
||||
{authored: "mediumslateblue", name: "mediumslateblue", hex: "#7B68EE", hsl: "hsl(248.507, 80%, 67%)", rgb: "rgb(123, 104, 238)"},
|
||||
{authored: "mediumspringgreen", name: "mediumspringgreen", hex: "#00FA9A", hsl: "hsl(156.96, 100%, 49%)", rgb: "rgb(0, 250, 154)"},
|
||||
{authored: "mediumturquoise", name: "mediumturquoise", hex: "#48D1CC", hsl: "hsl(177.81, 60%, 55%)", rgb: "rgb(72, 209, 204)"},
|
||||
{authored: "mediumvioletred", name: "mediumvioletred", hex: "#C71585", hsl: "hsl(322.247, 81%, 43%)", rgb: "rgb(199, 21, 133)"},
|
||||
{authored: "mediumorchid", name: "mediumorchid", hex: "#BA55D3", hsl: "hsl(288, 59%, 58%)", rgb: "rgb(186, 85, 211)"},
|
||||
{authored: "mediumpurple", name: "mediumpurple", hex: "#9370DB", hsl: "hsl(260, 60%, 65%)", rgb: "rgb(147, 112, 219)"},
|
||||
{authored: "mediumseagreen", name: "mediumseagreen", hex: "#3CB371", hsl: "hsl(147, 50%, 47%)", rgb: "rgb(60, 179, 113)"},
|
||||
{authored: "mediumslateblue", name: "mediumslateblue", hex: "#7B68EE", hsl: "hsl(249, 80%, 67%)", rgb: "rgb(123, 104, 238)"},
|
||||
{authored: "mediumspringgreen", name: "mediumspringgreen", hex: "#00FA9A", hsl: "hsl(157, 100%, 49%)", rgb: "rgb(0, 250, 154)"},
|
||||
{authored: "mediumturquoise", name: "mediumturquoise", hex: "#48D1CC", hsl: "hsl(178, 60%, 55%)", rgb: "rgb(72, 209, 204)"},
|
||||
{authored: "mediumvioletred", name: "mediumvioletred", hex: "#C71585", hsl: "hsl(322, 81%, 43%)", rgb: "rgb(199, 21, 133)"},
|
||||
{authored: "midnightblue", name: "midnightblue", hex: "#191970", hsl: "hsl(240, 64%, 27%)", rgb: "rgb(25, 25, 112)"},
|
||||
{authored: "mintcream", name: "mintcream", hex: "#F5FFFA", hsl: "hsl(150, 100%, 98%)", rgb: "rgb(245, 255, 250)"},
|
||||
{authored: "mistyrose", name: "mistyrose", hex: "#FFE4E1", hsl: "hsl(6, 100%, 94%)", rgb: "rgb(255, 228, 225)"},
|
||||
{authored: "moccasin", name: "moccasin", hex: "#FFE4B5", hsl: "hsl(38.108, 100%, 85%)", rgb: "rgb(255, 228, 181)"},
|
||||
{authored: "navajowhite", name: "navajowhite", hex: "#FFDEAD", hsl: "hsl(35.854, 100%, 84%)", rgb: "rgb(255, 222, 173)"},
|
||||
{authored: "moccasin", name: "moccasin", hex: "#FFE4B5", hsl: "hsl(38, 100%, 85%)", rgb: "rgb(255, 228, 181)"},
|
||||
{authored: "navajowhite", name: "navajowhite", hex: "#FFDEAD", hsl: "hsl(36, 100%, 84%)", rgb: "rgb(255, 222, 173)"},
|
||||
{authored: "navy", name: "navy", hex: "#000080", hsl: "hsl(240, 100%, 25%)", rgb: "rgb(0, 0, 128)"},
|
||||
{authored: "oldlace", name: "oldlace", hex: "#FDF5E6", hsl: "hsl(39.13, 85%, 95%)", rgb: "rgb(253, 245, 230)"},
|
||||
{authored: "oldlace", name: "oldlace", hex: "#FDF5E6", hsl: "hsl(39, 85%, 95%)", rgb: "rgb(253, 245, 230)"},
|
||||
{authored: "olive", name: "olive", hex: "#808000", hsl: "hsl(60, 100%, 25%)", rgb: "rgb(128, 128, 0)"},
|
||||
{authored: "olivedrab", name: "olivedrab", hex: "#6B8E23", hsl: "hsl(79.626, 60%, 35%)", rgb: "rgb(107, 142, 35)"},
|
||||
{authored: "orange", name: "orange", hex: "#FFA500", hsl: "hsl(38.824, 100%, 50%)", rgb: "rgb(255, 165, 0)"},
|
||||
{authored: "orangered", name: "orangered", hex: "#FF4500", hsl: "hsl(16.235, 100%, 50%)", rgb: "rgb(255, 69, 0)"},
|
||||
{authored: "orchid", name: "orchid", hex: "#DA70D6", hsl: "hsl(302.264, 59%, 65%)", rgb: "rgb(218, 112, 214)"},
|
||||
{authored: "palegoldenrod", name: "palegoldenrod", hex: "#EEE8AA", hsl: "hsl(54.706, 67%, 80%)", rgb: "rgb(238, 232, 170)"},
|
||||
{authored: "olivedrab", name: "olivedrab", hex: "#6B8E23", hsl: "hsl(80, 60%, 35%)", rgb: "rgb(107, 142, 35)"},
|
||||
{authored: "orange", name: "orange", hex: "#FFA500", hsl: "hsl(39, 100%, 50%)", rgb: "rgb(255, 165, 0)"},
|
||||
{authored: "orangered", name: "orangered", hex: "#FF4500", hsl: "hsl(16, 100%, 50%)", rgb: "rgb(255, 69, 0)"},
|
||||
{authored: "orchid", name: "orchid", hex: "#DA70D6", hsl: "hsl(302, 59%, 65%)", rgb: "rgb(218, 112, 214)"},
|
||||
{authored: "palegoldenrod", name: "palegoldenrod", hex: "#EEE8AA", hsl: "hsl(55, 67%, 80%)", rgb: "rgb(238, 232, 170)"},
|
||||
{authored: "palegreen", name: "palegreen", hex: "#98FB98", hsl: "hsl(120, 93%, 79%)", rgb: "rgb(152, 251, 152)"},
|
||||
{authored: "paleturquoise", name: "paleturquoise", hex: "#AFEEEE", hsl: "hsl(180, 65%, 81%)", rgb: "rgb(175, 238, 238)"},
|
||||
{authored: "palevioletred", name: "palevioletred", hex: "#DB7093", hsl: "hsl(340.374, 60%, 65%)", rgb: "rgb(219, 112, 147)"},
|
||||
{authored: "papayawhip", name: "papayawhip", hex: "#FFEFD5", hsl: "hsl(37.143, 100%, 92%)", rgb: "rgb(255, 239, 213)"},
|
||||
{authored: "peachpuff", name: "peachpuff", hex: "#FFDAB9", hsl: "hsl(28.286, 100%, 86%)", rgb: "rgb(255, 218, 185)"},
|
||||
{authored: "peru", name: "peru", hex: "#CD853F", hsl: "hsl(29.577, 59%, 53%)", rgb: "rgb(205, 133, 63)"},
|
||||
{authored: "pink", name: "pink", hex: "#FFC0CB", hsl: "hsl(349.524, 100%, 88%)", rgb: "rgb(255, 192, 203)"},
|
||||
{authored: "palevioletred", name: "palevioletred", hex: "#DB7093", hsl: "hsl(340, 60%, 65%)", rgb: "rgb(219, 112, 147)"},
|
||||
{authored: "papayawhip", name: "papayawhip", hex: "#FFEFD5", hsl: "hsl(37, 100%, 92%)", rgb: "rgb(255, 239, 213)"},
|
||||
{authored: "peachpuff", name: "peachpuff", hex: "#FFDAB9", hsl: "hsl(28, 100%, 86%)", rgb: "rgb(255, 218, 185)"},
|
||||
{authored: "peru", name: "peru", hex: "#CD853F", hsl: "hsl(30, 59%, 53%)", rgb: "rgb(205, 133, 63)"},
|
||||
{authored: "pink", name: "pink", hex: "#FFC0CB", hsl: "hsl(350, 100%, 88%)", rgb: "rgb(255, 192, 203)"},
|
||||
{authored: "plum", name: "plum", hex: "#DDA0DD", hsl: "hsl(300, 47%, 75%)", rgb: "rgb(221, 160, 221)"},
|
||||
{authored: "powderblue", name: "powderblue", hex: "#B0E0E6", hsl: "hsl(186.667, 52%, 80%)", rgb: "rgb(176, 224, 230)"},
|
||||
{authored: "powderblue", name: "powderblue", hex: "#B0E0E6", hsl: "hsl(187, 52%, 80%)", rgb: "rgb(176, 224, 230)"},
|
||||
{authored: "purple", name: "purple", hex: "#800080", hsl: "hsl(300, 100%, 25%)", rgb: "rgb(128, 0, 128)"},
|
||||
{authored: "red", name: "red", hex: "#F00", hsl: "hsl(0, 100%, 50%)", rgb: "rgb(255, 0, 0)"},
|
||||
{authored: "rosybrown", name: "rosybrown", hex: "#BC8F8F", hsl: "hsl(0, 25%, 65%)", rgb: "rgb(188, 143, 143)"},
|
||||
{authored: "royalblue", name: "royalblue", hex: "#4169E1", hsl: "hsl(225, 73%, 57%)", rgb: "rgb(65, 105, 225)"},
|
||||
{authored: "saddlebrown", name: "saddlebrown", hex: "#8B4513", hsl: "hsl(25, 76%, 31%)", rgb: "rgb(139, 69, 19)"},
|
||||
{authored: "salmon", name: "salmon", hex: "#FA8072", hsl: "hsl(6.176, 93%, 71%)", rgb: "rgb(250, 128, 114)"},
|
||||
{authored: "sandybrown", name: "sandybrown", hex: "#F4A460", hsl: "hsl(27.568, 87%, 67%)", rgb: "rgb(244, 164, 96)"},
|
||||
{authored: "seagreen", name: "seagreen", hex: "#2E8B57", hsl: "hsl(146.452, 50%, 36%)", rgb: "rgb(46, 139, 87)"},
|
||||
{authored: "seashell", name: "seashell", hex: "#FFF5EE", hsl: "hsl(24.706, 100%, 97%)", rgb: "rgb(255, 245, 238)"},
|
||||
{authored: "sienna", name: "sienna", hex: "#A0522D", hsl: "hsl(19.304, 56%, 40%)", rgb: "rgb(160, 82, 45)"},
|
||||
{authored: "salmon", name: "salmon", hex: "#FA8072", hsl: "hsl(6, 93%, 71%)", rgb: "rgb(250, 128, 114)"},
|
||||
{authored: "sandybrown", name: "sandybrown", hex: "#F4A460", hsl: "hsl(28, 87%, 67%)", rgb: "rgb(244, 164, 96)"},
|
||||
{authored: "seagreen", name: "seagreen", hex: "#2E8B57", hsl: "hsl(146, 50%, 36%)", rgb: "rgb(46, 139, 87)"},
|
||||
{authored: "seashell", name: "seashell", hex: "#FFF5EE", hsl: "hsl(25, 100%, 97%)", rgb: "rgb(255, 245, 238)"},
|
||||
{authored: "sienna", name: "sienna", hex: "#A0522D", hsl: "hsl(19, 56%, 40%)", rgb: "rgb(160, 82, 45)"},
|
||||
{authored: "silver", name: "silver", hex: "#C0C0C0", hsl: "hsl(0, 0%, 75%)", rgb: "rgb(192, 192, 192)"},
|
||||
{authored: "skyblue", name: "skyblue", hex: "#87CEEB", hsl: "hsl(197.4, 71%, 73%)", rgb: "rgb(135, 206, 235)"},
|
||||
{authored: "slateblue", name: "slateblue", hex: "#6A5ACD", hsl: "hsl(248.348, 53%, 58%)", rgb: "rgb(106, 90, 205)"},
|
||||
{authored: "skyblue", name: "skyblue", hex: "#87CEEB", hsl: "hsl(197, 71%, 73%)", rgb: "rgb(135, 206, 235)"},
|
||||
{authored: "slateblue", name: "slateblue", hex: "#6A5ACD", hsl: "hsl(248, 53%, 58%)", rgb: "rgb(106, 90, 205)"},
|
||||
{authored: "slategray", name: "slategray", hex: "#708090", hsl: "hsl(210, 13%, 50%)", rgb: "rgb(112, 128, 144)"},
|
||||
{authored: "slategrey", name: "slategray", hex: "#708090", hsl: "hsl(210, 13%, 50%)", rgb: "rgb(112, 128, 144)"},
|
||||
{authored: "snow", name: "snow", hex: "#FFFAFA", hsl: "hsl(0, 100%, 99%)", rgb: "rgb(255, 250, 250)"},
|
||||
{authored: "springgreen", name: "springgreen", hex: "#00FF7F", hsl: "hsl(149.882, 100%, 50%)", rgb: "rgb(0, 255, 127)"},
|
||||
{authored: "steelblue", name: "steelblue", hex: "#4682B4", hsl: "hsl(207.273, 44%, 49%)", rgb: "rgb(70, 130, 180)"},
|
||||
{authored: "tan", name: "tan", hex: "#D2B48C", hsl: "hsl(34.286, 44%, 69%)", rgb: "rgb(210, 180, 140)"},
|
||||
{authored: "springgreen", name: "springgreen", hex: "#00FF7F", hsl: "hsl(150, 100%, 50%)", rgb: "rgb(0, 255, 127)"},
|
||||
{authored: "steelblue", name: "steelblue", hex: "#4682B4", hsl: "hsl(207, 44%, 49%)", rgb: "rgb(70, 130, 180)"},
|
||||
{authored: "tan", name: "tan", hex: "#D2B48C", hsl: "hsl(34, 44%, 69%)", rgb: "rgb(210, 180, 140)"},
|
||||
{authored: "teal", name: "teal", hex: "#008080", hsl: "hsl(180, 100%, 25%)", rgb: "rgb(0, 128, 128)"},
|
||||
{authored: "thistle", name: "thistle", hex: "#D8BFD8", hsl: "hsl(300, 24%, 80%)", rgb: "rgb(216, 191, 216)"},
|
||||
{authored: "tomato", name: "tomato", hex: "#FF6347", hsl: "hsl(9.13, 100%, 64%)", rgb: "rgb(255, 99, 71)"},
|
||||
{authored: "tomato", name: "tomato", hex: "#FF6347", hsl: "hsl(9, 100%, 64%)", rgb: "rgb(255, 99, 71)"},
|
||||
{authored: "turquoise", name: "turquoise", hex: "#40E0D0", hsl: "hsl(174, 72%, 56%)", rgb: "rgb(64, 224, 208)"},
|
||||
{authored: "violet", name: "violet", hex: "#EE82EE", hsl: "hsl(300, 76%, 72%)", rgb: "rgb(238, 130, 238)"},
|
||||
{authored: "wheat", name: "wheat", hex: "#F5DEB3", hsl: "hsl(39.091, 77%, 83%)", rgb: "rgb(245, 222, 179)"},
|
||||
{authored: "wheat", name: "wheat", hex: "#F5DEB3", hsl: "hsl(39, 77%, 83%)", rgb: "rgb(245, 222, 179)"},
|
||||
{authored: "white", name: "white", hex: "#FFF", hsl: "hsl(0, 0%, 100%)", rgb: "rgb(255, 255, 255)"},
|
||||
{authored: "whitesmoke", name: "whitesmoke", hex: "#F5F5F5", hsl: "hsl(0, 0%, 96%)", rgb: "rgb(245, 245, 245)"},
|
||||
{authored: "yellow", name: "yellow", hex: "#FF0", hsl: "hsl(60, 100%, 50%)", rgb: "rgb(255, 255, 0)"},
|
||||
{authored: "yellowgreen", name: "yellowgreen", hex: "#9ACD32", hsl: "hsl(79.742, 61%, 50%)", rgb: "rgb(154, 205, 50)"},
|
||||
{authored: "yellowgreen", name: "yellowgreen", hex: "#9ACD32", hsl: "hsl(80, 61%, 50%)", rgb: "rgb(154, 205, 50)"},
|
||||
{authored: "rgba(0, 0, 0, 0)", name: "rgba(0, 0, 0, 0)", hex: "rgba(0, 0, 0, 0)", hsl: "hsla(0, 0%, 0%, 0)", rgb: "rgba(0, 0, 0, 0)"},
|
||||
{authored: "hsla(0, 0%, 0%, 0)", name: "rgba(0, 0, 0, 0)", hex: "rgba(0, 0, 0, 0)", hsl: "hsla(0, 0%, 0%, 0)", rgb: "rgba(0, 0, 0, 0)"},
|
||||
{authored: "rgba(50, 60, 70, 0.5)", name: "rgba(50, 60, 70, 0.5)", hex: "rgba(50, 60, 70, 0.5)", hsl: "hsla(210, 17%, 24%, 0.5)", rgb: "rgba(50, 60, 70, 0.5)"},
|
||||
{authored: "rgba(0, 0, 0, 0.3)", name: "rgba(0, 0, 0, 0.3)", hex: "rgba(0, 0, 0, 0.3)", hsl: "hsla(0, 0%, 0%, 0.3)", rgb: "rgba(0, 0, 0, 0.3)"},
|
||||
{authored: "rgba(255, 255, 255, 0.6)", name: "rgba(255, 255, 255, 0.6)", hex: "rgba(255, 255, 255, 0.6)", hsl: "hsla(0, 0%, 100%, 0.6)", rgb: "rgba(255, 255, 255, 0.6)"},
|
||||
{authored: "rgba(127, 89, 45, 1)", name: "#7F592D", hex: "#7F592D", hsl: "hsl(32.195, 48%, 34%)", rgb: "rgb(127, 89, 45)"},
|
||||
{authored: "hsla(19.304, 56%, 40%, 1)", name: "#9F512C", hex: "#9F512C", hsl: "hsl(19.304, 57%, 40%)", rgb: "rgb(159, 81, 44)"},
|
||||
{authored: "rgba(127, 89, 45, 1)", name: "#7F592D", hex: "#7F592D", hsl: "hsl(32, 48%, 34%)", rgb: "rgb(127, 89, 45)"},
|
||||
{authored: "hsla(19.304, 56%, 40%, 1)", name: "#9F512C", hex: "#9F512C", hsl: "hsl(19, 57%, 40%)", rgb: "rgb(159, 81, 44)"},
|
||||
{authored: "currentcolor", name: "currentcolor", hex: "currentcolor", hsl: "currentcolor", rgb: "currentcolor"},
|
||||
{authored: "inherit", name: "inherit", hex: "inherit", hsl: "inherit", rgb: "inherit"},
|
||||
{authored: "initial", name: "initial", hex: "initial", hsl: "initial", rgb: "initial"},
|
||||
|
@ -13,6 +13,7 @@ const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
const {colorUtils} = require("devtools/css-color");
|
||||
const Heritage = require("sdk/core/heritage");
|
||||
const {CSSTransformPreviewer} = require("devtools/shared/widgets/CSSTransformPreviewer");
|
||||
const {Eyedropper} = require("devtools/eyedropper/eyedropper");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
@ -692,7 +693,7 @@ Tooltip.prototype = {
|
||||
let iframe = this.doc.createElementNS(XHTML_NS, "iframe");
|
||||
iframe.setAttribute("transparent", true);
|
||||
iframe.setAttribute("width", "210");
|
||||
iframe.setAttribute("height", "195");
|
||||
iframe.setAttribute("height", "220");
|
||||
iframe.setAttribute("flex", "1");
|
||||
iframe.setAttribute("class", "devtools-tooltip-iframe");
|
||||
|
||||
@ -707,12 +708,21 @@ Tooltip.prototype = {
|
||||
let container = win.document.getElementById("spectrum");
|
||||
let spectrum = new Spectrum(container, color);
|
||||
|
||||
// Finalize spectrum's init when the tooltip becomes visible
|
||||
panel.addEventListener("popupshown", function shown() {
|
||||
panel.removeEventListener("popupshown", shown, true);
|
||||
function finalizeSpectrum() {
|
||||
spectrum.show();
|
||||
def.resolve(spectrum);
|
||||
}, true);
|
||||
}
|
||||
|
||||
// Finalize spectrum's init when the tooltip becomes visible
|
||||
if (panel.state == "open") {
|
||||
finalizeSpectrum();
|
||||
}
|
||||
else {
|
||||
panel.addEventListener("popupshown", function shown() {
|
||||
panel.removeEventListener("popupshown", shown, true);
|
||||
finalizeSpectrum();
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
iframe.addEventListener("load", onLoad, true);
|
||||
iframe.setAttribute("src", SPECTRUM_FRAME);
|
||||
@ -832,7 +842,11 @@ SwatchBasedEditorTooltip.prototype = {
|
||||
show: function() {
|
||||
if (this.activeSwatch) {
|
||||
this.tooltip.show(this.activeSwatch, "topcenter bottomleft");
|
||||
this.tooltip.once("hidden", () => this.activeSwatch = null);
|
||||
this.tooltip.once("hidden", () => {
|
||||
if (!this.eyedropperOpen) {
|
||||
this.activeSwatch = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@ -951,6 +965,7 @@ function SwatchColorPickerTooltip(doc) {
|
||||
// resolves to the spectrum instance
|
||||
this.spectrum = this.tooltip.setColorPickerContent([0, 0, 0, 1]);
|
||||
this._onSpectrumColorChange = this._onSpectrumColorChange.bind(this);
|
||||
this._openEyeDropper = this._openEyeDropper.bind(this);
|
||||
}
|
||||
|
||||
module.exports.SwatchColorPickerTooltip = SwatchColorPickerTooltip;
|
||||
@ -975,16 +990,59 @@ SwatchColorPickerTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.pr
|
||||
spectrum.updateUI();
|
||||
});
|
||||
}
|
||||
|
||||
let tooltipDoc = this.tooltip.content.contentDocument;
|
||||
let eyeButton = tooltipDoc.querySelector("#eyedropper-button");
|
||||
eyeButton.addEventListener("click", this._openEyeDropper);
|
||||
},
|
||||
|
||||
_onSpectrumColorChange: function(event, rgba, cssColor) {
|
||||
this._selectColor(cssColor);
|
||||
},
|
||||
|
||||
_selectColor: function(color) {
|
||||
if (this.activeSwatch) {
|
||||
this.activeSwatch.style.backgroundColor = cssColor;
|
||||
this.currentSwatchColor.textContent = cssColor;
|
||||
this.preview(cssColor);
|
||||
this.activeSwatch.style.backgroundColor = color;
|
||||
this.currentSwatchColor.textContent = color;
|
||||
this.preview(color);
|
||||
}
|
||||
},
|
||||
|
||||
_openEyeDropper: function() {
|
||||
let chromeWindow = this.tooltip.doc.defaultView.top;
|
||||
let windowType = chromeWindow.document.documentElement
|
||||
.getAttribute("windowtype");
|
||||
let toolboxWindow;
|
||||
if (windowType != "navigator:browser") {
|
||||
// this means the toolbox is in a seperate window. We need to make
|
||||
// sure we'll be inspecting the browser window instead
|
||||
toolboxWindow = chromeWindow;
|
||||
chromeWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
chromeWindow.focus();
|
||||
}
|
||||
let dropper = new Eyedropper(chromeWindow, { copyOnSelect: false });
|
||||
|
||||
dropper.once("select", (event, color) => {
|
||||
if (toolboxWindow) {
|
||||
toolboxWindow.focus();
|
||||
}
|
||||
this._selectColor(color);
|
||||
});
|
||||
|
||||
dropper.once("destroy", () => {
|
||||
this.eyedropperOpen = false;
|
||||
this.activeSwatch = null;
|
||||
})
|
||||
|
||||
dropper.open();
|
||||
this.eyedropperOpen = true;
|
||||
|
||||
// close the colorpicker tooltip so that only the eyedropper is open.
|
||||
this.hide();
|
||||
|
||||
this.tooltip.emit("eyedropper-opened", dropper);
|
||||
},
|
||||
|
||||
_colorToRgba: function(color) {
|
||||
color = new colorUtils.CssColor(color);
|
||||
let rgba = color._getRGBATuple();
|
||||
|
@ -19,5 +19,6 @@
|
||||
</head>
|
||||
<body role="application">
|
||||
<div id="spectrum"></div>
|
||||
<button id="eyedropper-button"></button>
|
||||
</body>
|
||||
</html>
|
@ -2,6 +2,20 @@
|
||||
* 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/. */
|
||||
|
||||
#eyedropper-button {
|
||||
background: url("chrome://browser/skin/devtools/eyedropper-black.png") no-repeat center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
-moz-margin-start: 6px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.theme-dark #eyedropper-button {
|
||||
filter: url(chrome://browser/skin/devtools/filters.svg#colorpicker-invert);
|
||||
}
|
||||
|
||||
/* Mix-in classes */
|
||||
|
||||
.spectrum-checker {
|
||||
|
@ -11,6 +11,8 @@ const TAB_SIZE = "devtools.editor.tabsize";
|
||||
const EXPAND_TAB = "devtools.editor.expandtab";
|
||||
const KEYMAP = "devtools.editor.keymap";
|
||||
const AUTO_CLOSE = "devtools.editor.autoclosebrackets";
|
||||
const DETECT_INDENT = "devtools.editor.detectindentation";
|
||||
const DETECT_INDENT_MAX_LINES = 500;
|
||||
const L10N_BUNDLE = "chrome://browser/locale/devtools/sourceeditor.properties";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
@ -312,6 +314,9 @@ Editor.prototype = {
|
||||
|
||||
this.container = env;
|
||||
editors.set(this, cm);
|
||||
|
||||
this.resetIndentUnit();
|
||||
|
||||
def.resolve();
|
||||
};
|
||||
|
||||
@ -360,6 +365,33 @@ Editor.prototype = {
|
||||
setText: function (value) {
|
||||
let cm = editors.get(this);
|
||||
cm.setValue(value);
|
||||
|
||||
this.resetIndentUnit();
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the editor's indentation based on the current prefs and
|
||||
* re-detect indentation if we should.
|
||||
*/
|
||||
resetIndentUnit: function() {
|
||||
let cm = editors.get(this);
|
||||
|
||||
let indentWithTabs = !Services.prefs.getBoolPref(EXPAND_TAB);
|
||||
let indentUnit = Services.prefs.getIntPref(TAB_SIZE);
|
||||
let shouldDetect = Services.prefs.getBoolPref(DETECT_INDENT);
|
||||
|
||||
cm.setOption("tabSize", indentUnit);
|
||||
|
||||
if (shouldDetect) {
|
||||
let indent = detectIndentation(this);
|
||||
if (indent != null) {
|
||||
indentWithTabs = indent.tabs;
|
||||
indentUnit = indent.spaces ? indent.spaces : indentUnit;
|
||||
}
|
||||
}
|
||||
|
||||
cm.setOption("indentUnit", indentUnit);
|
||||
cm.setOption("indentWithTabs", indentWithTabs);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -968,4 +1000,70 @@ function controller(ed) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the indentation used in an editor. Returns an object
|
||||
* with 'tabs' - whether this is tab-indented and 'spaces' - the
|
||||
* width of one indent in spaces. Or `null` if it's inconclusive.
|
||||
*/
|
||||
function detectIndentation(ed) {
|
||||
let cm = editors.get(ed);
|
||||
|
||||
let spaces = {}; // # spaces indent -> # lines with that indent
|
||||
let last = 0; // indentation width of the last line we saw
|
||||
let tabs = 0; // # of lines that start with a tab
|
||||
let total = 0; // # of indented lines (non-zero indent)
|
||||
|
||||
cm.eachLine(0, DETECT_INDENT_MAX_LINES, (line) => {
|
||||
let text = line.text;
|
||||
|
||||
if (text.startsWith("\t")) {
|
||||
tabs++;
|
||||
total++;
|
||||
return;
|
||||
}
|
||||
let width = 0;
|
||||
while (text[width] === " ") {
|
||||
width++;
|
||||
}
|
||||
// don't count lines that are all spaces
|
||||
if (width == text.length) {
|
||||
last = 0;
|
||||
return;
|
||||
}
|
||||
if (width > 1) {
|
||||
total++;
|
||||
}
|
||||
|
||||
// see how much this line is offset from the line above it
|
||||
let indent = Math.abs(width - last);
|
||||
if (indent > 1) {
|
||||
spaces[indent] = (spaces[indent] || 0) + 1;
|
||||
}
|
||||
last = width;
|
||||
});
|
||||
|
||||
// this file is not indented at all
|
||||
if (total == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// mark as tabs if they start more than half the lines
|
||||
if (tabs >= total / 2) {
|
||||
return { tabs: true };
|
||||
}
|
||||
|
||||
// find most frequent non-zero width difference between adjacent lines
|
||||
let freqIndent = null, max = 0;
|
||||
for (let width in spaces) {
|
||||
width = parseInt(width, 10);
|
||||
let tally = spaces[width];
|
||||
if (tally > max) {
|
||||
max = tally;
|
||||
freqIndent = width;
|
||||
}
|
||||
}
|
||||
|
||||
return { tabs: false, spaces: freqIndent };
|
||||
}
|
||||
|
||||
module.exports = Editor;
|
||||
|
@ -31,6 +31,7 @@ support-files =
|
||||
[browser_css_autocompletion.js]
|
||||
[browser_css_getInfo.js]
|
||||
[browser_css_statemachine.js]
|
||||
[browser_detectindent.js]
|
||||
[browser_vimemacs.js]
|
||||
skip-if = os == 'linux'&&debug # bug 981707
|
||||
|
||||
|
90
browser/devtools/sourceeditor/test/browser_detectindent.js
Normal file
@ -0,0 +1,90 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
const TWO_SPACES_CODE = [
|
||||
"/*",
|
||||
" * tricky comment block",
|
||||
" */",
|
||||
"div {",
|
||||
" color: red;",
|
||||
" background: blue;",
|
||||
"}",
|
||||
" ",
|
||||
"span {",
|
||||
" padding-left: 10px;",
|
||||
"}"
|
||||
].join("\n");
|
||||
|
||||
const FOUR_SPACES_CODE = [
|
||||
"var obj = {",
|
||||
" addNumbers: function() {",
|
||||
" var x = 5;",
|
||||
" var y = 18;",
|
||||
" return x + y;",
|
||||
" },",
|
||||
" ",
|
||||
" /*",
|
||||
" * Do some stuff to two numbers",
|
||||
" * ",
|
||||
" * @param x",
|
||||
" * @param y",
|
||||
" * ",
|
||||
" * @return the result of doing stuff",
|
||||
" */",
|
||||
" subtractNumbers: function(x, y) {",
|
||||
" var x += 7;",
|
||||
" var y += 18;",
|
||||
" var result = x - y;",
|
||||
" result %= 2;",
|
||||
" }",
|
||||
"}"
|
||||
].join("\n");
|
||||
|
||||
const TABS_CODE = [
|
||||
"/*",
|
||||
" * tricky comment block",
|
||||
" */",
|
||||
"div {",
|
||||
"\tcolor: red;",
|
||||
"\tbackground: blue;",
|
||||
"}",
|
||||
"",
|
||||
"span {",
|
||||
"\tpadding-left: 10px;",
|
||||
"}"
|
||||
].join("\n");
|
||||
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
setup((ed, win) => {
|
||||
is(ed.getOption("indentUnit"), 4,
|
||||
"4 spaces before code added");
|
||||
is(ed.getOption("indentWithTabs"), false,
|
||||
"spaces is default");
|
||||
|
||||
ed.setText(TWO_SPACES_CODE);
|
||||
is(ed.getOption("indentUnit"), 2,
|
||||
"2 spaces detected in 2 space code");
|
||||
is(ed.getOption("indentWithTabs"), false,
|
||||
"spaces detected in 2 space code");
|
||||
|
||||
ed.setText(FOUR_SPACES_CODE);
|
||||
is(ed.getOption("indentUnit"), 4,
|
||||
"4 spaces detected in 4 space code");
|
||||
is(ed.getOption("indentWithTabs"), false,
|
||||
"spaces detected in 4 space code");
|
||||
|
||||
ed.setText(TABS_CODE);
|
||||
is(ed.getOption("indentUnit"), 4,
|
||||
"4 space indentation unit");
|
||||
is(ed.getOption("indentWithTabs"), true,
|
||||
"tabs detected in majority tabs code");
|
||||
|
||||
teardown(ed, win);
|
||||
});
|
||||
}
|
@ -2,21 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const gcli = devtools.require("gcli/index");
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
/**
|
||||
* 'edit' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items = [{
|
||||
name: "edit",
|
||||
description: gcli.lookup("editDesc"),
|
||||
manual: gcli.lookup("editManual2"),
|
||||
@ -42,10 +32,11 @@ gcli.addCommand({
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let target = context.environment.target;
|
||||
let gDevTools = require("resource:///modules/devtools/gDevTools.jsm").gDevTools;
|
||||
return gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
|
||||
let styleEditor = toolbox.getCurrentPanel();
|
||||
styleEditor.selectStyleSheet(args.resource.element, args.line);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
});
|
||||
}];
|
@ -1997,7 +1997,8 @@ TextPropertyEditor.prototype = {
|
||||
*/
|
||||
get editing() {
|
||||
return !!(this.nameSpan.inplaceEditor || this.valueSpan.inplaceEditor ||
|
||||
this.ruleEditor.ruleView.colorPicker.tooltip.isShown());
|
||||
this.ruleEditor.ruleView.colorPicker.tooltip.isShown() ||
|
||||
this.ruleEditor.ruleView.colorPicker.eyedropperOpen);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -60,6 +60,8 @@ support-files =
|
||||
[browser_ruleview_edit-property-order.js]
|
||||
[browser_ruleview_edit-property_01.js]
|
||||
[browser_ruleview_edit-property_02.js]
|
||||
[browser_ruleview_eyedropper.js]
|
||||
skip-if = os == "win" && debug # bug 963492
|
||||
[browser_ruleview_inherit.js]
|
||||
[browser_ruleview_keybindings.js]
|
||||
[browser_ruleview_livepreview.js]
|
||||
|
@ -0,0 +1,141 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const PAGE_CONTENT = [
|
||||
'<style type="text/css">',
|
||||
' body {',
|
||||
' background-color: #ff5;',
|
||||
' padding: 50px',
|
||||
' }',
|
||||
' div {',
|
||||
' width: 100px;',
|
||||
' height: 100px;',
|
||||
' background-color: #f09;',
|
||||
' }',
|
||||
'</style>',
|
||||
'<body><div></div></body>'
|
||||
].join("\n");
|
||||
|
||||
const ORIGINAL_COLOR = "rgb(255, 0, 153)"; // #f09
|
||||
const EXPECTED_COLOR = "rgb(255, 255, 85)"; // #ff5
|
||||
|
||||
// Test opening the eyedropper from the color picker. Pressing escape
|
||||
// to close it, and clicking the page to select a color.
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
yield addTab("data:text/html,rule view eyedropper test");
|
||||
content.document.body.innerHTML = PAGE_CONTENT;
|
||||
let {toolbox, inspector, view} = yield openRuleView();
|
||||
|
||||
let element = content.document.querySelector("div");
|
||||
inspector.selection.setNode(element, "test");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
let property = getRuleViewProperty(view, "div", "background-color");
|
||||
let swatch = property.valueSpan.querySelector(".ruleview-colorswatch");
|
||||
ok(swatch, "Color swatch is displayed for the bg-color property");
|
||||
|
||||
let dropper = yield openEyedropper(view, swatch);
|
||||
|
||||
let tooltip = view.colorPicker.tooltip;
|
||||
ok(tooltip.isHidden(),
|
||||
"color picker tooltip is closed after opening eyedropper");
|
||||
|
||||
yield testESC(swatch, dropper);
|
||||
|
||||
dropper = yield openEyedropper(view, swatch);
|
||||
|
||||
ok(dropper, "dropper opened");
|
||||
|
||||
yield testSelect(swatch, dropper);
|
||||
});
|
||||
|
||||
|
||||
function testESC(swatch, dropper) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
dropper.once("destroy", () => {
|
||||
let color = swatch.style.backgroundColor;
|
||||
is(color, ORIGINAL_COLOR, "swatch didn't change after pressing ESC");
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
inspectPage(dropper, false).then(pressESC);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function testSelect(swatch, dropper) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
dropper.once("destroy", () => {
|
||||
let color = swatch.style.backgroundColor;
|
||||
is(color, EXPECTED_COLOR, "swatch changed colors");
|
||||
|
||||
// the change to the content is done async after rule view change
|
||||
executeSoon(() => {
|
||||
let element = content.document.querySelector("div");
|
||||
is(content.window.getComputedStyle(element).backgroundColor,
|
||||
EXPECTED_COLOR,
|
||||
"div's color set to body color after dropper");
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
inspectPage(dropper);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
||||
/* Helpers */
|
||||
|
||||
function openEyedropper(view, swatch) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let tooltip = view.colorPicker.tooltip;
|
||||
|
||||
tooltip.once("shown", () => {
|
||||
let tooltipDoc = tooltip.content.contentDocument;
|
||||
let dropperButton = tooltipDoc.querySelector("#eyedropper-button");
|
||||
|
||||
tooltip.once("eyedropper-opened", (event, dropper) => {
|
||||
deferred.resolve(dropper)
|
||||
});
|
||||
dropperButton.click();
|
||||
});
|
||||
|
||||
swatch.click();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function inspectPage(dropper, click=true) {
|
||||
let target = content.document.body;
|
||||
let win = content.window;
|
||||
|
||||
EventUtils.synthesizeMouse(target, 10, 10, { type: "mousemove" }, win);
|
||||
|
||||
return dropperLoaded(dropper).then(() => {
|
||||
EventUtils.synthesizeMouse(target, 20, 20, { type: "mousemove" }, win);
|
||||
if (click) {
|
||||
EventUtils.synthesizeMouse(target, 20, 20, {}, win);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function dropperLoaded(dropper) {
|
||||
if (dropper.loaded) {
|
||||
return promise.resolve();
|
||||
}
|
||||
|
||||
return dropper.once("load");
|
||||
}
|
||||
|
||||
function pressESC() {
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", { });
|
||||
}
|
@ -1,9 +0,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/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
||||
$(NSINSTALL) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools/tilt
|
@ -1,8 +1,19 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
JS_MODULES_PATH = 'modules/devtools/tilt'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'tilt-commands.js',
|
||||
'tilt-gl.js',
|
||||
'tilt-math.js',
|
||||
'tilt-utils.js',
|
||||
'tilt-visualizer-style.js',
|
||||
'tilt-visualizer.js',
|
||||
'tilt.js',
|
||||
'TiltWorkerCrafter.js',
|
||||
'TiltWorkerPicker.js'
|
||||
]
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
@ -1,40 +1,28 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ ];
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
const { devtools } = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const gcli = devtools.require("gcli/index");
|
||||
const gcli = require("gcli/index");
|
||||
|
||||
// Fetch TiltManager using the current loader, but don't save a
|
||||
// reference to it, because it might change with a tool reload.
|
||||
// We can clean this up once the command line is loadered.
|
||||
Object.defineProperty(this, "TiltManager", {
|
||||
get: function() {
|
||||
return devtools.require("devtools/tilt/tilt").TiltManager;
|
||||
return require("devtools/tilt/tilt").TiltManager;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
/**
|
||||
* 'tilt' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
exports.items = [
|
||||
{
|
||||
name: 'tilt',
|
||||
description: gcli.lookup("tiltDesc"),
|
||||
manual: gcli.lookup("tiltManual")
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt open' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt open',
|
||||
description: gcli.lookup("tiltOpenDesc"),
|
||||
manual: gcli.lookup("tiltOpenManual"),
|
||||
@ -45,13 +33,8 @@ gcli.addCommand({
|
||||
Tilt.toggle();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt toggle' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: "tilt toggle",
|
||||
buttonId: "command-button-tilt",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
@ -80,13 +63,8 @@ gcli.addCommand({
|
||||
let Tilt = TiltManager.getTiltForBrowser(chromeWindow);
|
||||
Tilt.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt translate' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt translate',
|
||||
description: gcli.lookup("tiltTranslateDesc"),
|
||||
manual: gcli.lookup("tiltTranslateManual"),
|
||||
@ -113,13 +91,8 @@ gcli.addCommand({
|
||||
Tilt.currentInstance.controller.arcball.translate([args.x, args.y]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt rotate' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt rotate',
|
||||
description: gcli.lookup("tiltRotateDesc"),
|
||||
manual: gcli.lookup("tiltRotateManual"),
|
||||
@ -153,13 +126,8 @@ gcli.addCommand({
|
||||
Tilt.currentInstance.controller.arcball.rotate([args.x, args.y, args.z]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt zoom' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt zoom',
|
||||
description: gcli.lookup("tiltZoomDesc"),
|
||||
manual: gcli.lookup("tiltZoomManual"),
|
||||
@ -179,13 +147,8 @@ gcli.addCommand({
|
||||
Tilt.currentInstance.controller.arcball.zoom(-args.zoom);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt reset' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt reset',
|
||||
description: gcli.lookup("tiltResetDesc"),
|
||||
manual: gcli.lookup("tiltResetManual"),
|
||||
@ -197,13 +160,8 @@ gcli.addCommand({
|
||||
Tilt.currentInstance.controller.arcball.reset();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'tilt close' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
},
|
||||
{
|
||||
name: 'tilt close',
|
||||
description: gcli.lookup("tiltCloseDesc"),
|
||||
manual: gcli.lookup("tiltCloseManual"),
|
||||
@ -213,4 +171,5 @@ gcli.addCommand({
|
||||
|
||||
Tilt.destroy(Tilt.currentWindowId);
|
||||
}
|
||||
});
|
||||
}
|
||||
];
|
99
browser/devtools/webconsole/console-commands.js
Normal file
@ -0,0 +1,99 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const gcli = require("gcli/index");
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
const { gDevTools } = require("resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
gDevTools.on("toolbox-ready", (e, toolbox) => {
|
||||
if (!toolbox.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
let fireChangeForTab = () => {
|
||||
eventEmitter.emit("changed", toolbox.target.tab);
|
||||
};
|
||||
|
||||
toolbox.on("split-console", fireChangeForTab);
|
||||
toolbox.on("select", fireChangeForTab);
|
||||
|
||||
toolbox.once("destroyed", () => {
|
||||
toolbox.off("split-console", fireChangeForTab);
|
||||
toolbox.off("select", fireChangeForTab);
|
||||
});
|
||||
});
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
name: 'splitconsole',
|
||||
hidden: true,
|
||||
buttonId: "command-button-splitconsole",
|
||||
buttonClass: "command-button command-button-invertable",
|
||||
tooltipText: gcli.lookup("splitconsoleTooltip"),
|
||||
state: {
|
||||
isChecked: function(target) {
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
return toolbox && toolbox.splitConsole;
|
||||
},
|
||||
onChange: function(target, changeHandler) {
|
||||
eventEmitter.on("changed", changeHandler);
|
||||
},
|
||||
offChange: function(target, changeHandler) {
|
||||
eventEmitter.off("changed", changeHandler);
|
||||
},
|
||||
},
|
||||
exec: function(args, context) {
|
||||
let target = context.environment.target;
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
|
||||
if (!toolbox) {
|
||||
return gDevTools.showToolbox(target, "inspector").then((toolbox) => {
|
||||
toolbox.toggleSplitConsole();
|
||||
});
|
||||
} else {
|
||||
toolbox.toggleSplitConsole();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "console",
|
||||
description: gcli.lookup("consoleDesc"),
|
||||
manual: gcli.lookup("consoleManual")
|
||||
},
|
||||
{
|
||||
name: "console clear",
|
||||
description: gcli.lookup("consoleclearDesc"),
|
||||
exec: function(args, context) {
|
||||
let toolbox = gDevTools.getToolbox(context.environment.target);
|
||||
if (toolbox == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let panel = toolbox.getPanel("webconsole");
|
||||
if (panel == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
panel.hud.jsterm.clearOutput();
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "console close",
|
||||
description: gcli.lookup("consolecloseDesc"),
|
||||
exec: function(args, context) {
|
||||
return gDevTools.closeToolbox(context.environment.target);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "console open",
|
||||
description: gcli.lookup("consoleopenDesc"),
|
||||
exec: function(args, context) {
|
||||
return gDevTools.showToolbox(context.environment.target, "webconsole");
|
||||
}
|
||||
}
|
||||
];
|
@ -3,7 +3,7 @@ skip-if = e10s # Bug 942707 - PDF viewer doesn't work with e10s.
|
||||
support-files = file_pdfjs_test.pdf
|
||||
|
||||
[browser_pdfjs_main.js]
|
||||
skip-if = (os == "mac" && debug) # Bug 963075 - leaks when run in chunked mochitest-bc mode
|
||||
skip-if = (os == "mac" && debug) || os == "win" # Bug 963075 - leaks when run in chunked mochitest-bc mode
|
||||
[browser_pdfjs_savedialog.js]
|
||||
[browser_pdfjs_views.js]
|
||||
skip-if = (os == "mac" && debug) # Bug 963075 - leaks when run in chunked mochitest-bc mode
|
||||
skip-if = (os == "mac" && debug) || os == "win" # Bug 963075 - leaks when run in chunked mochitest-bc mode
|
||||
|
@ -232,6 +232,9 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
||||
<!ENTITY responsiveDesignTool.accesskey "R">
|
||||
<!ENTITY responsiveDesignTool.commandkey "M">
|
||||
|
||||
<!ENTITY eyedropper.label "Eyedropper">
|
||||
<!ENTITY eyedropper.accesskey "Y">
|
||||
|
||||
<!-- LOCALIZATION NOTE (scratchpad.label): This menu item label appears
|
||||
- in the Tools menu. See bug 653093.
|
||||
- The Scratchpad is intended to provide a simple text editor for creating
|
||||
|
@ -0,0 +1,14 @@
|
||||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE These strings are used in the Eyedropper color tool.
|
||||
# LOCALIZATION NOTE The correct localization of this file might be to keep it
|
||||
# in English, or another language commonly spoken among web developers.
|
||||
# You want to make that choice consistent across the developer tools.
|
||||
# A good criteria is the language in which you'd find the best documentation
|
||||
# on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (colorValue.copied): This text is displayed when the user selects a
|
||||
# color with the eyedropper and it's copied to the clipboard.
|
||||
colorValue.copied=copied
|
@ -562,10 +562,9 @@ cmdDesc=Manipulate the commands
|
||||
# name, which is why it should be as short as possible.
|
||||
cmdRefreshDesc=Re-read mozcmd directory
|
||||
|
||||
# LOCALIZATION NOTE (cmdStatus) When the we load new commands from mozcmd
|
||||
# directory, we report on how many we loaded. %1$S is a count of the number
|
||||
# of loaded commands, and %2$S is the directory we loaded from.
|
||||
cmdStatus=Read %1$S commands from '%2$S'
|
||||
# LOCALIZATION NOTE (cmdStatus2) When the we load new commands from mozcmd
|
||||
# directory, we report where we loaded from using %1$S.
|
||||
cmdStatus2=Read commands from '%1$S'
|
||||
|
||||
# LOCALIZATION NOTE (cmdSetdirDesc)
|
||||
cmdSetdirDesc=Setup a mozcmd directory
|
||||
|
@ -55,6 +55,7 @@
|
||||
locale/browser/devtools/toolbox.dtd (%chrome/browser/devtools/toolbox.dtd)
|
||||
locale/browser/devtools/toolbox.properties (%chrome/browser/devtools/toolbox.properties)
|
||||
locale/browser/devtools/inspector.dtd (%chrome/browser/devtools/inspector.dtd)
|
||||
locale/browser/devtools/eyedropper.properties (%chrome/browser/devtools/eyedropper.properties)
|
||||
locale/browser/devtools/connection-screen.dtd (%chrome/browser/devtools/connection-screen.dtd)
|
||||
locale/browser/devtools/connection-screen.properties (%chrome/browser/devtools/connection-screen.properties)
|
||||
locale/browser/devtools/font-inspector.dtd (%chrome/browser/devtools/font-inspector.dtd)
|
||||
|
@ -2263,6 +2263,19 @@ chatbox {
|
||||
|
||||
%include ../shared/UITour.inc.css
|
||||
|
||||
#UITourHighlight {
|
||||
/* Below are some fixes for people without an X compositor on Linux.
|
||||
This is why we can't have nice things: */
|
||||
/* Animations don't repaint properly without an X compositor. */
|
||||
animation-name: none !important;
|
||||
/* Opacity rounds to 0 or 1 on Linux without an X compositor so make the
|
||||
background be transparent in that case by having all alpha values < 0.5 */
|
||||
background-image: radial-gradient(50% 100%, rgba(0,149,220,0.3) 50%, rgba(0,149,220,0.49) 100%);
|
||||
/* The highlight isn't anti-aliased without an X compositor so make it thicker.
|
||||
Make it a darker color since we don't have the box-shadow in this case. */
|
||||
border: 4px solid rgb(0,149,220);
|
||||
}
|
||||
|
||||
#UITourTooltipDescription {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
@ -120,12 +120,13 @@
|
||||
color: hsl(210,30%,75%);
|
||||
}
|
||||
|
||||
.gcli-menu-option:hover {
|
||||
.gcli-menu-name:hover,
|
||||
.gcli-menu-desc:hover {
|
||||
background-color: hsla(0,0%,0%,.3);
|
||||
}
|
||||
|
||||
.gcli-menu-highlight,
|
||||
.gcli-menu-highlight.gcli-menu-option:hover {
|
||||
.gcli-menu-highlight:hover {
|
||||
background-color: hsla(0,100%,100%,.1);
|
||||
}
|
||||
|
||||
|
@ -221,6 +221,7 @@ browser.jar:
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
* skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
skin/classic/browser/devtools/eyedropper.css (../shared/devtools/eyedropper.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (../shared/devtools/images/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
|
||||
skin/classic/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
|
||||
@ -296,6 +297,7 @@ browser.jar:
|
||||
skin/classic/browser/devtools/app-manager/rocket.svg (../shared/devtools/app-manager/images/rocket.svg)
|
||||
skin/classic/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
|
||||
skin/classic/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
|
||||
skin/classic/browser/devtools/eyedropper-black.png (../shared/devtools/images/eyedropper-black.png)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
|
@ -9,7 +9,6 @@
|
||||
%define forwardTransitionLength 150ms
|
||||
%define conditionalForwardWithUrlbar window:not([chromehidden~="toolbar"]) #urlbar-container
|
||||
%define conditionalForwardWithUrlbarWidth 30
|
||||
%define nativeTitlebarHeight 22px
|
||||
%define spaceAboveTabbar 9px
|
||||
%define toolbarButtonPressed :hover:active:not([disabled="true"]):not([cui-areatype="menu-panel"])
|
||||
%define windowButtonMarginTop 11px
|
||||
@ -59,25 +58,18 @@
|
||||
|
||||
@media (-moz-mac-lion-theme) {
|
||||
.titlebar-placeholder[type="fullscreen-button"],
|
||||
#titlebar-fullscreen-button {
|
||||
#titlebar-secondary-buttonbox {
|
||||
margin-right: 7px;
|
||||
margin-left: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
#main-window:not(:-moz-lwtheme):not([privatebrowsingmode=temporary]) > #titlebar {
|
||||
#main-window:not(:-moz-lwtheme) > #titlebar {
|
||||
-moz-appearance: -moz-window-titlebar;
|
||||
}
|
||||
|
||||
#main-window:not([tabsintitlebar]) > #titlebar {
|
||||
min-height: @nativeTitlebarHeight@;
|
||||
}
|
||||
|
||||
/**
|
||||
* When we hide #titlebar-content, we display the native window buttons in
|
||||
* their default locations.
|
||||
*/
|
||||
#main-window:not([tabsintitlebar]) > #titlebar > #titlebar-content {
|
||||
display: none;
|
||||
height: 22px; /* The native titlebar on OS X is 22px tall. */
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,11 +84,11 @@
|
||||
* We also vertically center the window buttons.
|
||||
*/
|
||||
#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-buttonbox-container,
|
||||
#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-fullscreen-button {
|
||||
#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-secondary-buttonbox > #titlebar-fullscreen-button {
|
||||
margin-top: @windowButtonMarginTop@;
|
||||
}
|
||||
|
||||
#main-window[tabsintitlebar][customize-entered] > #titlebar {
|
||||
#main-window[customizing] > #titlebar {
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
@ -2776,11 +2768,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
text-shadow: inherit;
|
||||
}
|
||||
|
||||
.tabbrowser-tabs[closebuttons="hidden"] > * > * > * > .tab-close-button:not([pinned]) {
|
||||
display: -moz-box;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tabs-newtab-button > .toolbarbutton-icon {
|
||||
-moz-box-align: center;
|
||||
border: solid transparent;
|
||||
@ -2808,8 +2795,8 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#main-window:not(:-moz-any([privatebrowsingmode=temporary],[customizing])) #navigator-toolbox[inFullscreen]:not(:-moz-lwtheme)::before,
|
||||
#main-window:not(:-moz-any([privatebrowsingmode=temporary],[customizing],[tabsintitlebar])) #navigator-toolbox:not(:-moz-lwtheme)::before {
|
||||
#main-window:not([customizing]) #navigator-toolbox[inFullscreen]:not(:-moz-lwtheme)::before,
|
||||
#main-window:not(:-moz-any([customizing],[tabsintitlebar])) #navigator-toolbox:not(:-moz-lwtheme)::before {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@ -2846,7 +2833,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#main-window:-moz-any([privatebrowsingmode=temporary],[sizemode="fullscreen"],[customize-entered]) #TabsToolbar::after,
|
||||
#main-window:-moz-any([sizemode="fullscreen"],[customize-entered]) #TabsToolbar::after,
|
||||
#main-window:not([tabsintitlebar]) #TabsToolbar::after,
|
||||
#TabsToolbar:-moz-lwtheme::after {
|
||||
visibility: visible;
|
||||
@ -3974,11 +3961,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
* total height of this pseudo-element, not just the top-padding. */
|
||||
height: calc(@tabMinHeight@ + @spaceAboveTabbar@) !important;
|
||||
}
|
||||
#main-window[inFullscreen][privatebrowsingmode=temporary] {
|
||||
/* Adjust by the full element height of #titlebar, since that element is
|
||||
* not displayed in native full-screen. */
|
||||
padding-top: @spaceAboveTabbar@;
|
||||
}
|
||||
}
|
||||
|
||||
#full-screen-warning-message {
|
||||
@ -4308,6 +4290,7 @@ window > chatbox {
|
||||
}
|
||||
|
||||
#main-window[tabsintitlebar][customize-entered] > #titlebar,
|
||||
#main-window[privatebrowsingmode=temporary]:not([tabsintitlebar])[customize-entered] > #titlebar,
|
||||
#main-window[customize-entered] > #tab-view-deck {
|
||||
background-image: url("chrome://browser/skin/customizableui/customizeMode-gridTexture.png"),
|
||||
url("chrome://browser/skin/customizableui/background-noise-toolbar.png"),
|
||||
@ -4377,59 +4360,68 @@ window > chatbox {
|
||||
|
||||
/* End customization mode */
|
||||
|
||||
#main-window[privatebrowsingmode=temporary] {
|
||||
.private-browsing-indicator {
|
||||
background-image: url("chrome://browser/skin/privatebrowsing-mask.png");
|
||||
background-position: top right;
|
||||
background-repeat: no-repeat;
|
||||
background-color: -moz-mac-chrome-active;
|
||||
background-size: 100% auto;
|
||||
width: 38px;
|
||||
height: 28px;
|
||||
/**
|
||||
* The private browsing mask graphic has a 3px flare at the top. The distance
|
||||
* we want between the mask and items on either side is 7px, so we use 4px,
|
||||
* since the other 3px is accounted for by the empty space on either side.
|
||||
*/
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#titlebar-secondary-buttonbox > .private-browsing-indicator {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary]:not([tabsintitlebar]) > #titlebar > #titlebar-content > #titlebar-secondary-buttonbox > .private-browsing-indicator {
|
||||
background-image: url("chrome://browser/skin/privatebrowsing-mask-short.png");
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
#main-window:not([privatebrowsingmode=temporary]) .private-browsing-indicator,
|
||||
#main-window[privatebrowsingmode=temporary][inFullscreen] > #titlebar > #titlebar-content > #titlebar-secondary-buttonbox > .private-browsing-indicator,
|
||||
#main-window[privatebrowsingmode=temporary]:not([inFullscreen]) > #tab-view-deck > #browser-panel > #navigator-toolbox > #TabsToolbar > .private-browsing-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
#main-window[privatebrowsingmode=temporary] {
|
||||
.private-browsing-indicator {
|
||||
background-image: url("chrome://browser/skin/privatebrowsing-mask@2x.png");
|
||||
background-size: 38px;
|
||||
}
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary] {
|
||||
background-position: top right 20px;
|
||||
}
|
||||
|
||||
/* Note that the caption and fullscreen buttons stay in the same position for LTR and RTL but we
|
||||
move the private browsing indicator to the left in RTL. */
|
||||
#main-window[privatebrowsingmode=temporary]:-moz-locale-dir(rtl) {
|
||||
background-position: top left 70px;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary][inFullscreen]:-moz-locale-dir(rtl) {
|
||||
background-position: top left 10px;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary][inFullscreen] .titlebar-placeholder[type="fullscreen-button"]:-moz-locale-dir(ltr) {
|
||||
/* Override display:none for .titlebar-placeholder in fullscreen so we can have consistent
|
||||
position and padding for the private browsing indicator. */
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary]:-moz-window-inactive {
|
||||
background-color: -moz-mac-chrome-inactive;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary] #TabsToolbar {
|
||||
-moz-padding-end: 46px;
|
||||
#main-window[privatebrowsingmode=temporary]:not([tabsintitlebar]) > #titlebar > #titlebar-content > #titlebar-secondary-buttonbox > .private-browsing-indicator {
|
||||
background-image: url("chrome://browser/skin/privatebrowsing-mask-short@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-mac-lion-theme) {
|
||||
#main-window[privatebrowsingmode=temporary] #TabsToolbar:-moz-locale-dir(ltr) {
|
||||
-moz-padding-end: 36px;
|
||||
#TabsToolbar > .private-browsing-indicator {
|
||||
transform: translateY(-@spaceAboveTabbar@);
|
||||
/* We offset by 38px for mask graphic, plus 4px to account for the
|
||||
* margin-left, which sums to 42px.
|
||||
*/
|
||||
margin-right: -42px;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary] .titlebar-placeholder[type="fullscreen-button"],
|
||||
#main-window[privatebrowsingmode=temporary] > #titlebar > #titlebar-content > #titlebar-secondary-buttonbox > #titlebar-fullscreen-button {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
#main-window[privatebrowsingmode=temporary][inFullscreen] .titlebar-placeholder[type="fullscreen-button"] {
|
||||
/* Override display:none for .titlebar-placeholder in fullscreen so we can have consistent
|
||||
position and padding for the private browsing indicator. */
|
||||
display: -moz-box;
|
||||
}
|
||||
}
|
||||
|
||||
@media not all and (-moz-mac-lion-theme) {
|
||||
/* There is no OS fullscreen button prior to Lion so the PB indicator can move closer. */
|
||||
#main-window[privatebrowsingmode=temporary] {
|
||||
background-position: top right 10px;
|
||||
}
|
||||
#TabsToolbar > .private-browsing-indicator:-moz-locale-dir(rtl) {
|
||||
-moz-box-ordinal-group: 0;
|
||||
}
|
||||
|
||||
%include ../shared/UITour.inc.css
|
||||
|
@ -122,12 +122,13 @@
|
||||
color: hsl(210,30%,75%);
|
||||
}
|
||||
|
||||
.gcli-menu-option:hover {
|
||||
.gcli-menu-name:hover,
|
||||
.gcli-menu-desc:hover {
|
||||
background-color: hsla(0,0%,0%,.3);
|
||||
}
|
||||
|
||||
.gcli-menu-highlight,
|
||||
.gcli-menu-highlight.gcli-menu-option:hover {
|
||||
.gcli-menu-highlight:hover {
|
||||
background-color: hsla(0,100%,100%,.1);
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,8 @@ browser.jar:
|
||||
skin/classic/browser/Privacy-48.png
|
||||
skin/classic/browser/privatebrowsing-mask.png
|
||||
skin/classic/browser/privatebrowsing-mask@2x.png
|
||||
skin/classic/browser/privatebrowsing-mask-short.png
|
||||
skin/classic/browser/privatebrowsing-mask-short@2x.png
|
||||
skin/classic/browser/reload-stop-go.png
|
||||
skin/classic/browser/reload-stop-go@2x.png
|
||||
skin/classic/browser/searchbar-dropmarker.png
|
||||
@ -340,6 +342,7 @@ browser.jar:
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
* skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
skin/classic/browser/devtools/eyedropper.css (../shared/devtools/eyedropper.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (../shared/devtools/images/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
|
||||
skin/classic/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
|
||||
@ -415,6 +418,8 @@ browser.jar:
|
||||
skin/classic/browser/devtools/app-manager/rocket.svg (../shared/devtools/app-manager/images/rocket.svg)
|
||||
skin/classic/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
|
||||
skin/classic/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
|
||||
skin/classic/browser/devtools/eyedropper-black.png (../shared/devtools/images/eyedropper-black.png)
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
|
BIN
browser/themes/osx/privatebrowsing-mask-short.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
browser/themes/osx/privatebrowsing-mask-short@2x.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 918 B |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.1 KiB |
@ -18,7 +18,9 @@
|
||||
background-image: radial-gradient(50% 100%, rgba(0,149,220,0.4) 50%, rgba(0,149,220,0.6) 100%);
|
||||
border-radius: 40px;
|
||||
border: 1px solid white;
|
||||
box-shadow: 0 0 3px 0 rgba(0,0,0,0.5);
|
||||
/* The box-shadow opacity needs to be < 0.5 so it doesn't appear at 100% opacity
|
||||
on Linux without an X compositor where opacity is either 0 or 1. */
|
||||
box-shadow: 0 0 3px 0 rgba(0,0,0,0.49);
|
||||
min-height: 32px;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
@ -215,3 +215,14 @@
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Eyedropper Widget */
|
||||
|
||||
.devtools-eyedropper-panel {
|
||||
pointer-events: none;
|
||||
-moz-appearance: none;
|
||||
width: 156px;
|
||||
height: 120px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
45
browser/themes/shared/devtools/eyedropper.css
Normal file
@ -0,0 +1,45 @@
|
||||
/* 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/. */
|
||||
|
||||
#canvas {
|
||||
image-rendering: -moz-crisp-edges;
|
||||
cursor: none;
|
||||
border: 3px solid #E0E0E0;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#canvas-overflow {
|
||||
overflow: hidden;
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
#color-preview {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
box-shadow: 0px 0px 0px black;
|
||||
border: solid 1px #fff;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
#color-value-box {
|
||||
background-color: #E0E0E0;
|
||||
border-radius: 1px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#color-value {
|
||||
padding: 0.3em;
|
||||
text-shadow: 1px 1px 1px #fff;
|
||||
}
|
||||
|
||||
#color-value.highlight {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
window {
|
||||
/* inexplicably, otherwise background shows up on Linux */
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
}
|
@ -6,4 +6,11 @@
|
||||
<feFuncB type="table" tableValues=".1 0"/>
|
||||
</feComponentTransfer>
|
||||
</filter>
|
||||
<filter id="colorpicker-invert" x="0%" y="0%" width="100%" height="100%" >
|
||||
<feComponentTransfer>
|
||||
<feFuncR type="table" tableValues=".6 0"/>
|
||||
<feFuncG type="table" tableValues=".6 0"/>
|
||||
<feFuncB type="table" tableValues=".6 0"/>
|
||||
</feComponentTransfer>
|
||||
</filter>
|
||||
</svg>
|
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 596 B |
BIN
browser/themes/shared/devtools/images/eyedropper-black.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
@ -29,3 +29,11 @@
|
||||
background-position: 0 0, 0 0, right top;
|
||||
background-repeat: repeat-x, repeat-x, no-repeat;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
|
||||
@fgTabTextureLWT@;/*,
|
||||
lwtHeader;*/
|
||||
}
|
||||
}
|
||||
|
@ -1809,6 +1809,39 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
|
||||
|
||||
%include ../shared/tabs.inc.css
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
/* image preloading hack from shared/tabs.inc.css */
|
||||
#tabbrowser-tabs::before {
|
||||
background-image:
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-end@2x.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-middle@2x.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png);
|
||||
}
|
||||
|
||||
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]),
|
||||
.tabs-newtab-button:hover {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-middle@2x.png),
|
||||
url(chrome://browser/skin/tabbrowser/tab-background-end@2x.png);
|
||||
}
|
||||
|
||||
.tab-background-middle[selected=true] {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
|
||||
@fgTabTexture@,
|
||||
none;
|
||||
}
|
||||
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-start@2x.png);
|
||||
}
|
||||
|
||||
.tab-background-end[selected=true]:-moz-locale-dir(ltr)::after,
|
||||
.tab-background-start[selected=true]:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-end@2x.png);
|
||||
}
|
||||
}
|
||||
|
||||
%ifndef WINDOWS_AERO
|
||||
/* Use lighter colors of buttons and text in the titlebar on luna-blue */
|
||||
@media (-moz-windows-theme: luna-blue) {
|
||||
|
@ -120,12 +120,13 @@
|
||||
color: hsl(210,30%,75%);
|
||||
}
|
||||
|
||||
.gcli-menu-option:hover {
|
||||
.gcli-menu-name:hover,
|
||||
.gcli-menu-desc:hover {
|
||||
background-color: hsla(0,0%,0%,.3);
|
||||
}
|
||||
|
||||
.gcli-menu-highlight,
|
||||
.gcli-menu-highlight.gcli-menu-option:hover {
|
||||
.gcli-menu-highlight:hover {
|
||||
background-color: hsla(0,100%,100%,.1);
|
||||
}
|
||||
|
||||
|
@ -185,11 +185,15 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png)
|
||||
skin/classic/browser/tabbrowser/tab.png (tabbrowser/tab.png)
|
||||
skin/classic/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png)
|
||||
skin/classic/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png)
|
||||
skin/classic/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png)
|
||||
skin/classic/browser/tabbrowser/tab-arrow-left-inverted.png (tabbrowser/tab-arrow-left-inverted.png)
|
||||
skin/classic/browser/tabbrowser/tab-background-start.png (tabbrowser/tab-background-start.png)
|
||||
skin/classic/browser/tabbrowser/tab-background-start@2x.png (tabbrowser/tab-background-start@2x.png)
|
||||
skin/classic/browser/tabbrowser/tab-background-middle.png (tabbrowser/tab-background-middle.png)
|
||||
skin/classic/browser/tabbrowser/tab-background-middle@2x.png (tabbrowser/tab-background-middle@2x.png)
|
||||
skin/classic/browser/tabbrowser/tab-background-end.png (tabbrowser/tab-background-end.png)
|
||||
skin/classic/browser/tabbrowser/tab-background-end@2x.png (tabbrowser/tab-background-end@2x.png)
|
||||
skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png)
|
||||
|
||||
# NOTE: The following two files (tab-selected-end.svg, tab-selected-start.svg) get pre-processed in
|
||||
@ -198,7 +202,9 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/tab-selected-start.svg (tab-selected-start.svg)
|
||||
|
||||
skin/classic/browser/tabbrowser/tab-stroke-end.png (tabbrowser/tab-stroke-end.png)
|
||||
skin/classic/browser/tabbrowser/tab-stroke-end@2x.png (tabbrowser/tab-stroke-end@2x.png)
|
||||
skin/classic/browser/tabbrowser/tab-stroke-start.png (tabbrowser/tab-stroke-start.png)
|
||||
skin/classic/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png)
|
||||
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/browser/tabbrowser/tab-separator-luna-blue.png (tabbrowser/tab-separator-luna-blue.png)
|
||||
skin/classic/browser/tabbrowser/tab-separator.png (tabbrowser/tab-separator.png)
|
||||
@ -252,6 +258,7 @@ browser.jar:
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
* skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
* skin/classic/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
skin/classic/browser/devtools/eyedropper.css (../shared/devtools/eyedropper.css)
|
||||
skin/classic/browser/devtools/magnifying-glass.png (../shared/devtools/images/magnifying-glass.png)
|
||||
skin/classic/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
|
||||
skin/classic/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
|
||||
@ -326,6 +333,8 @@ browser.jar:
|
||||
skin/classic/browser/devtools/app-manager/rocket.svg (../shared/devtools/app-manager/images/rocket.svg)
|
||||
skin/classic/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
|
||||
skin/classic/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
|
||||
skin/classic/browser/devtools/eyedropper-black.png (../shared/devtools/images/eyedropper-black.png)
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
@ -540,11 +549,15 @@ browser.jar:
|
||||
skin/classic/aero/browser/tabbrowser/loading.png (tabbrowser/loading.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab.png (tabbrowser/tab.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-arrow-left-inverted.png (tabbrowser/tab-arrow-left-inverted.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-background-start.png (tabbrowser/tab-background-start.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-background-start@2x.png (tabbrowser/tab-background-start@2x.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-background-middle.png (tabbrowser/tab-background-middle.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-background-middle@2x.png (tabbrowser/tab-background-middle@2x.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-background-end.png (tabbrowser/tab-background-end.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-background-end@2x.png (tabbrowser/tab-background-end@2x.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png)
|
||||
|
||||
# NOTE: The following two files (tab-selected-end.svg, tab-selected-start.svg) get pre-processed in
|
||||
@ -553,7 +566,9 @@ browser.jar:
|
||||
skin/classic/aero/browser/tabbrowser/tab-selected-start.svg (tab-selected-start-aero.svg)
|
||||
|
||||
skin/classic/aero/browser/tabbrowser/tab-stroke-end.png (tabbrowser/tab-stroke-end.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-stroke-end@2x.png (tabbrowser/tab-stroke-end@2x.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-stroke-start.png (tabbrowser/tab-stroke-start.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-stroke-start@2x.png (tabbrowser/tab-stroke-start@2x.png)
|
||||
skin/classic/aero/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-separator.png (tabbrowser/tab-separator-aero.png)
|
||||
skin/classic/aero/browser/tabview/close.png (tabview/close.png)
|
||||
@ -606,6 +621,7 @@ browser.jar:
|
||||
* skin/classic/aero/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
* skin/classic/aero/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
* skin/classic/aero/browser/devtools/scratchpad.css (devtools/scratchpad.css)
|
||||
skin/classic/aero/browser/devtools/eyedropper.css (../shared/devtools/eyedropper.css)
|
||||
skin/classic/aero/browser/devtools/magnifying-glass.png (../shared/devtools/images/magnifying-glass.png)
|
||||
skin/classic/aero/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
|
||||
skin/classic/aero/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
|
||||
@ -680,6 +696,7 @@ browser.jar:
|
||||
skin/classic/aero/browser/devtools/app-manager/rocket.svg (../shared/devtools/app-manager/images/rocket.svg)
|
||||
skin/classic/aero/browser/devtools/app-manager/noise.png (../shared/devtools/app-manager/images/noise.png)
|
||||
skin/classic/aero/browser/devtools/app-manager/default-app-icon.png (../shared/devtools/app-manager/images/default-app-icon.png)
|
||||
skin/classic/aero/browser/devtools/eyedropper-black.png (../shared/devtools/images/eyedropper-black.png)
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/aero/browser/sync-16.png
|
||||
|
BIN
browser/themes/windows/tabbrowser/tab-active-middle@2x.png
Normal file
After Width: | Height: | Size: 117 B |
BIN
browser/themes/windows/tabbrowser/tab-background-end@2x.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
browser/themes/windows/tabbrowser/tab-background-middle@2x.png
Normal file
After Width: | Height: | Size: 767 B |
BIN
browser/themes/windows/tabbrowser/tab-background-start@2x.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
browser/themes/windows/tabbrowser/tab-stroke-end@2x.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
browser/themes/windows/tabbrowser/tab-stroke-start@2x.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
@ -10,7 +10,6 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.FennecNativeDriver.LogLevel;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.LayerView.DrawListener;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
|
@ -791,8 +791,8 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
|
||||
loadContext->GetUsePrivateBrowsing(&callData->mPrivate);
|
||||
}
|
||||
|
||||
uint32_t maxDepth = aMethodName == MethodTrace ?
|
||||
DEFAULT_MAX_STACKTRACE_DEPTH : 1;
|
||||
uint32_t maxDepth = ShouldIncludeStackrace(aMethodName) ?
|
||||
DEFAULT_MAX_STACKTRACE_DEPTH : 1;
|
||||
nsCOMPtr<nsIStackFrame> stack = CreateStack(aCx, maxDepth);
|
||||
|
||||
if (!stack) {
|
||||
@ -979,7 +979,7 @@ Console::ProcessCallData(ConsoleCallData* aData)
|
||||
ArgumentsToValueList(aData->mArguments, event.mArguments.Value());
|
||||
}
|
||||
|
||||
if (aData->mMethodName == MethodTrace) {
|
||||
if (ShouldIncludeStackrace(aData->mMethodName)) {
|
||||
event.mStacktrace.Construct();
|
||||
event.mStacktrace.Value().SwapElements(aData->mStack);
|
||||
}
|
||||
@ -1479,5 +1479,19 @@ Console::ClearConsoleData()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Console::ShouldIncludeStackrace(MethodName aMethodName)
|
||||
{
|
||||
switch (aMethodName) {
|
||||
case MethodError:
|
||||
case MethodException:
|
||||
case MethodAssert:
|
||||
case MethodTrace:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -191,6 +191,9 @@ private:
|
||||
void
|
||||
ClearConsoleData();
|
||||
|
||||
bool
|
||||
ShouldIncludeStackrace(MethodName aMethodName);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsIConsoleAPIStorage> mStorage;
|
||||
|
@ -120,7 +120,7 @@ function runTest(aCallback) {
|
||||
['dom.messageChannel.enabled', true],
|
||||
['media.peerconnection.enabled', true],
|
||||
['media.peerconnection.identity.enabled', true],
|
||||
['media.peerconnection.identity.timeout', 3000],
|
||||
['media.peerconnection.identity.timeout', 12000],
|
||||
['media.navigator.permission.disabled', true]]
|
||||
}, function () {
|
||||
try {
|
||||
|