[英]Gnome Shell Extension Key Binding
(全局)将组合键(例如<Super>+A
)绑定到 gnome shell 扩展中的函数的最简单方法是什么?
检查了几个扩展,我遇到了以下代码:
global.display.add_keybinding('random-name',
new Gio.Settings({schema: 'org.gnome.shell.keybindings'}),
Meta.KeyBindingFlags.NONE,
function() { /* ... some code */ });
我知道组合键是由模式参数指定的,并且可以创建一个描述组合的 XML 文件。 有没有更简单的方法来做到这一点?
以下是我在这里的答案的副本我只在 Gnome 3.22 中测试过
这是一个类:
KeyManager: new Lang.Class({
Name: 'MyKeyManager',
_init: function() {
this.grabbers = new Map()
global.display.connect(
'accelerator-activated',
Lang.bind(this, function(display, action, deviceId, timestamp){
log('Accelerator Activated: [display={}, action={}, deviceId={}, timestamp={}]',
display, action, deviceId, timestamp)
this._onAccelerator(action)
}))
},
listenFor: function(accelerator, callback){
log('Trying to listen for hot key [accelerator={}]', accelerator)
let action = global.display.grab_accelerator(accelerator)
if(action == Meta.KeyBindingAction.NONE) {
log('Unable to grab accelerator [binding={}]', accelerator)
} else {
log('Grabbed accelerator [action={}]', action)
let name = Meta.external_binding_name_for_action(action)
log('Received binding name for action [name={}, action={}]',
name, action)
log('Requesting WM to allow binding [name={}]', name)
Main.wm.allowKeybinding(name, Shell.ActionMode.ALL)
this.grabbers.set(action, {
name: name,
accelerator: accelerator,
callback: callback
})
}
},
_onAccelerator: function(action) {
let grabber = this.grabbers.get(action)
if(grabber) {
this.grabbers.get(action).callback()
} else {
log('No listeners [action={}]', action)
}
}
})
这就是你使用它的方式:
let keyManager = new KeyManager()
keyManager.listenFor("<ctrl><shift>a", function(){
log("Hot keys are working!!!")
})
您将需要导入:
const Lang = imports.lang
const Meta = imports.gi.Meta
const Shell = imports.gi.Shell
const Main = imports.ui.main
我可能是非常错误的,但这是我最近几天想出来的。
首先是 Mutter 负责监听热键。 Mutter 是一个用于创建窗口管理器的框架,它本身并不是一个窗口管理器。 Gnome Shell 有一个用 JS 编写的类,称为“窗口管理器”——这是真正的窗口管理器,它在内部使用 Mutter 来做所有低级的事情。 Mutter 有一个对象 MetaDisplay。 这是您用来请求侦听热键的对象。 但! 但是 Mutter 将需要 Window Manager 批准使用此热键。 那么当按下热键时会发生什么? - MetaDisplay 生成事件“过滤器键绑定”。 - Gnome Shell 中的窗口管理器检查是否允许处理此热键。 - 窗口管理器向 MetaDisplay 返回适当的值 - 如果允许处理此热键,则 MetaDisplay 生成事件 'accelerator-actived' - 您的扩展程序必须侦听该事件并通过操作 ID 确定哪个热键被激活。
这个问题很老,但我刚刚为 Gnome Shell 40 实现了它。所以我是这样做的。
密钥在用于扩展设置的普通架构文件中定义。 所以它看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema id="org.gnome.shell.extensions.mycoolstuff" path="/org/gnome/shell/extensions/mycoolstuff/">
<key name="cool-hotkey" type="as">
<default><![CDATA[['<Ctrl><Super>T']]]></default>
<summary>Hotkey to open the cool stuff.</summary>
</key>
... other config options
</schema>
</schemalist>
键类型是“字符串数组”,因此您可以为操作配置多个键组合。
在您的代码中,您可以这样使用它:
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
...
let my_settings = ExtensionUtils.getSettings("org.gnome.shell.extensions.mycoolstuff");
Main.wm.addKeybinding("cool-hotkey", my_settings,
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW
this._hotkeyActionMethod.bind(this));
我建议在扩展程序被禁用时删除键绑定。 如果你不这样做,不知道会发生什么。
Main.wm.removeKeybinding("cool-hotkey");
顺便说一句:对设置的更改(通过 dconf 编辑器、gsettings 或您的扩展首选项)会立即生效。
与@p2t2p 相同,但使用 ES5 类重铸。 这也是使用我的记录器类,但您可以用 log() 替换它。
const Lang = imports.lang
const Meta = imports.gi.Meta
const Shell = imports.gi.Shell
const Main = imports.ui.main
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Logger = Me.imports.logger.Logger;
var KeyboardShortcuts = class KeyboardShortcuts {
constructor(settings) {
this._grabbers = {};
this.logger = new Logger('kt kbshortcuts', settings);
global.display.connect('accelerator-activated', (display, action, deviceId, timestamp) => {
this.logger.debug("Accelerator Activated: [display=%s, action=%s, deviceId=%s, timestamp=%s]",
display, action, deviceId, timestamp)
this._onAccelerator(action)
});
}
listenFor(accelerator, callback) {
this.logger.debug('Trying to listen for hot key [accelerator=%s]', accelerator);
let action = global.display.grab_accelerator(accelerator, 0);
if (action == Meta.KeyBindingAction.NONE) {
this.logger.error('Unable to grab accelerator [%s]', accelerator);
return;
}
this.logger.debug('Grabbed accelerator [action={}]', action);
let name = Meta.external_binding_name_for_action(action);
this.logger.debug('Received binding name for action [name=%s, action=%s]',
name, action)
this.logger.debug('Requesting WM to allow binding [name=%s]', name)
Main.wm.allowKeybinding(name, Shell.ActionMode.ALL)
this._grabbers[action]={
name: name,
accelerator: accelerator,
callback: callback
};
}
_onAccelerator(action) {
let grabber = this._grabbers[action];
if (grabber) {
grabber.callback();
} else {
this.logger.debug('No listeners [action=%s]', action);
}
}
}
并使用它,
this.accel = new KeyboardShortcuts(this.settings);
this.accel.listenFor("<ctrl><super>T", () => {
this.logger.debug("Toggling show endtime");
this._timers.settings.show_endtime = !this._timers.settings.show_endtime;
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.