为什么在没有 XPeekEvent 调用的情况下 while 循环无法工作?

问题描述 投票:0回答:1

标题说明了一切。 该代码与

XPeekEvent
之前的
while XCheckTypedEvent
一起使用,但如果没有它,条件计算结果为 false,我不知道为什么会这样。

#include <X11/Xlib.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define false 0
#define true 1


int main(void)
{
    Display* dpy;
    XWindowAttributes attr;

    // state of cursor at the start of move/resize
    XButtonEvent cur_start;

    // return failure status if we can't connect
    if (!(dpy = XOpenDisplay(0x0))) return 1;

    char* keys_to_grab[] = {"F1"};
    for (size_t i = 0; i < sizeof(keys_to_grab) / sizeof(keys_to_grab[0]); i++)
    {
        XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym(keys_to_grab[i])), Mod1Mask,
            DefaultRootWindow(dpy), True, GrabModeAsync, GrabModeAsync);
    }

    XGrabButton(dpy, 1, Mod1Mask, DefaultRootWindow(dpy), True,
            ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None);

    XGrabButton(dpy, 3, Mod1Mask, DefaultRootWindow(dpy), True,
            ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None);

    cur_start.subwindow = None;

    for(;;)
    {
        XNextEvent(dpy, &ev);
        switch(ev.type)
        {
            case KeyPress:
                if (ev.xkey.subwindow != None)
                    XRaiseWindow(dpy, ev.xkey.subwindow);
                break;

            case ButtonPress:
                if (ev.xbutton.subwindow != None)
                    cur_start = ev.xbutton;
                break;
                
            case MotionNotify:
                if (cur_start.subwindow != None)
                {
                    XPeekEvent(dpy, &ev);
                    while(XCheckTypedEvent(dpy, MotionNotify, &ev))
                    {
                        int xdiff = ev.xbutton.x_root - cur_start.x_root;
                        int ydiff = ev.xbutton.y_root - cur_start.y_root;
                       XMoveWindow(dpy, cur_start.subwindow,
                                attr.x + (cur_start.button==1 ? xdiff : 0),
                                attr.y + (cur_start.button==1 ? ydiff : 0));
                    }
                }
                break;

            case ButtonRelease:
                cur_start.subwindow = None;
                break;

            default:
                break;
        }
    }
}

这就是我运行代码的方式:

xinit ./xinitrc -- /usr/bin/Xephyr :100 -ac -screen 500x500 -host-cursor
以此作为 xinitrc:

xclock &
xeyes &
sleep 2 && xterm &

exec ./a.out

“有效”是指我可以拖动窗口。

c linux x11 xlib window-management
1个回答
0
投票

来自

XPeekEvent
的手册页。

如果队列为空,XPeekEvent 将刷新输出缓冲区并阻塞,直到收到事件。然后,它将事件复制到客户端提供的 XEvent 结构中,而不将其从事件队列中删除。

我猜想事件还没有被接收到,所以

XPeekEvent
会阻塞,直到接收到事件,然后
XCheckTypedEvent
正在获取该事件并处理它。

考虑到

XPeekEvent
还将事件结构复制到
&ev
并返回
True
,您可以使用
XPeekEvent
作为您的
while
条件并摆脱对
XCheckTypedEvent
的调用。

© www.soinside.com 2019 - 2024. All rights reserved.