PuglStatus puglProcessEvents(PuglView* view) { XEvent event; while (XPending(view->impl->display) > 0) { XNextEvent(view->impl->display, &event); if (x_fib_handle_events(view->impl->display, &event)) { const int status = x_fib_status(); if (status > 0) { char* const filename = x_fib_filename(); x_fib_close(view->impl->display); if (view->fileSelectedFunc) { view->fileSelectedFunc(view, filename); } free(filename); } else if (status < 0) { x_fib_close(view->impl->display); if (view->fileSelectedFunc) { view->fileSelectedFunc(view, NULL); } } break; } if (event.xany.window != view->impl->win) { continue; } switch (event.type) { case MapNotify: puglReshape(view, view->width, view->height); break; case ConfigureNotify: if ((event.xconfigure.width != view->width) || (event.xconfigure.height != view->height)) { puglReshape(view, event.xconfigure.width, event.xconfigure.height); } break; case Expose: if (event.xexpose.count != 0) { break; } puglDisplay(view); break; case MotionNotify: setModifiers(view, event.xmotion.state, event.xmotion.time); if (view->motionFunc) { view->motionFunc(view, event.xmotion.x, event.xmotion.y); } break; case ButtonPress: setModifiers(view, event.xbutton.state, event.xbutton.time); if (event.xbutton.button >= 4 && event.xbutton.button <= 7) { if (view->scrollFunc) { float dx = 0, dy = 0; switch (event.xbutton.button) { case 4: dy = 1.0f; break; case 5: dy = -1.0f; break; case 6: dx = -1.0f; break; case 7: dx = 1.0f; break; } view->scrollFunc(view, event.xbutton.x, event.xbutton.y, dx, dy); } break; } // nobreak case ButtonRelease: setModifiers(view, event.xbutton.state, event.xbutton.time); if (view->mouseFunc && (event.xbutton.button < 4 || event.xbutton.button > 7)) { view->mouseFunc(view, event.xbutton.button, event.type == ButtonPress, event.xbutton.x, event.xbutton.y); } break; case KeyPress: setModifiers(view, event.xkey.state, event.xkey.time); dispatchKey(view, &event, true); break; case KeyRelease: { setModifiers(view, event.xkey.state, event.xkey.time); bool repeated = false; if (view->ignoreKeyRepeat && XEventsQueued(view->impl->display, QueuedAfterReading)) { XEvent next; XPeekEvent(view->impl->display, &next); if (next.type == KeyPress && next.xkey.time == event.xkey.time && next.xkey.keycode == event.xkey.keycode) { XNextEvent(view->impl->display, &event); repeated = true; } } if (!repeated) { dispatchKey(view, &event, false); } } break; case ClientMessage: { char* type = XGetAtomName(view->impl->display, event.xclient.message_type); if (!strcmp(type, "WM_PROTOCOLS")) { if (view->closeFunc) { view->closeFunc(view); view->redisplay = false; } } XFree(type); } break; #ifdef PUGL_GRAB_FOCUS case EnterNotify: XSetInputFocus(view->impl->display, view->impl->win, RevertToPointerRoot, CurrentTime); break; #endif default: break; } } if (view->redisplay) { puglDisplay(view); } return PUGL_SUCCESS; }
void gl_handle_events () { XEvent event; while (XPending(_gl_display) > 0) { XNextEvent(_gl_display, &event); #ifdef XDLG if (handle_xdlg_event(_gl_display, &event)) continue; #endif #ifdef XFIB if (x_fib_handle_events (_gl_display, &event)) { if (x_fib_status () > 0) { char *fn = x_fib_filename (); xapi_open (fn); free (fn); } } #endif if (event.xany.window != _gl_win) { continue; } #ifdef DND if (handle_dnd_event(_gl_display, _gl_win, &event)) continue; #endif switch (event.type) { case MapNotify: loop_run=1; break; case UnmapNotify: loop_run=0; break; case ConfigureNotify: if ( (event.xconfigure.width > 1 && event.xconfigure.height > 1) && (event.xconfigure.width != _gl_width || event.xconfigure.height != _gl_height) ) { gl_reshape(event.xconfigure.width, event.xconfigure.height); } break; case Expose: if (event.xexpose.count != 0) { break; } _gl_reexpose = true; break; case MotionNotify: if (osd_seeking && ui_syncsource() == SYNC_NONE && OSD_mode & OSD_POS) { const float sk = calc_slider (event.xmotion.x, event.xmotion.y); if (sk >= 0) ui_sync_manual (sk); } break; case ButtonPress: if (event.xbutton.button == 1 && ui_syncsource() == SYNC_NONE && OSD_mode & OSD_POS) { const float sk = calc_slider (event.xbutton.x, event.xbutton.y); if (sk >= 0) { ui_sync_manual (sk); osd_seeking = 1; force_redraw = 1; } } break; case ButtonRelease: if (osd_seeking) { osd_seeking = 0; force_redraw = 1; } else #ifdef XDLG if (event.xbutton.button == 3) { if (event.xbutton.x >= 0 && event.xbutton.x < _gl_width && event.xbutton.y >= 0 && event.xbutton.y < _gl_height) show_x_dialog(_gl_display, _gl_win, event.xbutton.x_root, event.xbutton.y_root ); } else #endif xjglButton(event.xbutton.button); break; case ReparentNotify: break; case KeyPress: { KeySym sym; char buf[6] = {0,0,0,0,0,0}; static XComposeStatus stat; int n = XLookupString(&event.xkey, buf, sizeof(buf), &sym, &stat); if (event.xkey.state & ControlMask && n == 1 && sym == XK_o) { #ifdef XFIB if (!(interaction_override & OVR_LOADFILE)) { x_fib_cfg_filter_callback(fib_filter_movie_filename); x_fib_show (_gl_display, _gl_win, 0, 0); } #endif } else if (event.xkey.state & ControlMask && n == 1 && sym == XK_w) { if (!(interaction_override & OVR_LOADFILE)) xapi_close (NULL); } else if (event.xkey.state & ControlMask && n == 1 && sym == XK_q) { if (!(interaction_override&OVR_QUIT_WMG)) loop_flag = 0; } else if (n == 1) { xjglKeyPress(sym, buf); } } break; case ClientMessage: if (!strcmp(XGetAtomName(_gl_display, event.xclient.message_type), "WM_PROTOCOLS")) { if ((interaction_override&OVR_QUIT_WMG) == 0) loop_flag=0; } break; default: break; } } if (_gl_reexpose) { _gl_reexpose = false; force_redraw = true; } static int periodic = 10; if (--periodic == 0) { periodic = 50 * framerate; // we should use 1/delay if delay > 0 XResetScreenSaver(_gl_display); // ..or spawn `xdg-screensaver` } }