diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/internal.c | 47 | ||||
-rw-r--r-- | src/internal.h | 12 | ||||
-rw-r--r-- | src/mac.m | 83 | ||||
-rw-r--r-- | src/win.c | 83 | ||||
-rw-r--r-- | src/x11.c | 120 |
5 files changed, 184 insertions, 161 deletions
diff --git a/src/internal.c b/src/internal.c index 31345f3..38a595a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -9,9 +9,17 @@ #include <assert.h> #include <stdbool.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> +static PuglPoint +make_point(const PuglCoord x, const PuglCoord y) +{ + const PuglPoint point = {x, y}; + return point; +} + bool puglIsValidPosition(const int x, const int y) { @@ -30,6 +38,45 @@ puglIsValidArea(const PuglArea size) return size.width && size.height; } +PuglArea +puglGetInitialSize(const PuglView* const view) +{ + if (view->lastConfigure.type == PUGL_CONFIGURE) { + // Use the last configured size + const PuglConfigureEvent config = view->lastConfigure; + const PuglArea size = {config.width, config.height}; + return size; + } + + // Use the default size hint set by the application + return view->sizeHints[PUGL_DEFAULT_SIZE]; +} + +PuglPoint +puglGetInitialPosition(const PuglView* const view, const PuglArea size) +{ + if (view->lastConfigure.type == PUGL_CONFIGURE) { + // Use the last configured frame + return make_point(view->lastConfigure.x, view->lastConfigure.y); + } + + if (puglIsValidPosition(view->defaultX, view->defaultY)) { + // Use the default position hint set by the application + return make_point((PuglCoord)view->defaultX, (PuglCoord)view->defaultY); + } + + if (view->parent) { + // Default to the top/left origin of the parent + return make_point(0, 0); + } + + // Center frame on a transient ancestor, or failing that, the screen + const PuglPoint center = puglGetAncestorCenter(view); + const PuglPoint pos = {(PuglCoord)(center.x - (size.width / 2)), + (PuglCoord)(center.y - (size.height / 2))}; + return pos; +} + void puglEnsureHint(PuglView* const view, const PuglViewHint hint, const int value) { diff --git a/src/internal.h b/src/internal.h index 8497c50..7387494 100644 --- a/src/internal.h +++ b/src/internal.h @@ -30,6 +30,18 @@ puglIsValidSize(unsigned x, unsigned y); bool puglIsValidArea(PuglArea size); +/// Return the center point of some "soft" ancestor (parent window or screen) +PuglPoint +puglGetAncestorCenter(const PuglView* view); + +/// Return the initial size of a view +PuglArea +puglGetInitialSize(const PuglView* view); + +/// Return the initial position of a view if known, or an invalid position +PuglPoint +puglGetInitialPosition(const PuglView* view, PuglArea size); + /// Set hint to a default value if it is unset (PUGL_DONT_CARE) void puglEnsureHint(PuglView* view, PuglViewHint hint, int value); @@ -7,6 +7,7 @@ #include "mac.h" #include "internal.h" +#include "macros.h" #include "platform.h" #include "pugl/pugl.h" @@ -121,7 +122,7 @@ viewScreen(const PuglView* view) } static NSRect -nsRectToPoints(PuglView* view, const NSRect rect) +nsRectToPoints(const PuglView* view, const NSRect rect) { const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -132,7 +133,7 @@ nsRectToPoints(PuglView* view, const NSRect rect) } static NSRect -nsRectFromPoints(PuglView* view, const NSRect rect) +nsRectFromPoints(const PuglView* view, const NSRect rect) { const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -143,7 +144,7 @@ nsRectFromPoints(PuglView* view, const NSRect rect) } static NSPoint -nsPointFromPoints(PuglView* view, const NSPoint point) +nsPointFromPoints(const PuglView* view, const NSPoint point) { const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -1153,30 +1154,9 @@ updateSizeHints(PuglView* const view) } } -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 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, - view->sizeHints[PUGL_DEFAULT_SIZE].width, - view->sizeHints[PUGL_DEFAULT_SIZE].height}; - return frame; - } - - // Get a bounding rect from the transient parent or the screen const NSScreen* const screen = viewScreen(view); const NSRect boundsPt = rectFromScreen(screen, @@ -1184,17 +1164,11 @@ getInitialFrame(PuglView* const view) ? [[(const NSView*)view->transientParent window] frame] : [screen frame]); - // Center the frame around the center of the bounding rectangle - const PuglArea defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; - const NSRect boundsPx = nsRectFromPoints(view, boundsPt); - const double centerX = boundsPx.origin.x + boundsPx.size.width / 2; - const double centerY = boundsPx.origin.y + boundsPx.size.height / 2; - - const PuglRect frame = {(PuglCoord)(centerX - (defaultSize.width / 2U)), - (PuglCoord)(centerY - (defaultSize.height / 2U)), - view->sizeHints[PUGL_DEFAULT_SIZE].width, - view->sizeHints[PUGL_DEFAULT_SIZE].height}; - return frame; + const NSRect boundsPx = nsRectFromPoints(view, boundsPt); + const PuglPoint center = { + (PuglCoord)(boundsPx.origin.x + boundsPx.size.width / 2.0), + (PuglCoord)(boundsPx.origin.y + boundsPx.size.height / 2.0)}; + return center; } PuglStatus @@ -1243,7 +1217,9 @@ puglRealize(PuglView* view) } // Get the initial frame to use from the defaults or last configuration - const PuglRect initialFrame = getInitialFrame(view); + const PuglArea size = puglGetInitialSize(view); + const PuglPoint pos = puglGetInitialPosition(view, size); + const PuglRect initialFrame = {pos.x, pos.y, size.width, size.height}; // Convert frame to points const NSRect framePx = rectToNsRect(initialFrame); @@ -1669,22 +1645,37 @@ puglGetTime(const PuglWorld* world) } PuglStatus -puglPostRedisplay(PuglView* view) +puglObscureView(PuglView* view) { [view->impl->drawView setNeedsDisplay:YES]; return PUGL_SUCCESS; } PuglStatus -puglPostRedisplayRect(PuglView* view, const PuglRect rect) +puglObscureRegion(PuglView* view, + const int x, + const int y, + const unsigned width, + const unsigned height) { - const NSRect rectPx = { - {(double)rect.x, - (double)view->lastConfigure.height - (rect.y + rect.height)}, - {(double)rect.width, (double)rect.height}, - }; + if (!puglIsValidPosition(x, y) || !puglIsValidSize(width, height)) { + return PUGL_BAD_PARAMETER; + } + + const PuglSpan viewHeight = view->lastConfigure.height; - [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)]; + const int cx = MAX(0, x); + const int cy = MAX(0, viewHeight - y - (int)height); + const unsigned cw = MIN(view->lastConfigure.width, width); + const unsigned ch = MIN(view->lastConfigure.height, height); + + if (cw == view->lastConfigure.width && ch == view->lastConfigure.height) { + [view->impl->drawView setNeedsDisplay:YES]; + } else { + const NSRect rectPx = NSMakeRect(cx, cy, cw, ch); + + [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)]; + } return PUGL_SUCCESS; } @@ -4,6 +4,7 @@ #include "win.h" #include "internal.h" +#include "macros.h" #include "platform.h" #include "pugl/pugl.h" @@ -1042,7 +1043,7 @@ puglSetViewStyle(PuglView* const view, const PuglViewStyleFlags flags) const bool newMaximized = styleIsMaximized(flags); if (oldMaximized != newMaximized) { ShowWindow(impl->hwnd, newMaximized ? SW_SHOWMAXIMIZED : SW_RESTORE); - puglPostRedisplay(view); + puglObscureView(view); } return PUGL_SUCCESS; @@ -1209,20 +1210,29 @@ puglGetTime(const PuglWorld* world) } PuglStatus -puglPostRedisplay(PuglView* view) +puglObscureView(PuglView* view) { InvalidateRect(view->impl->hwnd, NULL, false); return PUGL_SUCCESS; } PuglStatus -puglPostRedisplayRect(PuglView* view, const PuglRect rect) +puglObscureRegion(PuglView* const view, + const int x, + const int y, + const unsigned width, + const unsigned height) { - const RECT r = {(long)floor(rect.x), - (long)floor(rect.y), - (long)ceil(rect.x + rect.width), - (long)ceil(rect.y + rect.height)}; + if (!puglIsValidPosition(x, y) || !puglIsValidSize(width, height)) { + return PUGL_BAD_PARAMETER; + } + const int cx = MAX(0, x); + const int cy = MAX(0, y); + const unsigned cw = MIN(view->lastConfigure.width, width); + const unsigned ch = MIN(view->lastConfigure.height, height); + + const RECT r = {cx, cy, cx + (long)cw, cy + (long)ch}; InvalidateRect(view->impl->hwnd, &r, false); return PUGL_SUCCESS; @@ -1576,42 +1586,18 @@ puglWinGetPixelFormatDescriptor(const PuglHints hints) return pfd; } -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 a bounding rect from the "nearest" parent or parent-like window - const HWND hwnd = puglWinGetWindow(view); - RECT rect = {0, 0, 0, 0}; - GetWindowRect(hwnd ? hwnd : GetDesktopWindow(), &rect); + RECT rect = {0, 0, 0, 0}; + GetWindowRect(view->transientParent ? (HWND)view->transientParent + : GetDesktopWindow(), + &rect); - // Center the frame around the center of the bounding rectangle - const LONG centerX = rect.left + (rect.right - rect.left) / 2; - const LONG centerY = rect.top + (rect.bottom - rect.top) / 2; - const PuglRect frame = {(PuglCoord)(centerX - (defaultWidth / 2)), - (PuglCoord)(centerY - (defaultHeight / 2)), - defaultWidth, - defaultHeight}; - return frame; + const PuglPoint center = { + (PuglCoord)(rect.left + (rect.right - rect.left) / 2), + (PuglCoord)(rect.top + (rect.bottom - rect.top) / 2)}; + return center; } PuglStatus @@ -1626,13 +1612,14 @@ puglWinCreateWindow(PuglView* const view, PuglNativeView parent = view->parent ? view->parent : view->transientParent; // Calculate initial window rectangle - const unsigned winFlags = puglWinGetWindowFlags(view); - const unsigned winExFlags = puglWinGetWindowExFlags(view); - const PuglRect frame = getInitialFrame(view); - RECT wr = {(long)frame.x, - (long)frame.y, - (long)frame.x + frame.width, - (long)frame.y + frame.height}; + const unsigned winFlags = puglWinGetWindowFlags(view); + const unsigned winExFlags = puglWinGetWindowExFlags(view); + const PuglArea size = puglGetInitialSize(view); + const PuglPoint pos = puglGetInitialPosition(view, size); + RECT wr = {(long)pos.x, + (long)pos.y, + (long)pos.x + size.width, + (long)pos.y + size.height}; AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags); ArgStringChar* const classNameArg = puglArgStringNew(className); @@ -510,48 +510,21 @@ clearX11Clipboard(PuglX11Clipboard* const board) board->data.len = 0; } -static PuglRect -getInitialFrame(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)); - - // Get the position/size of the parent as bounds for the new window - XWindowAttributes parentAttrs = PUGL_INIT_STRUCT; - XGetWindowAttributes(display, parent, &parentAttrs); +PuglPoint +puglGetAncestorCenter(const PuglView* const view) +{ + 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); - // 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 +579,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 +744,7 @@ puglShow(PuglView* const view, const PuglShowCommand command) } if (view->stage == PUGL_VIEW_STAGE_CONFIGURED) { - st = puglPostRedisplay(view); + st = puglObscureView(view); } } @@ -1099,17 +1073,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; + 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); @@ -1546,7 +1522,7 @@ 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 { @@ -1867,8 +1843,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 { @@ -1900,20 +1877,29 @@ puglGetTime(const PuglWorld* const world) } 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, 0, cx, cy, cw, ch}; if (view->world->impl->dispatchingEvents) { // Currently dispatching events, add/expand expose for the loop end |