在 Xlib 中捕获按钮事件,然后将事件传递给客户端

2023-11-25

我正在开发一个窗口管理器,主要是作为练习,但我遇到了一个问题。我希望能够将单击的窗口提升到堆栈顶部。目前,我在 Button1 和 ControlMask 上使用 XGrabButton 来允许移动窗口,当我按住 Ctrl 键并单击窗口时,即可实现所需的效果。但是,如果我在带有 AnyModifier 的 Button1 上使用 XGrabButton,虽然实现了我想要的效果,但我无法再通过鼠标按钮与客户端窗口交互(突出显示文本等)。我尝试过抓取 EnterNotify 上的按钮,然后在窗口升起后立即取消抓取按钮,但这似乎没有效果,窗口管理器的行为就好像我根本没有抓取按钮一样。

我的程序还比较小,所以代码如下:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "window_manager.h"


ewm_instance wm;

void 
ewm_init()
{
    wm._display = XOpenDisplay(NULL);

    if (!wm._display) {
        printf("Could not open display %s\n", XDisplayName(NULL));
    } 
    wm._root = DefaultRootWindow(wm._display);
}

void
ewm_run()
{
    XSelectInput(wm._display, 
                 wm._root, 
                 SubstructureRedirectMask | SubstructureNotifyMask | 
                 KeyPressMask | KeyReleaseMask | 
                 ButtonPressMask | ButtonReleaseMask);

    XSync(wm._display, 0);
    XGrabServer(wm._display);
    Window returned_root, returned_parent;
    Window *top_level_windows;
    unsigned int num_top_level_windows;
    XQueryTree(wm._display,
               wm._root,
               &returned_root,
               &returned_parent,
               &top_level_windows,
               &num_top_level_windows);
    XFree(top_level_windows);
    XUngrabServer(wm._display);
    XGrabButton(
        wm._display,
        Button1,
        ControlMask,
        wm._root,
        0,
        ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
        GrabModeAsync,
        GrabModeAsync,
        None,
        None);

    XGrabButton(
        wm._display,
        Button1,
        ControlMask,
        wm._root,
        0,
        ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
        GrabModeAsync,
        GrabModeAsync,
        None,
        None);

    for (;;) {
        XEvent e;
        XNextEvent(wm._display, &e);

        switch (e.type) {
        case CreateNotify:
            printf("CreateNotify\n");
            break;
        case DestroyNotify:
            printf("DestroyNotify\n");
            break;
        case ReparentNotify:
            printf("ReparentNotify\n");
            break;
        case MapNotify:
            printf("Mapping Window\n");
            break;
        case UnmapNotify:
            printf("UnmapNotify\n");
            break;
        case ConfigureNotify:
            printf("ConfigureNotify\n");
            break;
        case MapRequest:
            printf("MapRequest\n");
            ewm_on_map_request(&e.xmaprequest);
            break;
        case ConfigureRequest:
            printf("ConfigureRequest\n");
            break;
        case ButtonPress:
            printf("ButtonPress\n");
            ewm_on_button_press(&e.xbutton);
            break;
        case ButtonRelease:
            printf("ButtonRelease\n");
            break;
        case MotionNotify:
            ewm_on_motion_notify(&e.xmotion);
            break;
        case KeyPress:
            printf("KeyPress\n");
            ewm_on_key_press(&e.xkey);
            break;
        case KeyRelease:
            printf("KeyRelease\n");
            break;
        case EnterNotify:
            ewm_on_enter_notify(&e.xcrossing);
            break;
        default:
            printf("Something else\n");
        }
    }
}

void
ewm_on_map_request(const XMapRequestEvent *e)
{
    XSelectInput(
            wm._display,
            e->window,
            KeyPressMask | KeyReleaseMask |
            EnterWindowMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);

    XMapWindow(wm._display, e->window);
    XSetInputFocus(wm._display, e->window, RevertToPointerRoot, CurrentTime);

}

void
ewm_on_enter_notify(const XEnterWindowEvent *e)
{
    printf("Entered window: %lu\n", e->window);
    XSetInputFocus(wm._display, e->window, RevertToParent, CurrentTime);
}


void
ewm_on_key_press(const XKeyEvent *e)
{
    if ((e->state & ControlMask) && 
         e->keycode == XKeysymToKeycode(wm._display, XK_q)) {
        printf("Destroying window\n");
        XDestroyWindow(wm._display, e->window);
    }

    if ((e->state & ControlMask) && 
         e->keycode == XKeysymToKeycode(wm._display, XK_Return)) {
        printf("Enter Works\n");
        system("urxvt &");

    }
}


void
ewm_on_button_press(const XButtonEvent *e)
{
    if (e->subwindow != 0) {

        // Save initial cursor position;
        wm._cursor_start_position = (Vector){e->x_root, e->y_root};

        // Save initial window info
        Window returned_root;
        int x, y;
        unsigned int width, height, depth, border_width;
        XGetGeometry(wm._display,
                     e->subwindow,
                     &returned_root,
                     &x, &y, 
                     &width, &height,
                     &border_width,
                     &depth);
        wm._window_start_position = (Vector){x, y};
        wm._window_start_size = (Size){width, height};

        XRaiseWindow(wm._display, e->subwindow);
        XSetInputFocus(wm._display, e->subwindow, RevertToParent, CurrentTime);
        printf("Raising window %lu\n", e->subwindow);
        printf("root id: %lu\n", wm._root);
        XUngrabButton(wm._display, Button1, AnyModifier, e->subwindow);
    }
}

void
ewm_on_motion_notify(const XMotionEvent *e)
{
    const Vector drag_pos = {e->x_root, e->y_root};
    const Vector delta = {
        (drag_pos.x - wm._cursor_start_position.x), 
        (drag_pos.y - wm._cursor_start_position.y)
    };

    if ((e->state & Button1Mask) && (e->state & ControlMask)) {
        const Vector dest_window_pos = {
            (wm._window_start_position.x + delta.x), 
            (wm._window_start_position.y + delta.y)
        };

        if (e->subwindow != 0) {
            XMoveWindow(wm._display, 
                    e->subwindow, 
                    dest_window_pos.x, 
                    dest_window_pos.y);
        }
    }
}

void 
ewm_cleanup()
{
    XCloseDisplay(wm._display);
}

我也尝试过使用 XSendEvent,但根据我从中得到的结果,我认为我不太明白它应该做什么。我对 Xlib 编程非常陌生,因此非常感谢任何帮助。

谢谢你!


我有完全相同的问题。原始问题中的评论有所帮助,但还没有完全实现,它们缺少一个重要的细节(前面的第 1 点)。最终我在这里找到了提示解决了它。

  1. 同步抓取事件(注意GrabModeSync给出为pointer_mode)
XGrabButton(dis, FOCUS_BUTTON, AnyModifier, root, False, BUTTONMASK, GrabModeSync, GrabModeAsync, None, None);
  1. Use XAllowEvents and Xsync为了达到传递效果
XAllowEvents(display, ReplayPointer, ev->xbutton.time);
XSync(display, 0);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Xlib 中捕获按钮事件,然后将事件传递给客户端 的相关文章

  • WinForms:如何确定窗口是否不再活动(没有子窗口具有焦点)?

    我的应用程序使用多个窗口 我想隐藏一个特定窗口 以防应用程序失去焦点 当活动窗口不是应用程序窗口时 source https stackoverflow com questions 466354 how can i tell if a wi
  • 迭代变量并查找特定类型实例的技术

    我想迭代进程中内存中的变量 通过插件动态加载 并查找特定类型的实例 以前我可以找到特定类型 或内存中的所有类型 我可以创建类型的实例 我可以获取作为不同类型的字段包含的实例 但我无论如何都不知道只是 搜索 特定类型的实例 一种方法是使用 W
  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • 为什么我不能用 `= delete;` 声明纯虚函数?

    Intro 纯虚函数使用通用语法声明 virtual f 0 然而 自 c 11 以来 有一种方法可以显式地传达non existence 特殊 成员函数的 Mystruct delete eg default constructor Q
  • 为什么大多数 C 开发人员使用 Define 而不是 const? [复制]

    这个问题在这里已经有答案了 在许多程序中 define与常量具有相同的用途 例如 define FIELD WIDTH 10 const int fieldWidth 10 我通常认为第一种形式优于另一种形式 它依赖于预处理器来处理基本上是
  • 如何在 Android NDK 中创建新的 NativeWindow 而无需 Android 操作系统源代码?

    我想编译一个 Android OpenGL 控制台应用程序 您可以直接从控制台启动 Android x86 运行 或者从 Android x86 GUI 内的 Android 终端应用程序运行 这个帖子 如何在 Android NDK 中创
  • 从 MVC 迁移到 ASP.NET Core 3.1 中的端点路由时,具有角色的 AuthorizeAttribute 不起作用

    我正在尝试将我的项目从 UseMVC asp net core 2 2 兼容样式 升级到 UseEndpoint Routing 并且我的所有请求都被重定向到我的验证失败页面 它与声明有关 如果我删除 Authorize Roles Adm
  • C# 中的接口继承

    我试图解决我在编写应用程序时遇到的相当大的 对我来说 问题 请看这个 为了简单起见 我将尝试缩短代码 我有一个名为的根接口IRepository
  • JSON 数组到 C# 列表

    如何将这个简单的 JSON 字符串反序列化为 C 中的列表 on4ThnU7 n71YZYVKD CVfSpM2W 10kQotV 这样 List
  • POCO HTTPSClientSession 发送请求时遇到问题 - 证书验证失败

    我正在尝试使用 POCO 库编写一个向服务器发出 HTTPS 请求的程序 出于测试目的 我正在连接到具有自签名证书的服务器 并且我希望允许客户端进行连接 为了允许这种情况发生 我尝试安装InvalidCertificateHandler这是
  • 从多个类访问串行端口

    我正在尝试使用串行端口在 arduino 和 C 程序之间进行通信 我对 C 编程有点陌生 该程序有多种用户控制形式 每一个都需要访问串口来发送数据 我需要做的就是从每个类的主窗体中写入串行端口 我了解如何设置和写入串行端口 这是我的 Fo
  • 访问者和模板化虚拟方法

    在一个典型的实现中Visitor模式 该类必须考虑基类的所有变体 后代 在许多情况下 访问者中的相同方法内容应用于不同的方法 在这种情况下 模板化的虚拟方法是理想的选择 但目前这是不允许的 那么 模板化方法可以用来解析父类的虚方法吗 鉴于
  • 如何重置捕获像素的值

    我正在尝试创建一个 C 函数 该函数返回屏幕截图位图中每四个像素的 R G 和 B 值 这是我的代码的一部分 for int ix 4 ix lt 1366 ix ix 4 x x 4 for int iy 3 iy lt 768 iy i
  • 在 C 中使用 GNU automake 中的解析器

    我是 GNU autotools 的新手 在我的项目中使用了 lex 和 yacc 解析器 将它们作为 makefile am 中的源代码会产生以下错误 配置 in AC CHECK PROGS YACC bison yacc none i
  • 如何挤出平面 2D 网格并赋予其深度

    我有一组共面 连接的三角形 即二维网格 现在我需要将其在 z 轴上挤出几个单位 网格由一组顶点定义 渲染器通过与三角形数组匹配来理解这些顶点 网格示例 顶点 0 0 0 10 0 0 10 10 0 0 10 0 所以这里我们有一个二维正方
  • 如何一步步遍历目录树?

    我发现了很多关于遍历目录树的示例 但我需要一些不同的东西 我需要一个带有某种方法的类 每次调用都会从目录返回一个文件 并逐渐遍历目录树 请问我该怎么做 我正在使用函数 FindFirstFile FindNextFile 和 FindClo
  • 将代码拆分为标头/源文件

    我从 Asio 的示例页面中获取了以下代码 class tcp connection public boost enable shared from this
  • 有没有一种简单的方法可以让 Visual Studio 2015 使用特定的 ToolsVersion?

    使用特定版本构建项目或解决方案时msbuild我可以使用以下命令选择早期的 net 工具链 toolsversion or tv switch C Program Files x86 MSBuild 14 0 bin msbuild tv
  • 使用 CSharpCodeProvider 类编译 C# 7.3 的 C# 编译器版本是什么?

    我想使用 Microsoft CSharp CSharpCodeProvider 类来编译 C 7 3 代码 编译器版本在 IDictionary 中指定 在创建新的 CSharpCodeProvider 时将其作为输入 例如 Compil
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐

  • typedef 和变量名

    忽略为什么我想这样做 只是想了解这里发生的事情 此代码编译 include
  • 使用backbone.js获取集合(所有模型)的总和

    我只是在学习骨干 我有以下内容 window ServerList Backbone Collection extend model Server cpuTotal function if this length return 0 NOT
  • 为什么任务对象不使用传递给它的参数?

    我在用着Task并行处理多个请求并向每个任务传递不同的参数 但似乎所有任务都采用一个最终参数并使用该参数执行该方法 下面是示例代码 我期望输出为 0 1 2 3 4 5 6 99 但我得到 100 100 100 10 可能在调用 prin
  • Angular2 和 webpack - i18n 插件与 ng2-translate

    我想使用 angular2 构建一个 Web 应用程序并将其与 webpack 捆绑在一起 提供多种语言的最佳方式是什么 i18n 插件 https github com webpack i18n webpack plugin or ng2
  • 为什么我的过滤器版本与 Swifts 的性能如此不同?

    作为练习 我重写了一些 Swift 的高阶函数 其中一个是 filter 我决定测量我的版本 filter反对斯威夫特使用乐器 我对结果感到相当困惑 这是我的过滤器版本 我承认这可能是不正确的 extension Array func my
  • 在 Delphi 中显示某些 JPG 文件时出现问题

    我尝试使用 TImage 组件在 Delphi 中打开一些 JPEG 文件 我还添加了 Jpeg 单元 我可以打开大部分 jpg 文件 没有问题 但是当我尝试打开一些 JPG 时 程序只是抛出异常 我还尝试在设计模式下加载该图像 但存在一些
  • 使用java确定Microsoft Office的版本

    我编写了一个程序 用于创建一组输出到 Excel 电子表格的数据 我最初使用 jexcel 库将数据写入文件 但我想更新程序 以便它可以检查并查看是否应该创建 xls 或 xlsx 文件 然后写入适当的文档类型 Apache POI 似乎是
  • c# HttpWebRequest POST'ing 失败

    所以我正在尝试将一些内容发布到网络服务器 System Net HttpWebRequest EventReq System Net HttpWebRequest System Net HttpWebRequest Create url S
  • 是否可以在
     标签内使用 CDATA                
                

    我想在 HTML 页面中显示异常跟踪 一种方法是转义异常跟踪中的 HTML 特殊字符并将其转储到 pre tag 虽然它有效 但效率非常低 我认为一种方法是用 CDATA 包装跟踪 我已经尝试过 但没有显示任何内容 我的问题是 这可以做到吗
  • Android:在 Cloudinary 中上传照片,并在 HttpURLConnection 中进行进度回调

    我正在尝试修改cloudinary的开源库 以便我可以收听照片上传的进度 该库类包含一个 MultipartUtility java 类 我对其进行了修改以监听上传进度 修改前的原代码可以在github上找到 https github co
  • 使用 Visual studio 2008 进行 Prefast

    有什么办法可以启用Prefast in Visual Studio 2008 专业版添加 我正在尝试编译本机 C 代码 我尝试过以下事情 下载的Windows SDK 将编译器的 Bin Include Lib 路径设置为 SDK 添加了
  • 为 PinterestLikeAdapterView 调用 notificationDataSetChanged() 时如何避免刷新单元格?

    背景 我正在使用PinterestLikeAdapterView 库显示一些来自互联网的图像 它类似于 gridView 但每个单元格的高度不同 问题 由于我使用这个库来显示来自互联网的图像 因此调用notifyDatasetChanged
  • id 的含义是什么?

    我正在 尝试 学习 Objective C 并且不断遇到这样的短语 id init 我明白了id是 Objective C 语言关键字 但是 编译器专门处理id就指针类型转换规则而言 Does id自动将其右侧的对象指定为指针 id是指向任
  • C# 中的数字文本框 - WPF [重复]

    这个问题在这里已经有答案了 我想在 WPF 中创建一个只接受数字的文本框 我研究过 人们说使用按键事件或屏蔽文本框 但它们是在 Windows 窗体中 For WPF private void textBox1 PreviewTextInp
  • xslt变量范围及其用法

    我正在学习 xslt 并且有一个关于如何在 diff 中使用 xslt 变量的问题 对于每个循环 我知道 xslt 不是过程语言 因此在 for 循环中声明的变量不能在另一个循环中访问 但是有什么方法可以声明全局变量 然后在第一个 for
  • Grunt 不更新主 scss 文件

    我有一个项目 将 GruntJS 与 grunt contrib sass grunt contrib watch 和 grunt newer 一起使用 我的主 app scss 文件使用 import 指令导入一些 scss 文件 例如
  • 猫鼬在预保存挂钩中获取数据库值

    我想知道在预保存猫鼬钩子中脏道具的 干净 值是多少 如下所示 UserSchema pre save function next var user this if user isModified password i want to kno
  • 删除该类后,JQuery 选择器仍然有效?

    我有两个协同工作的 jquery 函数 一个依赖于类 另一个删除类 一旦它被删除 我希望该功能停止工作 但它会继续吗 这是怎么回事 这里是fiddle 自己试试吧 div class container disabled a href ww
  • 为什么双切片 numpy 数组的赋值不起作用?

    为什么以下几行不能按我的预期工作 import numpy as np a np array 0 1 2 1 1 a a 1 1 3 print a gt gt gt 0 1 2 1 1 I would expect 0 1 2 3 3 这
  • 在 Xlib 中捕获按钮事件,然后将事件传递给客户端

    我正在开发一个窗口管理器 主要是作为练习 但我遇到了一个问题 我希望能够将单击的窗口提升到堆栈顶部 目前 我在 Button1 和 ControlMask 上使用 XGrabButton 来允许移动窗口 当我按住 Ctrl 键并单击窗口时