为什么有时覆盖 class 函数不起作用?
Why doesn't overriding a class function work sometimes?
我按照这个 https://wiki.gnome.org/Projects/GnomeShell/Extensions/StepByStepTutorial 来覆盖函数。
例如,我想覆盖函数 _setupKeyboard()
on the Keyboard
class,但我的覆盖没有被调用。我要更改的具体部分是这样的,以删除 if
守卫:
if (Meta.is_wayland_compositor()) {
this._connectSignal(this._keyboardController, 'emoji-visible',
this._onEmojiKeyVisible.bind(this));
}
我从源码中复制了函数,去掉了不需要的部分,然后设置替换函数如下:
const Keyboard = imports.ui.keyboard;
Keyboard.Keyboard.prototype._setupKeyboard = myOverride;
为什么我的覆盖没有被调用,我该如何实现?
有两个常见原因无法调用覆盖。如果在应用覆盖之前调用了该方法,或者如果该函数是一个回调集 Function.prototype.bind()
,它会创建一个新的闭包。
在这种情况下,函数 _setupKeyboard()
在应用覆盖之前被调用。当 GNOME Shell 启动时,它会创建一个 Keyboard.KeyboardManager
here:
的实例
// main.js, line #204
keyboard = new Keyboard.KeyboardManager();
当 keyboard
变量被分配给实例时,一个默认的 Keyboard.Keyboard
class 已经创建并且函数 _setupKeyboard()
已经被调用Keyboard._init()
,这比加载扩展程序要快得多。
由于没有办法轻松解决这个问题,您最好的选择是 re-create 您想要的代码的一部分 运行:
const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const Keyboard = imports.ui.keyboard.Keyboard;
const originalSetup = Keyboard.prototype._setupKeyboard;
const modifiedSetup = function () {
originalSetup.call(this);
if (!Meta.is_wayland_compositor()) {
this._connectSignal(this._keyboardController, 'emoji-visible',
this._onEmojiKeyVisible.bind(this));
}
this._relayout();
};
function init() {
}
// Your extension's enable function (might be a class method)
function enable() {
let kbd = Main.keyboard.keyboardActor;
if (kbd !== null) {
if (!Meta.is_wayland_compositor()) {
kbd.__mySignalId = kbd._connectSignal(kbd._keyboardController, 'emoji-visible',
kbd._onEmojiKeyVisible.bind(kbd));
}
}
Keyboard.prototype._setupKeyboard = modifiedSetup;
}
function disable() {
let kbd = Main.keyboard.keyboardActor;
if (kbd !== null && kbd.__mySignalId) {
kbd.disconnect(kbd.__mySignalId);
kbd.__mySignalId = 0;
}
Keyboard.prototype._setupKeyboard = originalSetup;
}
这不是很漂亮,但这通常是修补私有代码的代价。我也不能保证代码会做你想做的事,因为我怀疑表情符号密钥出于某种原因隐藏在 X11 上。
我按照这个 https://wiki.gnome.org/Projects/GnomeShell/Extensions/StepByStepTutorial 来覆盖函数。
例如,我想覆盖函数 _setupKeyboard()
on the Keyboard
class,但我的覆盖没有被调用。我要更改的具体部分是这样的,以删除 if
守卫:
if (Meta.is_wayland_compositor()) {
this._connectSignal(this._keyboardController, 'emoji-visible',
this._onEmojiKeyVisible.bind(this));
}
我从源码中复制了函数,去掉了不需要的部分,然后设置替换函数如下:
const Keyboard = imports.ui.keyboard;
Keyboard.Keyboard.prototype._setupKeyboard = myOverride;
为什么我的覆盖没有被调用,我该如何实现?
有两个常见原因无法调用覆盖。如果在应用覆盖之前调用了该方法,或者如果该函数是一个回调集 Function.prototype.bind()
,它会创建一个新的闭包。
在这种情况下,函数 _setupKeyboard()
在应用覆盖之前被调用。当 GNOME Shell 启动时,它会创建一个 Keyboard.KeyboardManager
here:
// main.js, line #204
keyboard = new Keyboard.KeyboardManager();
当 keyboard
变量被分配给实例时,一个默认的 Keyboard.Keyboard
class 已经创建并且函数 _setupKeyboard()
已经被调用Keyboard._init()
,这比加载扩展程序要快得多。
由于没有办法轻松解决这个问题,您最好的选择是 re-create 您想要的代码的一部分 运行:
const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const Keyboard = imports.ui.keyboard.Keyboard;
const originalSetup = Keyboard.prototype._setupKeyboard;
const modifiedSetup = function () {
originalSetup.call(this);
if (!Meta.is_wayland_compositor()) {
this._connectSignal(this._keyboardController, 'emoji-visible',
this._onEmojiKeyVisible.bind(this));
}
this._relayout();
};
function init() {
}
// Your extension's enable function (might be a class method)
function enable() {
let kbd = Main.keyboard.keyboardActor;
if (kbd !== null) {
if (!Meta.is_wayland_compositor()) {
kbd.__mySignalId = kbd._connectSignal(kbd._keyboardController, 'emoji-visible',
kbd._onEmojiKeyVisible.bind(kbd));
}
}
Keyboard.prototype._setupKeyboard = modifiedSetup;
}
function disable() {
let kbd = Main.keyboard.keyboardActor;
if (kbd !== null && kbd.__mySignalId) {
kbd.disconnect(kbd.__mySignalId);
kbd.__mySignalId = 0;
}
Keyboard.prototype._setupKeyboard = originalSetup;
}
这不是很漂亮,但这通常是修补私有代码的代价。我也不能保证代码会做你想做的事,因为我怀疑表情符号密钥出于某种原因隐藏在 X11 上。