diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/.clang-tidy | 3 | ||||
-rw-r--r-- | src/common.c | 114 | ||||
-rw-r--r-- | src/internal.c | 84 | ||||
-rw-r--r-- | src/internal.h | 37 | ||||
-rw-r--r-- | src/mac.h | 2 | ||||
-rw-r--r-- | src/mac.m | 331 | ||||
-rw-r--r-- | src/mac_cairo.m | 2 | ||||
-rw-r--r-- | src/mac_gl.m | 2 | ||||
-rw-r--r-- | src/mac_stub.m | 2 | ||||
-rw-r--r-- | src/mac_vulkan.m | 6 | ||||
-rw-r--r-- | src/platform.h | 8 | ||||
-rw-r--r-- | src/stub.h | 2 | ||||
-rw-r--r-- | src/types.h | 33 | ||||
-rw-r--r-- | src/win.c | 492 | ||||
-rw-r--r-- | src/win.h | 21 | ||||
-rw-r--r-- | src/win_cairo.c | 2 | ||||
-rw-r--r-- | src/win_gl.c | 64 | ||||
-rw-r--r-- | src/win_stub.c | 2 | ||||
-rw-r--r-- | src/win_vulkan.c | 4 | ||||
-rw-r--r-- | src/x11.c | 309 | ||||
-rw-r--r-- | src/x11.h | 8 | ||||
-rw-r--r-- | src/x11_cairo.c | 18 | ||||
-rw-r--r-- | src/x11_gl.c | 10 | ||||
-rw-r--r-- | src/x11_stub.c | 4 | ||||
-rw-r--r-- | src/x11_vulkan.c | 4 |
25 files changed, 757 insertions, 807 deletions
diff --git a/src/.clang-tidy b/src/.clang-tidy index d57b1a8..cfc824d 100644 --- a/src/.clang-tidy +++ b/src/.clang-tidy @@ -1,8 +1,9 @@ -# Copyright 2020-2022 David Robillard <d@drobilla.net> +# Copyright 2020-2024 David Robillard <d@drobilla.net> # SPDX-License-Identifier: 0BSD OR ISC Checks: > -bugprone-easily-swappable-parameters, + -bugprone-multi-level-implicit-pointer-conversion, -hicpp-multiway-paths-covered, -hicpp-signed-bitwise, -llvm-header-guard, diff --git a/src/common.c b/src/common.c index 46b2f3d..c8ac3d4 100644 --- a/src/common.c +++ b/src/common.c @@ -4,13 +4,11 @@ // Common implementations of public API functions in the core library #include "internal.h" - #include "platform.h" #include "types.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> -#include <limits.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> @@ -106,27 +104,37 @@ puglGetWorldString(const PuglWorld* const world, const PuglStringHint key) } static void -puglSetDefaultHints(PuglHints hints) +puglSetDefaultHints(PuglView* const view) { - hints[PUGL_CONTEXT_API] = PUGL_OPENGL_API; - hints[PUGL_CONTEXT_VERSION_MAJOR] = 2; - hints[PUGL_CONTEXT_VERSION_MINOR] = 0; - hints[PUGL_CONTEXT_PROFILE] = PUGL_OPENGL_CORE_PROFILE; - hints[PUGL_CONTEXT_DEBUG] = PUGL_FALSE; - hints[PUGL_RED_BITS] = 8; - hints[PUGL_GREEN_BITS] = 8; - hints[PUGL_BLUE_BITS] = 8; - hints[PUGL_ALPHA_BITS] = 8; - hints[PUGL_DEPTH_BITS] = 0; - hints[PUGL_STENCIL_BITS] = 0; - hints[PUGL_SAMPLE_BUFFERS] = PUGL_DONT_CARE; - hints[PUGL_SAMPLES] = 0; - hints[PUGL_DOUBLE_BUFFER] = PUGL_TRUE; - hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE; - hints[PUGL_RESIZABLE] = PUGL_FALSE; - hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE; - hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE; - hints[PUGL_VIEW_TYPE] = PUGL_DONT_CARE; + view->hints[PUGL_CONTEXT_API] = PUGL_OPENGL_API; + view->hints[PUGL_CONTEXT_VERSION_MAJOR] = 2; + view->hints[PUGL_CONTEXT_VERSION_MINOR] = 0; + view->hints[PUGL_CONTEXT_PROFILE] = PUGL_OPENGL_CORE_PROFILE; + view->hints[PUGL_CONTEXT_DEBUG] = PUGL_FALSE; + view->hints[PUGL_RED_BITS] = 8; + view->hints[PUGL_GREEN_BITS] = 8; + view->hints[PUGL_BLUE_BITS] = 8; + view->hints[PUGL_ALPHA_BITS] = 8; + view->hints[PUGL_DEPTH_BITS] = 0; + view->hints[PUGL_STENCIL_BITS] = 0; + view->hints[PUGL_SAMPLE_BUFFERS] = PUGL_DONT_CARE; + view->hints[PUGL_SAMPLES] = 0; + view->hints[PUGL_DOUBLE_BUFFER] = PUGL_TRUE; + view->hints[PUGL_SWAP_INTERVAL] = PUGL_DONT_CARE; + view->hints[PUGL_RESIZABLE] = PUGL_FALSE; + view->hints[PUGL_IGNORE_KEY_REPEAT] = PUGL_FALSE; + view->hints[PUGL_REFRESH_RATE] = PUGL_DONT_CARE; + view->hints[PUGL_VIEW_TYPE] = PUGL_DONT_CARE; + + for (unsigned i = 0U; i < PUGL_NUM_POSITION_HINTS; ++i) { + view->positionHints[i].x = INT16_MIN; + view->positionHints[i].y = INT16_MIN; + } + + for (unsigned i = 0U; i < PUGL_NUM_SIZE_HINTS; ++i) { + view->sizeHints[i].width = 0U; + view->sizeHints[i].height = 0U; + } } PuglView* @@ -138,13 +146,8 @@ puglNewView(PuglWorld* const world) return NULL; } - view->world = world; - view->sizeHints[PUGL_MIN_SIZE].width = 1; - view->sizeHints[PUGL_MIN_SIZE].height = 1; - view->defaultX = INT_MIN; - view->defaultY = INT_MIN; - - puglSetDefaultHints(view->hints); + view->world = world; + puglSetDefaultHints(view); // Enlarge world view list const size_t newNumViews = world->numViews + 1U; @@ -287,43 +290,48 @@ puglGetViewString(const PuglView* const view, const PuglStringHint key) return view->strings[key]; } -PuglRect -puglGetFrame(const PuglView* view) +PuglPoint +puglGetPositionHint(const PuglView* const view, const PuglPositionHint hint) { - if (view->lastConfigure.type == PUGL_CONFIGURE) { - // Return the last configured frame - const PuglRect frame = {view->lastConfigure.x, - view->lastConfigure.y, - view->lastConfigure.width, - view->lastConfigure.height}; - return frame; + if (hint == PUGL_CURRENT_POSITION) { + PuglPoint pos = {0, 0}; + if (view->lastConfigure.type == PUGL_CONFIGURE) { + pos.x = view->lastConfigure.x; + pos.y = view->lastConfigure.y; + } else { + const PuglPoint defaultPos = view->positionHints[PUGL_DEFAULT_POSITION]; + if (puglIsValidPosition(defaultPos.x, defaultPos.y)) { + pos.x = defaultPos.x; + pos.y = defaultPos.y; + } + } + return pos; } - // Get the default position if set, or fallback to (0, 0) - int x = view->defaultX; - int y = view->defaultY; - if (x < INT16_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) { - x = 0; - y = 0; + return view->positionHints[hint]; +} + +PuglArea +puglGetSizeHint(const PuglView* const view, const PuglSizeHint hint) +{ + if (hint == PUGL_CURRENT_SIZE && view->lastConfigure.type == PUGL_CONFIGURE) { + const PuglArea area = {view->lastConfigure.width, + view->lastConfigure.height}; + return area; } - // Return the default frame, sanitized if necessary - const PuglRect frame = {(PuglCoord)x, - (PuglCoord)y, - view->sizeHints[PUGL_DEFAULT_SIZE].width, - view->sizeHints[PUGL_DEFAULT_SIZE].height}; - return frame; + return view->sizeHints[hint]; } PuglStatus -puglSetParentWindow(PuglView* view, PuglNativeView parent) +puglSetParent(PuglView* view, PuglNativeView parent) { view->parent = parent; return PUGL_SUCCESS; } PuglNativeView -puglGetParentWindow(const PuglView* const view) +puglGetParent(const PuglView* const view) { return view->parent; } diff --git a/src/internal.c b/src/internal.c index 3c4d304..ca84ed1 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5,19 +5,80 @@ #include "types.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> #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) +{ + // INT16_MIN is a sentinel, INT16_MAX is impossible with non-zero size + return x > INT16_MIN && x < INT16_MAX && y > INT16_MIN && y < INT16_MAX; +} + +bool +puglIsValidSize(const unsigned width, const unsigned height) +{ + return width && height && width <= INT16_MAX && height <= INT16_MAX; +} + bool -puglIsValidSize(const PuglViewSize size) +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); + } + + const PuglPoint defaultPos = view->positionHints[PUGL_DEFAULT_POSITION]; + if (puglIsValidPosition(defaultPos.x, defaultPos.y)) { + // Use the default position hint set by the application + return make_point(defaultPos.x, defaultPos.y); + } + + 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) { @@ -68,6 +129,21 @@ puglSetString(char** dest, const char* string) } } +PuglStatus +puglStoreSizeHint(PuglView* const view, + const PuglSizeHint hint, + const unsigned width, + const unsigned height) +{ + if (!puglIsValidSize(width, height)) { + return PUGL_BAD_PARAMETER; + } + + view->sizeHints[hint].width = (PuglSpan)width; + view->sizeHints[hint].height = (PuglSpan)height; + return PUGL_SUCCESS; +} + uint32_t puglDecodeUTF8(const uint8_t* buf) { @@ -159,7 +235,7 @@ puglPreRealize(PuglView* const view) } // Ensure that the default size is set to a valid size - if (!puglIsValidSize(view->sizeHints[PUGL_DEFAULT_SIZE])) { + if (!puglIsValidArea(view->sizeHints[PUGL_DEFAULT_SIZE])) { return PUGL_BAD_CONFIGURATION; } @@ -173,7 +249,7 @@ puglDispatchSimpleEvent(PuglView* view, const PuglEventType type) type == PUGL_UPDATE || type == PUGL_CLOSE || type == PUGL_LOOP_ENTER || type == PUGL_LOOP_LEAVE); - const PuglEvent event = {{type, 0}}; + const PuglEvent event = {{type, 0U}}; return puglDispatchEvent(view, &event); } diff --git a/src/internal.h b/src/internal.h index 3721c10..8678982 100644 --- a/src/internal.h +++ b/src/internal.h @@ -9,8 +9,8 @@ #include "attributes.h" #include "types.h" -#include "pugl/attributes.h" -#include "pugl/pugl.h" +#include <pugl/attributes.h> +#include <pugl/pugl.h> #include <stdbool.h> #include <stddef.h> @@ -18,9 +18,29 @@ PUGL_BEGIN_DECLS +/// Return true if `x`,`y` is a valid position +bool +puglIsValidPosition(int x, int y); + +/// Return true if `width`,`height` is a valid position +bool +puglIsValidSize(unsigned x, unsigned y); + /// Return true if `size` is a valid view size bool -puglIsValidSize(PuglViewSize size); +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 @@ -34,8 +54,14 @@ puglSetBlob(PuglBlob* dest, const void* data, size_t len); void puglSetString(char** dest, const char* string); +/// Store `width` and `height` as the current value of a size `hint` +PuglStatus +puglStoreSizeHint(PuglView* view, + PuglSizeHint hint, + unsigned width, + unsigned height); + /// Handle a changed string property -PUGL_API PuglStatus puglViewStringChanged(PuglView* view, PuglStringHint key, const char* value); @@ -56,8 +82,7 @@ PuglStatus puglDispatchSimpleEvent(PuglView* view, PuglEventType type); /// Process configure event while already in the graphics context -PUGL_WARN_UNUSED_RESULT -PuglStatus +PUGL_WARN_UNUSED_RESULT PuglStatus puglConfigure(PuglView* view, const PuglEvent* event); /// Dispatch `event` to `view`, entering graphics context if necessary @@ -5,7 +5,7 @@ #ifndef PUGL_SRC_MAC_H #define PUGL_SRC_MAC_H -#include "pugl/pugl.h" +#include <pugl/pugl.h> #import <Cocoa/Cocoa.h> @@ -7,9 +7,10 @@ #include "mac.h" #include "internal.h" +#include "macros.h" #include "platform.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> #import <Cocoa/Cocoa.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,21 +144,15 @@ 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]; return NSMakePoint(point.x * scaleFactor, point.y * scaleFactor); } -static NSRect -rectToNsRect(const PuglRect rect) -{ - return NSMakeRect(rect.x, rect.y, rect.width, rect.height); -} - static NSSize -sizePoints(PuglView* view, const double width, const double height) +sizePoints(PuglView* view, const PuglSpan width, const PuglSpan height) { const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -199,7 +194,7 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) const PuglConfigureEvent ev = { PUGL_CONFIGURE, - 0, + 0U, (PuglCoord)framePx.origin.x, (PuglCoord)framePx.origin.y, (PuglSpan)framePx.size.width, @@ -249,7 +244,7 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) const PuglConfigureEvent ev = { PUGL_CONFIGURE, - 0, + 0U, (PuglCoord)contentPx.origin.x, (PuglCoord)(screenHeight - contentPx.origin.y - contentPx.size.height), (PuglSpan)contentPx.size.width, @@ -326,11 +321,14 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) return; } + const double viewY = (double)puglview->lastConfigure.height - + ((rect.origin.y + rect.size.height) * scaleFactor); + const PuglExposeEvent ev = { PUGL_EXPOSE, - 0, + 0U, (PuglCoord)(rect.origin.x * scaleFactor), - (PuglCoord)(rect.origin.y * scaleFactor), + (PuglCoord)viewY, (PuglSpan)(rect.size.width * scaleFactor), (PuglSpan)(rect.size.height * scaleFactor), }; @@ -342,9 +340,9 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) - (NSSize)intrinsicContentSize { - const PuglViewSize defaultSize = puglview->sizeHints[PUGL_DEFAULT_SIZE]; + const PuglArea defaultSize = puglview->sizeHints[PUGL_DEFAULT_SIZE]; - return puglIsValidSize(defaultSize) + return puglIsValidArea(defaultSize) ? sizePoints(puglview, defaultSize.width, defaultSize.height) : NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric); } @@ -460,7 +458,7 @@ keySymToSpecial(const NSEvent* const ev) return PUGL_KEY_PAD_9; } - return (PuglKey)0; + return PUGL_KEY_NONE; } - (void)updateTrackingAreas @@ -493,7 +491,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const NSPoint rloc = [NSEvent mouseLocation]; const PuglCrossingEvent ev = { type, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -534,7 +532,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const NSPoint rloc = [NSEvent mouseLocation]; const PuglMotionEvent ev = { PUGL_MOTION, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -569,7 +567,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const NSPoint rloc = [NSEvent mouseLocation]; const PuglButtonEvent ev = { PUGL_BUTTON_PRESS, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -590,7 +588,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const NSPoint rloc = [NSEvent mouseLocation]; const PuglButtonEvent ev = { PUGL_BUTTON_RELEASE, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -627,10 +625,16 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) - (void)scrollWheel:(NSEvent*)event { - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const double dx = -[event scrollingDeltaX]; - const double dy = [event scrollingDeltaY]; + const NSPoint wloc = [self eventLocation:event]; + const NSPoint rloc = [NSEvent mouseLocation]; + + double dx = -[event scrollingDeltaX]; + double dy = [event scrollingDeltaY]; + if ([event hasPreciseScrollingDeltas]) { + dx /= 20.0; + dy /= 20.0; + } + const PuglScrollDirection dir = ((dx == 0.0 && dy > 0.0) ? PUGL_SCROLL_UP @@ -643,14 +647,14 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const PuglScrollEvent ev = { PUGL_SCROLL, - 0, + 0U, [event timestamp], wloc.x, wloc.y, rloc.x, [[NSScreen mainScreen] frame].size.height - rloc.y, getModifiers(event), - [event hasPreciseScrollingDeltas] ? PUGL_SCROLL_SMOOTH : dir, + dir, dx, dy, }; @@ -675,7 +679,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const PuglKeyEvent ev = { PUGL_KEY_PRESS, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -706,7 +710,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) const PuglKeyEvent ev = { PUGL_KEY_RELEASE, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -818,7 +822,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) PuglTextEvent ev = { PUGL_TEXT, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -847,7 +851,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) - (void)flagsChanged:(NSEvent*)event { const uint32_t mods = getModifiers(event); - PuglKey special = (PuglKey)0; + PuglKey special = PUGL_KEY_NONE; const uint16_t keyCode = [event keyCode]; if (flagDiffers(mods, puglview->impl->mods, PUGL_MOD_SHIFT)) { @@ -868,7 +872,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) const bool release = [event type] == NSEventTypeKeyUp; const PuglKeyEvent ev = {release ? PUGL_KEY_RELEASE : PUGL_KEY_PRESS, - 0, + 0U, [event timestamp], wloc.x, wloc.y, @@ -910,7 +914,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) - (void)timerTick:(NSTimer*)userTimer { const NSNumber* userInfo = userTimer.userInfo; - const PuglTimerEvent ev = {PUGL_TIMER, 0, userInfo.unsignedLongValue}; + const PuglTimerEvent ev = {PUGL_TIMER, 0U, userInfo.unsignedLongValue}; PuglEvent timerEvent; timerEvent.timer = ev; @@ -975,7 +979,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) { (void)notification; - PuglEvent ev = {{PUGL_FOCUS_IN, 0}}; + PuglEvent ev = {{PUGL_FOCUS_IN, 0U}}; ev.focus.mode = PUGL_CROSSING_NORMAL; puglDispatchEvent(window->puglview, &ev); } @@ -984,7 +988,7 @@ flagDiffers(const uint32_t lhs, const uint32_t rhs, const uint32_t mask) { (void)notification; - PuglEvent ev = {{PUGL_FOCUS_OUT, 0}}; + PuglEvent ev = {{PUGL_FOCUS_OUT, 0U}}; ev.focus.mode = PUGL_CROSSING_NORMAL; puglDispatchEvent(window->puglview, &ev); } @@ -1108,12 +1112,13 @@ updateSizeHint(PuglView* const view, const PuglSizeHint hint) { const PuglSpan width = view->sizeHints[hint].width; const PuglSpan height = view->sizeHints[hint].height; - if (!puglIsValidSize(view->sizeHints[hint])) { + if (!puglIsValidArea(view->sizeHints[hint])) { return PUGL_FAILURE; } switch (hint) { case PUGL_DEFAULT_SIZE: + case PUGL_CURRENT_SIZE: break; case PUGL_MIN_SIZE: @@ -1144,30 +1149,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 (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) { - // 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, @@ -1175,17 +1159,11 @@ getInitialFrame(PuglView* const view) ? [[(const NSView*)view->transientParent window] frame] : [screen frame]); - // Center the frame around the center of the bounding rectangle - const PuglViewSize 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 @@ -1233,11 +1211,12 @@ puglRealize(PuglView* view) CVDisplayLinkRelease(link); } - // Get the initial frame to use from the defaults or last configuration - const PuglRect initialFrame = getInitialFrame(view); + // Get the initial size and position from the defaults or last configuration + const PuglArea size = puglGetInitialSize(view); + const PuglPoint pos = puglGetInitialPosition(view, size); // Convert frame to points - const NSRect framePx = rectToNsRect(initialFrame); + const NSRect framePx = NSMakeRect(pos.x, pos.y, size.width, size.height); const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor, framePx.origin.y / scaleFactor, framePx.size.width / scaleFactor, @@ -1263,7 +1242,7 @@ puglRealize(PuglView* view) NSLayoutRelationGreaterThanOrEqual, view->sizeHints[PUGL_MIN_SIZE].height)]; - if (puglIsValidSize(view->sizeHints[PUGL_MAX_SIZE])) { + if (puglIsValidArea(view->sizeHints[PUGL_MAX_SIZE])) { [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView, NSLayoutAttributeWidth, @@ -1323,8 +1302,17 @@ puglRealize(PuglView* view) ((NSWindow*)window).delegate = [[PuglWindowDelegate alloc] initWithPuglWindow:window]; - // Set basic window hints and attributes - puglSetFrame(view, initialFrame); + // Set window frame + const NSRect screenPt = rectToScreen(screen, framePt); + const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; + [impl->window setFrame:winFrame display:NO]; + + // Resize views and move them to (0, 0) + const NSRect sizePx = {{0, 0}, {framePx.size.width, framePx.size.height}}; + const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; + [impl->wrapperView setFrame:sizePt]; + [impl->drawView setFrame:sizePt]; + puglSetTransientParent(view, view->transientParent); updateSizeHints(view); @@ -1596,14 +1584,6 @@ puglSendEvent(PuglView* view, const PuglEvent* event) return PUGL_UNSUPPORTED; } -#ifndef PUGL_DISABLE_DEPRECATED -PuglStatus -puglWaitForEvent(PuglView* view) -{ - return puglPollEvents(view->world, -1.0); -} -#endif - PuglStatus puglUpdate(PuglWorld* world, const double timeout) { @@ -1641,14 +1621,6 @@ puglUpdate(PuglWorld* world, const double timeout) return PUGL_SUCCESS; } -#ifndef PUGL_DISABLE_DEPRECATED -PuglStatus -puglProcessEvents(PuglView* view) -{ - return puglDispatchEvents(view->world); -} -#endif - double puglGetTime(const PuglWorld* world) { @@ -1660,22 +1632,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; + + 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)]; + [view->impl->drawView setNeedsDisplayInRect:nsRectToPoints(view, rectPx)]; + } return PUGL_SUCCESS; } @@ -1720,108 +1707,36 @@ puglGetScaleFactor(const PuglView* const view) return [viewScreen(view) backingScaleFactor]; } -PuglStatus -puglSetFrame(PuglView* view, const PuglRect frame) -{ - PuglInternals* const impl = view->impl; - const NSRect framePx = rectToNsRect(frame); - const NSRect framePt = nsRectToPoints(view, framePx); - - if (!impl->wrapperView) { - // Set defaults to be used when realized - view->defaultX = frame.x; - view->defaultY = frame.y; - view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)frame.width; - view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)frame.height; - return PUGL_SUCCESS; - } - - if (impl->window) { - const NSRect screenPt = rectToScreen(viewScreen(view), framePt); - - // Move and resize window to fit new content rect - const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; - [impl->window setFrame:winFrame display:NO]; - - // Resize views - const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height); - const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; - [impl->wrapperView setFrame:sizePt]; - [impl->drawView setFrame:sizePt]; - [impl->window dispatchCurrentConfiguration]; - return PUGL_SUCCESS; - } - - // Resize view - const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height); - const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx]; - - [impl->wrapperView setFrame:framePt]; - [impl->drawView setFrame:sizePt]; - return dispatchCurrentChildViewConfiguration(view); -} - -PuglStatus -puglSetPosition(PuglView* const view, const int x, const int y) +static PuglStatus +puglSetWindowPosition(PuglView* const view, const int x, const int y) { - if (x < INT16_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) { - return PUGL_BAD_PARAMETER; - } - PuglInternals* const impl = view->impl; - if (!impl->wrapperView) { - // Set defaults to be used when realized - view->defaultX = x; - view->defaultY = y; - return PUGL_SUCCESS; - } - const PuglRect frame = {(PuglCoord)x, - (PuglCoord)y, - view->lastConfigure.width, - view->lastConfigure.height}; + const NSRect framePx = + NSMakeRect(x, y, view->lastConfigure.width, view->lastConfigure.height); + + const NSRect framePt = nsRectToPoints(view, framePx); if (impl->window) { // Adjust top-level window frame - return puglSetFrame(view, frame); + const NSRect screenPt = rectToScreen(viewScreen(view), framePt); + [impl->window setFrameOrigin:screenPt.origin]; + return PUGL_SUCCESS; } // Set wrapper view origin - const NSRect framePx = rectToNsRect(frame); - const NSRect framePt = nsRectToPoints(view, framePx); [impl->wrapperView setFrameOrigin:framePt.origin]; - // Set draw view origin - const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height); - const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx]; - [impl->drawView setFrameOrigin:drawPt.origin]; - // Dispatch new configuration return dispatchCurrentChildViewConfiguration(view); } -PuglStatus -puglSetSize(PuglView* const view, const unsigned width, const unsigned height) +static PuglStatus +puglSetWindowSize(PuglView* const view, + const unsigned width, + const unsigned height) { - if (width > INT16_MAX || height > INT16_MAX) { - return PUGL_BAD_PARAMETER; - } - PuglInternals* const impl = view->impl; - if (!impl->wrapperView) { - // 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; - } - - if (impl->window) { - // Adjust top-level window frame - PuglRect frame = puglGetFrame(view); - frame.width = (PuglSpan)width; - frame.height = (PuglSpan)height; - return puglSetFrame(view, frame); - } // Set wrapper view size const double scaleFactor = [viewScreen(view) backingScaleFactor]; @@ -1833,24 +1748,50 @@ puglSetSize(PuglView* const view, const unsigned width, const unsigned height) const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx]; [impl->drawView setFrameSize:drawPt.size]; + if (impl->window) { + const NSRect framePx = + NSMakeRect(view->lastConfigure.x, view->lastConfigure.y, width, height); + const NSRect framePt = nsRectToPoints(view, framePx); + const NSRect screenPt = rectToScreen(viewScreen(view), framePt); + + // Resize window to fit new content rect + const NSRect winFrame = [impl->window frameRectForContentRect:screenPt]; + [impl->window setFrame:winFrame display:NO]; + [impl->window dispatchCurrentConfiguration]; + } + // Dispatch new configuration return dispatchCurrentChildViewConfiguration(view); } PuglStatus -puglSetSizeHint(PuglView* const view, - const PuglSizeHint hint, - const PuglSpan width, - const PuglSpan height) +puglSetPositionHint(PuglView* const view, + const PuglPositionHint hint, + const int x, + const int y) { - if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) { + if (x <= INT16_MIN || x > INT16_MAX || y <= INT16_MIN || y > INT16_MAX) { return PUGL_BAD_PARAMETER; } - view->sizeHints[hint].width = width; - view->sizeHints[hint].height = height; + view->positionHints[hint].x = (PuglCoord)x; + view->positionHints[hint].y = (PuglCoord)y; + + return (hint == PUGL_CURRENT_POSITION) ? puglSetWindowPosition(view, x, y) + : PUGL_SUCCESS; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const unsigned width, + const unsigned height) +{ + const PuglStatus st = puglStoreSizeHint(view, hint, width, height); - return view->impl->window ? updateSizeHint(view, hint) : PUGL_SUCCESS; + return st ? st + : (hint == PUGL_CURRENT_SIZE) ? puglSetWindowSize(view, width, height) + : updateSizeHint(view, hint); } PuglStatus @@ -1878,7 +1819,7 @@ puglPaste(PuglView* const view) { const PuglDataOfferEvent offer = { PUGL_DATA_OFFER, - 0, + 0U, puglGetTime(view->world), }; diff --git a/src/mac_cairo.m b/src/mac_cairo.m index e4d2f5f..112b727 100644 --- a/src/mac_cairo.m +++ b/src/mac_cairo.m @@ -5,7 +5,7 @@ #include "mac.h" #include "stub.h" -#include "pugl/cairo.h" +#include <pugl/cairo.h> #include <cairo-quartz.h> diff --git a/src/mac_gl.m b/src/mac_gl.m index f177bf9..57dfc41 100644 --- a/src/mac_gl.m +++ b/src/mac_gl.m @@ -5,7 +5,7 @@ #include "mac.h" #include "stub.h" -#include "pugl/gl.h" +#include <pugl/gl.h> #ifndef __MAC_10_10 # define NSOpenGLProfileVersion4_1Core NSOpenGLProfileVersion3_2Core diff --git a/src/mac_stub.m b/src/mac_stub.m index 9ebedca..c7e4512 100644 --- a/src/mac_stub.m +++ b/src/mac_stub.m @@ -5,7 +5,7 @@ #include "mac.h" #include "stub.h" -#include "pugl/stub.h" +#include <pugl/stub.h> #import <Cocoa/Cocoa.h> diff --git a/src/mac_vulkan.m b/src/mac_vulkan.m index 4fdbaf6..f3563e2 100644 --- a/src/mac_vulkan.m +++ b/src/mac_vulkan.m @@ -8,9 +8,9 @@ #include "stub.h" #include "types.h" -#include "pugl/pugl.h" -#include "pugl/stub.h" -#include "pugl/vulkan.h" +#include <pugl/pugl.h> +#include <pugl/stub.h> +#include <pugl/vulkan.h> #include <vulkan/vulkan_core.h> #include <vulkan/vulkan_macos.h> diff --git a/src/platform.h b/src/platform.h index cfdb1b7..e43a58e 100644 --- a/src/platform.h +++ b/src/platform.h @@ -8,13 +8,12 @@ #include "types.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> PUGL_BEGIN_DECLS /// Allocate and initialise world internals (implemented once per platform) -PUGL_MALLOC_FUNC -PuglWorldInternals* +PUGL_MALLOC_FUNC PuglWorldInternals* puglInitWorldInternals(PuglWorldType type, PuglWorldFlags flags); /// Destroy and free world internals (implemented once per platform) @@ -22,8 +21,7 @@ void puglFreeWorldInternals(PuglWorld* world); /// Allocate and initialise view internals (implemented once per platform) -PUGL_MALLOC_FUNC -PuglInternals* +PUGL_MALLOC_FUNC PuglInternals* puglInitViewInternals(PuglWorld* world); /// Destroy and free view internals (implemented once per platform) @@ -4,7 +4,7 @@ #ifndef PUGL_SRC_STUB_H #define PUGL_SRC_STUB_H -#include "pugl/pugl.h" +#include <pugl/pugl.h> #include <stddef.h> diff --git a/src/types.h b/src/types.h index 9817474..b453f11 100644 --- a/src/types.h +++ b/src/types.h @@ -6,7 +6,7 @@ #include "attributes.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> #include <stdbool.h> #include <stddef.h> @@ -21,18 +21,6 @@ typedef struct PuglInternalsImpl PuglInternals; /// View hints typedef int PuglHints[PUGL_NUM_VIEW_HINTS]; -/// View position (both X and Y coordinates) or general point -typedef struct { - PuglCoord x; - PuglCoord y; -} PuglPoint; - -/// View size (both X and Y coordinates) -typedef struct { - PuglSpan width; - PuglSpan height; -} PuglViewSize; - /// Blob of arbitrary data typedef struct { void* data; ///< Dynamically allocated data @@ -57,10 +45,9 @@ struct PuglViewImpl { uintptr_t transientParent; PuglConfigureEvent lastConfigure; PuglHints hints; - PuglViewSize sizeHints[PUGL_NUM_SIZE_HINTS]; + PuglPoint positionHints[PUGL_NUM_POSITION_HINTS]; + PuglArea sizeHints[PUGL_NUM_SIZE_HINTS]; char* strings[PUGL_NUM_STRING_HINTS]; - int defaultX; - int defaultY; PuglViewStage stage; bool resizing; }; @@ -82,23 +69,21 @@ typedef void PuglSurface; /// Graphics backend interface struct PuglBackendImpl { /// Get visual information from display and setup view as necessary - PUGL_WARN_UNUSED_RESULT - PuglStatus (*configure)(PuglView*); + PUGL_WARN_UNUSED_RESULT PuglStatus (*configure)(PuglView*); /// Create surface and drawing context - PUGL_WARN_UNUSED_RESULT - PuglStatus (*create)(PuglView*); + PUGL_WARN_UNUSED_RESULT PuglStatus (*create)(PuglView*); /// Destroy surface and drawing context void (*destroy)(PuglView*); /// Enter drawing context, for drawing if expose is non-null - PUGL_WARN_UNUSED_RESULT - PuglStatus (*enter)(PuglView*, const PuglExposeEvent*); + PUGL_WARN_UNUSED_RESULT PuglStatus (*enter)(PuglView*, + const PuglExposeEvent*); /// Leave drawing context, after drawing if expose is non-null - PUGL_WARN_UNUSED_RESULT - PuglStatus (*leave)(PuglView*, const PuglExposeEvent*); + PUGL_WARN_UNUSED_RESULT PuglStatus (*leave)(PuglView*, + const PuglExposeEvent*); /// Return the puglGetContext() handle for the application, if any void* (*getContext)(PuglView*); @@ -4,9 +4,10 @@ #include "win.h" #include "internal.h" +#include "macros.h" #include "platform.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> #include <dwmapi.h> #include <windows.h> @@ -43,12 +44,10 @@ #ifdef __cplusplus # define PUGL_INIT_STRUCT \ - {} -#else -# define PUGL_INIT_STRUCT \ { \ - 0 \ } +#else +# define PUGL_INIT_STRUCT {0} #endif typedef BOOL(WINAPI* PFN_SetProcessDPIAware)(void); @@ -58,8 +57,12 @@ typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*); LRESULT CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -static wchar_t* -puglUtf8ToWideChar(const char* const utf8) +#ifdef UNICODE + +typedef wchar_t ArgStringChar; + +static ArgStringChar* +puglArgStringNew(const char* const utf8) { const int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); if (len > 0) { @@ -71,6 +74,30 @@ puglUtf8ToWideChar(const char* const utf8) return NULL; } +static void +puglArgStringFree(ArgStringChar* const utf8) +{ + free(utf8); +} + +#else // !defined(UNICODE) + +typedef const char ArgStringChar; + +static ArgStringChar* +puglArgStringNew(const char* const utf8) +{ + return utf8; +} + +static void +puglArgStringFree(ArgStringChar* const utf8) +{ + (void)utf8; +} + +#endif + static char* puglWideCharToUtf8(const wchar_t* const wstr, size_t* len) { @@ -94,6 +121,8 @@ puglWinStatus(const BOOL success) static bool puglRegisterWindowClass(const char* name) { + ArgStringChar* const nameArg = puglArgStringNew(name); + HMODULE module = NULL; if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, @@ -103,7 +132,7 @@ puglRegisterWindowClass(const char* name) } WNDCLASSEX wc = PUGL_INIT_STRUCT; - if (GetClassInfoEx(module, name, &wc)) { + if (GetClassInfoEx(module, nameArg, &wc)) { return true; // Already registered } @@ -114,9 +143,11 @@ puglRegisterWindowClass(const char* name) wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - wc.lpszClassName = name; + wc.lpszClassName = nameArg; - return !!RegisterClassEx(&wc); + const bool success = !!RegisterClassEx(&wc); + puglArgStringFree(nameArg); + return success; } static unsigned @@ -174,7 +205,7 @@ static double puglWinGetViewScaleFactor(const PuglView* const view) { const HMODULE shcore = - LoadLibraryEx("Shcore.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + LoadLibraryEx(TEXT("Shcore.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); if (!shcore) { return 1.0; } @@ -209,7 +240,7 @@ puglInitWorldInternals(PuglWorldType type, PuglWorldFlags PUGL_UNUSED(flags)) if (type == PUGL_PROGRAM) { HMODULE user32 = - LoadLibraryEx("user32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + LoadLibraryEx(TEXT("user32.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); if (user32) { PFN_SetProcessDPIAware SetProcessDPIAware = (PFN_SetProcessDPIAware)GetProcAddress(user32, "SetProcessDPIAware"); @@ -240,20 +271,6 @@ puglInitViewInternals(PuglWorld* PUGL_UNUSED(world)) return (PuglInternals*)calloc(1, sizeof(PuglInternals)); } -static PuglStatus -puglPollWinEvents(PuglWorld* world, const double timeout) -{ - (void)world; - - if (timeout < 0) { - WaitMessage(); - } else { - MsgWaitForMultipleObjects( - 0, NULL, FALSE, (DWORD)(timeout * 1e3), QS_ALLEVENTS); - } - return PUGL_SUCCESS; -} - PuglStatus puglRealize(PuglView* view) { @@ -277,9 +294,9 @@ puglRealize(PuglView* view) puglEnsureHint(view, PUGL_ALPHA_BITS, 8); // Get refresh rate for resize draw timer - DEVMODEA devMode; + DEVMODE devMode; memset(&devMode, 0, sizeof(devMode)); - EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devMode); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode); view->hints[PUGL_REFRESH_RATE] = (int)devMode.dmDisplayFrequency; // Register window class if necessary @@ -298,16 +315,16 @@ puglRealize(PuglView* view) puglSetViewString(view, PUGL_WINDOW_TITLE, view->strings[PUGL_WINDOW_TITLE]); puglSetTransientParent(view, view->transientParent); - view->impl->scaleFactor = puglWinGetViewScaleFactor(view); - view->impl->cursor = LoadCursor(NULL, IDC_ARROW); + impl->scaleFactor = puglWinGetViewScaleFactor(view); + impl->cursor = LoadCursor(NULL, IDC_ARROW); if (view->hints[PUGL_DARK_FRAME]) { const BOOL useDarkMode = TRUE; - if ((DwmSetWindowAttribute(view->impl->hwnd, + if ((DwmSetWindowAttribute(impl->hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &useDarkMode, sizeof(useDarkMode)) != S_OK)) { - DwmSetWindowAttribute(view->impl->hwnd, + DwmSetWindowAttribute(impl->hwnd, PRE_20H1_DWMWA_USE_IMMERSIVE_DARK_MODE, &useDarkMode, sizeof(useDarkMode)); @@ -333,24 +350,22 @@ puglUnrealize(PuglView* const view) view->backend->destroy(view); } - ReleaseDC(view->impl->hwnd, view->impl->hdc); - view->impl->hdc = NULL; - - DestroyWindow(view->impl->hwnd); - view->impl->hwnd = NULL; - memset(&view->lastConfigure, 0, sizeof(PuglConfigureEvent)); - return PUGL_SUCCESS; + ReleaseDC(impl->hwnd, impl->hdc); + impl->hdc = NULL; + + const PuglStatus st = puglWinStatus(DestroyWindow(impl->hwnd)); + impl->hwnd = NULL; + return st; } PuglStatus puglShow(PuglView* view, const PuglShowCommand command) { PuglInternals* impl = view->impl; - + PuglStatus st = PUGL_SUCCESS; if (!impl->hwnd) { - const PuglStatus st = puglRealize(view); - if (st) { + if ((st = puglRealize(view))) { return st; } } @@ -369,15 +384,13 @@ puglShow(PuglView* view, const PuglShowCommand command) break; } - return PUGL_SUCCESS; + return st; } PuglStatus puglHide(PuglView* view) { - PuglInternals* impl = view->impl; - - ShowWindow(impl->hwnd, SW_HIDE); + ShowWindow(view->impl->hwnd, SW_HIDE); return PUGL_SUCCESS; } @@ -398,7 +411,11 @@ puglFreeViewInternals(PuglView* view) void puglFreeWorldInternals(PuglWorld* world) { - UnregisterClass(world->strings[PUGL_CLASS_NAME], NULL); + const char* const className = world->strings[PUGL_CLASS_NAME]; + ArgStringChar* const classNameArg = puglArgStringNew(className); + + UnregisterClass(classNameArg, NULL); + puglArgStringFree(classNameArg); free(world->impl); } @@ -409,14 +426,14 @@ keyInRange(const WPARAM winSym, const PuglKey puglMin) { return (winSym >= winMin && winSym <= winMax) - ? (PuglKey)(puglMin + (winSym - winMin)) - : (PuglKey)0; + ? (PuglKey)((WPARAM)puglMin + (winSym - winMin)) + : PUGL_KEY_NONE; } static PuglKey keySymToSpecial(const WPARAM sym, const bool ext) { - PuglKey key = (PuglKey)0; + PuglKey key = PUGL_KEY_NONE; if ((key = keyInRange(sym, VK_F1, VK_F12, PUGL_KEY_F1)) || (key = keyInRange(sym, VK_PRIOR, @@ -465,23 +482,26 @@ keySymToSpecial(const WPARAM sym, const bool ext) // clang-format on } - return (PuglKey)0; + return PUGL_KEY_NONE; +} + +static bool +is_toggled(int vkey) +{ + return (unsigned)GetKeyState(vkey) & 1U; } static uint32_t getModifiers(void) { - // clang-format off - return ( - ((GetKeyState(VK_SHIFT) < 0) ? (uint32_t)PUGL_MOD_SHIFT : 0U) | - ((GetKeyState(VK_CONTROL) < 0) ? (uint32_t)PUGL_MOD_CTRL : 0U) | - ((GetKeyState(VK_MENU) < 0) ? (uint32_t)PUGL_MOD_ALT : 0U) | - ((GetKeyState(VK_LWIN) < 0) ? (uint32_t)PUGL_MOD_SUPER : 0U) | - ((GetKeyState(VK_RWIN) < 0) ? (uint32_t)PUGL_MOD_SUPER : 0U) | - ((GetKeyState(VK_NUMLOCK) & 1U) ? (uint32_t)PUGL_MOD_NUM_LOCK : 0U) | - ((GetKeyState(VK_SCROLL) & 1U) ? (uint32_t)PUGL_MOD_SCROLL_LOCK : 0U) | - ((GetKeyState(VK_CAPITAL) & 1U) ? (uint32_t)PUGL_MOD_CAPS_LOCK : 0U)); - // clang-format on + return ((uint32_t)(((GetKeyState(VK_SHIFT) < 0) ? PUGL_MOD_SHIFT : 0) | + ((GetKeyState(VK_CONTROL) < 0) ? PUGL_MOD_CTRL : 0) | + ((GetKeyState(VK_MENU) < 0) ? PUGL_MOD_ALT : 0) | + ((GetKeyState(VK_LWIN) < 0) ? PUGL_MOD_SUPER : 0) | + ((GetKeyState(VK_RWIN) < 0) ? PUGL_MOD_SUPER : 0) | + (is_toggled(VK_NUMLOCK) ? PUGL_MOD_NUM_LOCK : 0) | + (is_toggled(VK_SCROLL) ? PUGL_MOD_SCROLL_LOCK : 0) | + (is_toggled(VK_CAPITAL) ? PUGL_MOD_CAPS_LOCK : 0))); } static void @@ -656,7 +676,7 @@ handleCrossing(PuglView* view, const PuglEventType type, POINT pos) const PuglCrossingEvent ev = { type, - 0, + 0U, GetMessageTime() / 1e3, (double)pos.x, (double)pos.y, @@ -666,7 +686,7 @@ handleCrossing(PuglView* view, const PuglEventType type, POINT pos) PUGL_CROSSING_NORMAL, }; - PuglEvent crossingEvent = {{type, 0}}; + PuglEvent crossingEvent = {{type, 0U}}; crossingEvent.crossing = ev; puglDispatchEvent(view, &crossingEvent); } @@ -676,8 +696,8 @@ constrainAspect(const PuglView* const view, RECT* const size, const WPARAM wParam) { - const PuglViewSize minAspect = view->sizeHints[PUGL_MIN_ASPECT]; - const PuglViewSize maxAspect = view->sizeHints[PUGL_MAX_ASPECT]; + const PuglArea minAspect = view->sizeHints[PUGL_MIN_ASPECT]; + const PuglArea maxAspect = view->sizeHints[PUGL_MAX_ASPECT]; const float minA = (float)minAspect.width / (float)minAspect.height; const float maxA = (float)maxAspect.width / (float)maxAspect.height; @@ -716,7 +736,7 @@ constrainAspect(const PuglView* const view, static LRESULT handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) { - PuglEvent event = {{PUGL_NOTHING, 0}}; + PuglEvent event = {{PUGL_NOTHING, 0U}}; RECT rect = {0, 0, 0, 0}; POINT pt = {0, 0}; MINMAXINFO* mmi = NULL; @@ -762,8 +782,8 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) handleConfigure(view, &event); break; case WM_SIZING: - if (puglIsValidSize(view->sizeHints[PUGL_MIN_ASPECT]) && - puglIsValidSize(view->sizeHints[PUGL_MAX_ASPECT])) { + if (puglIsValidArea(view->sizeHints[PUGL_MIN_ASPECT]) && + puglIsValidArea(view->sizeHints[PUGL_MAX_ASPECT])) { constrainAspect(view, (RECT*)lParam, wParam); return TRUE; } @@ -778,7 +798,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_TIMER: if (wParam >= PUGL_USER_TIMER_MIN) { - PuglEvent ev = {{PUGL_TIMER, 0}}; + PuglEvent ev = {{PUGL_TIMER, 0U}}; ev.timer.id = wParam - PUGL_USER_TIMER_MIN; puglDispatchEvent(view, &ev); } @@ -795,7 +815,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) mmi = (MINMAXINFO*)lParam; mmi->ptMinTrackSize.x = view->sizeHints[PUGL_MIN_SIZE].width; mmi->ptMinTrackSize.y = view->sizeHints[PUGL_MIN_SIZE].height; - if (puglIsValidSize(view->sizeHints[PUGL_MAX_SIZE])) { + if (puglIsValidArea(view->sizeHints[PUGL_MAX_SIZE])) { mmi->ptMaxTrackSize.x = view->sizeHints[PUGL_MAX_SIZE].width; mmi->ptMaxTrackSize.y = view->sizeHints[PUGL_MAX_SIZE].height; } @@ -931,8 +951,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) PuglStatus puglGrabFocus(PuglView* view) { - SetFocus(view->impl->hwnd); - return PUGL_SUCCESS; + return puglWinStatus(!!SetFocus(view->impl->hwnd)); } bool @@ -1006,7 +1025,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; @@ -1017,9 +1036,8 @@ puglStartTimer(PuglView* view, uintptr_t id, double timeout) { const UINT msec = (UINT)floor(timeout * 1000.0); - return (SetTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id, msec, NULL) - ? PUGL_SUCCESS - : PUGL_UNKNOWN_ERROR); + SetTimer(view->impl->hwnd, PUGL_USER_TIMER_MIN + id, msec, NULL); + return PUGL_SUCCESS; } PuglStatus @@ -1032,31 +1050,19 @@ PuglStatus puglSendEvent(PuglView* view, const PuglEvent* event) { if (event->type == PUGL_CLOSE) { - PostMessage(view->impl->hwnd, WM_CLOSE, 0, 0); - return PUGL_SUCCESS; + return puglWinStatus(PostMessage(view->impl->hwnd, WM_CLOSE, 0, 0)); } if (event->type == PUGL_CLIENT) { - PostMessage(view->impl->hwnd, - PUGL_LOCAL_CLIENT_MSG, - (WPARAM)event->client.data1, - (LPARAM)event->client.data2); - - return PUGL_SUCCESS; + return puglWinStatus(PostMessage(view->impl->hwnd, + PUGL_LOCAL_CLIENT_MSG, + (WPARAM)event->client.data1, + (LPARAM)event->client.data2)); } return PUGL_UNSUPPORTED; } -#ifndef PUGL_DISABLE_DEPRECATED -PuglStatus -puglWaitForEvent(PuglView* PUGL_UNUSED(view)) -{ - WaitMessage(); - return PUGL_SUCCESS; -} -#endif - static PuglStatus puglDispatchViewEvents(PuglView* view) { @@ -1101,21 +1107,24 @@ puglDispatchWinEvents(PuglWorld* world) PuglStatus puglUpdate(PuglWorld* world, double timeout) { + static const double minWaitSeconds = 0.002; + const double startTime = puglGetTime(world); PuglStatus st = PUGL_SUCCESS; if (timeout < 0.0) { - st = puglPollWinEvents(world, timeout); - st = st ? st : puglDispatchWinEvents(world); - } else if (timeout <= 0.001) { + WaitMessage(); + st = puglDispatchWinEvents(world); + } else if (timeout < minWaitSeconds) { st = puglDispatchWinEvents(world); } else { - const double endTime = startTime + timeout - 0.001; - for (double t = startTime; t < endTime; t = puglGetTime(world)) { - if ((st = puglPollWinEvents(world, endTime - t)) || - (st = puglDispatchWinEvents(world))) { - break; - } + const double endTime = startTime + timeout - minWaitSeconds; + double t = startTime; + while (!st && t < endTime) { + const DWORD timeoutMs = (DWORD)((endTime - t) * 1e3); + MsgWaitForMultipleObjects(0, NULL, FALSE, timeoutMs, QS_ALLEVENTS); + st = puglDispatchWinEvents(world); + t = puglGetTime(world); } } @@ -1130,14 +1139,6 @@ puglUpdate(PuglWorld* world, double timeout) return st; } -#ifndef PUGL_DISABLE_DEPRECATED -PuglStatus -puglProcessEvents(PuglView* view) -{ - return puglUpdate(view->world, 0.0); -} -#endif - LRESULT CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -1171,23 +1172,29 @@ puglGetTime(const PuglWorld* world) } PuglStatus -puglPostRedisplay(PuglView* view) +puglObscureView(PuglView* view) { - InvalidateRect(view->impl->hwnd, NULL, false); - return PUGL_SUCCESS; + return puglWinStatus(InvalidateRect(view->impl->hwnd, NULL, false)); } 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; + } - InvalidateRect(view->impl->hwnd, &r, false); + 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); - return PUGL_SUCCESS; + const RECT r = {cx, cy, cx + (long)cw, cy + (long)ch}; + return puglWinStatus(InvalidateRect(view->impl->hwnd, &r, false)); } PuglNativeView @@ -1201,19 +1208,18 @@ puglViewStringChanged(PuglView* const view, const PuglStringHint key, const char* const value) { + PuglStatus st = PUGL_SUCCESS; if (!view->impl->hwnd) { - return PUGL_SUCCESS; + return st; } if (key == PUGL_WINDOW_TITLE) { - wchar_t* const wtitle = puglUtf8ToWideChar(value); - if (wtitle) { - SetWindowTextW(view->impl->hwnd, wtitle); - free(wtitle); - } + ArgStringChar* const titleArg = puglArgStringNew(value); + st = puglWinStatus(SetWindowText(view->impl->hwnd, titleArg)); + puglArgStringFree(titleArg); } - return PUGL_SUCCESS; + return st; } static RECT @@ -1238,45 +1244,9 @@ puglGetScaleFactor(const PuglView* const view) : puglWinGetViewScaleFactor(view); } -PuglStatus -puglSetFrame(PuglView* view, const PuglRect frame) -{ - if (!view->impl->hwnd) { - // 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; - } - - const RECT rect = - adjustedWindowRect(view, frame.x, frame.y, frame.width, frame.height); - - return puglWinStatus( - SetWindowPos(view->impl->hwnd, - HWND_TOP, - rect.left, - rect.top, - rect.right - rect.left, - rect.bottom - rect.top, - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER)); -} - -PuglStatus -puglSetPosition(PuglView* const view, const int x, const int y) +static PuglStatus +puglSetWindowPosition(PuglView* const view, 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->hwnd) { - // Set defaults to be used when realized - view->defaultX = x; - view->defaultY = y; - return PUGL_SUCCESS; - } - const RECT rect = adjustedWindowRect( view, x, y, view->lastConfigure.width, view->lastConfigure.height); @@ -1287,20 +1257,11 @@ puglSetPosition(PuglView* const view, const int x, const int y) SetWindowPos(view->impl->hwnd, HWND_TOP, rect.left, rect.top, 0, 0, flags)); } -PuglStatus -puglSetSize(PuglView* const view, const unsigned width, const unsigned height) +static PuglStatus +puglSetWindowSize(PuglView* const view, + const unsigned width, + const unsigned height) { - if (width > INT16_MAX || height > INT16_MAX) { - return PUGL_BAD_PARAMETER; - } - - if (!view->impl->hwnd) { - // 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; - } - const RECT rect = adjustedWindowRect(view, view->lastConfigure.x, view->lastConfigure.y, @@ -1320,18 +1281,33 @@ puglSetSize(PuglView* const view, const unsigned width, const unsigned height) } PuglStatus -puglSetSizeHint(PuglView* const view, - const PuglSizeHint hint, - const PuglSpan width, - const PuglSpan height) +puglSetPositionHint(PuglView* const view, + const PuglPositionHint hint, + const int x, + const int y) { - if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) { + if (x <= INT16_MIN || x > INT16_MAX || y <= INT16_MIN || y > INT16_MAX) { return PUGL_BAD_PARAMETER; } - view->sizeHints[hint].width = width; - view->sizeHints[hint].height = height; - return PUGL_SUCCESS; + view->positionHints[hint].x = (PuglCoord)x; + view->positionHints[hint].y = (PuglCoord)y; + + return (hint == PUGL_CURRENT_POSITION) ? puglSetWindowPosition(view, x, y) + : PUGL_SUCCESS; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const unsigned width, + const unsigned height) +{ + const PuglStatus st = puglStoreSizeHint(view, hint, width, height); + + return (!st && hint == PUGL_CURRENT_SIZE) + ? puglSetWindowSize(view, width, height) + : st; } PuglStatus @@ -1377,15 +1353,14 @@ puglAcceptOffer(PuglView* const view, const PuglDataEvent data = { PUGL_DATA, - 0, + 0U, GetMessageTime() / 1e3, 0, }; PuglEvent dataEvent; dataEvent.data = data; - puglDispatchEvent(view, &dataEvent); - return PUGL_SUCCESS; + return puglDispatchEvent(view, &dataEvent); } const void* @@ -1395,8 +1370,21 @@ puglGetClipboard(PuglView* const view, { PuglInternals* const impl = view->impl; - if (typeIndex > 0U || !IsClipboardFormatAvailable(CF_UNICODETEXT) || - !OpenClipboard(impl->hwnd)) { + if (typeIndex > 0U || !IsClipboardFormatAvailable(CF_UNICODETEXT)) { + return NULL; + } + + // Try to open the clipboard several times since others may have locked it + BOOL opened = FALSE; + static const unsigned max_tries = 16U; + for (unsigned i = 0U; !opened && i < max_tries; ++i) { + opened = OpenClipboard(impl->hwnd); + if (!opened) { + Sleep(0); + } + } + + if (!opened) { return NULL; } @@ -1407,15 +1395,14 @@ puglGetClipboard(PuglView* const view, return NULL; } - free(view->impl->clipboard.data); - view->impl->clipboard.data = - puglWideCharToUtf8(wstr, &view->impl->clipboard.len); + free(impl->clipboard.data); + impl->clipboard.data = puglWideCharToUtf8(wstr, &impl->clipboard.len); GlobalUnlock(mem); CloseClipboard(); - *len = view->impl->clipboard.len; - return view->impl->clipboard.data; + *len = impl->clipboard.len; + return impl->clipboard.data; } PuglStatus @@ -1426,7 +1413,7 @@ puglSetClipboard(PuglView* const view, { PuglInternals* const impl = view->impl; - PuglStatus st = puglSetBlob(&view->impl->clipboard, data, len); + PuglStatus st = puglSetBlob(&impl->clipboard, data, len); if (st) { return st; } @@ -1471,17 +1458,16 @@ puglPaste(PuglView* const view) { const PuglDataOfferEvent offer = { PUGL_DATA_OFFER, - 0, + 0U, GetMessageTime() / 1e3, }; PuglEvent offerEvent; offerEvent.offer = offer; - puglDispatchEvent(view, &offerEvent); - return PUGL_SUCCESS; + return puglDispatchEvent(view, &offerEvent); } -static const char* const cursor_ids[] = { +static const TCHAR* const cursor_ids[] = { IDC_ARROW, // ARROW IDC_IBEAM, // CARET IDC_CROSS, // CROSSHAIR @@ -1546,42 +1532,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 (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) { - // 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 @@ -1596,28 +1558,35 @@ 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); + ArgStringChar* const titleArg = puglArgStringNew(title); + // Create window and get drawing context - if (!(*hwnd = CreateWindowEx(winExFlags, - className, - title, - winFlags, - wr.left, - wr.right, - wr.right - wr.left, - wr.bottom - wr.top, - (HWND)parent, - NULL, - NULL, - NULL))) { + *hwnd = CreateWindowEx(winExFlags, + classNameArg, + titleArg, + winFlags, + wr.left, + wr.right, + wr.right - wr.left, + wr.bottom - wr.top, + (HWND)parent, + NULL, + NULL, + NULL); + puglArgStringFree(titleArg); + puglArgStringFree(classNameArg); + if (!*hwnd) { return PUGL_REALIZE_FAILED; } @@ -1643,7 +1612,6 @@ puglWinConfigure(PuglView* view) { PuglInternals* const impl = view->impl; PuglStatus st = PUGL_SUCCESS; - if ((st = puglWinCreateWindow(view, "Pugl", &impl->hwnd, &impl->hdc))) { return st; } @@ -1656,20 +1624,18 @@ puglWinConfigure(PuglView* view) DestroyWindow(impl->hwnd); impl->hwnd = NULL; impl->hdc = NULL; - return PUGL_SET_FORMAT_FAILED; + st = PUGL_SET_FORMAT_FAILED; } - return PUGL_SUCCESS; + return st; } PuglStatus puglWinEnter(PuglView* view, const PuglExposeEvent* expose) { - if (expose) { - BeginPaint(view->impl->hwnd, &view->impl->paint); - } - - return PUGL_SUCCESS; + return expose + ? puglWinStatus(!!BeginPaint(view->impl->hwnd, &view->impl->paint)) + : PUGL_SUCCESS; } PuglStatus @@ -6,7 +6,7 @@ #include "internal.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> #include <windows.h> @@ -37,28 +37,19 @@ struct PuglInternalsImpl { bool fullscreen; }; -PUGL_API -PuglWinPFD +PUGL_API PuglWinPFD puglWinGetPixelFormatDescriptor(const PuglHints hints); -PUGL_WARN_UNUSED_RESULT -PUGL_API -PuglStatus +PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus puglWinCreateWindow(PuglView* view, const char* title, HWND* hwnd, HDC* hdc); -PUGL_WARN_UNUSED_RESULT -PUGL_API -PuglStatus +PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus puglWinConfigure(PuglView* view); -PUGL_WARN_UNUSED_RESULT -PUGL_API -PuglStatus +PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus puglWinEnter(PuglView* view, const PuglExposeEvent* expose); -PUGL_WARN_UNUSED_RESULT -PUGL_API -PuglStatus +PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus puglWinLeave(PuglView* view, const PuglExposeEvent* expose); #endif // PUGL_SRC_WIN_H diff --git a/src/win_cairo.c b/src/win_cairo.c index 0aab254..873d395 100644 --- a/src/win_cairo.c +++ b/src/win_cairo.c @@ -5,7 +5,7 @@ #include "types.h" #include "win.h" -#include "pugl/cairo.h" +#include <pugl/cairo.h> #include <cairo-win32.h> #include <cairo.h> diff --git a/src/win_gl.c b/src/win_gl.c index f707fc6..4f33e36 100644 --- a/src/win_gl.c +++ b/src/win_gl.c @@ -5,7 +5,7 @@ #include "types.h" #include "win.h" -#include "pugl/gl.h" +#include <pugl/gl.h> #include <windows.h> @@ -14,30 +14,42 @@ #include <stdbool.h> #include <stdlib.h> -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_ALPHA_BITS_ARB 0x201b -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_TYPE_RGBA_ARB 0x202b -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 - -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 - -#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 +typedef enum { + WGL_DRAW_TO_WINDOW_ARB = 0x2001, + WGL_ACCELERATION_ARB = 0x2003, + WGL_SUPPORT_OPENGL_ARB = 0x2010, + WGL_DOUBLE_BUFFER_ARB = 0x2011, + WGL_PIXEL_TYPE_ARB = 0x2013, + WGL_RED_BITS_ARB = 0x2015, + WGL_GREEN_BITS_ARB = 0x2017, + WGL_BLUE_BITS_ARB = 0x2019, + WGL_ALPHA_BITS_ARB = 0x201B, + WGL_DEPTH_BITS_ARB = 0x2022, + WGL_STENCIL_BITS_ARB = 0x2023, + WGL_SAMPLE_BUFFERS_ARB = 0x2041, + WGL_SAMPLES_ARB = 0x2042, +} PuglWinGlHintName; + +typedef enum { + WGL_FULL_ACCELERATION_ARB = 0x2027, + WGL_TYPE_RGBA_ARB = 0x202B, +} PuglWinGlHintValue; + +typedef enum { + WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091, + WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092, + WGL_CONTEXT_FLAGS_ARB = 0x2094, + WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126, +} PuglWinGlContextAttribName; + +typedef enum { + WGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001, + WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002, +} PuglWinGlContextProfileBit; + +typedef enum { + WGL_CONTEXT_DEBUG_BIT_ARB = 0x00000001, +} PuglWinGlContextDebugBit; typedef HGLRC(WINAPI* WglCreateContextAttribs)(HDC, HGLRC, const int*); @@ -288,7 +300,7 @@ puglGetProcAddress(const char* name) return func ? func - : (PuglGlFunc)GetProcAddress(GetModuleHandle("opengl32.dll"), name); + : (PuglGlFunc)GetProcAddress(GetModuleHandleA("opengl32.dll"), name); } PuglStatus diff --git a/src/win_stub.c b/src/win_stub.c index e98357c..d2dc3f3 100644 --- a/src/win_stub.c +++ b/src/win_stub.c @@ -5,7 +5,7 @@ #include "types.h" #include "win.h" -#include "pugl/stub.h" +#include <pugl/stub.h> static PuglStatus puglWinStubConfigure(PuglView* view) diff --git a/src/win_vulkan.c b/src/win_vulkan.c index 6d7c632..bd3bf45 100644 --- a/src/win_vulkan.c +++ b/src/win_vulkan.c @@ -7,7 +7,7 @@ #include "types.h" #include "win.h" -#include "pugl/vulkan.h" +#include <pugl/vulkan.h> #include <vulkan/vulkan.h> #include <vulkan/vulkan_win32.h> @@ -32,7 +32,7 @@ puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world), const char* const filename = libraryName ? libraryName : "vulkan-1.dll"; if (!(loader->libvulkan = - LoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS))) { + LoadLibraryExA(filename, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS))) { free(loader); return NULL; } @@ -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,12 +70,10 @@ #ifdef __cplusplus # define PUGL_INIT_STRUCT \ - {} -#else -# define PUGL_INIT_STRUCT \ { \ - 0 \ } +#else +# define PUGL_INIT_STRUCT {0} #endif enum WmClientStateMessageAction { @@ -407,39 +405,44 @@ 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 { - const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; - if (puglIsValidSize(defaultSize)) { + // Avoid setting PBaseSize for top level views to avoid window manager bugs + const PuglArea defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (puglIsValidArea(defaultSize) && view->parent) { sizeHints.flags |= PBaseSize; sizeHints.base_width = defaultSize.width; sizeHints.base_height = defaultSize.height; } - const PuglViewSize minSize = view->sizeHints[PUGL_MIN_SIZE]; - if (puglIsValidSize(minSize)) { + const PuglArea minSize = view->sizeHints[PUGL_MIN_SIZE]; + if (puglIsValidArea(minSize)) { sizeHints.flags |= PMinSize; sizeHints.min_width = minSize.width; sizeHints.min_height = minSize.height; } - const PuglViewSize maxSize = view->sizeHints[PUGL_MAX_SIZE]; - if (puglIsValidSize(maxSize)) { + const PuglArea maxSize = view->sizeHints[PUGL_MAX_SIZE]; + if (puglIsValidArea(maxSize)) { sizeHints.flags |= PMaxSize; sizeHints.max_width = maxSize.width; sizeHints.max_height = maxSize.height; } - const PuglViewSize minAspect = view->sizeHints[PUGL_MIN_ASPECT]; - const PuglViewSize maxAspect = view->sizeHints[PUGL_MAX_ASPECT]; - if (puglIsValidSize(minAspect) && puglIsValidSize(maxAspect)) { + const PuglArea minAspect = view->sizeHints[PUGL_MIN_ASPECT]; + const PuglArea maxAspect = view->sizeHints[PUGL_MAX_ASPECT]; + if (puglIsValidArea(minAspect) && puglIsValidArea(maxAspect)) { sizeHints.flags |= PAspect; sizeHints.min_aspect.x = minAspect.width; sizeHints.min_aspect.y = minAspect.height; @@ -447,8 +450,8 @@ updateSizeHints(const PuglView* const view) sizeHints.max_aspect.y = maxAspect.height; } - const PuglViewSize fixedAspect = view->sizeHints[PUGL_FIXED_ASPECT]; - if (puglIsValidSize(fixedAspect)) { + const PuglArea fixedAspect = view->sizeHints[PUGL_FIXED_ASPECT]; + if (puglIsValidArea(fixedAspect)) { sizeHints.flags |= PAspect; sizeHints.min_aspect.x = fixedAspect.width; sizeHints.min_aspect.y = fixedAspect.height; @@ -512,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 (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) { - // Use the default position set with puglSetPosition while unrealized - const PuglRect frame = { - (PuglCoord)x, (PuglCoord)y, defaultWidth, defaultHeight}; - return frame; - } + 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 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); - - // 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 @@ -608,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, @@ -649,7 +626,7 @@ puglRealize(PuglView* const view) if (XRRQueryExtension(display, &ignored, &ignored)) { // Set refresh rate hint to the real refresh rate XRRScreenConfiguration* conf = XRRGetScreenInfo(display, parent); - short current_rate = XRRConfigCurrentRate(conf); + const short current_rate = XRRConfigCurrentRate(conf); view->hints[PUGL_REFRESH_RATE] = current_rate; XRRFreeScreenConfigInfo(conf); @@ -772,7 +749,7 @@ puglShow(PuglView* const view, const PuglShowCommand command) } if (view->stage == PUGL_VIEW_STAGE_CONFIGURED) { - st = puglPostRedisplay(view); + st = puglObscureView(view); } } @@ -816,13 +793,13 @@ keyInRange(const KeySym xSym, const PuglKey puglMin) { return (xSym >= xMin && xSym <= xMax) ? (PuglKey)(puglMin + (xSym - xMin)) - : (PuglKey)0; + : PUGL_KEY_NONE; } static PuglKey keySymToSpecial(const KeySym sym) { - PuglKey key = (PuglKey)0; + PuglKey key = PUGL_KEY_NONE; if ((key = keyInRange(sym, XK_F1, XK_F12, PUGL_KEY_F1)) || (key = keyInRange(sym, XK_Page_Up, XK_End, PUGL_KEY_PAGE_UP)) || (key = keyInRange(sym, XK_Home, XK_Down, PUGL_KEY_HOME)) || @@ -855,7 +832,7 @@ keySymToSpecial(const KeySym sym) } // clang-format on - return (PuglKey)0; + return PUGL_KEY_NONE; } static int @@ -896,7 +873,8 @@ translateKey(PuglView* const view, XEvent* const xevent, PuglEvent* const event) event->key.key = (PuglKey)puglDecodeUTF8((const uint8_t*)ustr); } - if (xevent->type == KeyPress && !filter && !special && view->impl->xic) { + if (xevent->type == KeyPress && !filter && !(special && ufound <= 0) && + view->impl->xic) { // Lookup shifted key for possible text event xevent->xkey.state = state; @@ -1027,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]; @@ -1100,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); @@ -1139,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 @@ -1189,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) { @@ -1210,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; @@ -1533,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 { @@ -1611,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 @@ -1621,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; @@ -1698,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; @@ -1752,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); } @@ -1850,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) { @@ -1868,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 { @@ -1895,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); } @@ -1975,80 +1952,54 @@ 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 (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->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 (width > INT16_MAX || height > INT16_MAX) { +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 puglSetSizeHint(PuglView* const view, const PuglSizeHint hint, - const PuglSpan width, - const PuglSpan height) + const unsigned width, + const unsigned height) { - if ((unsigned)hint >= PUGL_NUM_SIZE_HINTS) { - return PUGL_BAD_PARAMETER; - } + const PuglStatus st = puglStoreSizeHint(view, hint, width, height); - view->sizeHints[hint].width = width; - view->sizeHints[hint].height = height; - return updateSizeHints(view); + return st ? st + : (hint == PUGL_CURRENT_SIZE) ? puglSetWindowSize(view, width, height) + : updateSizeHints(view); } PuglStatus @@ -2194,7 +2145,7 @@ puglSetCursor(PuglView* const view, const PuglCursor cursor) #else (void)view; (void)cursor; - return PUGL_FAILURE; + return PUGL_UNSUPPORTED; #endif } @@ -7,8 +7,8 @@ #include "attributes.h" #include "types.h" -#include "pugl/attributes.h" -#include "pugl/pugl.h" +#include <pugl/attributes.h> +#include <pugl/pugl.h> #include <X11/X.h> #include <X11/Xlib.h> @@ -93,9 +93,7 @@ struct PuglInternalsImpl { bool mapped; }; -PUGL_WARN_UNUSED_RESULT -PUGL_API -PuglStatus +PUGL_WARN_UNUSED_RESULT PUGL_API PuglStatus puglX11Configure(PuglView* view); #endif // PUGL_SRC_X11_H diff --git a/src/x11_cairo.c b/src/x11_cairo.c index d6fbaec..bc7b133 100644 --- a/src/x11_cairo.c +++ b/src/x11_cairo.c @@ -5,8 +5,8 @@ #include "types.h" #include "x11.h" -#include "pugl/cairo.h" -#include "pugl/pugl.h" +#include <pugl/cairo.h> +#include <pugl/pugl.h> #include <cairo-xlib.h> #include <cairo.h> @@ -19,10 +19,10 @@ typedef struct { cairo_t* cr; } PuglX11CairoSurface; -static PuglViewSize +static PuglArea puglX11CairoGetViewSize(const PuglView* const view) { - PuglViewSize size = {0U, 0U}; + PuglArea size = {0U, 0U}; if (view->lastConfigure.type == PUGL_CONFIGURE) { // Use the size of the last configured frame @@ -97,11 +97,11 @@ puglX11CairoEnter(PuglView* view, const PuglExposeEvent* expose) PuglStatus st = PUGL_SUCCESS; if (expose) { - const PuglViewSize viewSize = puglX11CairoGetViewSize(view); - const PuglSpan right = (PuglSpan)(expose->x + expose->width); - const PuglSpan bottom = (PuglSpan)(expose->y + expose->height); - const PuglSpan surfaceWidth = MAX(right, viewSize.width); - const PuglSpan surfaceHeight = MAX(bottom, viewSize.height); + const PuglArea viewSize = puglX11CairoGetViewSize(view); + const PuglSpan right = (PuglSpan)(expose->x + expose->width); + const PuglSpan bottom = (PuglSpan)(expose->y + expose->height); + const PuglSpan surfaceWidth = MAX(right, viewSize.width); + const PuglSpan surfaceHeight = MAX(bottom, viewSize.height); if (!(st = puglX11CairoOpen(view, surfaceWidth, surfaceHeight))) { surface->cr = cairo_create(surface->front); if (cairo_status(surface->cr)) { diff --git a/src/x11_gl.c b/src/x11_gl.c index de22b34..527335b 100644 --- a/src/x11_gl.c +++ b/src/x11_gl.c @@ -6,8 +6,8 @@ #include "types.h" #include "x11.h" -#include "pugl/gl.h" -#include "pugl/pugl.h" +#include <pugl/gl.h> +#include <pugl/pugl.h> #include <GL/glx.h> #include <X11/X.h> @@ -101,8 +101,7 @@ puglX11GlConfigure(PuglView* view) return PUGL_SUCCESS; } -PUGL_WARN_UNUSED_RESULT -static PuglStatus +PUGL_WARN_UNUSED_RESULT static PuglStatus puglX11GlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) { PuglX11GlSurface* surface = (PuglX11GlSurface*)view->impl->surface; @@ -115,8 +114,7 @@ puglX11GlEnter(PuglView* view, const PuglExposeEvent* PUGL_UNUSED(expose)) : PUGL_FAILURE; } -PUGL_WARN_UNUSED_RESULT -static PuglStatus +PUGL_WARN_UNUSED_RESULT static PuglStatus puglX11GlLeave(PuglView* view, const PuglExposeEvent* expose) { Display* const display = view->world->impl->display; diff --git a/src/x11_stub.c b/src/x11_stub.c index 844b4db..11143fe 100644 --- a/src/x11_stub.c +++ b/src/x11_stub.c @@ -1,13 +1,13 @@ // Copyright 2012-2021 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC -#include "pugl/stub.h" +#include <pugl/stub.h> #include "stub.h" #include "types.h" #include "x11.h" -#include "pugl/pugl.h" +#include <pugl/pugl.h> const PuglBackend* puglStubBackend(void) diff --git a/src/x11_vulkan.c b/src/x11_vulkan.c index 834ac37..078e524 100644 --- a/src/x11_vulkan.c +++ b/src/x11_vulkan.c @@ -8,8 +8,8 @@ #include "types.h" #include "x11.h" -#include "pugl/pugl.h" -#include "pugl/vulkan.h" +#include <pugl/pugl.h> +#include <pugl/vulkan.h> #include <vulkan/vulkan_core.h> #include <vulkan/vulkan_xlib.h> |