diff options
author | David Robillard <d@drobilla.net> | 2020-11-22 17:50:32 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2020-11-22 17:50:32 +0100 |
commit | 0a5b734f6d373b5230d79db625ca311255a49abf (patch) | |
tree | 8ec68e217707c088a256d2e6d24aec226b7a0b3a /src | |
parent | c7213092415732272aa5ccd4547940bf9fe4c7b5 (diff) | |
download | pugl-0a5b734f6d373b5230d79db625ca311255a49abf.tar.gz pugl-0a5b734f6d373b5230d79db625ca311255a49abf.tar.bz2 pugl-0a5b734f6d373b5230d79db625ca311255a49abf.zip |
X11: Fix position of child windows and clean up window creation code
This fixes an issue where the default frame position would be set based on the
screen size for child windows. This went unnoticed so far because most
plugins, like pugl_embed_demo, explicitly set the frame and so avoided this
code path.
Also generally tidy up puglRealize() along the way to make it a bit more
readable.
Diffstat (limited to 'src')
-rw-r--r-- | src/x11.c | 118 |
1 files changed, 68 insertions, 50 deletions
@@ -74,12 +74,6 @@ enum WmClientStateMessageAction { WM_STATE_TOGGLE }; -static const long eventMask = - (ExposureMask | StructureNotifyMask | - VisibilityChangeMask | FocusChangeMask | - EnterWindowMask | LeaveWindowMask | PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask); - static bool puglInitXSync(PuglWorldInternals* impl) { @@ -277,64 +271,89 @@ puglDefineCursorShape(PuglView* view, unsigned shape) PuglStatus puglRealize(PuglView* view) { - PuglInternals* const impl = view->impl; - if (impl->win) { - return PUGL_FAILURE; - } - + PuglInternals* const impl = view->impl; PuglWorld* const world = view->world; PuglX11Atoms* const atoms = &view->world->impl->atoms; Display* const display = world->impl->display; + const int screen = DefaultScreen(display); + const Window root = RootWindow(display, screen); + const Window parent = view->parent ? (Window)view->parent : root; + XSetWindowAttributes attr = {0}; + PuglStatus st = PUGL_SUCCESS; - impl->display = display; - impl->screen = DefaultScreen(display); - - if (!view->backend || !view->backend->configure) { + // Ensure that we're unrealized and that a reasonable backend has been set + if (impl->win) { + return PUGL_FAILURE; + } else if (!view->backend || !view->backend->configure) { return PUGL_BAD_BACKEND; - } else if (view->frame.width == 0.0 && view->frame.height == 0.0) { - if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) { + } + + // Set the size to the default if it has not already been set + if (view->frame.width == 0.0 && view->frame.height == 0.0) { + if (view->defaultWidth == 0.0 || view->defaultHeight == 0.0) { return PUGL_BAD_CONFIGURATION; } - const int screenWidth = DisplayWidth(display, impl->screen); - const int screenHeight = DisplayHeight(display, impl->screen); - view->frame.width = view->defaultWidth; view->frame.height = view->defaultHeight; - view->frame.x = screenWidth / 2.0 - view->frame.width / 2.0; - view->frame.y = screenHeight / 2.0 - view->frame.height / 2.0; } - PuglStatus st = view->backend->configure(view); - if (st || !impl->vi) { + // Center top-level windows if a position has not been set + if (!view->parent && view->frame.x == 0.0 && view->frame.y == 0.0) { + const int screenWidth = DisplayWidth(display, screen); + const int screenHeight = DisplayHeight(display, screen); + + view->frame.x = screenWidth / 2.0 - view->frame.width / 2.0; + view->frame.y = screenHeight / 2.0 - view->frame.height / 2.0; + } + + // Configure the backend to get the visual info + impl->display = display; + impl->screen = screen; + if ((st = view->backend->configure(view)) || !impl->vi) { view->backend->destroy(view); return st ? st : PUGL_BACKEND_FAILED; } - Window xParent = view->parent ? (Window)view->parent - : RootWindow(display, impl->screen); - - Colormap cmap = XCreateColormap( - display, xParent, impl->vi->visual, AllocNone); - - XSetWindowAttributes attr = {0}; - attr.colormap = cmap; - attr.event_mask = eventMask; - - const Window win = impl->win = XCreateWindow( - display, xParent, - (int)view->frame.x, (int)view->frame.y, - (unsigned)view->frame.width, (unsigned)view->frame.height, - 0, impl->vi->depth, InputOutput, - impl->vi->visual, CWColormap | CWEventMask, &attr); - + // Create a colormap based on the visual info from the backend + attr.colormap = + XCreateColormap(display, parent, impl->vi->visual, AllocNone); + + // Set the event mask to request all of the event types we react to + attr.event_mask |= ButtonPressMask; + attr.event_mask |= ButtonReleaseMask; + attr.event_mask |= EnterWindowMask; + attr.event_mask |= ExposureMask; + attr.event_mask |= FocusChangeMask; + attr.event_mask |= KeyPressMask; + attr.event_mask |= KeyReleaseMask; + attr.event_mask |= LeaveWindowMask; + attr.event_mask |= PointerMotionMask; + attr.event_mask |= StructureNotifyMask; + attr.event_mask |= VisibilityChangeMask; + + // Create the window + impl->win = XCreateWindow(display, + parent, + (int)view->frame.x, + (int)view->frame.y, + (unsigned)view->frame.width, + (unsigned)view->frame.height, + 0, + impl->vi->depth, + InputOutput, + impl->vi->visual, + CWColormap | CWEventMask, + &attr); + + // Create the backend drawing context/surface if ((st = view->backend->create(view))) { return st; } #ifdef HAVE_XRANDR // Set refresh rate hint to the real refresh rate - XRRScreenConfiguration* conf = XRRGetScreenInfo(display, xParent); + XRRScreenConfiguration* conf = XRRGetScreenInfo(display, parent); short current_rate = XRRConfigCurrentRate(conf); view->hints[PUGL_REFRESH_RATE] = current_rate; @@ -344,26 +363,25 @@ puglRealize(PuglView* view) updateSizeHints(view); XClassHint classHint = { world->className, world->className }; - XSetClassHint(display, win, &classHint); + XSetClassHint(display, impl->win, &classHint); if (view->title) { puglSetWindowTitle(view, view->title); } - if (!view->parent) { - XSetWMProtocols(display, win, &atoms->WM_DELETE_WINDOW, 1); + if (parent == root) { + XSetWMProtocols(display, impl->win, &atoms->WM_DELETE_WINDOW, 1); } if (view->transientParent) { - XSetTransientForHint(display, win, (Window)(view->transientParent)); + XSetTransientForHint(display, impl->win, (Window)view->transientParent); } // Create input context - const XIMStyle im_style = XIMPreeditNothing | XIMStatusNothing; impl->xic = XCreateIC(world->impl->xim, - XNInputStyle, im_style, - XNClientWindow, win, - XNFocusWindow, win, + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, impl->win, + XNFocusWindow, impl->win, NULL); #ifdef HAVE_XCURSOR |