static void puglResize(PuglView* view) { int set_hints = 1; view->resize = false; if (!view->resizeFunc) { return; } /* ask the plugin about the new size */ view->resizeFunc(view, &view->width, &view->height, &set_hints); XSizeHints *hints = XAllocSizeHints(); hints->min_width = view->width; hints->min_height = view->height; hints->max_width = view->user_resizable ? 2048 : view->width; hints->max_height = view->user_resizable ? 2048 : view->height; hints->flags = PMaxSize | PMinSize; if (set_hints) { XSetWMNormalHints(view->impl->display, view->impl->win, hints); } XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); XFlush(view->impl->display); XFree(hints); #ifdef VERBOSE_PUGL printf("puGL: window resize (%dx%d)\n", view->width, view->height); #endif /* and call Reshape in glX context */ puglReshape(view, view->width, view->height); }
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; }
PuglStatus puglProcessEvents(PuglView* view) { XEvent event; while (XPending(view->impl->display) > 0) { XNextEvent(view->impl->display, &event); 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); view->redisplay = false; break; case MotionNotify: setModifiers(view, event.xmotion.state); if (view->motionFunc) { view->motionFunc(view, event.xmotion.x, event.xmotion.y); } break; case ButtonPress: setModifiers(view, event.xbutton.state); 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, dx, dy); } break; } // nobreak case ButtonRelease: setModifiers(view, event.xbutton.state); 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); KeySym sym; char str[5]; int n = XLookupString(&event.xkey, str, 4, &sym, NULL); PuglKey key = keySymToSpecial(sym); if (!key && view->keyboardFunc) { if (n == 1) { view->keyboardFunc(view, true, str[0]); } else { fprintf(stderr, "warning: Unknown key %X\n", (int)sym); } } else if (view->specialFunc) { view->specialFunc(view, true, key); } } break; case KeyRelease: { setModifiers(view, event.xkey.state); 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 && view->keyboardFunc) { KeySym sym = XKeycodeToKeysym( view->impl->display, event.xkey.keycode, 0); PuglKey special = keySymToSpecial(sym); if (!special) { view->keyboardFunc(view, false, sym); } else if (view->specialFunc) { view->specialFunc(view, false, special); } } } break; case ClientMessage: if (!strcmp(XGetAtomName(view->impl->display, event.xclient.message_type), "WM_PROTOCOLS")) { if (view->closeFunc) { view->closeFunc(view); } } break; default: break; } } if (view->redisplay) { puglDisplay(view); } return PUGL_SUCCESS; }
static LRESULT handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) { MSG msg; PAINTSTRUCT ps; PuglKey key; setModifiers(view); switch (message) { case WM_CREATE: case WM_SHOWWINDOW: case WM_SIZE: puglReshape(view, view->width, view->height); break; case WM_PAINT: BeginPaint(view->impl->hwnd, &ps); puglDisplay(view); EndPaint(view->impl->hwnd, &ps); break; case WM_MOUSEMOVE: if (view->motionFunc) { view->motionFunc( view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); } break; case WM_LBUTTONDOWN: processMouseEvent(view, 1, true, lParam); break; case WM_MBUTTONDOWN: processMouseEvent(view, 2, true, lParam); break; case WM_RBUTTONDOWN: processMouseEvent(view, 3, true, lParam); break; case WM_LBUTTONUP: processMouseEvent(view, 1, false, lParam); break; case WM_MBUTTONUP: processMouseEvent(view, 2, false, lParam); break; case WM_RBUTTONUP: processMouseEvent(view, 3, false, lParam); break; case WM_MOUSEWHEEL: if (view->scrollFunc) { view->scrollFunc( view, 0, (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA); } break; case WM_MOUSEHWHEEL: if (view->scrollFunc) { view->scrollFunc( view, (int16_t)HIWORD(wParam) / float(WHEEL_DELTA), 0); } break; case WM_KEYDOWN: if (view->ignoreKeyRepeat && (lParam & (1 << 30))) { break; } // else nobreak case WM_KEYUP: if (key = keySymToSpecial(wParam)) { if (view->specialFunc) { view->specialFunc(view, message == WM_KEYDOWN, key); } } else if (view->keyboardFunc) { view->keyboardFunc(view, message == WM_KEYDOWN, wParam); } break; case WM_QUIT: if (view->closeFunc) { view->closeFunc(view); } break; default: return DefWindowProc( view->impl->hwnd, message, wParam, lParam); } return 0; }
static LRESULT handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; PuglKey key; setModifiers(view); switch (message) { case WM_CREATE: case WM_SHOWWINDOW: case WM_SIZE: RECT rect; GetClientRect(view->impl->hwnd, &rect); puglReshape(view, rect.right, rect.bottom); view->width = rect.right; view->height = rect.bottom; break; case WM_PAINT: BeginPaint(view->impl->hwnd, &ps); puglDisplay(view); EndPaint(view->impl->hwnd, &ps); break; case WM_MOUSEMOVE: if (view->motionFunc) { view->event_timestamp_ms = GetMessageTime(); view->motionFunc(view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); } break; case WM_LBUTTONDOWN: processMouseEvent(view, 1, true, lParam); break; case WM_MBUTTONDOWN: processMouseEvent(view, 2, true, lParam); break; case WM_RBUTTONDOWN: processMouseEvent(view, 3, true, lParam); break; case WM_LBUTTONUP: processMouseEvent(view, 1, false, lParam); break; case WM_MBUTTONUP: processMouseEvent(view, 2, false, lParam); break; case WM_RBUTTONUP: processMouseEvent(view, 3, false, lParam); break; case WM_MOUSEWHEEL: if (view->scrollFunc) { view->event_timestamp_ms = GetMessageTime(); view->scrollFunc( view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0.0f, (int16_t)HIWORD(wParam) / (float)WHEEL_DELTA); } break; case WM_MOUSEHWHEEL: if (view->scrollFunc) { view->event_timestamp_ms = GetMessageTime(); view->scrollFunc( view, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), (int16_t)HIWORD(wParam) / float(WHEEL_DELTA), 0.0f); } break; case WM_KEYDOWN: if (view->ignoreKeyRepeat && (lParam & (1 << 30))) { break; } // else nobreak case WM_KEYUP: view->event_timestamp_ms = GetMessageTime(); if ((key = keySymToSpecial(wParam))) { if (view->specialFunc) { view->specialFunc(view, message == WM_KEYDOWN, key); } } else if (view->keyboardFunc) { view->keyboardFunc(view, message == WM_KEYDOWN, wParam); } break; case WM_QUIT: case PUGL_LOCAL_CLOSE_MSG: if (view->closeFunc) { view->closeFunc(view); } break; default: return DefWindowProc( view->impl->hwnd, message, wParam, lParam); } return 0; }