mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 23:37:33 +09:00
[PMkit] Add the shim for 'sdk/ui/button'
This commit is contained in:
parent
8c7026864a
commit
982a4b4507
3 changed files with 251 additions and 1 deletions
|
|
@ -85,10 +85,18 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk":
|
||||||
'sdk/ui/toolbar.js',
|
'sdk/ui/toolbar.js',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if CONFIG['MC_PALEMOON']:
|
||||||
|
EXTRA_JS_MODULES.commonjs.sdk.ui += [
|
||||||
|
'sdk/ui/buttons.js',
|
||||||
|
]
|
||||||
|
|
||||||
EXTRA_JS_MODULES.commonjs.sdk.ui.button += [
|
EXTRA_JS_MODULES.commonjs.sdk.ui.button += [
|
||||||
'sdk/ui/button/action.js',
|
'sdk/ui/button/action.js',
|
||||||
'sdk/ui/button/contract.js',
|
'sdk/ui/button/contract.js',
|
||||||
'sdk/ui/button/toggle.js',
|
'sdk/ui/button/toggle.js',
|
||||||
|
]
|
||||||
|
|
||||||
|
EXTRA_PP_JS_MODULES.commonjs.sdk.ui.button += [
|
||||||
'sdk/ui/button/view.js',
|
'sdk/ui/button/view.js',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,19 @@ const { isObject, isNil } = require('../../lang/type');
|
||||||
|
|
||||||
const { getMostRecentBrowserWindow } = require('../../window/utils');
|
const { getMostRecentBrowserWindow } = require('../../window/utils');
|
||||||
const { ignoreWindow } = require('../../private-browsing/utils');
|
const { ignoreWindow } = require('../../private-browsing/utils');
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
const { buttons } = require('../buttons');
|
||||||
|
#else
|
||||||
const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
|
const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
|
||||||
const { AREA_PANEL, AREA_NAVBAR } = CustomizableUI;
|
const { AREA_PANEL, AREA_NAVBAR } = CustomizableUI;
|
||||||
|
#endif
|
||||||
|
|
||||||
const { events: viewEvents } = require('./view/events');
|
const { events: viewEvents } = require('./view/events');
|
||||||
|
|
||||||
const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
|
const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
|
||||||
|
|
||||||
const views = new Map();
|
const views = new Map();
|
||||||
|
#ifndef MC_PALEMOON
|
||||||
const customizedWindows = new WeakMap();
|
const customizedWindows = new WeakMap();
|
||||||
|
|
||||||
const buttonListener = {
|
const buttonListener = {
|
||||||
|
|
@ -65,19 +70,25 @@ CustomizableUI.addListener(buttonListener);
|
||||||
require('../../system/unload').when( _ =>
|
require('../../system/unload').when( _ =>
|
||||||
CustomizableUI.removeListener(buttonListener)
|
CustomizableUI.removeListener(buttonListener)
|
||||||
);
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
function getNode(id, window) {
|
function getNode(id, window) {
|
||||||
return !views.has(id) || ignoreWindow(window)
|
return !views.has(id) || ignoreWindow(window)
|
||||||
? null
|
? null
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
: buttons.getNode(id, window);
|
||||||
|
#else
|
||||||
: CustomizableUI.getWidget(id).forWindow(window).node
|
: CustomizableUI.getWidget(id).forWindow(window).node
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef MC_PALEMOON
|
||||||
function isInToolbar(id) {
|
function isInToolbar(id) {
|
||||||
let placement = CustomizableUI.getPlacementOfWidget(id);
|
let placement = CustomizableUI.getPlacementOfWidget(id);
|
||||||
|
|
||||||
return placement && CustomizableUI.getAreaType(placement.area) === 'toolbar';
|
return placement && CustomizableUI.getAreaType(placement.area) === 'toolbar';
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
function getImage(icon, isInToolbar, pixelRatio) {
|
function getImage(icon, isInToolbar, pixelRatio) {
|
||||||
let targetSize = (isInToolbar ? 18 : 32) * pixelRatio;
|
let targetSize = (isInToolbar ? 18 : 32) * pixelRatio;
|
||||||
|
|
@ -110,7 +121,11 @@ function getImage(icon, isInToolbar, pixelRatio) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeFor(id, window=getMostRecentBrowserWindow()) {
|
function nodeFor(id, window=getMostRecentBrowserWindow()) {
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
return getNode(id, window);
|
||||||
|
#else
|
||||||
return customizedWindows.has(window) ? null : getNode(id, window);
|
return customizedWindows.has(window) ? null : getNode(id, window);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
exports.nodeFor = nodeFor;
|
exports.nodeFor = nodeFor;
|
||||||
|
|
||||||
|
|
@ -120,14 +135,23 @@ function create(options) {
|
||||||
if (views.has(id))
|
if (views.has(id))
|
||||||
throw new Error('The ID "' + id + '" seems already used.');
|
throw new Error('The ID "' + id + '" seems already used.');
|
||||||
|
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
buttons.createButton({
|
||||||
|
#else
|
||||||
CustomizableUI.createWidget({
|
CustomizableUI.createWidget({
|
||||||
|
#endif
|
||||||
id: id,
|
id: id,
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
|
||||||
|
onBuild: function(document, _id) {
|
||||||
|
#else
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
removable: true,
|
removable: true,
|
||||||
defaultArea: AREA_NAVBAR,
|
defaultArea: AREA_NAVBAR,
|
||||||
allowedAreas: [ AREA_PANEL, AREA_NAVBAR ],
|
allowedAreas: [ AREA_PANEL, AREA_NAVBAR ],
|
||||||
|
|
||||||
onBuild: function(document) {
|
onBuild: function(document) {
|
||||||
|
#endif
|
||||||
let window = document.defaultView;
|
let window = document.defaultView;
|
||||||
|
|
||||||
let node = document.createElementNS(XUL_NS, 'toolbarbutton');
|
let node = document.createElementNS(XUL_NS, 'toolbarbutton');
|
||||||
|
|
@ -137,16 +161,28 @@ function create(options) {
|
||||||
if (ignoreWindow(window))
|
if (ignoreWindow(window))
|
||||||
node.style.display = 'none';
|
node.style.display = 'none';
|
||||||
|
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
node.setAttribute('id', _id);
|
||||||
|
#else
|
||||||
node.setAttribute('id', this.id);
|
node.setAttribute('id', this.id);
|
||||||
|
#endif
|
||||||
node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional badged-button');
|
node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional badged-button');
|
||||||
|
#ifndef MC_PALEMOON
|
||||||
node.setAttribute('type', type);
|
node.setAttribute('type', type);
|
||||||
|
#endif
|
||||||
node.setAttribute('label', label);
|
node.setAttribute('label', label);
|
||||||
node.setAttribute('tooltiptext', label);
|
node.setAttribute('tooltiptext', label);
|
||||||
node.setAttribute('image', image);
|
node.setAttribute('image', image);
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
node.setAttribute('pmkit-button', 'true');
|
||||||
|
#else
|
||||||
node.setAttribute('constrain-size', 'true');
|
node.setAttribute('constrain-size', 'true');
|
||||||
|
#endif
|
||||||
|
|
||||||
views.set(id, {
|
views.set(id, {
|
||||||
|
#ifndef MC_PALEMOON
|
||||||
area: this.currentArea,
|
area: this.currentArea,
|
||||||
|
#endif
|
||||||
icon: icon,
|
icon: icon,
|
||||||
label: label
|
label: label
|
||||||
});
|
});
|
||||||
|
|
@ -172,7 +208,11 @@ function dispose(id) {
|
||||||
if (!views.has(id)) return;
|
if (!views.has(id)) return;
|
||||||
|
|
||||||
views.delete(id);
|
views.delete(id);
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
buttons.destroyButton(id);
|
||||||
|
#else
|
||||||
CustomizableUI.destroyWidget(id);
|
CustomizableUI.destroyWidget(id);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
exports.dispose = dispose;
|
exports.dispose = dispose;
|
||||||
|
|
||||||
|
|
@ -180,8 +220,12 @@ function setIcon(id, window, icon) {
|
||||||
let node = getNode(id, window);
|
let node = getNode(id, window);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
|
#ifdef MC_PALEMOON
|
||||||
|
let image = getImage(icon, true, window.devicePixelRatio);
|
||||||
|
#else
|
||||||
icon = customizedWindows.has(window) ? views.get(id).icon : icon;
|
icon = customizedWindows.has(window) ? views.get(id).icon : icon;
|
||||||
let image = getImage(icon, isInToolbar(id), window.devicePixelRatio);
|
let image = getImage(icon, isInToolbar(id), window.devicePixelRatio);
|
||||||
|
#endif
|
||||||
|
|
||||||
node.setAttribute('image', image);
|
node.setAttribute('image', image);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
198
toolkit/jetpack/sdk/ui/buttons.js
Normal file
198
toolkit/jetpack/sdk/ui/buttons.js
Normal file
|
|
@ -0,0 +1,198 @@
|
||||||
|
/* 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/.
|
||||||
|
* PMkit shim for 'sdk/ui/button', (c) JustOff, 2017 */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.metadata = {
|
||||||
|
"stability": "experimental",
|
||||||
|
"engines": {
|
||||||
|
"Palemoon": "> 27"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const { Ci, Cc } = require('chrome');
|
||||||
|
const prefs = require('../preferences/service');
|
||||||
|
|
||||||
|
const buttonsList = new Map();
|
||||||
|
const LOCATION_PREF_ROOT = "extensions.sdk-button-location.";
|
||||||
|
|
||||||
|
let gWindowListener;
|
||||||
|
|
||||||
|
function getLocation(id) {
|
||||||
|
let toolbarId = "nav-bar", nextItemId = "";
|
||||||
|
let location = prefs.get(LOCATION_PREF_ROOT + id);
|
||||||
|
if (location && location.indexOf(",") !== -1) {
|
||||||
|
[toolbarId, nextItemId] = location.split(",");
|
||||||
|
}
|
||||||
|
return [toolbarId, nextItemId];
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveLocation(id, toolbarId, nextItemId) {
|
||||||
|
let _toolbarId = toolbarId || "";
|
||||||
|
let _nextItemId = nextItemId || "";
|
||||||
|
prefs.set(LOCATION_PREF_ROOT + id, [_toolbarId, _nextItemId].join(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert button into window
|
||||||
|
function insertButton(aWindow, id, onBuild) {
|
||||||
|
// Build button and save reference to it
|
||||||
|
let doc = aWindow.document;
|
||||||
|
let b = onBuild(doc, id);
|
||||||
|
aWindow[id] = b;
|
||||||
|
|
||||||
|
// Add to the customization palette
|
||||||
|
let toolbox = doc.getElementById("navigator-toolbox");
|
||||||
|
toolbox.palette.appendChild(b);
|
||||||
|
|
||||||
|
// Retrieve button location from preferences
|
||||||
|
let [toolbarId, nextItemId] = getLocation(id);
|
||||||
|
let toolbar = toolbarId != "" && doc.getElementById(toolbarId);
|
||||||
|
|
||||||
|
if (toolbar) {
|
||||||
|
let nextItem = doc.getElementById(nextItemId);
|
||||||
|
// If nextItem not in toolbar then retrieve it by reading currentset attribute
|
||||||
|
if (!(nextItem && nextItem.parentNode && nextItem.parentNode.id == toolbarId)) {
|
||||||
|
nextItem = null;
|
||||||
|
let currentSet = toolbar.getAttribute("currentset");
|
||||||
|
let ids = (currentSet == "__empty") ? [] : currentSet.split(",");
|
||||||
|
let idx = ids.indexOf(id);
|
||||||
|
if (idx != -1) {
|
||||||
|
for (let i = idx; i < ids.length; i++) {
|
||||||
|
nextItem = doc.getElementById(ids[i]);
|
||||||
|
if (nextItem)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Finally insert button in the right toolbar and in the right position
|
||||||
|
toolbar.insertItem(id, nextItem, null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove button from window
|
||||||
|
function removeButton(aWindow, id) {
|
||||||
|
let b = aWindow[id];
|
||||||
|
b.parentNode.removeChild(b);
|
||||||
|
delete aWindow[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save locations of buttons after customization
|
||||||
|
function afterCustomize(e) {
|
||||||
|
for (let [id] of buttonsList) {
|
||||||
|
let toolbox = e.target;
|
||||||
|
let b = toolbox.parentNode.querySelector("#" + id);
|
||||||
|
let toolbarId = null, nextItemId = null;
|
||||||
|
if (b) {
|
||||||
|
let parent = b.parentNode;
|
||||||
|
let nextItem = b.nextSibling;
|
||||||
|
if (parent && parent.localName == "toolbar") {
|
||||||
|
toolbarId = parent.id;
|
||||||
|
nextItemId = nextItem && nextItem.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveLocation(id, toolbarId, nextItemId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global window observer
|
||||||
|
function browserWindowObserver(handlers) {
|
||||||
|
this.handlers = handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
browserWindowObserver.prototype = {
|
||||||
|
observe: function(aSubject, aTopic, aData) {
|
||||||
|
if (aTopic == "domwindowopened") {
|
||||||
|
aSubject.QueryInterface(Ci.nsIDOMWindow).addEventListener("load", this, false);
|
||||||
|
} else if (aTopic == "domwindowclosed") {
|
||||||
|
if (aSubject.document.documentElement.getAttribute("windowtype") == "navigator:browser") {
|
||||||
|
this.handlers.onShutdown(aSubject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEvent: function(aEvent) {
|
||||||
|
let aWindow = aEvent.currentTarget;
|
||||||
|
aWindow.removeEventListener(aEvent.type, this, false);
|
||||||
|
|
||||||
|
if (aWindow.document.documentElement.getAttribute("windowtype") == "navigator:browser") {
|
||||||
|
this.handlers.onStartup(aWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run on every window startup
|
||||||
|
function browserWindowStartup(aWindow) {
|
||||||
|
for (let [id, onBuild] of buttonsList) {
|
||||||
|
insertButton(aWindow, id, onBuild);
|
||||||
|
}
|
||||||
|
aWindow.addEventListener("aftercustomization", afterCustomize, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run on every window shutdown
|
||||||
|
function browserWindowShutdown(aWindow) {
|
||||||
|
for (let [id, onBuild] of buttonsList) {
|
||||||
|
removeButton(aWindow, id);
|
||||||
|
}
|
||||||
|
aWindow.removeEventListener("aftercustomization", afterCustomize, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main object
|
||||||
|
const buttons = {
|
||||||
|
createButton: function(aProperties) {
|
||||||
|
// If no buttons were inserted yet, setup global window observer
|
||||||
|
if (buttonsList.size == 0) {
|
||||||
|
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);
|
||||||
|
gWindowListener = new browserWindowObserver({
|
||||||
|
onStartup: browserWindowStartup,
|
||||||
|
onShutdown: browserWindowShutdown
|
||||||
|
});
|
||||||
|
ww.registerNotification(gWindowListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add button to list
|
||||||
|
buttonsList.set(aProperties.id, aProperties.onBuild);
|
||||||
|
|
||||||
|
// Inster button to all open windows
|
||||||
|
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
|
||||||
|
let winenu = wm.getEnumerator("navigator:browser");
|
||||||
|
while (winenu.hasMoreElements()) {
|
||||||
|
let win = winenu.getNext();
|
||||||
|
insertButton(win, aProperties.id, aProperties.onBuild);
|
||||||
|
// When first button inserted, add afterCustomize listener
|
||||||
|
if (buttonsList.size == 1) {
|
||||||
|
win.addEventListener("aftercustomization", afterCustomize, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyButton: function(id) {
|
||||||
|
// Remove button from list
|
||||||
|
buttonsList.delete(id);
|
||||||
|
|
||||||
|
// If no more buttons exist, remove global window observer
|
||||||
|
if (buttonsList.size == 0) {
|
||||||
|
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);
|
||||||
|
ww.unregisterNotification(gWindowListener);
|
||||||
|
gWindowListener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove button from all open windows
|
||||||
|
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
|
||||||
|
let winenu = wm.getEnumerator("navigator:browser");
|
||||||
|
while (winenu.hasMoreElements()) {
|
||||||
|
let win = winenu.getNext();
|
||||||
|
removeButton(win, id);
|
||||||
|
// If no more buttons exist, remove afterCustomize listener
|
||||||
|
if (buttonsList.size == 0) {
|
||||||
|
win.removeEventListener("aftercustomization", afterCustomize, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getNode: function(id, window) {
|
||||||
|
return window[id];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.buttons = buttons;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue