如何允许工作线程更新X11窗口?

3

我是一名有用的助手,可以为您进行文本翻译。

我有一个应用程序,我试图修改它,使工作线程能够告诉窗口使用新数据更新自己。

变量定义如下:

Display *d;
Window w;
XEvent exppp;

窗口是通过以下代码启动的:
XEvent e;

d = XOpenDisplay(NULL);
if (d == NULL) 
  return 0;

s = DefaultScreen(d);
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 200, 800, 1,
                        BlackPixel(d, s), WhitePixel(d, s));
XSelectInput(d, w, ExposureMask | KeyPressMask);
XMapWindow(d, w);

while (1) {
  XNextEvent(d, &e);
  if (e.type == Expose || e.type == KeyPress) {
    // redraw routine goes here
  }
}

我试图使用的是一个可以被另一个线程调用的函数来重新绘制窗口:
void graphical_out::redraw()
{
  exppp.type = Expose;
  XSendEvent(d, w, false, Expose, &exppp);
}

窗口只有在被重新调整大小或接收到按键时才会更新自己。这似乎有点像一个初学者的问题,但谷歌在这方面没有给我帮助。任何建议可以告诉我做错了什么吗?

1个回答

6
  1. 您对XSendEvent的参数是错误的。您需要传递掩码(ExposureMask),而不是事件类型。
  2. exppp.xexpose.window = w;是必需的(XSendEvent的窗口参数不是XEvent结构的窗口)。
  3. 在发送事件之前请清除事件:memset(&exppp, 0, sizeof(exppp));,以防万一。
  4. Xlib不是线程安全的,从多个线程调用其函数可能是危险的。

更新:在多线程程序中,需要时不时地调用XFlush(尽管使用Xlib永远不能保证多线程工作)。

以下代码适用于我:

#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <memory.h>

Display *d;
Window w;
int s;

void* tp (void* q)
{
    XEvent exppp;

    while (1)
    {
        sleep (3);
        printf ("Sending event of type Expose\n");
        memset(&exppp, 0, sizeof(exppp));
        exppp.type = Expose;
        exppp.xexpose.window = w;
        XSendEvent(d,w,False,ExposureMask,&exppp);
        XFlush(d);
    }
    return NULL;
}


int main ()
{
    XEvent e;
    pthread_t thread;

    d = XOpenDisplay(NULL);
    if (d == NULL)
        return 0;

    s = DefaultScreen(d);
    w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 200, 800, 1,
                            BlackPixel(d, s), WhitePixel(d, s));
    XSelectInput(d, w, ExposureMask | KeyPressMask);
    XMapWindow(d, w);

    pthread_create(&thread, NULL, tp, NULL);

    while (1) {
        XNextEvent(d, &e);
        if (e.type == Expose) {
            printf ("Got Expose event%s\n", e.xexpose.send_event ? " (SendEvent)" : "");
        }
        else if (e.type == KeyPress) {
            printf ("Got KeyPress event%s\n", e.xkey.send_event ? " (SendEvent)" : "");
        }
    }
}

这可能适用于您,也可能失败。Xlib不是线程安全的,请自行决定是否使用。


好的,我尝试添加了那个,但是仍然没有成功。还有其他我忽略的地方吗?或者这只是一个不好的方法来解决这个问题? - undefined
在多线程环境中,你可能需要在每个XSendEvent之后添加一个对XFlush的调用。请参考更新答案中的代码。 - undefined
非常感谢,已经解决了。由于某种原因,如果两个线程都调用XOpenDisplay并使用单独的display结构,则它能够稳定运行。如果它们都使用相同的display d,会导致一些稳定性问题。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接