void rungui(const char **user, const char **pass) { Input *i; XEvent ev; running = True; XSetInputFocus(dpy, inputs->win, RevertToPointerRoot, CurrentTime); XSync(dpy, False); while (running && !XNextEvent(dpy, &ev)) { if (XFilterEvent(&ev, None) || !(i = wintoinput(ev.xany.window))) continue; switch (ev.type) { case Expose: if (ev.xexpose.count == 0) drawinput(i); break; case KeyPress: keypress(i, &ev.xkey); break; case FocusIn: i->cursor = strlen(i->text); /* fallthrough */ case FocusOut: drawinput(i); break; } } *user = inputs->text; *pass = inputs->next->text; }
void BrowserControl::sendKeyboardEventToNix(const XEvent& event) { if (XFilterEvent(const_cast<XEvent*>(&event), m_browserWindow->window())) return; NIXKeyEvent ev; char buf[20]; bool shouldUseUpperCase; const XKeyEvent* keyEvent = reinterpret_cast<const XKeyEvent*>(&event); int count = 0; KeySym keySym = 0; Status status; keySym = chooseSymbolForXKeyEvent(keyEvent, &shouldUseUpperCase); ev = convertXKeyEventToNixKeyEvent(keyEvent, keySym, shouldUseUpperCase); count = Xutf8LookupString(m_ic, const_cast<XKeyEvent*>(keyEvent), buf, 20, &keySym, &status); if (count) { buf[count] = '\0'; ev.text = buf; } if (ev.type == kNIXInputEventTypeKeyDown) m_client->handleKeyPress(&ev); else m_client->handleKeyRelease(&ev); }
static void run(void) { XEvent ev; while (!XNextEvent(dpy, &ev)) { if (XFilterEvent(&ev, win)) continue; switch(ev.type) { case Expose: if (ev.xexpose.count == 0) drw_map(drw, win, 0, 0, mw, mh); break; case FocusIn: /* regrab focus from parent window */ if (ev.xfocus.window != win) grabfocus(); break; case KeyPress: keypress(&ev.xkey); break; case SelectionNotify: if (ev.xselection.property == utf8) paste(); break; case VisibilityNotify: if (ev.xvisibility.state != VisibilityUnobscured) XRaiseWindow(dpy, win); break; } } }
void run(void) { XEvent ev; while(running && !XNextEvent(dc->dpy, &ev)) { if(XFilterEvent(&ev, win)) continue; switch(ev.type) { case Expose: if(ev.xexpose.count == 0) mapdc(dc, win, mw, mh); break; case KeyPress: keypress(&ev.xkey); break; case SelectionNotify: if(ev.xselection.property == utf8) paste(); break; case VisibilityNotify: if(ev.xvisibility.state != VisibilityUnobscured) XRaiseWindow(dc->dpy, win); break; } } }
/*********************************************************************** * process_events */ static int process_events( Display *display, ULONG_PTR mask ) { XEvent event; HWND hwnd; int count = 0; x11drv_event_handler handler; wine_tsx11_lock(); while (XCheckIfEvent( display, &event, filter_event, (char *)mask )) { count++; if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */ if (!(handler = find_handler( event.type ))) { TRACE( "%s, ignoring\n", dbgstr_event( event.type )); continue; /* no handler, ignore it */ } if (XFindContext( display, event.xany.window, winContext, (char **)&hwnd ) != 0) hwnd = 0; /* not for a registered window */ if (!hwnd && event.xany.window == root_window) hwnd = GetDesktopWindow(); wine_tsx11_unlock(); TRACE( "%s for hwnd/window %p/%lx\n", dbgstr_event( event.type ), hwnd, event.xany.window ); handler( hwnd, &event ); wine_tsx11_lock(); } XFlush( gdi_display ); wine_tsx11_unlock(); if (count) TRACE( "processed %d events\n", count ); return count; }
void DesktopWindowLinux::sendKeyboardEventToNix(const XEvent& event) { if (XFilterEvent(const_cast<XEvent*>(&event), m_window)) return; NIXKeyEvent ev; memset(&ev, 0, sizeof(NIXKeyEvent)); char buf[20]; bool shouldUseUpperCase; const XKeyEvent* keyEvent = reinterpret_cast<const XKeyEvent*>(&event); KeySym symbol = chooseSymbolForXKeyEvent(keyEvent, &shouldUseUpperCase); ev = convertXKeyEventToNixKeyEvent(keyEvent, symbol, shouldUseUpperCase); Status status; int count = Xutf8LookupString(m_ic, const_cast<XKeyEvent*>(keyEvent), buf, 20, &symbol, &status); if (count) { buf[count] = '\0'; ev.text = buf; } if (ev.type == kNIXInputEventTypeKeyDown) m_client->onKeyPress(&ev); else m_client->onKeyRelease(&ev); }
int main(int argc, char *argv[]) { Display *display; int screen; GC gc; Window window; XWMHints hints; Atom protocols; XEvent event; unsigned long mask; Font xfont1, xfont2; display = XOpenDisplay(""); screen = DefaultScreen(display); gc = DefaultGC(display, screen); /* * Font names are hard-coded. */ xfont1 = XLoadFont(display, "a14"); xfont2 = XLoadFont(display, "k14"); window = XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, W_WIDTH, W_HEIGHT, 2, BlackPixel(display, screen), WhitePixel(display, screen)); XStoreName(display, window, "XFontStruct demo"); hints.flags = InputHint; hints.input = True; XSetWMHints(display, window, &hints); protocols = XInternAtom(display, "WM_DELETE_WINDOW", True); XSetWMProtocols(display, window, &protocols, 1); mask = ExposureMask; XSelectInput(display, window, mask); XMapWindow(display, window); for (;;) { XNextEvent(display, &event); if (XFilterEvent(&event, window) == True) continue; switch (event.type) { case Expose: { XSetFont(display, gc, xfont1); XDrawString(display, window, gc, 10, 50, "abcdef", 6); XSetFont(display, gc, xfont2); /* JIS */ XDrawString16(display, window, gc, 10, 80, (XChar2b *) "\x24\x22\x24\x24", 4); break; } default: { break; } } } }
static void gfx_ctx_xegl_check_window(void *data, bool *quit, bool *resize, unsigned *width, unsigned *height, unsigned frame_count) { XEvent event; unsigned new_width = *width; unsigned new_height = *height; (void)frame_count; gfx_ctx_xegl_get_video_size(data, &new_width, &new_height); if (new_width != *width || new_height != *height) { *resize = true; *width = new_width; *height = new_height; } while (XPending(g_dpy)) { bool filter; /* Can get events from older windows. Check this. */ XNextEvent(g_dpy, &event); filter = XFilterEvent(&event, g_win); switch (event.type) { case ClientMessage: if (event.xclient.window == g_win && (Atom)event.xclient.data.l[0] == g_quit_atom) g_quit = true; break; case DestroyNotify: if (event.xdestroywindow.window == g_win) g_quit = true; break; case MapNotify: if (event.xmap.window == g_win) g_has_focus = true; break; case UnmapNotify: if (event.xunmap.window == g_win) g_has_focus = false; break; case KeyPress: case KeyRelease: if (event.xkey.window == g_win) x11_handle_key_event(&event, g_xic, filter); break; } } *quit = g_quit; }
bool WindowContextBase::im_filter_keypress(GdkEventKey* event) { static size_t buf_len = 12; static char *buffer = NULL; if (buffer == NULL) { buffer = (char*)malloc(buf_len * sizeof (char)); } KeySym keysym; Status status; XKeyPressedEvent xevent = convert_event(event); if (XFilterEvent((XEvent*) & xevent, GDK_WINDOW_XID(gdk_window))) { return TRUE; } if (event->type == GDK_KEY_RELEASE) { process_key(event); return TRUE; } int len = Xutf8LookupString(xim.ic, &xevent, buffer, buf_len - 1, &keysym, &status); if (status == XBufferOverflow) { buf_len = len + 1; buffer = (char*)realloc(buffer, buf_len * sizeof (char)); len = Xutf8LookupString(xim.ic, &xevent, buffer, buf_len - 1, &keysym, &status); } switch (status) { case XLookupKeySym: case XLookupBoth: if (xevent.keycode) { //process it as a normal key process_key(event); break; } // fall-through case XLookupChars: buffer[len] = 0; jstring str = mainEnv->NewStringUTF(buffer); EXCEPTION_OCCURED(mainEnv); jsize slen = mainEnv->GetStringLength(str); mainEnv->CallVoidMethod(jview, jViewNotifyInputMethod, str, NULL, NULL, NULL, slen, slen, 0); LOG_EXCEPTION(mainEnv) break; } return TRUE; }
static void gfx_ctx_glx_check_window(void *data, bool *quit, bool *resize, unsigned *width, unsigned *height, unsigned frame_count) { gfx_ctx_glx_data_t *glx = (gfx_ctx_glx_data_t*)driver.video_context_data; unsigned new_width = *width, new_height = *height; (void)frame_count; gfx_ctx_glx_get_video_size(data, &new_width, &new_height); if (new_width != *width || new_height != *height) { *resize = true; *width = new_width; *height = new_height; } XEvent event; while (XPending(glx->g_dpy)) { XNextEvent(glx->g_dpy, &event); bool filter = XFilterEvent(&event, glx->g_win); switch (event.type) { case ClientMessage: if (event.xclient.window == glx->g_win && (Atom)event.xclient.data.l[0] == g_quit_atom) g_quit = true; break; case DestroyNotify: if (event.xdestroywindow.window == glx->g_win) g_quit = true; break; case MapNotify: if (event.xmap.window == glx->g_win) glx->g_has_focus = true; break; case UnmapNotify: if (event.xunmap.window == glx->g_win) glx->g_has_focus = false; break; case KeyPress: case KeyRelease: x11_handle_key_event(&event, glx->g_xic, filter); break; } } *quit = g_quit; }
int main() { int size; fd_set fds; struct timeval tv; u8 buf[BUFSIZE]; XEvent ev; xwindow xw; terminal term; /* init */ x_init(&xw); term_init(&term, xw.res); load_ctrl_func(ctrl_func, CTRL_CHARS); load_esc_func(esc_func, ESC_CHARS); load_csi_func(csi_func, ESC_CHARS); /* fork */ eforkpty(&term.fd, term.lines, term.cols); signal(SIGCHLD, sigchld); setvbuf(stdout, NULL, _IONBF, 0); /* main loop */ while (loop_flag) { check_fds(&fds, &tv, term.fd); while(XPending(xw.dsp)) { XNextEvent(xw.dsp, &ev); if(XFilterEvent(&ev, xw.win)) continue; if (event_func[ev.type]) event_func[ev.type](&xw, &term, &ev); } if (FD_ISSET(term.fd, &fds)) { size = read(term.fd, buf, BUFSIZE); if (size > 0) { if (DEBUG) ewrite(STDOUT_FILENO, buf, size); parse(&term, buf, size); if (size == BUFSIZE) continue; refresh(&xw, &term); } } } term_die(&term); x_die(&xw); return 0; }
void gui_loop(xccore_t *xccore) { while (1) { XEvent event; winlist_t *win; if ((xccore->oxim_mode & OXIM_RUN_EXITALL)) { xim_terminate(); exit(0); } XFlush(gui->display); if (XPending(gui->display)) { XNextEvent(gui->display, &event); if (XFilterEvent(&event, None) != True) { win = gui_search_win(event.xany.window); if (win && win->win_event_func) { win->win_event_func(win, &(event)); } } } else { struct timeval tv; fd_set readfds; int fd = ConnectionNumber(gui->display); FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = 5; tv.tv_usec = 0; if (select(fd + 1, &readfds, NULL, NULL, &tv) == 0) { continue; } } } }
static void X11ProcessEventRealInternal(FcitxX11 *x11priv) { XEvent event; while (XPending(x11priv->dpy)) { XNextEvent(x11priv->dpy, &event); if (XFilterEvent(&event, None) == False) { switch (event.type) { case DestroyNotify: if (event.xany.window == x11priv->compManager) X11HandlerComposite(x11priv, false); break; case ClientMessage: if (event.xclient.data.l[1] == x11priv->compManagerAtom) { if (X11GetCompositeManager(x11priv)) X11HandlerComposite(x11priv, true); } break; case ConfigureNotify: if (event.xconfigure.window == x11priv->rootWindow) X11InitScreen(x11priv); break; case SelectionNotify: X11ProcessSelectionNotifyEvent(x11priv, (XSelectionEvent*)&event); break; default: #ifdef HAVE_XFIXES if (x11priv->hasXfixes && X11ProcessXFixesEvent(x11priv, &event)) break; #endif break; } FcitxXEventHandler* handler; for (handler = (FcitxXEventHandler*)utarray_front(&x11priv->handlers); handler != NULL; handler = (FcitxXEventHandler*)utarray_next(&x11priv->handlers, handler)) if (handler->eventHandler(handler->instance, &event)) break; } } }
int main(int argc, char *argv[]) { XEvent event; uint32_t timestamp = 0; init_x(); font_init(); ejoy2d_win_init(argc, argv); for (;;) { while(XPending(g_X.display) > 0) { XNextEvent(g_X.display, &event); if (XFilterEvent(&event,None)) continue; switch (event.type) { case Expose: if (event.xexpose.count==0) update_frame(); break; case ButtonPress: ejoy2d_win_touch(event.xbutton.x, event.xbutton.y, TOUCH_BEGIN); break; case ButtonRelease: ejoy2d_win_touch(event.xbutton.x,event.xbutton.y,TOUCH_END); break; case MotionNotify: ejoy2d_win_touch(event.xbutton.x,event.xbutton.y,TOUCH_MOVE); break; } } uint32_t old = timestamp; timestamp= _gettime(); if (timestamp - old >= UPDATE_INTERVAL) { ejoy2d_win_update(); update_frame(); } else usleep(1000); } }
static int process_nonkey_event(PLAYER *player, XEvent *evnt) { if (XFilterEvent(evnt, wnd)) return 0; switch (evnt->type) { case Expose: { XExposeEvent *xee; game.status &= ~GMST_SUSPENDED; xee = (XExposeEvent *) evnt; // if (xee->count == 0) flush_pane(PT_FOREGROUND, xee->x, xee->y, xee->width, xee->height); } break; case MapNotify: game.status &= ~GMST_SUSPENDED; break; case UnmapNotify: if (game.level < Levels && player->type == 0) game.status |= GMST_SUSPENDED; break; case ClientMessage: { XClientMessageEvent *xcme; xcme = (XClientMessageEvent *)evnt; if (xcme->message_type == WMProtAtom && xcme->data.l[0] == WMDelAtom) return 1; } break; } return 0; }
value caml_next_event(value unit) { CAMLparam1(unit); CAMLlocal1(mlev); XEvent ev; char buf[32]; KeySym ksym = NoSymbol; Status status; size_t len; while(!XNextEvent(dc->dpy, &ev)) { if(XFilterEvent(&ev, win)) continue; switch(ev.type) { case Expose: if(ev.xexpose.count == 0) mapdc(dc, win, mw, mh); break; case KeyPress: len = XmbLookupString(xic, &ev.xkey, buf, sizeof buf, &ksym, &status); buf[len] = '\0'; mlev = caml_alloc_tuple(2); Field(mlev, 0) = Val_int(ksym); Field(mlev, 1) = caml_copy_string (buf); CAMLreturn (mlev); break; case SelectionNotify: /* if(ev.xselection.property == utf8) paste(); */ break; case VisibilityNotify: if(ev.xvisibility.state != VisibilityUnobscured) XRaiseWindow(dc->dpy, win); break; } } caml_failwith("unexpected return from XNextEvent") ; }
void _gdk_x11_display_queue_events (GdkDisplay *display) { GdkEvent *event; XEvent xevent; Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); GdkEventSource *event_source; GdkX11Display *display_x11; display_x11 = GDK_X11_DISPLAY (display); event_source = (GdkEventSource *) display_x11->event_source; while (!_gdk_event_queue_find_first (display) && XPending (xdisplay)) { XNextEvent (xdisplay, &xevent); switch (xevent.type) { case KeyPress: case KeyRelease: break; default: if (XFilterEvent (&xevent, None)) continue; } event = gdk_event_source_translate_event (event_source, &xevent); if (event) { GList *node; node = _gdk_event_queue_append (display, event); _gdk_windowing_got_event (display, node, event, xevent.xany.serial); } } }
static Boolean PrintDispatchEvent (XEvent *event) { XPPrintEvent * xpev = (XPPrintEvent *) event ; Widget widget = NULL ; /* I only have a context, not a window, so I can't use XtWindowToWidget.. I have to maintain my own table widget/context. Limitation: one context to one widget for now */ GetFromTable(xpev->display, xpev->context, &widget); /* If ever supported, need to loop thru a list, if several print_shell have been created under the same XPContext, and dispatch the event to all of them */ if (!widget) return False ; /* spec says to call filter first, even though in my case, I shouldn't have any IM around... */ if (XFilterEvent(event, XtWindow(widget))) return True ; return XtDispatchEventToWidget(widget, event); }
static GdkFilterReturn my_gdk_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) { XEvent *xeve = (XEvent *)xevent; #if 0 dbg("a zzz %d\n", xeve->type); #endif // only very old WM will enter this if (xeve->type == FocusIn || xeve->type == FocusOut) { #if 0 dbg("focus %s\n", xeve->type == FocusIn ? "in":"out"); #endif return GDK_FILTER_REMOVE; } #if USE_XIM if (XFilterEvent(xeve, None) == True) return GDK_FILTER_REMOVE; #endif return GDK_FILTER_CONTINUE; }
int main(int argc, char **argv) { Display *display; int screen_num; Window win; //窗口ID unsigned int width, height; //窗口尺寸 unsigned int border_width = 4; //边界空白 unsigned int display_width, display_height;//屏幕尺寸 XEvent report; GC gc; unsigned long valuemask = 0; XGCValues values; char *display_name = NULL; Atom protocols; //edit int len = 127; unsigned char string[128], s_tab[ROW][127]; KeySym keysym; int row = 0, col = 0; int i, count = 0; Status status; //字体集 XFontSet fontset; char **missing_charsets; int num_missing_charsets; char *default_string; XFontSetExtents *fs_ext; int dec; //XIM XIM im; XIC ic; //overspot XRectangle spot, s_rect; XVaNestedList preedit_attr, status_attr; //设置locale if((setlocale(LC_ALL, "")) == NULL){ printf("cannot set locale\n"); exit(1); } //判断X是否支持locale if(!XSupportsLocale()){ printf("X does not support current locale\n"); exit(1); } //设置locale修饰 if(XSetLocaleModifiers(NULL)){ printf("Cannot set locale modifiers\n"); exit(1); } // 和X 服务器连接 if ( (display=XOpenDisplay(display_name)) == NULL ) { printf("Cannot connect to X server %s\n", XDisplayName(display_name)); exit(-1); } //获得缺省的 screen_num screen_num = DefaultScreen(display); //获得屏幕的宽度和高度 display_width = DisplayWidth(display, screen_num); display_height = DisplayHeight(display, screen_num); //建立字体集 fontset = XCreateFontSet(display, "8x16,-*-song-medium-r-normal--16-*-*-*-*-*-gb2312.1980-0", &missing_charsets, &num_missing_charsets, &default_string); if(num_missing_charsets > 0){ int i; printf("Following charsets are missing:\n"); for(i=0; i<num_missing_charsets; i++){ printf("Missing %d: %s\n", i, missing_charsets[i]); } printf("\nDefault string:%s\n", default_string); XFreeStringList(missing_charsets); } //字体的Extents fs_ext = XExtentsOfFontSet(fontset); dec = fs_ext->max_logical_extent.height + fs_ext->max_logical_extent.y; width = W_WIDTH; height = W_HEIGHT + dec; //建立窗口 win = XCreateSimpleWindow(display, //display RootWindow(display,screen_num), //父窗口 0, 0, width, height, //位置和大小 border_width, //边界宽度 BlackPixel(display,screen_num), //前景色 WhitePixel(display,screen_num));//背景色 //选择窗口感兴趣的事件掩码 XSelectInput(display, win, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask); //建立GC gc = XCreateGC(display, win, valuemask, &values); protocols = XInternAtom(display, "WM_DELETE_WINDOW", True); XSetWMProtocols(display, win, &protocols, 1); //显示窗口 XMapWindow(display, win); //联接输入服务器 if((im = XOpenIM(display, NULL, NULL, NULL)) == NULL){ printf("Error : XOpenIM !\n"); exit(1); } //设置输入服务器的位置 spot.x = F_SIZE / 2 * col; spot.y = F_SIZE * (row + 1) - dec; preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, XNFontSet, fontset, NULL); s_rect.x = 0; s_rect.y = F_SIZE * ROW + dec + 2; s_rect.width = W_WIDTH; s_rect.height = F_SIZE; status_attr = XVaCreateNestedList(0, XNArea, &s_rect, XNFontSet, fontset, NULL); //建立IC if((ic = XCreateIC(im, XNInputStyle, XIMPreeditPosition | XIMStatusNothing, XNClientWindow, win, XNPreeditAttributes, preedit_attr, XNStatusAttributes, status_attr, NULL)) == NULL){ printf("Error : XCreateIC() ! \n"); XCloseIM(im); exit(0); } //释放内存 XFree(preedit_attr); XFree(status_attr); //写屏缓冲区初始化 for(i = 0; i < ROW; i++)s_tab[i][0] = 0; //进入事件循环 while (1) { //取得队列中的事件 XNextEvent(display, &report); //过滤事件 if(XFilterEvent(&report, None) == True) continue; switch (report.type) { //聚焦发声变化 case FocusIn: XSetICFocus(ic); break; case FocusOut: XUnsetICFocus(ic); break; //曝光事件, 窗口应重绘 case Expose: //取得最后一个曝光事件 if (report.xexpose.count != 0) break; for ( i=0; i < ROW; i++) XmbDrawString(display, win, fontset,gc, 0, F_SIZE * (i +1), s_tab[i], strlen(s_tab[i])); break; //窗口尺寸改变, 重新取得窗口的宽度和高度 case ConfigureNotify: width = report.xconfigure.width; height = report.xconfigure.height; break; //鼠标点击或有按键, 释放资源则退出 case KeyPress: count = XmbLookupString(ic, (XKeyPressedEvent *) &report, string, len, &keysym, &status); string[count] = 0; if (status == XLookupBoth&&keysym == XK_Return){ row = (++row) % ROW; col = 0; s_tab[row][0] = 0; XClearArea(display, win, 0, F_SIZE * row + dec, W_WIDTH, F_SIZE, False); } else if (status = XLookupChars || status == XLookupBoth){ XmbDrawString(display, win, fontset, gc, F_SIZE / 2 * col, F_SIZE * (row + 1), string, count); for (i = 0; i < count && col < len && string[i]; i++, col++) s_tab[row][col] = string[i]; s_tab[row][col] = 0; } //更新输入服务器位置 spot.x = F_SIZE / 2 * col; spot.y = F_SIZE * (row + 1); preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); XSetICValues(ic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); break; case ClientMessage: if (report.xclient.data.l[0] == protocols) { XDestroyIC(ic); XCloseIM(im); XDestroyWindow(display, win); XCloseDisplay(display); exit(0); } break; default: break; } } }
int main_loop(int argc, char *argv[]) { setup_language(); se_env* env = se_env_init(); se_text_xviewer* viewer = se_text_xviewer_create( env ); long im_event_mask; XGetICValues( viewer->xic, XNFilterEvents, &im_event_mask, NULL ); int mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | SubstructureNotifyMask | FocusChangeMask | im_event_mask; XSelectInput( env->display, viewer->view, mask ); XSetICFocus( viewer->xic ); viewer->repaint( viewer ); viewer->show( viewer ); while ( 1 ) { // sync the first expose event XEvent ev; XNextEvent( env->display, &ev ); if ( ev.xany.window == viewer->view && ev.type == Expose ) { viewer->redisplay( viewer ); break; } } while( !env->exitLoop ) { XEvent ev; XNextEvent( env->display, &ev ); if ( XFilterEvent( &ev, None ) == True ) { se_debug("IM filtered event: %s", XEventTypeString(ev.type) ); continue; } if ( ev.xany.window != viewer->view ) { se_msg( "skip event does not forward to view" ); continue; } switch( ev.type ) { case Expose: se_debug( "Expose" ); if ( ev.xexpose.count > 0 ) break; viewer->redisplay( viewer ); break; case KeyPress: case KeyRelease: viewer->key_handler( viewer, &ev ); break; case ConfigureNotify: case MapNotify: se_debug( "confiugration changed" ); viewer->configure_change_handler( viewer, &ev ); break; default: break; } } se_debug( "exit loop" ); XUnsetICFocus( viewer->xic ); XDestroyIC( viewer->xic ); se_env_release( env ); return 0; }
void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { // X11 functions don't know what const is XKeyEvent *xkeyevent = p_event; // This code was pretty difficult to write. // The docs stink and every toolkit seems to // do it in a different way. /* Phase 1, obtain a proper keysym */ // This was also very difficult to figure out. // You'd expect you could just use Keysym provided by // XKeycodeToKeysym to obtain internationalized // input.. WRONG!! // you must use XLookupString (???) which not only wastes // cycles generating an unnecesary string, but also // still works in half the cases. (won't handle deadkeys) // For more complex input methods (deadkeys and more advanced) // you have to use XmbLookupString (??). // So.. then you have to chosse which of both results // you want to keep. // This is a real bizarreness and cpu waster. KeySym keysym_keycode=0; // keysym used to find a keycode KeySym keysym_unicode=0; // keysym used to find unicode int nbytes=0; // bytes the string takes // XLookupString returns keysyms usable as nice scancodes/ char str[256+1]; nbytes=XLookupString(xkeyevent, str, 256, &keysym_keycode, NULL); // Meanwhile, XLookupString returns keysyms useful for unicode. if (!xmbstring) { // keep a temporary buffer for the string xmbstring=(char*)memalloc(sizeof(char)*8); xmblen=8; } if (xkeyevent->type == KeyPress && xic) { Status status; do { int mnbytes = XmbLookupString (xic, xkeyevent, xmbstring, xmblen - 1, &keysym_unicode, &status); xmbstring[mnbytes] = '\0'; if (status == XBufferOverflow) { xmblen = mnbytes + 1; xmbstring = (char*)memrealloc (xmbstring, xmblen); } } while (status == XBufferOverflow); } /* Phase 2, obtain a pigui keycode from the keysym */ // KeyMappingX11 just translated the X11 keysym to a PIGUI // keysym, so it works in all platforms the same. unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode); /* Phase 3, obtain an unicode character from the keysym */ // KeyMappingX11 also translates keysym to unicode. // It does a binary search on a table to translate // most properly. //print_line("keysym_unicode: "+rtos(keysym_unicode)); unsigned int unicode = keysym_unicode>0? KeyMappingX11::get_unicode_from_keysym(keysym_unicode):0; /* Phase 4, determine if event must be filtered */ // This seems to be a side-effect of using XIM. // XEventFilter looks like a core X11 funciton, // but it's actually just used to see if we must // ignore a deadkey, or events XIM determines // must not reach the actual gui. // Guess it was a design problem of the extension bool keypress = xkeyevent->type == KeyPress; if (xkeyevent->type == KeyPress && xic) { if (XFilterEvent((XEvent*)xkeyevent, x11_window)) return; } if (keycode==0 && unicode==0) return; /* Phase 5, determine modifier mask */ // No problems here, except I had no way to // know Mod1 was ALT and Mod4 was META (applekey/winkey) // just tried Mods until i found them. //print_line("mod1: "+itos(xkeyevent->state&Mod1Mask)+" mod 5: "+itos(xkeyevent->state&Mod5Mask)); InputModifierState state = get_key_modifier_state(xkeyevent->state); /* Phase 6, determine echo character */ // Echo characters in X11 are a keyrelease and a keypress // one after the other with the (almot) same timestamp. // To detect them, i use XPeekEvent and check that their // difference in time is below a treshold. if (xkeyevent->type != KeyPress) { // make sure there are events pending, // so this call won't block. if (XPending(x11_display)>0) { XEvent peek_event; XPeekEvent(x11_display, &peek_event); // I'm using a treshold of 5 msecs, // since sometimes there seems to be a little // jitter. I'm still not convinced that all this approach // is correct, but the xorg developers are // not very helpful today. ::Time tresh=ABS(peek_event.xkey.time-xkeyevent->time); if (peek_event.type == KeyPress && tresh<5 ) { KeySym rk; nbytes=XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL); if (rk==keysym_keycode) { XEvent event; XNextEvent(x11_display, &event); //erase next event handle_key_event( (XKeyEvent*)&event,true ); return; //ignore current, echo next } } // use the time from peek_event so it always works } // save the time to check for echo when keypress happens } /* Phase 7, send event to Window */ InputEvent event; event.ID=++event_id; event.type = InputEvent::KEY; event.device=0; event.key.mod=state; event.key.pressed=keypress; if (keycode>='a' && keycode<='z') keycode-='a'-'A'; event.key.scancode=keycode; event.key.unicode=unicode; event.key.echo=p_echo; if (event.key.scancode==KEY_BACKTAB) { //make it consistent accross platforms. event.key.scancode=KEY_TAB; event.key.mod.shift=true; } //printf("key: %x\n",event.key.scancode); input->parse_input_event( event); }
uni_t dpy_getchar(int timeout) { while (numqueued == 0) { /* If a timeout was asked for, wait that long for an event. */ if ((timeout != -1) && !XPending(display)) { struct pollfd pfd = { .fd = ConnectionNumber(display), .events = POLLIN, .revents = 0 }; poll(&pfd, 1, timeout*1000); if (!pfd.revents) return -VK_TIMEOUT; } XEvent e; XNextEvent(display, &e); if (XFilterEvent(&e, window)) continue; switch (e.type) { case MapNotify: break; case Expose: { /* Mark some of the screen as needing redrawing. */ if (frontbuffer) { for (int y=0; y<screenheight; y++) { unsigned int* p = &frontbuffer[y * screenwidth]; for (int x=0; x<screenwidth; x++) p[x] = 0; } } redraw(); break; } case ConfigureNotify: { XConfigureEvent* xce = &e.xconfigure; int w = xce->width / fontwidth; int h = xce->height / fontheight; if ((w != screenwidth) || (h != screenheight)) { screenwidth = w; screenheight = h; if (frontbuffer) free(frontbuffer); frontbuffer = NULL; if (backbuffer) free(backbuffer); backbuffer = calloc(screenwidth * screenheight, sizeof(unsigned int)); push_key(-VK_RESIZE); } break; } case MappingNotify: case KeymapNotify: XRefreshKeyboardMapping(&e.xmapping); break; case KeyPress: { XKeyPressedEvent* xke = &e.xkey; KeySym keysym; char buffer[32]; Status status = 0; int charcount = Xutf8LookupString(xic, xke, buffer, sizeof(buffer)-1, &keysym, &status); int mods = 0; if (xke->state & ShiftMask) mods |= VKM_SHIFT; if (xke->state & ControlMask) mods |= VKM_CTRL; if ((keysym & 0xffffff00) == 0xff00) { /* Special function key. */ if (!IsModifierKey(keysym)) push_key(-(keysym | mods)); } else { const char* p = buffer; while ((p-buffer) < charcount) { uni_t c = readu8(&p); if (c < 32) { /* Ctrl + letter key */ push_key(-(VKM_CTRLASCII | c | mods)); } else { if (xke->state & Mod1Mask) push_key(-XK_Escape); push_key(c); } } } break; } } } return dequeue(); } const char* dpy_getkeyname(uni_t k) { static char buffer[32]; switch (-k) { case VK_RESIZE: return "KEY_RESIZE"; case VK_TIMEOUT: return "KEY_TIMEOUT"; case VK_REDRAW: return "KEY_REDRAW"; } int key = -k & ~VKM__MASK; int mods = -k & VKM__MASK; if (mods & VKM_CTRLASCII) { sprintf(buffer, "KEY_%s^%c", (mods & VKM_SHIFT) ? "S" : "", key + 64); return buffer; } const char* template = NULL;
int main(int argc, char **argv) { /* Platform */ int running = 1; struct XWindow win; GLXContext glContext; struct nk_context *ctx; struct nk_color background; memset(&win, 0, sizeof(win)); win.dpy = XOpenDisplay(NULL); if (!win.dpy) die("Failed to open X display\n"); { /* check glx version */ int glx_major, glx_minor; if (!glXQueryVersion(win.dpy, &glx_major, &glx_minor)) die("[X11]: Error: Failed to query OpenGL version\n"); if ((glx_major == 1 && glx_minor < 3) || (glx_major < 1)) die("[X11]: Error: Invalid GLX version!\n"); } { /* find and pick matching framebuffer visual */ int fb_count; static GLint attr[] = { GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 24, GLX_STENCIL_SIZE, 8, GLX_DOUBLEBUFFER, True, None }; GLXFBConfig *fbc; fbc = glXChooseFBConfig(win.dpy, DefaultScreen(win.dpy), attr, &fb_count); if (!fbc) die("[X11]: Error: failed to retrieve framebuffer configuration\n"); { /* pick framebuffer with most samples per pixel */ int i; int fb_best = -1, best_num_samples = -1; for (i = 0; i < fb_count; ++i) { XVisualInfo *vi = glXGetVisualFromFBConfig(win.dpy, fbc[i]); if (vi) { int sample_buffer, samples; glXGetFBConfigAttrib(win.dpy, fbc[i], GLX_SAMPLE_BUFFERS, &sample_buffer); glXGetFBConfigAttrib(win.dpy, fbc[i], GLX_SAMPLES, &samples); if ((fb_best < 0) || (sample_buffer && samples > best_num_samples)) fb_best = i; best_num_samples = samples; } } win.fbc = fbc[fb_best]; XFree(fbc); win.vis = glXGetVisualFromFBConfig(win.dpy, win.fbc); } } { /* create window */ win.cmap = XCreateColormap(win.dpy, RootWindow(win.dpy, win.vis->screen), win.vis->visual, AllocNone); win.swa.colormap = win.cmap; win.swa.background_pixmap = None; win.swa.border_pixel = 0; win.swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPress | ButtonReleaseMask| ButtonMotionMask | Button1MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask| PointerMotionMask| StructureNotifyMask; win.win = XCreateWindow(win.dpy, RootWindow(win.dpy, win.vis->screen), 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, win.vis->depth, InputOutput, win.vis->visual, CWBorderPixel|CWColormap|CWEventMask, &win.swa); if (!win.win) die("[X11]: Failed to create window\n"); XFree(win.vis); XStoreName(win.dpy, win.win, "Demo"); XMapWindow(win.dpy, win.win); } { /* create opengl context */ typedef GLXContext(*glxCreateContext)(Display*, GLXFBConfig, GLXContext, Bool, const int*); int(*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(gl_error_handler); const char *extensions_str = glXQueryExtensionsString(win.dpy, DefaultScreen(win.dpy)); glxCreateContext create_context = (glxCreateContext) glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB"); gl_err = FALSE; if (!has_extension(extensions_str, "GLX_ARB_create_context") || !create_context) { fprintf(stdout, "[X11]: glXCreateContextAttribARB() not found...\n"); fprintf(stdout, "[X11]: ... using old-style GLX context\n"); glContext = glXCreateNewContext(win.dpy, win.fbc, GLX_RGBA_TYPE, 0, True); } else { GLint attr[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, None }; glContext = create_context(win.dpy, win.fbc, 0, True, attr); XSync(win.dpy, False); if (gl_err || !glContext) { /* Could not create GL 3.0 context. Fallback to old 2.x context. * If a version below 3.0 is requested, implementations will * return the newest context version compatible with OpenGL * version less than version 3.0.*/ attr[1] = 1; attr[3] = 0; gl_err = FALSE; fprintf(stdout, "[X11] Failed to create OpenGL 3.0 context\n"); fprintf(stdout, "[X11] ... using old-style GLX context!\n"); glContext = create_context(win.dpy, win.fbc, 0, True, attr); } } XSync(win.dpy, False); XSetErrorHandler(old_handler); if (gl_err || !glContext) die("[X11]: Failed to create an OpenGL context\n"); glXMakeCurrent(win.dpy, win.win, glContext); } ctx = nk_x11_init(win.dpy, win.win); /* Load Fonts: if none of these are loaded a default font will be used */ {struct nk_font_atlas *atlas; nk_x11_font_stash_begin(&atlas); /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/ /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/ /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/ /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/ /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/ /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/ nk_x11_font_stash_end(); /*nk_style_set_font(ctx, &droid->handle);*/} /* style.c */ /*set_style(ctx, THEME_WHITE);*/ /*set_style(ctx, THEME_RED);*/ /*set_style(ctx, THEME_BLUE);*/ /*set_style(ctx, THEME_DARK);*/ background = nk_rgb(28,48,62); while (running) { /* Input */ XEvent evt; nk_input_begin(ctx); while (XCheckWindowEvent(win.dpy, win.win, win.swa.event_mask, &evt)){ if (XFilterEvent(&evt, win.win)) continue; nk_x11_handle_event(&evt); } nk_input_end(ctx); /* GUI */ {struct nk_panel layout; if (nk_begin(ctx, &layout, "Demo", nk_rect(50, 50, 200, 200), NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) { enum {EASY, HARD}; static int op = EASY; static int property = 20; nk_layout_row_static(ctx, 30, 80, 1); if (nk_button_label(ctx, "button", NK_BUTTON_DEFAULT)) fprintf(stdout, "button pressed\n"); nk_layout_row_dynamic(ctx, 30, 2); if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; nk_layout_row_dynamic(ctx, 25, 1); nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); {struct nk_panel combo; nk_layout_row_dynamic(ctx, 20, 1); nk_label(ctx, "background:", NK_TEXT_LEFT); nk_layout_row_dynamic(ctx, 25, 1); if (nk_combo_begin_color(ctx, &combo, background, 400)) { nk_layout_row_dynamic(ctx, 120, 1); background = nk_color_picker(ctx, background, NK_RGBA); nk_layout_row_dynamic(ctx, 25, 1); background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1); background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1); background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1); background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1); nk_combo_end(ctx); }} } nk_end(ctx);} if (nk_window_is_closed(ctx, "Demo")) break; /* -------------- EXAMPLES ---------------- */ /*calculator(ctx);*/ /*overview(ctx);*/ /*node_editor(ctx);*/ /* ----------------------------------------- */ /* Draw */ {float bg[4]; nk_color_fv(bg, background); XGetWindowAttributes(win.dpy, win.win, &win.attr); glViewport(0, 0, win.width, win.height); glClear(GL_COLOR_BUFFER_BIT); glClearColor(bg[0], bg[1], bg[2], bg[3]); /* IMPORTANT: `nk_x11_render` modifies some global OpenGL state * with blending, scissor, face culling, depth test and viewport and * defaults everything back into a default state. * Make sure to either a.) save and restore or b.) reset your own state after * rendering the UI. */ nk_x11_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER); glXSwapBuffers(win.dpy, win.win);} } nk_x11_shutdown(); glXMakeCurrent(win.dpy, 0, 0); glXDestroyContext(win.dpy, glContext); XUnmapWindow(win.dpy, win.win); XFreeColormap(win.dpy, win.cmap); XDestroyWindow(win.dpy, win.win); XCloseDisplay(win.dpy); return 0; }
int main(int argc, char *argv[]) { XEvent event; KeySym keysym; char keychar[255]; uint32_t timestamp = 0; uint32_t current; init_x(); pixel_start(WIDTH, HEIGHT, argv[1]); for (;;) { while(XPending(g_X.display) > 0) { XNextEvent(g_X.display, &event); if (XFilterEvent(&event, None)) continue; switch (event.type) { case Expose: if (event.xexpose.count==0) { pixel_frame(0.01f); glXSwapBuffers(g_X.display, g_X.wnd); } break; case KeyPress: XLookupString(&event.xkey, keychar, 255, &keysym, 0); pixel_key(KEY_DOWN, keychar[0]); break; case KeyRelease: XLookupString(&event.xkey, keychar, 255, &keysym, 0); pixel_key(KEY_UP, keychar[0]); break; case ButtonPress: pixel_touch(0, TOUCH_BEGIN, event.xbutton.x, event.xbutton.y); break; case ButtonRelease: pixel_touch(0, TOUCH_END, event.xbutton.x, event.xbutton.y); break; case MotionNotify: pixel_touch(0, TOUCH_MOVE, event.xbutton.x, event.xbutton.y); break; case ClientMessage: if ((Atom)event.xclient.data.l[0] == wm_delete_window) { Display *dis; pixel_close(); glXMakeCurrent(g_X.display, g_X.wnd, NULL); dis = g_X.display; XFreeGC(dis, gc); XDestroyWindow(dis, g_X.wnd); XCloseDisplay(dis); exit(0); } break; } } current = _gettime(); if (current - timestamp >= UPDATE_INTERVAL) { float t = (current - timestamp)/100.0f; timestamp = current; pixel_update(t); pixel_frame(t); glXSwapBuffers(g_X.display, g_X.wnd); } else { usleep(1000); } } }
static void X11_DispatchEvent(_THIS) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; Display *display = videodata->display; SDL_WindowData *data; XEvent xevent; int i; SDL_zero(xevent); /* valgrind fix. --ryan. */ XNextEvent(display, &xevent); /* filter events catchs XIM events and sends them to the correct handler */ if (XFilterEvent(&xevent, None) == True) { #if 0 printf("Filtered event type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif return; } /* Send a SDL_SYSWMEVENT if the application wants them */ if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) { SDL_SysWMmsg wmmsg; SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; wmmsg.x11.event = xevent; SDL_SendSysWMEvent(&wmmsg); } data = NULL; if (videodata && videodata->windowlist) { for (i = 0; i < videodata->numwindows; ++i) { if ((videodata->windowlist[i] != NULL) && (videodata->windowlist[i]->xwindow == xevent.xany.window)) { data = videodata->windowlist[i]; break; } } } if (!data) { return; } #if 0 printf("type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif switch (xevent.type) { /* Gaining mouse coverage? */ case EnterNotify:{ #ifdef DEBUG_XEVENTS printf("EnterNotify! (%d,%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif SDL_SetMouseFocus(data->window); } break; /* Losing mouse coverage? */ case LeaveNotify:{ #ifdef DEBUG_XEVENTS printf("LeaveNotify! (%d,%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif if (xevent.xcrossing.mode != NotifyGrab && xevent.xcrossing.mode != NotifyUngrab && xevent.xcrossing.detail != NotifyInferior) { SDL_SetMouseFocus(NULL); } } break; /* Gaining input focus? */ case FocusIn:{ #ifdef DEBUG_XEVENTS printf("FocusIn!\n"); #endif SDL_SetKeyboardFocus(data->window); #ifdef X_HAVE_UTF8_STRING if (data->ic) { XSetICFocus(data->ic); } #endif } break; /* Losing input focus? */ case FocusOut:{ #ifdef DEBUG_XEVENTS printf("FocusOut!\n"); #endif SDL_SetKeyboardFocus(NULL); #ifdef X_HAVE_UTF8_STRING if (data->ic) { XUnsetICFocus(data->ic); } #endif } break; /* Generated upon EnterWindow and FocusIn */ case KeymapNotify:{ #ifdef DEBUG_XEVENTS printf("KeymapNotify!\n"); #endif /* FIXME: X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); */ } break; /* Has the keyboard layout changed? */ case MappingNotify:{ #ifdef DEBUG_XEVENTS printf("MappingNotify!\n"); #endif X11_UpdateKeymap(_this); } break; /* Key press? */ case KeyPress:{ KeyCode keycode = xevent.xkey.keycode; KeySym keysym = NoSymbol; SDL_scancode scancode; char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; Status status = 0; #ifdef DEBUG_XEVENTS printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]); #if 1 if (videodata->key_layout[keycode] == SDLK_UNKNOWN) { int min_keycode, max_keycode; XDisplayKeycodes(display, &min_keycode, &max_keycode); keysym = XKeycodeToKeysym(display, keycode, 0); fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <*****@*****.**> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n", keycode, keycode - min_keycode, keysym, XKeysymToString(keysym)); } #endif /* */ SDL_zero(text); #ifdef X_HAVE_UTF8_STRING if (data->ic) { Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text), &keysym, &status); } #else XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); #endif if (*text) { SDL_SendKeyboardText(text); } } break; /* Key release? */ case KeyRelease:{ KeyCode keycode = xevent.xkey.keycode; #ifdef DEBUG_XEVENTS printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif if (X11_KeyRepeat(display, &xevent)) { /* We're about to get a repeated key down, ignore the key up */ break; } SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]); } break; /* Have we been iconified? */ case UnmapNotify:{ #ifdef DEBUG_XEVENTS printf("UnmapNotify!\n"); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0); SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0); } break; /* Have we been restored? */ case MapNotify:{ #ifdef DEBUG_XEVENTS printf("MapNotify!\n"); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0); SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0); } break; /* Have we been resized or moved? */ case ConfigureNotify:{ #ifdef DEBUG_XEVENTS printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, xevent.xconfigure.x, xevent.xconfigure.y); SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, xevent.xconfigure.width, xevent.xconfigure.height); } break; /* Have we been requested to quit (or another client message?) */ case ClientMessage:{ if ((xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); } } break; /* Do we need to refresh ourselves? */ case Expose:{ #ifdef DEBUG_XEVENTS printf("Expose (count = %d)\n", xevent.xexpose.count); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0); } break; case MotionNotify:{ #ifdef DEBUG_MOTION printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); #endif SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y); } break; case ButtonPress:{ SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button); } break; case ButtonRelease:{ SDL_SendMouseButton(data->window, SDL_RELEASED, xevent.xbutton.button); } break; case PropertyNotify:{ #ifdef DEBUG_XEVENTS unsigned char *propdata; int status, real_format; Atom real_type; unsigned long items_read, items_left, i; char *name = XGetAtomName(display, xevent.xproperty.atom); if (name) { printf("PropertyNotify: %s %s\n", name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed"); XFree(name); } status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata); if (status == Success && items_read > 0) { if (real_type == XA_INTEGER) { int *values = (int *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_type == XA_CARDINAL) { if (real_format == 32) { Uint32 *values = (Uint32 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_format == 16) { Uint16 *values = (Uint16 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_format == 8) { Uint8 *values = (Uint8 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } } else if (real_type == XA_STRING || real_type == videodata->UTF8_STRING) { printf("{ \"%s\" }\n", propdata); } else if (real_type == XA_ATOM) { Atom *atoms = (Atom *)propdata; printf("{"); for (i = 0; i < items_read; i++) { char *name = XGetAtomName(display, atoms[i]); if (name) { printf(" %s", name); XFree(name); } } printf(" }\n"); } else { char *name = XGetAtomName(display, real_type); printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN"); if (name) { XFree(name); } } } #endif } break; /* Copy the selection from XA_CUT_BUFFER0 to the requested property */ case SelectionRequest: { XSelectionRequestEvent *req; XEvent sevent; int seln_format; unsigned long nbytes; unsigned long overflow; unsigned char *seln_data; req = &xevent.xselectionrequest; #ifdef DEBUG_XEVENTS printf("SelectionRequest (requestor = %ld, target = %ld)\n", req->requestor, req->target); #endif SDL_zero(sevent); sevent.xany.type = SelectionNotify; sevent.xselection.selection = req->selection; sevent.xselection.target = None; sevent.xselection.property = None; sevent.xselection.requestor = req->requestor; sevent.xselection.time = req->time; if (XGetWindowProperty(display, DefaultRootWindow(display), XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target, &sevent.xselection.target, &seln_format, &nbytes, &overflow, &seln_data) == Success) { if (sevent.xselection.target == req->target) { XChangeProperty(display, req->requestor, req->property, sevent.xselection.target, seln_format, PropModeReplace, seln_data, nbytes); sevent.xselection.property = req->property; } XFree(seln_data); } XSendEvent(display, req->requestor, False, 0, &sevent); XSync(display, False); } break; case SelectionNotify: { #ifdef DEBUG_XEVENTS printf("SelectionNotify (requestor = %ld, target = %ld)\n", xevent.xselection.requestor, xevent.xselection.target); #endif videodata->selection_waiting = SDL_FALSE; } break; default:{ #ifdef DEBUG_XEVENTS printf("Unhandled event %d\n", xevent.type); #endif } break; } }
static void X11_DispatchEvent(_THIS) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; Display *display = videodata->display; SDL_WindowData *data; XEvent xevent; int i; SDL_zero(xevent); /* valgrind fix. --ryan. */ XNextEvent(display, &xevent); /* filter events catchs XIM events and sends them to the correct handler */ if (XFilterEvent(&xevent, None) == True) { #if 0 printf("Filtered event type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif return; } /* Send a SDL_SYSWMEVENT if the application wants them */ if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) { SDL_SysWMmsg wmmsg; SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; wmmsg.msg.x11.event = xevent; SDL_SendSysWMEvent(&wmmsg); } #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS if(xevent.type == GenericEvent) { X11_HandleGenericEvent(videodata,xevent); return; } #endif #if 0 printf("type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif data = NULL; if (videodata && videodata->windowlist) { for (i = 0; i < videodata->numwindows; ++i) { if ((videodata->windowlist[i] != NULL) && (videodata->windowlist[i]->xwindow == xevent.xany.window)) { data = videodata->windowlist[i]; break; } } } if (!data) { return; } switch (xevent.type) { /* Gaining mouse coverage? */ case EnterNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: EnterNotify! (%d,%d,%d)\n", data, xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif SDL_SetMouseFocus(data->window); } break; /* Losing mouse coverage? */ case LeaveNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: LeaveNotify! (%d,%d,%d)\n", data, xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif if (xevent.xcrossing.mode != NotifyGrab && xevent.xcrossing.mode != NotifyUngrab && xevent.xcrossing.detail != NotifyInferior) { SDL_SetMouseFocus(NULL); } } break; /* Gaining input focus? */ case FocusIn:{ if (xevent.xfocus.detail == NotifyInferior) { #ifdef DEBUG_XEVENTS printf("window %p: FocusIn (NotifierInferior, ignoring)\n", data); #endif break; } #ifdef DEBUG_XEVENTS printf("window %p: FocusIn!\n", data); #endif if (data->pending_focus == PENDING_FOCUS_OUT && data->window == SDL_GetKeyboardFocus()) { /* We want to reset the keyboard here, because we may have missed keyboard messages after our previous FocusOut. */ SDL_ResetKeyboard(); } data->pending_focus = PENDING_FOCUS_IN; data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME; } break; /* Losing input focus? */ case FocusOut:{ if (xevent.xfocus.detail == NotifyInferior) { /* We still have focus if a child gets focus */ #ifdef DEBUG_XEVENTS printf("window %p: FocusOut (NotifierInferior, ignoring)\n", data); #endif break; } #ifdef DEBUG_XEVENTS printf("window %p: FocusOut!\n", data); #endif data->pending_focus = PENDING_FOCUS_OUT; data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME; } break; /* Generated upon EnterWindow and FocusIn */ case KeymapNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: KeymapNotify!\n", data); #endif /* FIXME: X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); */ } break; /* Has the keyboard layout changed? */ case MappingNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: MappingNotify!\n", data); #endif X11_UpdateKeymap(_this); } break; /* Key press? */ case KeyPress:{ KeyCode keycode = xevent.xkey.keycode; KeySym keysym = NoSymbol; char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; Status status = 0; #ifdef DEBUG_XEVENTS printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode); #endif SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]); #if 1 if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN) { int min_keycode, max_keycode; XDisplayKeycodes(display, &min_keycode, &max_keycode); #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM keysym = XkbKeycodeToKeysym(display, keycode, 0, 0); #else keysym = XKeycodeToKeysym(display, keycode, 0); #endif fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <*****@*****.**> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n", keycode, keycode - min_keycode, keysym, XKeysymToString(keysym)); } #endif /* */ SDL_zero(text); #ifdef X_HAVE_UTF8_STRING if (data->ic) { Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text), &keysym, &status); } #else XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); #endif if (*text) { SDL_SendKeyboardText(text); } } break; /* Key release? */ case KeyRelease:{ KeyCode keycode = xevent.xkey.keycode; #ifdef DEBUG_XEVENTS printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode); #endif if (X11_KeyRepeat(display, &xevent)) { /* We're about to get a repeated key down, ignore the key up */ break; } SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]); } break; /* Have we been iconified? */ case UnmapNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: UnmapNotify!\n", data); #endif X11_DispatchUnmapNotify(data); } break; /* Have we been restored? */ case MapNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: MapNotify!\n", data); #endif X11_DispatchMapNotify(data); } break; /* Have we been resized or moved? */ case ConfigureNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data, xevent.xconfigure.x, xevent.xconfigure.y, xevent.xconfigure.width, xevent.xconfigure.height); #endif if (xevent.xconfigure.x != data->last_xconfigure.x || xevent.xconfigure.y != data->last_xconfigure.y) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, xevent.xconfigure.x, xevent.xconfigure.y); } if (xevent.xconfigure.width != data->last_xconfigure.width || xevent.xconfigure.height != data->last_xconfigure.height) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, xevent.xconfigure.width, xevent.xconfigure.height); } data->last_xconfigure = xevent.xconfigure; } break; /* Have we been requested to quit (or another client message?) */ case ClientMessage:{ if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && (xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) { Window root = DefaultRootWindow(display); #ifdef DEBUG_XEVENTS printf("window %p: _NET_WM_PING\n", data); #endif xevent.xclient.window = root; XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent); break; } else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && (xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { #ifdef DEBUG_XEVENTS printf("window %p: WM_DELETE_WINDOW\n", data); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); break; } } break; /* Do we need to refresh ourselves? */ case Expose:{ #ifdef DEBUG_XEVENTS printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0); } break; case MotionNotify:{ SDL_Mouse *mouse = SDL_GetMouse(); if(!mouse->relative_mode) { #ifdef DEBUG_MOTION printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); #endif SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y); } } break; case ButtonPress:{ int ticks = 0; if (X11_IsWheelEvent(display,&xevent,&ticks) == SDL_TRUE) { SDL_SendMouseWheel(data->window, 0, ticks); } else { SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button); } } break; case ButtonRelease:{ SDL_SendMouseButton(data->window, SDL_RELEASED, xevent.xbutton.button); } break; case PropertyNotify:{ #ifdef DEBUG_XEVENTS unsigned char *propdata; int status, real_format; Atom real_type; unsigned long items_read, items_left, i; char *name = XGetAtomName(display, xevent.xproperty.atom); if (name) { printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed"); XFree(name); } status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata); if (status == Success && items_read > 0) { if (real_type == XA_INTEGER) { int *values = (int *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_type == XA_CARDINAL) { if (real_format == 32) { Uint32 *values = (Uint32 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_format == 16) { Uint16 *values = (Uint16 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_format == 8) { Uint8 *values = (Uint8 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } } else if (real_type == XA_STRING || real_type == videodata->UTF8_STRING) { printf("{ \"%s\" }\n", propdata); } else if (real_type == XA_ATOM) { Atom *atoms = (Atom *)propdata; printf("{"); for (i = 0; i < items_read; i++) { char *name = XGetAtomName(display, atoms[i]); if (name) { printf(" %s", name); XFree(name); } } printf(" }\n"); } else { char *name = XGetAtomName(display, real_type); printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN"); if (name) { XFree(name); } } } if (status == Success) { XFree(propdata); } #endif /* DEBUG_XEVENTS */ if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) { /* Get the new state from the window manager. Compositing window managers can alter visibility of windows without ever mapping / unmapping them, so we handle that here, because they use the NETWM protocol to notify us of changes. */ Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window); if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN) { if (flags & SDL_WINDOW_HIDDEN) { X11_DispatchUnmapNotify(data); } else { X11_DispatchMapNotify(data); } } } } break; /* Copy the selection from XA_CUT_BUFFER0 to the requested property */ case SelectionRequest: { XSelectionRequestEvent *req; XEvent sevent; int seln_format; unsigned long nbytes; unsigned long overflow; unsigned char *seln_data; req = &xevent.xselectionrequest; #ifdef DEBUG_XEVENTS printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data, req->requestor, req->target); #endif SDL_zero(sevent); sevent.xany.type = SelectionNotify; sevent.xselection.selection = req->selection; sevent.xselection.target = None; sevent.xselection.property = None; sevent.xselection.requestor = req->requestor; sevent.xselection.time = req->time; if (XGetWindowProperty(display, DefaultRootWindow(display), XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target, &sevent.xselection.target, &seln_format, &nbytes, &overflow, &seln_data) == Success) { if (sevent.xselection.target == req->target) { XChangeProperty(display, req->requestor, req->property, sevent.xselection.target, seln_format, PropModeReplace, seln_data, nbytes); sevent.xselection.property = req->property; } XFree(seln_data); } XSendEvent(display, req->requestor, False, 0, &sevent); XSync(display, False); } break; case SelectionNotify: { #ifdef DEBUG_XEVENTS printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data, xevent.xselection.requestor, xevent.xselection.target); #endif videodata->selection_waiting = SDL_FALSE; } break; default:{ #ifdef DEBUG_XEVENTS printf("window %p: Unhandled event %d\n", data, xevent.type); #endif } break; } }
static void X11_DispatchEvent(_THIS) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; SDL_WindowData *data; XEvent xevent; int i; SDL_zero(xevent); /* valgrind fix. --ryan. */ XNextEvent(videodata->display, &xevent); /* filter events catchs XIM events and sends them to the correct handler */ if (XFilterEvent(&xevent, None) == True) { #if 0 printf("Filtered event type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif return; } /* Send a SDL_SYSWMEVENT if the application wants them */ if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { SDL_SysWMmsg wmmsg; SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; wmmsg.event.xevent = xevent; SDL_SendSysWMEvent(&wmmsg); } data = NULL; if (videodata && videodata->windowlist) { for (i = 0; i < videodata->numwindows; ++i) { if ((videodata->windowlist[i] != NULL) && (videodata->windowlist[i]->window == xevent.xany.window)) { data = videodata->windowlist[i]; break; } } } if (!data) { return; } #if 0 printf("type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif switch (xevent.type) { /* Gaining mouse coverage? */ case EnterNotify:{ #ifdef DEBUG_XEVENTS printf("EnterNotify! (%d,%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif #if 1 /* FIXME: Should we reset data for all mice? */ for (i = 0; i < SDL_GetNumMice(); ++i) { SDL_Mouse *mouse = SDL_GetMouse(i); SDL_SetMouseFocus(mouse->id, data->windowID); } #endif } break; /* Losing mouse coverage? */ case LeaveNotify:{ #ifdef DEBUG_XEVENTS printf("LeaveNotify! (%d,%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif if (xevent.xcrossing.detail != NotifyInferior) { #if 1 /* FIXME: Should we reset data for all mice? */ for (i = 0; i < SDL_GetNumMice(); ++i) { SDL_Mouse *mouse = SDL_GetMouse(i); SDL_SetMouseFocus(mouse->id, 0); } #endif } } break; /* Gaining input focus? */ case FocusIn:{ #ifdef DEBUG_XEVENTS printf("FocusIn!\n"); #endif SDL_SetKeyboardFocus(videodata->keyboard, data->windowID); #ifdef X_HAVE_UTF8_STRING if (data->ic) { XSetICFocus(data->ic); } #endif } break; /* Losing input focus? */ case FocusOut:{ #ifdef DEBUG_XEVENTS printf("FocusOut!\n"); #endif SDL_SetKeyboardFocus(videodata->keyboard, 0); #ifdef X_HAVE_UTF8_STRING if (data->ic) { XUnsetICFocus(data->ic); } #endif } break; /* Generated upon EnterWindow and FocusIn */ case KeymapNotify:{ #ifdef DEBUG_XEVENTS printf("KeymapNotify!\n"); #endif /* FIXME: X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); */ } break; /* Has the keyboard layout changed? */ case MappingNotify:{ #ifdef DEBUG_XEVENTS printf("MappingNotify!\n"); #endif X11_UpdateKeymap(_this); } break; /* Key press? */ case KeyPress:{ KeyCode keycode = xevent.xkey.keycode; KeySym keysym = NoSymbol; char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; Status status = 0; #ifdef DEBUG_XEVENTS printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif SDL_SendKeyboardKey(videodata->keyboard, SDL_PRESSED, videodata->key_layout[keycode]); #if 0 if (videodata->key_layout[keycode] == SDLK_UNKNOWN) { int min_keycode, max_keycode; XDisplayKeycodes(videodata->display, &min_keycode, &max_keycode); keysym = XKeycodeToKeysym(videodata->display, keycode, 0); fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <*****@*****.**> X11 KeyCode %d (%d), X11 KeySym 0x%X (%s).\n", keycode, keycode - min_keycode, keysym, XKeysymToString(keysym)); } #endif /* */ SDL_zero(text); #ifdef X_HAVE_UTF8_STRING if (data->ic) { Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text), &keysym, &status); } #else XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); #endif if (*text) { SDL_SendKeyboardText(videodata->keyboard, text); } } break; /* Key release? */ case KeyRelease:{ KeyCode keycode = xevent.xkey.keycode; #ifdef DEBUG_XEVENTS printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif SDL_SendKeyboardKey(videodata->keyboard, SDL_RELEASED, videodata->key_layout[keycode]); } break; /* Have we been iconified? */ case UnmapNotify:{ #ifdef DEBUG_XEVENTS printf("UnmapNotify!\n"); #endif SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, 0); SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0, 0); } break; /* Have we been restored? */ case MapNotify:{ #ifdef DEBUG_XEVENTS printf("MapNotify!\n"); #endif SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0); SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESTORED, 0, 0); } break; /* Have we been resized or moved? */ case ConfigureNotify:{ #ifdef DEBUG_XEVENTS printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height); #endif SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED, xevent.xconfigure.x, xevent.xconfigure.y); SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED, xevent.xconfigure.width, xevent.xconfigure.height); } break; /* Have we been requested to quit (or another client message?) */ case ClientMessage:{ if ((xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0, 0); } } break; /* Do we need to refresh ourselves? */ case Expose:{ #ifdef DEBUG_XEVENTS printf("Expose (count = %d)\n", xevent.xexpose.count); #endif SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED, 0, 0); } break; default:{ for (i = 0; i < SDL_GetNumMice(); ++i) { SDL_Mouse *mouse; #if SDL_VIDEO_DRIVER_X11_XINPUT X11_MouseData *data; #endif mouse = SDL_GetMouse(i); if (!mouse->driverdata) { switch (xevent.type) { case MotionNotify: #ifdef DEBUG_MOTION printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); #endif SDL_SendMouseMotion(mouse->id, 0, xevent.xmotion.x, xevent.xmotion.y, 0); break; case ButtonPress: SDL_SendMouseButton(mouse->id, SDL_PRESSED, xevent.xbutton.button); break; case ButtonRelease: SDL_SendMouseButton(mouse->id, SDL_RELEASED, xevent.xbutton.button); break; } continue; } #if SDL_VIDEO_DRIVER_X11_XINPUT data = (X11_MouseData *) mouse->driverdata; if (xevent.type == data->motion) { XDeviceMotionEvent *move = (XDeviceMotionEvent *) & xevent; #ifdef DEBUG_MOTION printf("X11 motion: %d,%d\n", move->x, move->y); #endif SDL_SendMouseMotion(move->deviceid, 0, move->x, move->y, move->axis_data[2]); return; } if (xevent.type == data->button_pressed) { XDeviceButtonPressedEvent *pressed = (XDeviceButtonPressedEvent *) & xevent; SDL_SendMouseButton(pressed->deviceid, SDL_PRESSED, pressed->button); return; } if (xevent.type == data->button_released) { XDeviceButtonReleasedEvent *released = (XDeviceButtonReleasedEvent *) & xevent; SDL_SendMouseButton(released->deviceid, SDL_RELEASED, released->button); return; } if (xevent.type == data->proximity_in) { XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) & xevent; SDL_SendProximity(proximity->deviceid, proximity->x, proximity->y, SDL_PROXIMITYIN); return; } if (xevent.type == data->proximity_out) { XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) & xevent; SDL_SendProximity(proximity->deviceid, proximity->x, proximity->y, SDL_PROXIMITYOUT); return; } #endif } #ifdef DEBUG_XEVENTS printf("Unhandled event %d\n", xevent.type); #endif } break; } }
static void TransferXEventsToTcl( Display *display) { union { int type; XEvent x; TkKeyEvent k; } event; Window w; TkDisplay *dispPtr = NULL; /* * Transfer events from the X event queue to the Tk event queue after XIM * event filtering. KeyPress and KeyRelease events need special treatment * so that they get directed according to Tk's focus rules during XIM * handling. Theoretically they can go to the wrong place still (if * there's a focus change in the queue) but if we push the handling off * until Tk_HandleEvent then many input methods actually cease to work * correctly. Most of the time, Tk processes its event queue fast enough * for this to not be an issue anyway. [Bug 1924761] */ while (QLength(display) > 0) { XNextEvent(display, &event.x); w = None; if (event.type == KeyPress || event.type == KeyRelease) { for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) { if (dispPtr == NULL) { break; } else if (dispPtr->display == event.x.xany.display) { if (dispPtr->focusPtr != NULL) { w = dispPtr->focusPtr->window; } break; } } } if (XFilterEvent(&event.x, w)) { continue; } if (event.type == KeyPress || event.type == KeyRelease) { event.k.charValuePtr = NULL; event.k.charValueLen = 0; event.k.keysym = NoSymbol; /* * Force the calling of the input method engine now. The results * from it will be cached in the event so that they don't get lost * (to a race condition with other XIM-handled key events) between * entering the event queue and getting serviced. [Bug 1924761] */ #ifdef TK_USE_INPUT_METHODS if (event.type == KeyPress && dispPtr && (dispPtr->flags & TK_DISPLAY_USE_IM)) { if (dispPtr->focusPtr && dispPtr->focusPtr->inputContext) { Tcl_DString ds; Tcl_DStringInit(&ds); (void) TkpGetString(dispPtr->focusPtr, &event.x, &ds); Tcl_DStringFree(&ds); } } #endif } Tk_QueueWindowEvent(&event.x, TCL_QUEUE_TAIL); } }
ACTION kbd_interface_routine(PLAYER *player, int edit_mode) { XEvent evnt; ACTION act = ACT_NONE; int evnt_count; ACTION (*process_key_fun)(PLAYER *, XKeyEvent *); #ifdef USE_MOUSE ACTION (*process_button_fun)(PLAYER *, XButtonEvent *); #endif /* evnt_count = XPending(disp); */ evnt_count = XEventsQueued(disp, QueuedAfterReading); process_key_fun = edit_mode ? process_key_event_edit : process_key_event; #ifdef USE_MOUSE process_button_fun = edit_mode ? process_button_event_edit : process_button_event; #endif while (--evnt_count >= 0) { XNextEvent(disp, &evnt); #ifdef USE_XDGA if (dgaModeCurrent >= 0) { if (evnt.type == (dgaEventBase + KeyPress)) { if (act == ACT_NONE) { XKeyEvent xk; XDGAKeyEventToXKeyEvent((XDGAKeyEvent *) &evnt, &xk); act = (*process_key_fun)(player, &xk); } } # ifdef USE_MOUSE else if (MouseInUse && evnt.type == (dgaEventBase + ButtonPress)) { if (act == ACT_NONE) { XButtonEvent xb; ConvertXDGAButtonEventToXButtonEvent((XDGAButtonEvent *) &evnt, &xb); act = (*process_button_fun)(player, &xb); } } # endif } else #endif if (evnt.type == KeyPress) { if (act == ACT_NONE && !XFilterEvent(&evnt, wnd)) act = (*process_key_fun)(player, (XKeyEvent *)&evnt); } # ifdef USE_MOUSE else if (MouseInUse && evnt.type == ButtonPress) { if (act == ACT_NONE && !XFilterEvent(&evnt, wnd)) { XButtonEvent *bevnt = (XButtonEvent *)&evnt; if (bevnt->button == 1 && game.level == ScoresLevel) { act = process_top_screen_coordinate(bevnt->x, bevnt->y); } else act = (*process_button_fun)(player, bevnt); } } #endif else if (process_nonkey_event(player, &evnt)) { act = ACT_QUIT; break; } } return act; }