From 72279b8e7c8d1a80132e42bcbc9761c3c8911190 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 30 Sep 2018 01:20:29 +0200 Subject: Update pugl base files and X11 code --- dgl/src/Window.cpp | 6 +- dgl/src/pugl/pugl.h | 51 ++++++- dgl/src/pugl/pugl_internal.h | 190 +++++++----------------- dgl/src/pugl/pugl_osx.m | 4 +- dgl/src/pugl/pugl_win.cpp | 4 +- dgl/src/pugl/pugl_x11.c | 335 +++++++++++++++++++++++++------------------ 6 files changed, 300 insertions(+), 290 deletions(-) (limited to 'dgl') diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index f809777b..6a221690 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -19,10 +19,6 @@ #include "../Base.hpp" -#undef PUGL_HAVE_CAIRO -#undef PUGL_HAVE_GL -#define PUGL_HAVE_GL 1 - #include "pugl/pugl.h" #if defined(__GNUC__) && (__GNUC__ >= 7) @@ -619,7 +615,7 @@ struct Window::PrivateData { sizeHints.max_width = static_cast(width); sizeHints.max_height = static_cast(height); - XSetNormalHints(xDisplay, xWindow, &sizeHints); + XSetWMNormalHints(xDisplay, xWindow, &sizeHints); } if (! forced) diff --git a/dgl/src/pugl/pugl.h b/dgl/src/pugl/pugl.h index 09846463..32a10a2b 100644 --- a/dgl/src/pugl/pugl.h +++ b/dgl/src/pugl/pugl.h @@ -32,6 +32,7 @@ # include "OpenGL/gl.h" #else # ifdef _WIN32 +# include # include /* Broken Windows GL headers require this */ # endif # include "GL/gl.h" @@ -177,6 +178,16 @@ typedef void (*PuglMouseFunc)( */ typedef void (*PuglReshapeFunc)(PuglView* view, int width, int height); +/** + A function called outside of gl-context when the plugin schedules a resize via puglPostResize. + + @param view The view being resized. + @param width The new width to resize to (variable is initialized to current size) + @param height The new height to resize to (variable is initialized to current size) + @param set_hints If not null, set window-hints + */ +typedef void (*PuglResizeFunc)(PuglView* view, int *width, int *height, int *set_hints); + /** A function called on scrolling (e.g. mouse wheel or track pad). @@ -281,13 +292,31 @@ PUGL_API int puglCreateWindow(PuglView* view, const char* title); /** - Show the current window. + Create a new GL window. + @param parent Parent window, or 0 for top level. + @param title Window title, or NULL. + @param width Window width in pixels. + @param height Window height in pixels. + @param resizable Whether window should be user resizable. +*/ +PUGL_API PuglView* +puglCreate(PuglNativeWindow parent, + const char* title, + int min_width, + int min_height, + int width, + int height, + bool resizable, + unsigned long transientId); + +/** + Show Window (external ui) */ PUGL_API void puglShowWindow(PuglView* view); /** - Hide the current window. + Hide Window (external ui) */ PUGL_API void puglHideWindow(PuglView* view); @@ -394,6 +423,12 @@ puglSetSpecialFunc(PuglView* view, PuglSpecialFunc specialFunc); PUGL_API void puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc); +/** + Set callback function to change window size. +*/ +PUGL_API void +puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc); + /** Set the function to call on file-browser selections. */ @@ -404,6 +439,12 @@ puglSetFileSelectedFunc(PuglView* view, PuglFileSelectedFunc fileSelectedFunc); @} */ +/** + TODO document this. + */ +PUGL_API int +puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect); + /** Grab the input focus. */ @@ -425,6 +466,12 @@ puglProcessEvents(PuglView* view); PUGL_API void puglPostRedisplay(PuglView* view); +/** + Request a resize on the next call to puglProcessEvents(). +*/ +PUGL_API void +puglPostResize(PuglView* view); + /** Destroy a GL window. */ diff --git a/dgl/src/pugl/pugl_internal.h b/dgl/src/pugl/pugl_internal.h index c84d77bd..fa52df40 100644 --- a/dgl/src/pugl/pugl_internal.h +++ b/dgl/src/pugl/pugl_internal.h @@ -20,26 +20,9 @@ Note this file contains function definitions, so it must be compiled into the final binary exactly once. Each platform specific implementation file including it once should achieve this. - - If you are copying the pugl code into your source tree, the following - symbols can be defined to tweak pugl behaviour: - - PUGL_HAVE_CAIRO: Include Cairo support code. - PUGL_HAVE_GL: Include OpenGL support code. - PUGL_GRAB_FOCUS: Work around reparent keyboard issues by grabbing focus. - PUGL_VERBOSE: Print GL information to console. */ -#include "pugl/pugl.h" - -#ifdef PUGL_VERBOSE -# include -# define PUGL_LOG(str) fprintf(stderr, "pugl: " str) -# define PUGL_LOGF(fmt, ...) fprintf(stderr, "pugl: " fmt, __VA_ARGS__) -#else -# define PUGL_LOG(str) -# define PUGL_LOGF(fmt, ...) -#endif +#include "pugl.h" typedef struct PuglInternalsImpl PuglInternals; @@ -51,12 +34,12 @@ struct PuglViewImpl { PuglMotionFunc motionFunc; PuglMouseFunc mouseFunc; PuglReshapeFunc reshapeFunc; + PuglResizeFunc resizeFunc; PuglScrollFunc scrollFunc; PuglSpecialFunc specialFunc; PuglFileSelectedFunc fileSelectedFunc; - PuglInternals* impl; - + PuglInternals* impl; PuglNativeWindow parent; uintptr_t transient_parent; @@ -68,7 +51,8 @@ struct PuglViewImpl { bool mouse_in_view; bool ignoreKeyRepeat; bool redisplay; - bool resizable; + bool user_resizable; + bool pending_resize; uint32_t event_timestamp_ms; }; @@ -118,7 +102,7 @@ puglInitWindowParent(PuglView* view, PuglNativeWindow parent) void puglInitUserResizable(PuglView* view, bool resizable) { - view->resizable = resizable; + view->user_resizable = resizable; } void @@ -127,6 +111,35 @@ puglInitTransientFor(PuglView* view, uintptr_t parent) view->transient_parent = parent; } +PuglView* +puglCreate(PuglNativeWindow parent, + const char* title, + int min_width, + int min_height, + int width, + int height, + bool resizable, + unsigned long transientId) +{ + PuglView* view = puglInit(); + if (!view) { + return NULL; + } + + puglInitWindowParent(view, parent); + puglInitWindowMinSize(view, min_width, min_height); + puglInitWindowSize(view, width, height); + puglInitUserResizable(view, resizable); + puglInitTransientFor(view, transientId); + + if (!puglCreateWindow(view, title)) { + free(view); + return NULL; + } + + return view; +} + void puglSetHandle(PuglView* view, PuglHandle handle) { @@ -193,6 +206,12 @@ puglSetReshapeFunc(PuglView* view, PuglReshapeFunc reshapeFunc) view->reshapeFunc = reshapeFunc; } +void +puglSetResizeFunc(PuglView* view, PuglResizeFunc resizeFunc) +{ + view->resizeFunc = resizeFunc; +} + void puglSetScrollFunc(PuglView* view, PuglScrollFunc scrollFunc) { @@ -217,45 +236,19 @@ puglEnterContext(PuglView* view); void puglLeaveContext(PuglView* view, bool flush); -#if 0 -/** Return the code point for buf, or the replacement character on error. */ -static uint32_t -puglDecodeUTF8(const uint8_t* buf) -{ -#define FAIL_IF(cond) { if (cond) return 0xFFFD; } - - /* http://en.wikipedia.org/wiki/UTF-8 */ - - if (buf[0] < 0x80) { - return buf[0]; - } else if (buf[0] < 0xC2) { - return 0xFFFD; - } else if (buf[0] < 0xE0) { - FAIL_IF((buf[1] & 0xC0) != 0x80); - return (buf[0] << 6) + buf[1] - 0x3080; - } else if (buf[0] < 0xF0) { - FAIL_IF((buf[1] & 0xC0) != 0x80); - FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0); - FAIL_IF((buf[2] & 0xC0) != 0x80); - return (buf[0] << 12) + (buf[1] << 6) + buf[2] - 0xE2080; - } else if (buf[0] < 0xF5) { - FAIL_IF((buf[1] & 0xC0) != 0x80); - FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90); - FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90); - FAIL_IF((buf[2] & 0xC0) != 0x80); - FAIL_IF((buf[3] & 0xC0) != 0x80); - return ((buf[0] << 18) + - (buf[1] << 12) + - (buf[2] << 6) + - buf[3] - 0x3C82080); - } - return 0xFFFD; -} -#endif - static void -puglDefaultReshape(PuglView* view, int width, int height) +puglDefaultReshape(int width, int height) { +#ifdef ROBTK_HERE + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +#else glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, height, 0, 0, 1); @@ -263,82 +256,5 @@ puglDefaultReshape(PuglView* view, int width, int height) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - return; - - // unused - (void)view; -} - -#if 0 -static void -puglDispatchEvent(PuglView* view, const PuglEvent* event) -{ - if (view->eventFunc) { - view->eventFunc(view, event); - } - - switch (event->type) { - case PUGL_CONFIGURE: - puglEnterContext(view); - view->width = event->configure.width; - view->height = event->configure.height; - if (view->reshapeFunc) { - view->reshapeFunc(view, view->width, view->height); - } - puglLeaveContext(view, false); - break; - case PUGL_EXPOSE: - if (event->expose.count == 0) { - puglEnterContext(view); - if (view->displayFunc) { - view->displayFunc(view); - } - view->redisplay = false; - puglLeaveContext(view, true); - } - break; - case PUGL_MOTION_NOTIFY: - view->event_timestamp_ms = event->motion.time; - view->mods = event->motion.state; - if (view->motionFunc) { - view->motionFunc(view, event->motion.x, event->motion.y); - } - break; - case PUGL_SCROLL: - if (view->scrollFunc) { - view->scrollFunc(view, - event->scroll.x, event->scroll.y, - event->scroll.dx, event->scroll.dy); - } - break; - case PUGL_BUTTON_PRESS: - case PUGL_BUTTON_RELEASE: - view->event_timestamp_ms = event->button.time; - view->mods = event->button.state; - if (view->mouseFunc) { - view->mouseFunc(view, - event->button.button, - event->type == PUGL_BUTTON_PRESS, - event->button.x, - event->button.y); - } - break; - case PUGL_KEY_PRESS: - case PUGL_KEY_RELEASE: - view->event_timestamp_ms = event->key.time; - view->mods = event->key.state; - if (event->key.special && view->specialFunc) { - view->specialFunc(view, - event->type == PUGL_KEY_PRESS, - event->key.special); - } else if (event->key.character && view->keyboardFunc) { - view->keyboardFunc(view, - event->type == PUGL_KEY_PRESS, - event->key.character); - } - break; - default: - break; - } -} #endif +} diff --git a/dgl/src/pugl/pugl_osx.m b/dgl/src/pugl/pugl_osx.m index 82d68a0d..f9570333 100644 --- a/dgl/src/pugl/pugl_osx.m +++ b/dgl/src/pugl/pugl_osx.m @@ -218,7 +218,7 @@ puglDisplay(PuglView* view) if (puglview->reshapeFunc) { puglview->reshapeFunc(puglview, width, height); } else { - puglDefaultReshape(puglview, width, height); + puglDefaultReshape(width, height); } puglLeaveContext(puglview, false); @@ -459,7 +459,7 @@ puglCreateWindow(PuglView* view, const char* title) impl->glview->puglview = view; - if (view->resizable) { + if (view->user_resizable) { [impl->glview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; } diff --git a/dgl/src/pugl/pugl_win.cpp b/dgl/src/pugl/pugl_win.cpp index cc0cf9bb..5d0cd876 100644 --- a/dgl/src/pugl/pugl_win.cpp +++ b/dgl/src/pugl/pugl_win.cpp @@ -129,7 +129,7 @@ puglCreateWindow(PuglView* view, const char* title) } int winFlags = WS_POPUPWINDOW | WS_CAPTION; - if (view->resizable) { + if (view->user_resizable) { winFlags |= WS_SIZEBOX; if (view->min_width > 0 && view->min_height > 0) { // Adjust the minimum window size to accomodate requested view size @@ -223,7 +223,7 @@ puglReshape(PuglView* view, int width, int height) if (view->reshapeFunc) { view->reshapeFunc(view, width, height); } else { - puglDefaultReshape(view, width, height); + puglDefaultReshape(width, height); } view->width = width; diff --git a/dgl/src/pugl/pugl_x11.c b/dgl/src/pugl/pugl_x11.c index d8b091bf..3f98a33e 100644 --- a/dgl/src/pugl/pugl_x11.c +++ b/dgl/src/pugl/pugl_x11.c @@ -1,7 +1,7 @@ /* Copyright 2012-2014 David Robillard - Copyright 2013 Robin Gareus Copyright 2011-2012 Ben Loftis, Harrison Consoles + Copyright 2013,2015 Robin Gareus Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -24,15 +24,14 @@ #include #include +#include +#include #include #include #include #include -#include -#include - -#include "pugl/pugl_internal.h" +#include "pugl_internal.h" #ifndef DGL_FILE_BROWSER_DISABLED #define SOFD_HAVE_X11 @@ -40,108 +39,74 @@ #include "../sofd/libsofd.c" #endif +/* work around buggy re-parent & focus issues on some systems + * where no keyboard events are passed through even if the + * app has mouse-focus and all other events are working. + */ +//#define PUGL_GRAB_FOCUS + +/* show messages during initalization + */ +//#define PUGL_VERBOSE + struct PuglInternalsImpl { Display* display; int screen; Window win; - XIM xim; - XIC xic; GLXContext ctx; Bool doubleBuffered; }; -PuglInternals* -puglInitInternals(void) -{ - return (PuglInternals*)calloc(1, sizeof(PuglInternals)); -} - -static XVisualInfo* -getVisual(PuglView* view) -{ - PuglInternals* const impl = view->impl; - XVisualInfo* vi = NULL; - - /** - Attributes for single-buffered RGBA with at least - 4 bits per color and a 16 bit depth buffer. - */ - int attrListSgl[] = { - GLX_RGBA, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_DEPTH_SIZE, 16, - GLX_ARB_multisample, 1, - None - }; - - /** - Attributes for double-buffered RGBA with at least - 4 bits per color and a 16 bit depth buffer. - */ - int attrListDbl[] = { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_DEPTH_SIZE, 16, - GLX_ARB_multisample, 1, - None - }; - - /** - Attributes for double-buffered RGBA with multi-sampling - (antialiasing) - */ - int attrListDblMS[] = { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4, - GLX_ALPHA_SIZE, 4, - GLX_DEPTH_SIZE, 16, - GLX_SAMPLE_BUFFERS, 1, - GLX_SAMPLES, 4, - None - }; - - impl->doubleBuffered = True; - - vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); - - if (vi == NULL) { - vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); - PUGL_LOG("multisampling (antialiasing) is not available\n"); - } - - if (vi == NULL) { - vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); - impl->doubleBuffered = False; - PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n"); - } - - return vi; -} +/** + Attributes for single-buffered RGBA with at least + 4 bits per color and a 16 bit depth buffer. +*/ +static int attrListSgl[] = { + GLX_RGBA, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + GLX_ARB_multisample, 1, + None +}; -static bool -createContext(PuglView* view, XVisualInfo* vi) -{ - PuglInternals* const impl = view->impl; +/** + Attributes for double-buffered RGBA with at least + 4 bits per color and a 16 bit depth buffer. +*/ +static int attrListDbl[] = { + GLX_RGBA, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_DEPTH_SIZE, 16, + GLX_ARB_multisample, 1, + None +}; - impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); - return (impl->ctx != NULL); -} +/** + Attributes for double-buffered RGBA with multi-sampling + (antialiasing) +*/ +static int attrListDblMS[] = { + GLX_RGBA, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 4, + GLX_GREEN_SIZE, 4, + GLX_BLUE_SIZE, 4, + GLX_ALPHA_SIZE, 4, + GLX_DEPTH_SIZE, 16, + GLX_SAMPLE_BUFFERS, 1, + GLX_SAMPLES, 4, + None +}; -static void -destroyContext(PuglView* view) +PuglInternals* +puglInitInternals(void) { - PuglInternals* const impl = view->impl; - - glXDestroyContext(impl->display, impl->ctx); - impl->ctx = NULL; + return (PuglInternals*)calloc(1, sizeof(PuglInternals)); } void @@ -165,21 +130,53 @@ puglLeaveContext(PuglView* view, bool flush) int puglCreateWindow(PuglView* view, const char* title) { - PuglInternals* const impl = view->impl; + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + if (!impl) { + return 1; + } + view->impl = impl; impl->display = XOpenDisplay(NULL); - impl->screen = DefaultScreen(impl->display); + if (!impl->display) { + free(impl); + return 1; + } + impl->screen = DefaultScreen(impl->display); + impl->doubleBuffered = True; + + XVisualInfo* vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); + + if (!vi) { + vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); +#ifdef PUGL_VERBOSE + printf("puGL: multisampling (antialiasing) is not available\n"); +#endif + } + + if (!vi) { + vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); + impl->doubleBuffered = False; + } - XVisualInfo* const vi = getVisual(view); if (!vi) { XCloseDisplay(impl->display); - impl->display = NULL; + free(impl); return 1; } +#ifdef PUGL_VERBOSE int glxMajor, glxMinor; glXQueryVersion(impl->display, &glxMajor, &glxMinor); - PUGL_LOGF("GLX Version %d.%d\n", glxMajor, glxMinor); + printf("puGL: GLX-Version : %d.%d\n", glxMajor, glxMinor); +#endif + + impl->ctx = glXCreateContext(impl->display, vi, 0, GL_TRUE); + + if (!impl->ctx) { + XCloseDisplay(impl->display); + free(impl); + return 1; + } Window xParent = view->parent ? (Window)view->parent @@ -204,62 +201,40 @@ puglCreateWindow(PuglView* view, const char* title) 0, 0, view->width, view->height, 0, vi->depth, InputOutput, vi->visual, CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr); - if (!createContext(view, vi)) { - XDestroyWindow(impl->display, impl->win); - impl->win = 0; - + if (!impl->win) { XCloseDisplay(impl->display); - impl->display = NULL; - + free(impl); return 1; } - XSizeHints sizeHints; - memset(&sizeHints, 0, sizeof(sizeHints)); - if (!view->resizable) { - sizeHints.flags = PMinSize|PMaxSize; - sizeHints.min_width = view->width; - sizeHints.min_height = view->height; - sizeHints.max_width = view->width; - sizeHints.max_height = view->height; - XSetNormalHints(impl->display, impl->win, &sizeHints); - } else if (view->min_width > 0 && view->min_height > 0) { - sizeHints.flags = PMinSize; - sizeHints.min_width = view->min_width; - sizeHints.min_height = view->min_height; - XSetNormalHints(impl->display, impl->win, &sizeHints); - } + puglUpdateGeometryConstraints(view, view->min_width, view->min_height, view->min_width != view->width); + XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); if (title) { XStoreName(impl->display, impl->win, title); } - if (!view->parent) { + if (view->transient_parent > 0) { + XSetTransientForHint(impl->display, impl->win, (Window)view->transient_parent); + } + + if (view->parent) { + XMapRaised(impl->display, impl->win); + } else { Atom wmDelete = XInternAtom(impl->display, "WM_DELETE_WINDOW", True); XSetWMProtocols(impl->display, impl->win, &wmDelete, 1); } +#ifdef PUGL_VERBOSE if (glXIsDirect(impl->display, impl->ctx)) { - PUGL_LOG("DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); + printf("puGL: DRI enabled (to disable, set LIBGL_ALWAYS_INDIRECT=1\n"); } else { - PUGL_LOG("No DRI available\n"); + printf("puGL: No DRI available\n"); } +#endif XFree(vi); - - return PUGL_SUCCESS; -} - -void -puglShowWindow(PuglView* view) -{ - XMapRaised(view->impl->display, view->impl->win); -} - -void -puglHideWindow(PuglView* view) -{ - XUnmapWindow(view->impl->display, view->impl->win); + return 0; } void @@ -268,18 +243,29 @@ puglDestroy(PuglView* view) if (!view) { return; } - #ifndef DGL_FILE_BROWSER_DISABLED x_fib_close(view->impl->display); #endif - destroyContext(view); + glXDestroyContext(view->impl->display, view->impl->ctx); XDestroyWindow(view->impl->display, view->impl->win); XCloseDisplay(view->impl->display); free(view->impl); free(view); } +void +puglShowWindow(PuglView* view) +{ + XMapRaised(view->impl->display, view->impl->win); +} + +void +puglHideWindow(PuglView* view) +{ + XUnmapWindow(view->impl->display, view->impl->win); +} + static void puglReshape(PuglView* view, int width, int height) { @@ -288,7 +274,7 @@ puglReshape(PuglView* view, int width, int height) if (view->reshapeFunc) { view->reshapeFunc(view, width, height); } else { - puglDefaultReshape(view, width, height); + puglDefaultReshape(width, height); } puglLeaveContext(view, false); @@ -303,7 +289,6 @@ puglDisplay(PuglView* view) puglEnterContext(view); view->redisplay = false; - if (view->displayFunc) { view->displayFunc(view); } @@ -311,6 +296,36 @@ puglDisplay(PuglView* view) puglLeaveContext(view, true); } +static void +puglResize(PuglView* view) +{ + int set_hints = 1; + view->pending_resize = false; + if (!view->resizeFunc) { return; } + /* ask the plugin about the new size */ + view->resizeFunc(view, &view->width, &view->height, &set_hints); + + if (set_hints) { + XSizeHints sizeHints; + memset(&sizeHints, 0, sizeof(sizeHints)); + sizeHints.flags = PMinSize|PMaxSize; + sizeHints.min_width = view->width; + sizeHints.min_height = view->height; + sizeHints.max_width = view->user_resizable ? 4096 : view->width; + sizeHints.max_height = view->user_resizable ? 4096 : view->height; + XSetWMNormalHints(view->impl->display, view->impl->win, &sizeHints); + } + XResizeWindow(view->impl->display, view->impl->win, view->width, view->height); + XFlush(view->impl->display); + +#ifdef PUGL_VERBOSE + printf("puGL: window resize (%dx%d)\n", view->width, view->height); +#endif + + /* and call Reshape in glX context */ + puglReshape(view, view->width, view->height); +} + static PuglKey keySymToSpecial(KeySym sym) { @@ -439,6 +454,11 @@ puglProcessEvents(PuglView* view) } switch (event.type) { + case UnmapNotify: + if (view->motionFunc) { + view->motionFunc(view, -1, -1); + } + break; case MapNotify: puglReshape(view, view->width, view->height); break; @@ -530,6 +550,10 @@ puglProcessEvents(PuglView* view) } } + if (view->pending_resize) { + puglResize(view); + } + if (view->redisplay) { puglDisplay(view); } @@ -543,8 +567,35 @@ puglPostRedisplay(PuglView* view) view->redisplay = true; } +void +puglPostResize(PuglView* view) +{ + view->pending_resize = true; +} + PuglNativeWindow puglGetNativeWindow(PuglView* view) { return view->impl->win; } + +int +puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) +{ + XSizeHints sizeHints; + memset(&sizeHints, 0, sizeof(sizeHints)); + sizeHints.flags = PMinSize|PMaxSize; + sizeHints.min_width = min_width; + sizeHints.min_height = min_height; + sizeHints.max_width = view->user_resizable ? 4096 : min_width; + sizeHints.max_height = view->user_resizable ? 4096 : min_height; + if (aspect) { + sizeHints.flags |= PAspect; + sizeHints.min_aspect.x = min_width; + sizeHints.min_aspect.y = min_height; + sizeHints.max_aspect.x = min_width; + sizeHints.max_aspect.y = min_height; + } + XSetWMNormalHints(view->impl->display, view->impl->win, &sizeHints); + return 0; +} -- cgit v1.2.3