创建仅绑定键盘快捷键的Wayland桌面环境 [英] create Wayland desktop environment that simply binds keyboard shortcuts

查看:125
本文介绍了创建仅绑定键盘快捷键的Wayland桌面环境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有许多问题,询问如何在Wayland环境中创建全局键盘绑定.通常,答案是使用您的桌面环境"-对于大多数提出该问题的人来说,这个答案几乎没有用.

There are dozens of questions on here asking how to create global keyboard bindings in a Wayland environment. Generally, the answer is "use your desktop environment" - an answer that is pretty much useless to most anyone asking the question.

因此,为了得出一个更有用的答案,我问一个人如何创建一个最小的Wayland桌面环境,该环境可以绑定快捷键?

So, in order to draw out a more useful answer, I ask how does one create a minimal Wayland desktop environment which can bind shortcut keys?

我有Mutter作为我的WM运行,并且我正在使用GNOME Do作为启动器.除了我无法绑定热键之外,几乎完全是我想要的桌面环境.

I've got Mutter running as my WM, and I'm using GNOME Do as a launcher. It's pretty much exactly the desktop environment I want, with the exception that I can't bind hotkeys.

我不在乎是否必须编写一个1万行的C应用程序来完成这项工作.我只想知道如何进行. GNOME如何在Wayland中绑定键盘快捷键?代码在哪里? Wayland/Mutter的适当文档在哪里?

I don't care if I have to write a 10k line C app to make this work. I just want to know how to proceed. How does GNOME bind keyboard shortcuts within Wayland? Where is the code for that? Where is the appropriate documentation for Wayland/Mutter?

推荐答案

经过大量研究和实验,看来libevdev也许是正确的工具.我开发了以下程序,作为将Alt+X绑定到启动xterm的概念证明.

After much research and experimentation, it looks like libevdev is maybe the right tool. I developed the program below as a proof-of-concept to bind Alt+X to launch xterm.

不幸的是,它必须以root身份运行,所以我认为我需要以某种方式将其绑定到本地桌面会话中.就我的目的而言,只需setuid使用root用户并将其命名为一天就足够了.

Unfortunately, it has to be run as root, so I'm thinking I need to somehow tie this into the local desktop session. For my purposes, it's probably good enough to just setuid using the root user and call it a day.

我也不相信我的键盘检测试探法非常好.我本质上是在寻找具有按键和重复率的设备,这些设备在我的系统上仅与键盘匹配.

I'm also not convinced my keyboard detection heuristic is very good. I'm essentially looking for any device that has keys and a repeat rate, which on my system only matches my keyboard.

#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <libevdev/libevdev.h>

#define DEVROOT     "/dev/input/"
#define DEVROOT_LEN 12
#define PATH_LEN    (DEVROOT_LEN + NAME_MAX)

int outerr(int, const char*);
struct libevdev* open_device(int);
bool kblike(struct libevdev*);

int main(int argc, char* argv[]) {
    DIR* dir;
    struct dirent* entry;
    char path[PATH_LEN];
    int fd, err;
    struct libevdev* dev = NULL;
    struct input_event ev;
    bool key, rep, alt;

    if (!(dir = opendir("/dev/input"))) {
        return outerr(errno, "cannot enumerate devices");
    }

    // look for keyboard device
    while (entry = readdir(dir)) {
        if (DT_CHR == entry->d_type) {
            sprintf(path, "/dev/input/%s", entry->d_name);

            if (-1 == (fd = open(path, O_RDONLY|O_NONBLOCK))) {
                return outerr(errno, "cannot read device");
            }

            if (dev = open_device(fd)) {
                if (kblike(dev)) break;
                libevdev_free(dev);
                dev = NULL;
            }
        }
    }

    closedir(dir);

    // check if keyboard was found
    if (dev == NULL) {
        return outerr(ENODEV, "could not detect keyboard");
    } else do {
        err = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);

        if (err == 0 && ev.type == EV_KEY) switch (ev.code) {
            case KEY_LEFTALT:
                alt = ev.value == 1;
                break;
            case KEY_X:
                if (ev.value == 1 && alt) system("xterm");
                break;
        }
    } while (err == 1 || err == 0 || err == -EAGAIN);

    return 0;
}

int outerr(int errnum, const char* msg) {
    fprintf(stderr, "%s (%s)\n", msg, strerror(errnum));
    return errnum;
}

bool kblike(struct libevdev* dev) {
    return libevdev_has_event_type(dev, EV_KEY)
        && libevdev_has_event_type(dev, EV_REP);
}

struct libevdev* open_device(int fd) {
    struct libevdev* dev = libevdev_new();
    int err;

    if (dev == NULL) {
        errno = ENOMEM;
    } else if (0 > (err = libevdev_set_fd(dev, fd))) {
        libevdev_free(dev);
        dev = NULL;
        errno = -err;
    }

    return dev;
}

这篇关于创建仅绑定键盘快捷键的Wayland桌面环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆