Files
SysTray-X/webext/js/windowEvent.js

207 lines
6.7 KiB
JavaScript
Raw Normal View History

2022-07-11 22:30:29 +02:00
// This is the important part. It implements the functions and events defined in schema.json.
2020-05-10 20:55:27 +02:00
// The variable must have the same name you've been using so far, "myapi" in this case.
var windowEvent = class extends ExtensionCommon.ExtensionAPI {
getAPI(context) {
console.log("windowEvent API started");
// To be notified of the extension going away, call callOnClose with any object that has a
// close function, such as this one.
context.callOnClose(this);
return {
// Again, this key must have the same name.
windowEvent: {
2022-06-16 09:55:45 +02:00
setCloseType: async function (type) {
2020-08-02 16:59:53 +02:00
windowListener.setCloseType(type);
},
2020-05-10 20:55:27 +02:00
// An event. Most of this is boilerplate you don't need to worry about, just copy it.
onCloseButtonClick: new ExtensionCommon.EventManager({
context,
name: "windowEvent.onCloseButtonClick",
// In this function we add listeners for any events we want to listen to, and return a
// function that removes those listeners. To have the event fire in your extension,
// call fire.async.
register(fire) {
function callback(event) {
return fire.async();
}
windowListener.addOnCloseButton(callback);
return function () {
windowListener.removeOnCloseButton(callback);
};
},
}).api(),
},
};
}
close() {
// This function is called if the extension is disabled or removed, or Thunderbird closes.
// We registered it with callOnClose, above.
console.log("windowEvent API closed");
}
};
// A helpful class for listening to windows opening and closing.
// (This file had a lowercase E in Thunderbird 65 and earlier.)
var { ExtensionSupport } = ChromeUtils.import(
"resource:///modules/ExtensionSupport.jsm"
);
// This object is just what we're using to listen for toolbar clicks. The implementation isn't
// what this example is about, but you might be interested as it's a common pattern. We count the
// number of callbacks waiting for events so that we're only listening if we need to be.
var windowListener = new (class extends ExtensionCommon.EventEmitter {
constructor() {
super();
this.callbackOnCloseButtonCount = 0;
2020-08-03 23:40:03 +02:00
this.callbackOnLoadWindowCount = 0;
2020-08-02 16:59:53 +02:00
this.MESSAGE_CLOSE_TYPE_DEFAULT = 0;
2023-08-07 22:35:03 +02:00
this.MESSAGE_CLOSE_TYPE_MIN_MAIN_TRAY_CLOSE_CHILDREN = 1;
this.MESSAGE_CLOSE_TYPE_MIN_ALL_TRAY = 2;
this.MESSAGE_CLOSE_TYPE_MIN_MAIN_CLOSE_CHILDREN = 3;
this.MESSAGE_CLOSE_TYPE_MIN_ALL = 4;
2020-08-02 16:59:53 +02:00
this.closeType = this.MESSAGE_CLOSE_TYPE_MIN_MAIN_CLOSE_CHILDREN;
}
setCloseType(closeType) {
if (closeType === 0) {
this.closeType = this.MESSAGE_CLOSE_TYPE_DEFAULT;
} else if (closeType === 1) {
2023-08-05 15:00:50 +02:00
this.closeType = this.MESSAGE_CLOSE_TYPE_MIN_MAIN_TRAY_CLOSE_CHILDREN;
2020-08-02 16:59:53 +02:00
} else if (closeType === 2) {
2023-08-05 15:00:50 +02:00
this.closeType = this.MESSAGE_CLOSE_TYPE_MIN_ALL_TRAY;
2023-08-05 10:46:33 +02:00
} else if (closeType === 3) {
2023-08-05 15:00:50 +02:00
this.closeType = this.MESSAGE_CLOSE_TYPE_MIN_MAIN_CLOSE_CHILDREN;
2023-08-05 10:46:33 +02:00
} else if (closeType === 4) {
2023-08-05 15:00:50 +02:00
this.closeType = this.MESSAGE_CLOSE_TYPE_MIN_ALL;
2020-08-02 16:59:53 +02:00
} else console.log("Unknown close type: " + closeType);
2020-05-10 20:55:27 +02:00
}
addOnCloseButton(callback) {
if (this.callbackOnCloseButtonCount == 0) {
this.on("close-clicked", callback);
this.callbackOnCloseButtonCount++;
ExtensionSupport.registerWindowListener("closeButtonListener", {
chromeURLs: [
"chrome://messenger/content/messenger.xhtml",
"chrome://messenger/content/messenger.xul",
],
onLoadWindow: function (window) {
2020-08-03 23:40:03 +02:00
windowListener.callbackOnLoadWindowCount++;
2020-08-02 16:59:53 +02:00
if (
2020-08-03 23:40:03 +02:00
windowListener.callbackOnLoadWindowCount === 1 ||
2020-08-02 21:32:09 +02:00
windowListener.closeType ===
2023-08-05 10:46:33 +02:00
windowListener.MESSAGE_CLOSE_TYPE_MIN_ALL ||
windowListener.closeType ===
windowListener.MESSAGE_CLOSE_TYPE_MIN_ALL_TRAY
2020-08-02 16:59:53 +02:00
) {
window.addEventListener(
"close",
windowListener.onCloseButton,
true
);
2022-07-05 13:48:58 +02:00
windowListener.hijackTitlebarCloseButton(window);
2022-07-08 14:25:55 +02:00
windowListener.oldClose = window.close;
2022-07-09 16:30:14 +02:00
window.close = () => windowListener.onCloseButton(null);
2022-07-08 14:25:55 +02:00
2022-06-16 10:34:26 +02:00
console.log("Close listener added");
2020-08-02 16:59:53 +02:00
}
2020-05-10 20:55:27 +02:00
},
});
}
}
removeOnCloseButton(callback) {
if (this.callbackOnCloseButtonCount == 1) {
this.off("close-clicked", callback);
this.callbackOnCloseButtonCount--;
for (let window of ExtensionSupport.openWindows) {
if (
[
"chrome://messenger/content/messenger.xhtml",
"chrome://messenger/content/messenger.xul",
].includes(window.location.href)
) {
window.removeEventListener(
"close",
windowListener.onCloseButton,
true
);
2022-07-08 14:25:55 +02:00
window.close = windowListener.oldClose;
2022-06-16 10:34:26 +02:00
console.log("Close listener removed");
2020-05-10 20:55:27 +02:00
}
}
ExtensionSupport.unregisterWindowListener("closeButtonListener");
}
}
onCloseButton(event) {
2022-07-08 14:25:55 +02:00
if (event) event.preventDefault();
windowListener.emit("close-clicked");
2020-05-10 20:55:27 +02:00
return true;
}
2022-07-05 13:48:58 +02:00
hijackTitlebarCloseButton(window) {
if (
windowListener.replaceCommand(window, "titlebar-close", function () {
2022-07-09 16:30:14 +02:00
return windowListener.onCloseButton(null);
2022-07-05 13:48:58 +02:00
})
) {
console.log("replaced command= " + "titlebar-close");
}
}
replaceCommand(window, eltId, gotHidden) {
let elt = window.document.getElementById(eltId);
if (!elt) {
console.log("Element '" + eltId + "' not found. Command not replaced.");
return false;
}
let prevent = null;
if (elt.command) {
prevent = {
event: "click",
func: function (e) {
e.preventDefault();
},
};
} else if (elt.getAttribute("oncommand")) {
prevent = {
event: "command",
func: function (e) {
e.stopPropagation();
},
};
} else {
console.warn("Could not replace oncommand on " + eltId);
return false;
}
let callback = function (event) {
if (event.target.id === eltId) {
console.debug(prevent.event + " on " + eltId);
if (gotHidden()) prevent.func(event);
}
};
/* We put listeners on the "titlebar" parent node, because:
- we can hardly short-circuit command/oncommand (probably because they are
registered first)
- we'd have otherwise to alter "oncommand"/"command" attribute and use
Function(), which do not pass review nowadays. */
elt.parentNode.addEventListener(prevent.event, callback, true);
return true;
}
2020-05-10 20:55:27 +02:00
})();