diff options
Diffstat (limited to 'src/x11.c')
-rw-r--r-- | src/x11.c | 260 |
1 files changed, 108 insertions, 152 deletions
@@ -11,7 +11,7 @@ #include "platform.h" #include "types.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> #include <X11/X.h> #include <X11/Xatom.h> @@ -70,7 +70,8 @@ #ifdef __cplusplus # define PUGL_INIT_STRUCT \ - {} + { \ + } #else # define PUGL_INIT_STRUCT {0} #endif @@ -404,14 +405,18 @@ updateSizeHints(const PuglView* const view) XSizeHints sizeHints = PUGL_INIT_STRUCT; if (!view->hints[PUGL_RESIZABLE]) { - const PuglRect frame = puglGetFrame(view); + PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE); + if (!puglIsValidSize(size.width, size.height)) { + size = puglGetSizeHint(view, PUGL_DEFAULT_SIZE); + } + sizeHints.flags = PBaseSize | PMinSize | PMaxSize; - sizeHints.base_width = (int)frame.width; - sizeHints.base_height = (int)frame.height; - sizeHints.min_width = (int)frame.width; - sizeHints.min_height = (int)frame.height; - sizeHints.max_width = (int)frame.width; - sizeHints.max_height = (int)frame.height; + sizeHints.base_width = (int)size.width; + sizeHints.base_height = (int)size.height; + sizeHints.min_width = (int)size.width; + sizeHints.min_height = (int)size.height; + sizeHints.max_width = (int)size.width; + sizeHints.max_height = (int)size.height; } else { // Avoid setting PBaseSize for top level views to avoid window manager bugs const PuglArea defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; @@ -510,48 +515,21 @@ clearX11Clipboard(PuglX11Clipboard* const board) board->data.len = 0; } -static PuglRect -getInitialFrame(PuglView* const view) +PuglPoint +puglGetAncestorCenter(const PuglView* const view) { - if (view->lastConfigure.type == PUGL_CONFIGURE) { - // Use the last configured frame - const PuglRect frame = {view->lastConfigure.x, - view->lastConfigure.y, - view->lastConfigure.width, - view->lastConfigure.height}; - return frame; - } - - const PuglSpan defaultWidth = view->sizeHints[PUGL_DEFAULT_SIZE].width; - const PuglSpan defaultHeight = view->sizeHints[PUGL_DEFAULT_SIZE].height; - const int x = view->defaultX; - const int y = view->defaultY; - if (puglIsValidPosition(x, y)) { - // Use the default position set with puglSetPosition while unrealized - const PuglRect frame = { - (PuglCoord)x, (PuglCoord)y, defaultWidth, defaultHeight}; - return frame; - } - - // Get the best "parentish" window to position the window in - Display* const display = view->world->impl->display; - const Window parent = - (view->parent ? (Window)view->parent - : view->transientParent ? (Window)view->transientParent - : RootWindow(display, view->impl->screen)); + Display* const display = view->world->impl->display; + const int screen = view->impl->screen; + XWindowAttributes ancestorAttrs = PUGL_INIT_STRUCT; + XGetWindowAttributes(display, + view->transientParent ? (Window)view->transientParent + : RootWindow(display, screen), + &ancestorAttrs); - // Get the position/size of the parent as bounds for the new window - XWindowAttributes parentAttrs = PUGL_INIT_STRUCT; - XGetWindowAttributes(display, parent, &parentAttrs); - - // Center the frame within the parent bounds - const int centerX = parentAttrs.x + parentAttrs.width / 2; - const int centerY = parentAttrs.y + parentAttrs.height / 2; - const PuglRect frame = {(PuglCoord)(centerX - (defaultWidth / 2)), - (PuglCoord)(centerY - (defaultHeight / 2)), - defaultWidth, - defaultHeight}; - return frame; + const PuglPoint center = { + (PuglCoord)(ancestorAttrs.x + (ancestorAttrs.width / 2)), + (PuglCoord)(ancestorAttrs.y + (ancestorAttrs.height / 2))}; + return center; } PuglStatus @@ -606,16 +584,17 @@ puglRealize(PuglView* const view) attr.event_mask |= StructureNotifyMask; attr.event_mask |= VisibilityChangeMask; - // Calculate the initial window rectangle - const PuglRect initialFrame = getInitialFrame(view); + // Calculate the initial window frame + const PuglArea initialSize = puglGetInitialSize(view); + const PuglPoint initialPos = puglGetInitialPosition(view, initialSize); // Create the window impl->win = XCreateWindow(display, parent, - initialFrame.x, - initialFrame.y, - initialFrame.width, - initialFrame.height, + initialPos.x, + initialPos.y, + initialSize.width, + initialSize.height, 0, impl->vi->depth, InputOutput, @@ -770,7 +749,7 @@ puglShow(PuglView* const view, const PuglShowCommand command) } if (view->stage == PUGL_VIEW_STAGE_CONFIGURED) { - st = puglPostRedisplay(view); + st = puglObscureView(view); } } @@ -1026,7 +1005,7 @@ translateClientMessage(PuglView* const view, XClientMessageEvent message) { Display* const display = view->world->impl->display; const PuglX11Atoms* const atoms = &view->world->impl->atoms; - PuglEvent event = {{PUGL_NOTHING, 0}}; + PuglEvent event = {{PUGL_NOTHING, 0U}}; if (message.message_type == atoms->WM_PROTOCOLS) { const Atom protocol = (Atom)message.data.l[0]; @@ -1099,17 +1078,19 @@ getCurrentConfiguration(PuglView* const view) XWindowAttributes attrs; XGetWindowAttributes(display, view->impl->win, &attrs); - // Get window position relative to the root window + // Get window position (relative to the root window if not a child) Window ignoredChild = 0; - int rootX = 0; - int rootY = 0; - XTranslateCoordinates( - display, view->impl->win, attrs.root, 0, 0, &rootX, &rootY, &ignoredChild); + int x = attrs.x; + int y = attrs.y; + if (!view->parent) { + XTranslateCoordinates( + display, view->impl->win, attrs.root, 0, 0, &x, &y, &ignoredChild); + } // Build a configure event based on the current window configuration - PuglEvent configureEvent = {{PUGL_CONFIGURE, 0}}; - configureEvent.configure.x = (PuglCoord)rootX; - configureEvent.configure.y = (PuglCoord)rootY; + PuglEvent configureEvent = {{PUGL_CONFIGURE, 0U}}; + configureEvent.configure.x = (PuglCoord)x; + configureEvent.configure.y = (PuglCoord)y; configureEvent.configure.width = (PuglSpan)attrs.width; configureEvent.configure.height = (PuglSpan)attrs.height; configureEvent.configure.style = getCurrentViewStyleFlags(view); @@ -1138,7 +1119,7 @@ translatePropertyNotify(PuglView* const view, XPropertyEvent message) { const PuglInternals* const impl = view->impl; const PuglX11Atoms* const atoms = &view->world->impl->atoms; - PuglEvent event = {{PUGL_NOTHING, 0}}; + PuglEvent event = {{PUGL_NOTHING, 0U}}; if (message.atom == atoms->NET_WM_STATE) { // Get all the current states set in the window hints @@ -1188,7 +1169,7 @@ translatePropertyNotify(PuglView* const view, XPropertyEvent message) static PuglEvent translateEvent(PuglView* const view, XEvent xevent) { - PuglEvent event = {{PUGL_NOTHING, 0}}; + PuglEvent event = {{PUGL_NOTHING, 0U}}; event.any.flags = xevent.xany.send_event ? PUGL_IS_SEND_EVENT : 0; switch (xevent.type) { @@ -1209,6 +1190,9 @@ translateEvent(PuglView* const view, XEvent xevent) view->impl->mapped = false; event = makeConfigureEvent(view); break; + case DestroyNotify: + view->impl->win = None; + break; case ConfigureNotify: event = makeConfigureEvent(view); event.configure.width = (PuglSpan)xevent.xconfigure.width; @@ -1532,21 +1516,11 @@ puglSendEvent(PuglView* const view, const PuglEvent* const event) return PUGL_UNSUPPORTED; } -#ifndef PUGL_DISABLE_DEPRECATED -PuglStatus -puglWaitForEvent(PuglView* const view) -{ - XEvent xevent; - XPeekEvent(view->world->impl->display, &xevent); - return PUGL_SUCCESS; -} -#endif - static void mergeExposeEvents(PuglExposeEvent* const dst, const PuglExposeEvent* const src) { if (!dst->type) { - if (src->width > 0.0 && src->height > 0.0) { + if (src->width && src->height) { *dst = *src; } } else { @@ -1610,7 +1584,7 @@ handleSelectionNotify(const PuglWorld* const world, Display* const display = view->world->impl->display; const Atom selection = event->selection; PuglX11Clipboard* const board = getX11SelectionClipboard(view, selection); - PuglEvent puglEvent = {{PUGL_NOTHING, 0}}; + PuglEvent puglEvent = {{PUGL_NOTHING, 0U}}; if (event->target == atoms->TARGETS) { // Notification of available datatypes @@ -1620,7 +1594,7 @@ handleSelectionNotify(const PuglWorld* const world, view, event->requestor, event->property, &numFormats, &formats) && !setClipboardFormats(view, board, numFormats, formats)) { const PuglDataOfferEvent offer = { - PUGL_DATA_OFFER, 0, (double)event->time / 1e3}; + PUGL_DATA_OFFER, 0U, (double)event->time / 1e3}; puglEvent.offer = offer; board->acceptedFormatIndex = UINT32_MAX; @@ -1697,8 +1671,7 @@ handleSelectionRequest(const PuglWorld* const world, } /// Flush pending configure and expose events for all views -PUGL_WARN_UNUSED_RESULT -static PuglStatus +PUGL_WARN_UNUSED_RESULT static PuglStatus flushExposures(PuglWorld* const world) { PuglStatus st0 = PUGL_SUCCESS; @@ -1751,7 +1724,7 @@ handleTimerEvent(PuglWorld* const world, const XEvent xevent) for (size_t i = 0; i < world->impl->numTimers; ++i) { if (world->impl->timers[i].alarm == notify->alarm) { - PuglEvent event = {{PUGL_TIMER, 0}}; + PuglEvent event = {{PUGL_TIMER, 0U}}; event.timer.id = world->impl->timers[i].id; puglDispatchEvent(world->impl->timers[i].view, &event); } @@ -1849,14 +1822,6 @@ dispatchX11Events(PuglWorld* const world) return st; } -#ifndef PUGL_DISABLE_DEPRECATED -PuglStatus -puglProcessEvents(PuglView* const view) -{ - return puglUpdate(view->world, 0.0); -} -#endif - PuglStatus puglUpdate(PuglWorld* const world, const double timeout) { @@ -1867,8 +1832,9 @@ puglUpdate(PuglWorld* const world, const double timeout) world->impl->dispatchingEvents = true; if (timeout < 0.0) { - st0 = pollX11Socket(world, timeout); - st0 = st0 ? st0 : dispatchX11Events(world); + if (!(st0 = pollX11Socket(world, timeout))) { + st0 = dispatchX11Events(world); + } } else if (timeout <= 0.001) { st0 = dispatchX11Events(world); } else { @@ -1894,33 +1860,45 @@ double puglGetTime(const PuglWorld* const world) { struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); + if (clock_gettime(CLOCK_MONOTONIC, &ts)) { + return 0.0; + } + return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) - world->startTime; } PuglStatus -puglPostRedisplay(PuglView* const view) +puglObscureView(PuglView* const view) { - PuglRect rect = puglGetFrame(view); - rect.x = 0; - rect.y = 0; - - return puglPostRedisplayRect(view, rect); + return puglObscureRegion( + view, 0, 0, view->lastConfigure.width, view->lastConfigure.height); } PuglStatus -puglPostRedisplayRect(PuglView* const view, const PuglRect rect) +puglObscureRegion(PuglView* const view, + const int x, + const int y, + const unsigned width, + const unsigned height) { - const PuglExposeEvent event = { - PUGL_EXPOSE, 0, rect.x, rect.y, rect.width, rect.height}; + if (!puglIsValidPosition(x, y) || !puglIsValidSize(width, height)) { + return PUGL_BAD_PARAMETER; + } + + const PuglCoord cx = MAX((PuglCoord)0, (PuglCoord)x); + const PuglCoord cy = MAX((PuglCoord)0, (PuglCoord)y); + const PuglSpan cw = MIN(view->lastConfigure.width, (PuglSpan)width); + const PuglSpan ch = MIN(view->lastConfigure.height, (PuglSpan)height); + + const PuglExposeEvent event = {PUGL_EXPOSE, 0U, cx, cy, cw, ch}; if (view->world->impl->dispatchingEvents) { // Currently dispatching events, add/expand expose for the loop end mergeExposeEvents(&view->impl->pendingExpose.expose, &event); } else if (view->impl->win) { // Not dispatching events, send an X expose so we wake up next time - PuglEvent exposeEvent = {{PUGL_EXPOSE, 0}}; + PuglEvent exposeEvent = {{PUGL_EXPOSE, 0U}}; exposeEvent.expose = event; return puglSendEvent(view, &exposeEvent); } @@ -1974,65 +1952,41 @@ puglGetScaleFactor(const PuglView* const view) return view->world->impl->scaleFactor; } -PuglStatus -puglSetFrame(PuglView* const view, const PuglRect frame) -{ - if (!view->impl->win) { - // Set defaults to be used when realized - view->defaultX = frame.x; - view->defaultY = frame.y; - view->sizeHints[PUGL_DEFAULT_SIZE].width = frame.width; - view->sizeHints[PUGL_DEFAULT_SIZE].height = frame.height; - return PUGL_SUCCESS; - } - - return puglX11Status(XMoveResizeWindow(view->world->impl->display, - view->impl->win, - frame.x, - frame.y, - frame.width, - frame.height)); -} - -PuglStatus -puglSetPosition(PuglView* const view, const int x, const int y) +static PuglStatus +puglSetWindowPosition(PuglView* const view, const int x, const int y) { - Display* const display = view->world->impl->display; - - if (!puglIsValidPosition(x, y)) { - return PUGL_BAD_PARAMETER; - } - - if (!view->impl->win) { - // Set defaults to be used when realized - view->defaultX = x; - view->defaultY = y; - return PUGL_SUCCESS; - } - - return puglX11Status(XMoveWindow(display, + return puglX11Status(XMoveWindow(view->world->impl->display, view->impl->win, (int)(x - view->impl->frameExtentLeft), (int)(y - view->impl->frameExtentTop))); } -PuglStatus -puglSetSize(PuglView* const view, const unsigned width, const unsigned height) +static PuglStatus +puglSetWindowSize(PuglView* const view, + const unsigned width, + const unsigned height) { - Display* const display = view->world->impl->display; + return !view->impl->win + ? PUGL_SUCCESS + : puglX11Status(XResizeWindow( + view->world->impl->display, view->impl->win, width, height)); +} - if (!puglIsValidSize(width, height)) { +PuglStatus +puglSetPositionHint(PuglView* const view, + const PuglPositionHint hint, + const int x, + const int y) +{ + if (x <= INT16_MIN || x > INT16_MAX || y <= INT16_MIN || y > INT16_MAX) { return PUGL_BAD_PARAMETER; } - if (!view->impl->win) { - // Set defaults to be used when realized - view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width; - view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height; - return PUGL_SUCCESS; - } + view->positionHints[hint].x = (PuglCoord)x; + view->positionHints[hint].y = (PuglCoord)y; - return puglX11Status(XResizeWindow(display, view->impl->win, width, height)); + return (hint == PUGL_CURRENT_POSITION) ? puglSetWindowPosition(view, x, y) + : PUGL_SUCCESS; } PuglStatus @@ -2043,7 +1997,9 @@ puglSetSizeHint(PuglView* const view, { const PuglStatus st = puglStoreSizeHint(view, hint, width, height); - return st ? st : updateSizeHints(view); + return st ? st + : (hint == PUGL_CURRENT_SIZE) ? puglSetWindowSize(view, width, height) + : updateSizeHints(view); } PuglStatus |