xlib의 XNextEvent 차단을 중지하는 방법
창 아래에서 GUI 스레드는 일반적으로 GetMessage를 호출하여 메시지를 기다리고, PoseMessage를 사용하는 다른 스레드가 메시지를 큐에 넣으면 GUI 스레드가 GetMessage를 반환합니다(차단 중지).
XWindows에서 XNextEvent를 사용하여 이벤트를 기다릴 때 다른 스레드에서 GUI 스레드를 "웨이크업"하려면 어떻게 해야 하는지 알려줄 수 있는 사람이 있습니까?PoseMessage와 같은 API를 사용할 수 있습니까?
아니요. 이것이 대부분의 UI 프레임워크(Gtk, KDE 등)가 더 많은 이벤트 소스를 듣기 위해 사용자 지정 메인 루프를 사용하는 이유입니다.
내부적으로 XNextEvent는 소켓을 사용하기 때문에select()
언제 입력이 가능한지 알 수 있습니다.불러ConnectionNumber(display)
전달해야 할 파일 설명자를 가져오려면select()
이를 통해 여러 파일 설명자를 들을 수 있습니다.
http://www.linuxquestions.org/questions/showthread.php?p=2431345#post2431345 의 샘플 코드
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
Display *dis;
Window win;
int x11_fd;
fd_set in_fds;
struct timeval tv;
XEvent ev;
int main() {
dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 256, 256, \
0, BlackPixel (dis, 0), BlackPixel(dis, 0));
// You don't need all of these. Make the mask as you normally would.
XSelectInput(dis, win,
ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask | StructureNotifyMask
);
XMapWindow(dis, win);
XFlush(dis);
// This returns the FD of the X11 display (or something like that)
x11_fd = ConnectionNumber(dis);
// Main loop
while(1) {
// Create a File Description Set containing x11_fd
FD_ZERO(&in_fds);
FD_SET(x11_fd, &in_fds);
// Set our timer. One second sounds good.
tv.tv_usec = 0;
tv.tv_sec = 1;
// Wait for X Event or a Timer
int num_ready_fds = select(x11_fd + 1, &in_fds, NULL, NULL, &tv);
if (num_ready_fds > 0)
printf("Event Received!\n");
else if (num_ready_fds == 0)
// Handle timer here
printf("Timer Fired!\n");
else
printf("An error occured!\n");
// Handle XEvents and flush the input
while(XPending(dis))
XNextEvent(dis, &ev);
}
return(0);
}
더미 이벤트를 전송하여 차단 XNextEvent를 종료할 수 있습니다.
Window interClientCommunicationWindow;
Bool x11EventLoopActive = True;
// create a dummy window, that we can use to end the blocking XNextEvent call
interClientCommunicationWindow = XCreateSimpleWindow(dpy, root, 10, 10, 10, 10, 0, 0, 0);
XSelectInput(dpy, interClientCommunicationWindow, StructureNotifyMask);
XEvent event;
while(x11EventLoopActive) {
XNextEvent(dpy, &event);
...
}
다른 스레드에서 루프를 종료하기 위해 다음 작업을 수행할 수 있습니다.
x11EventLoopActive = False;
// push a dummy event into the queue so that the event loop has a chance to stop
XClientMessageEvent dummyEvent;
memset(&dummyEvent, 0, sizeof(XClientMessageEvent));
dummyEvent.type = ClientMessage;
dummyEvent.window = interClientCommunicationWindow;
dummyEvent.format = 32;
XSendEvent(dpy, interClientCommunicationWindow, 0, 0, (XEvent*)&dummyEvent);
XFlush(dpy);
사용해야 할 항목: Bool XCheckMaskEvent(Display*, long, XEvent)
그XCheckMaskEvent
function은 먼저 이벤트 큐를 검색한 다음 지정된 마스크와 일치하는 첫 번째 이벤트에 대해 서버 연결에서 사용 가능한 모든 이벤트를 검색합니다.
일치하는 걸 찾으면,XCheckMaskEvent
해당 이벤트를 제거하고 지정된 이벤트에 복사합니다.XEvent
구조 및 반환True
. 큐에 저장된 다른 이벤트는 폐기되지 않습니다.
요청하신 이벤트를 이용할 수 없는 경우,XCheckMaskEvent
돌아온다False
, 출력 버퍼가 플러시된 상태가 됩니다.
자신만의 루프 및 폴링을 실행할 수도 있습니다.pending
. 이 코드는 Crystal로 작성되어 있지만 C에서는 동일합니다.
loop do
while @display.pending > 0
event = @display.next_event
# do stuff with event
end
sleep 16.milliseconds
end
하지만 이런 식으로 (분명히 수면 시간에 따라) 자원이 더 많이 부족하기 때문에 수용된 대답이 더 나은 생각일 수 있습니다.
언급URL : https://stackoverflow.com/questions/8592292/how-to-quit-the-blocking-of-xlibs-xnextevent
'bestsource' 카테고리의 다른 글
cURL을 사용하여 HTTPS 사이트에 연결할 수 없습니다. 대신 0 길이의 컨텐츠를 반환합니다.어쩌죠? (0) | 2023.09.11 |
---|---|
SQL 트랜잭션 오류:현재 트랜잭션을 커밋할 수 없으며 로그 파일에 쓰는 작업을 지원할 수 없습니다. (0) | 2023.09.11 |
MariaDB의 열 값을 다른 테이블에서 바꾸기 (0) | 2023.09.11 |
liquibebase를 사용하여 DB의 기존 행을 업데이트 할 수 있습니까? (0) | 2023.09.11 |
열 이름의 공백 제거 또는 바꾸기 (0) | 2023.09.11 |