如何处理窗口事件在等待端子输入? [英] How to handle window events while waiting for terminal input?

查看:139
本文介绍了如何处理窗口事件在等待端子输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经有了一个跨平台(Windows和UNIX + XCB)终端+应用graphics_window,它主要是工作正常,直到等待时间过长,在输入提示,在重负载下的图像可能会消失。 (

我已经得到了国米preTER(后记间preTER)围绕其循环每次它调用的事件处理函数的主循环(REPL)。该事件处理程序执行的一个通常来说是窗口的消息/事件循环一次迭代。但是,输入与正常的C I / O处理,因此事件处理程序挡在时,不会被调用龟etc()

图形窗口是只输出。它没有按键,只需要像养,地图,暴露等事件。

我怎么能安排将输入读取过程中调用的事件处理循环调用堆栈更深?这需要有可能与POSIX和Win32 API的实现。

选项似乎


  • 非阻塞I / O结果
    在UNIX中比较简单。看起来像Windows中的疼痛

  • 查询

  • 输入线程结果
    pthreads的?

  • 窗口线程结果
    pthreads的?

是否有任何的这些可能是比其他痛苦少?

如果我能仅仅停留在UNIX上,那么这似乎做全伎俩:

 的#include<&errno.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&termios.h GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&fcntl.h GT;空隙idleproc(){/ *摸拟调用事件处理程序
                        (即窗口环路的一个片)* /
    //输出(闲置\\ n);
    的putchar('。');
}INT idlefgetc(FILE *流){
    INT RET;    做{
        RET =龟etc(流);
        idleproc();
    }而(RET == EOF和放大器;&安培;
            (错误== EAGAIN ||错误号== EINTR));    返回RET;
}INT setraw(FILE *流){
    结构termios的TBUF;
    如果(tcgetattr(的fileno(流),放大器; TBUF)== -1)
        返回-1;
    tbuf.c_iflag&安培; =〜(IGNBRK | BRKINT | PARMRK | ISTRIP
            | INLCR | IGNCR | ICRNL | IXON);
    tbuf.c_oflag&安培; =〜OPOST;
    tbuf.c_lflag&安培; =〜(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tbuf.c_cflag&安培; =〜(CSIZE | PARENB);
    tbuf.c_cflag | = CS8;
    如果(tcsetattr(的fileno(流),TCSANOW,&安培; TBUF)== -1)
        返回-1;
    返回0;
}INT setnonblocking(FILE *流){
    诠释标志;    如果(setraw(流)!= 0)
        返回-1;
    如果(((标志=的fcntl(的fileno(流),F_GETFL))及!O_NONBLOCK)){
        标志| = O_NONBLOCK;
        的fcntl(的fileno(流),F_SETFL,旗);
    }
    返回0;
}INT主(INT ARGC,字符** argv的){
    如果(setnonblocking(标准输入)){
        PERROR(的argv [0]);
        返回0;
    }
    的printf(%D'\\ n,idlefgetc(标准输入));
    系统(stty的理智);
    返回0;
}


解决方案

在Windows环境下,你需要使用控制台API。
您可以执行异步非阻塞,用的 ReadFileEx 。另一种可能性是 ReadConsoleInput 和民意调查continously输入,而不会阻塞。随着 SetConsole 你可以决定,哪些事件捕获。

对于Windows下的异步I / O的更多详细信息,请参阅的这里

I've got a cross-platform (windows and unix+xcb) terminal+graphics_window application and it mostly works ok, until you wait too long at the input prompt, where under heavy load the image may disappear. :(

I've got a mainloop (REPL) for the interpreter (postscript interpreter) which calls an event handler function each time around its loop. The event handler performs one iteration of what would normally be the window's message/event loop. But input is processed with normal C i/o and so the event handler never gets called when blocked in fgetc().

The graphics window is output-only. It has no buttons and only needs to respond to events like Raise, Map, Expose, etc.

How can I arrange to have the event handler called during input reading loops deeper in the call stack? This needs to be possible to implement with both POSIX and win32 APIs.

The options appear to be

  • Non-blocking i/o
    relatively simple in unix. looks like a pain in windows
  • Polling
  • Input thread
    pthreads?
  • Window thread
    pthreads?

Are any of these likely to be less painful than the others?

If I could just stay on unix, then this would seem to do the whole trick:

#include <errno.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

void idleproc () {  /* simulates calling the event handler 
                        (ie. one slice of the window loop) */
    //printf("idle\n");
    putchar('.');
}

int idlefgetc (FILE *stream) {
    int ret;

    do {
        ret = fgetc(stream);
        idleproc();
    } while(ret == EOF && 
            (errno == EAGAIN || errno == EINTR));

    return ret;
}

int setraw (FILE *stream) {
    struct termios tbuf;
    if (tcgetattr(fileno(stream), &tbuf) == -1)
        return -1;
    tbuf.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
            | INLCR | IGNCR | ICRNL | IXON);
    tbuf.c_oflag &= ~OPOST;
    tbuf.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tbuf.c_cflag &= ~(CSIZE | PARENB);
    tbuf.c_cflag |= CS8;
    if (tcsetattr(fileno(stream), TCSANOW, &tbuf) == -1)
        return -1;
    return 0;
}

int setnonblocking (FILE *stream) {
    int flags;

    if (setraw(stream) != 0)
        return -1;
    if (!((flags = fcntl(fileno(stream), F_GETFL)) & O_NONBLOCK)) {
        flags |= O_NONBLOCK;
        fcntl(fileno(stream), F_SETFL, flags);
    }
    return 0;
}

int main (int argc, char **argv) {
    if (setnonblocking(stdin)) {
        perror(argv[0]);
        return 0;
    }
    printf("'%d'\n", idlefgetc(stdin));
    system("stty sane");
    return 0;
}

解决方案

Under Windows you need to use the Console API. You can perform asynchronous, non-blocking, reading of characters with ReadFileEx. Another possibility is ReadConsoleInput, and poll continously for input, without blocking. With SetConsole you can decide, what events to capture.

For more details on asynchronous I/O under Windows, see here.

这篇关于如何处理窗口事件在等待端子输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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