diff options
-rw-r--r-- | doc/conf.py.in | 1 | ||||
-rw-r--r-- | examples/pugl_cairo_demo.c | 8 | ||||
-rw-r--r-- | examples/pugl_cpp_demo.cpp | 4 | ||||
-rw-r--r-- | examples/pugl_embed_demo.c | 27 | ||||
-rw-r--r-- | examples/pugl_window_demo.c | 25 | ||||
-rw-r--r-- | include/pugl/pugl.h | 50 | ||||
-rw-r--r-- | src/mac.m | 23 | ||||
-rw-r--r-- | src/mac_cairo.m | 5 | ||||
-rw-r--r-- | src/win.c | 25 | ||||
-rw-r--r-- | src/x11.c | 50 | ||||
-rw-r--r-- | test/test_size.c | 20 | ||||
-rw-r--r-- | test/test_utils.h | 25 |
12 files changed, 147 insertions, 116 deletions
diff --git a/doc/conf.py.in b/doc/conf.py.in index b208553..1d5923a 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -24,6 +24,7 @@ _opaque = [ "VkInstance", "VkResult", "VkSurfaceKHR", + "int16_t", "size_t", "uint16_t", "uint32_t", diff --git a/examples/pugl_cairo_demo.c b/examples/pugl_cairo_demo.c index cf34158..c0e89c7 100644 --- a/examples/pugl_cairo_demo.c +++ b/examples/pugl_cairo_demo.c @@ -101,10 +101,10 @@ postButtonRedisplay(PuglView* view) for (const Button* b = buttons; b->label; ++b) { const double span = sqrt(b->w * b->w + b->h * b->h); - const PuglRect rect = {(b->x - span) * scaleX, - (b->y - span) * scaleY, - span * 2.0 * scaleX, - span * 2.0 * scaleY}; + const PuglRect rect = {(PuglCoord)((b->x - span) * scaleX), + (PuglCoord)((b->y - span) * scaleY), + (PuglSpan)ceil(span * 2.0 * scaleX), + (PuglSpan)ceil(span * 2.0 * scaleY)}; puglPostRedisplayRect(view, rect); } diff --git a/examples/pugl_cpp_demo.cpp b/examples/pugl_cpp_demo.cpp index 015e7aa..19b8065 100644 --- a/examples/pugl_cpp_demo.cpp +++ b/examples/pugl_cpp_demo.cpp @@ -57,8 +57,8 @@ CubeView::onEvent(const pugl::UpdateEvent&) noexcept // return postRedisplay(); // But for testing, use sendEvent() instead: - return sendEvent( - pugl::ExposeEvent{0u, 0.0, 0.0, frame().width, frame().height}); + return sendEvent(pugl::ExposeEvent{ + 0u, PuglCoord{0}, PuglCoord{0}, frame().width, frame().height}); } pugl::Status diff --git a/examples/pugl_embed_demo.c b/examples/pugl_embed_demo.c index 66605b7..ae3956a 100644 --- a/examples/pugl_embed_demo.c +++ b/examples/pugl_embed_demo.c @@ -14,7 +14,7 @@ #include <stdio.h> #include <string.h> -static const int borderWidth = 64; +static const uint8_t borderWidth = 64u; static const uintptr_t reverseTimerId = 1u; typedef struct { @@ -55,10 +55,11 @@ static const float backgroundColorVertices[] = { static PuglRect getChildFrame(const PuglRect parentFrame) { - const PuglRect childFrame = {borderWidth, - borderWidth, - parentFrame.width - 2 * borderWidth, - parentFrame.height - 2 * borderWidth}; + const PuglRect childFrame = { + borderWidth, + borderWidth, + (PuglSpan)(parentFrame.width - 2 * borderWidth), + (PuglSpan)(parentFrame.height - 2 * borderWidth)}; return childFrame; } @@ -118,26 +119,26 @@ onKeyPress(PuglView* view, const PuglKeyEvent* event, const char* prefix) fprintf(stderr, "%sPaste \"%s\"\n", prefix, text); } else if (event->state & PUGL_MOD_SHIFT) { if (event->key == PUGL_KEY_UP) { - frame.height += 10; + frame.height = (PuglSpan)(frame.height + 10u); } else if (event->key == PUGL_KEY_DOWN) { - frame.height -= 10; + frame.height = (PuglSpan)(frame.height - 10u); } else if (event->key == PUGL_KEY_LEFT) { - frame.width -= 10; + frame.width = (PuglSpan)(frame.width - 10u); } else if (event->key == PUGL_KEY_RIGHT) { - frame.width += 10; + frame.width = (PuglSpan)(frame.width + 10u); } else { return; } puglSetFrame(view, frame); } else { if (event->key == PUGL_KEY_UP) { - frame.y -= 10; + frame.y = (PuglCoord)(frame.y - 10); } else if (event->key == PUGL_KEY_DOWN) { - frame.y += 10; + frame.y = (PuglCoord)(frame.y + 10); } else if (event->key == PUGL_KEY_LEFT) { - frame.x -= 10; + frame.x = (PuglCoord)(frame.x - 10); } else if (event->key == PUGL_KEY_RIGHT) { - frame.x += 10; + frame.x = (PuglCoord)(frame.x + 10); } else { return; } diff --git a/examples/pugl_window_demo.c b/examples/pugl_window_demo.c index 7cb3722..8d79f00 100644 --- a/examples/pugl_window_demo.c +++ b/examples/pugl_window_demo.c @@ -14,6 +14,7 @@ #include <math.h> #include <stdbool.h> +#include <stdint.h> #include <string.h> typedef struct { @@ -35,7 +36,7 @@ typedef struct { bool verbose; } PuglTestApp; -static const double pad = 64.0; +static const uint8_t pad = 64u; static void onDisplay(PuglView* view) @@ -69,26 +70,26 @@ onKeyPress(PuglView* view, const PuglKeyEvent* event) app->quit = 1; } else if (event->state & PUGL_MOD_SHIFT) { if (event->key == PUGL_KEY_UP) { - frame.height += 10; + frame.height = (PuglSpan)(frame.height + 10u); } else if (event->key == PUGL_KEY_DOWN) { - frame.height -= 10; + frame.height = (PuglSpan)(frame.height - 10u); } else if (event->key == PUGL_KEY_LEFT) { - frame.width -= 10; + frame.width = (PuglSpan)(frame.width - 10u); } else if (event->key == PUGL_KEY_RIGHT) { - frame.width += 10; + frame.width = (PuglSpan)(frame.width + 10u); } else { return; } puglSetFrame(view, frame); } else { if (event->key == PUGL_KEY_UP) { - frame.y -= 10; + frame.y = (PuglCoord)(frame.y - 10); } else if (event->key == PUGL_KEY_DOWN) { - frame.y += 10; + frame.y = (PuglCoord)(frame.y + 10); } else if (event->key == PUGL_KEY_LEFT) { - frame.x -= 10; + frame.x = (PuglCoord)(frame.x - 10); } else if (event->key == PUGL_KEY_RIGHT) { - frame.x += 10; + frame.x = (PuglCoord)(frame.x + 10); } else { return; } @@ -187,8 +188,10 @@ main(int argc, char** argv) for (unsigned i = 0; i < 2; ++i) { CubeView* cube = &app.cubes[i]; PuglView* view = cube->view; - const PuglRect frame = { - pad + (128.0 + pad) * i, pad + (128.0 + pad) * i, 512.0, 512.0}; + const PuglRect frame = {(PuglCoord)(pad + (128.0 + pad) * i), + (PuglCoord)(pad + (128.0 + pad) * i), + 512u, + 512u}; cube->dist = 10; diff --git a/include/pugl/pugl.h b/include/pugl/pugl.h index 2c00a30..3fc124e 100644 --- a/include/pugl/pugl.h +++ b/include/pugl/pugl.h @@ -60,6 +60,18 @@ PUGL_BEGIN_DECLS */ /** + A pixel coordinate within/of a view. + + This is relative to the top left corner of the view's parent, or to the top + left corner of the view itself, depending on the context. + + There are platform-imposed limits on window positions. For portability, + applications should keep coordinates between -16000 and 16000. Note that + negative frame coordinates are possible, for example with multiple screens. +*/ +typedef int16_t PuglCoord; + +/** A pixel span (width or height) within/of a view. Due to platform limits, the span of a view in either dimension should be @@ -68,16 +80,20 @@ PUGL_BEGIN_DECLS typedef uint16_t PuglSpan; /** - A rectangle. + A rectangle in a view or on the screen. + + This type is used to describe two things: the position and size of a view + (for configuring), or a rectangle within a view (for exposing). - This is used to describe things like view position and size. Pugl generally - uses coordinates where the top left corner is 0,0. + The coordinate (0, 0) represents the top-left pixel of the parent window (or + display if there isn't one), or the top-left pixel of the view, + respectively. */ typedef struct { - double x; - double y; - double width; - double height; + PuglCoord x; + PuglCoord y; + PuglSpan width; + PuglSpan height; } PuglRect; /** @@ -267,10 +283,10 @@ typedef PuglAnyEvent PuglDestroyEvent; typedef struct { PuglEventType type; ///< #PUGL_CONFIGURE PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values - double x; ///< New parent-relative X coordinate - double y; ///< New parent-relative Y coordinate - double width; ///< New width - double height; ///< New height + PuglCoord x; ///< Parent-relative X coordinate of view + PuglCoord y; ///< Parent-relative Y coordinate of view + PuglSpan width; ///< Width of view + PuglSpan height; ///< Height of view } PuglConfigureEvent; /** @@ -313,10 +329,10 @@ typedef PuglAnyEvent PuglUpdateEvent; typedef struct { PuglEventType type; ///< #PUGL_EXPOSE PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values - double x; ///< View-relative X coordinate - double y; ///< View-relative Y coordinate - double width; ///< Width of exposed region - double height; ///< Height of exposed region + PuglCoord x; ///< View-relative top-left X coordinate of region + PuglCoord y; ///< View-relative top-left Y coordinate of region + PuglSpan width; ///< Width of exposed region + PuglSpan height; ///< Height of exposed region } PuglExposeEvent; /** @@ -1451,8 +1467,8 @@ puglInitWindowSize(PuglView* view, int width, int height) { PuglRect frame = puglGetFrame(view); - frame.width = width; - frame.height = height; + frame.width = (PuglSpan)width; + frame.height = (PuglSpan)height; puglSetFrame(view, frame); } @@ -97,10 +97,12 @@ updateViewRect(PuglView* view) const NSRect contentPx = nsRectFromPoints(view, contentPt); const double screenHeight = screenFramePx.size.height; - view->frame.x = contentPx.origin.x; - view->frame.y = screenHeight - contentPx.origin.y - contentPx.size.height; - view->frame.width = contentPx.size.width; - view->frame.height = contentPx.size.height; + view->frame.x = (PuglCoord)contentPx.origin.x; + view->frame.y = + (PuglCoord)(screenHeight - contentPx.origin.y - contentPx.size.height); + + view->frame.width = (PuglSpan)contentPx.size.width; + view->frame.height = (PuglSpan)contentPx.size.height; } } @@ -207,10 +209,10 @@ updateViewRect(PuglView* view) const PuglExposeEvent ev = { PUGL_EXPOSE, 0, - rect.origin.x * scaleFactor, - rect.origin.y * scaleFactor, - rect.size.width * scaleFactor, - rect.size.height * scaleFactor, + (PuglCoord)(rect.origin.x * scaleFactor), + (PuglCoord)(rect.origin.y * scaleFactor), + (PuglSpan)(rect.size.width * scaleFactor), + (PuglSpan)(rect.size.height * scaleFactor), }; PuglEvent exposeEvent; @@ -985,8 +987,9 @@ puglRealize(PuglView* view) view->frame.width = defaultSize.width; view->frame.height = defaultSize.height; - view->frame.x = screenWidthPx / 2.0 - view->frame.width / 2.0; - view->frame.y = screenHeightPx / 2.0 - view->frame.height / 2.0; + + view->frame.x = (PuglCoord)((screenWidthPx - view->frame.width) / 2.0); + view->frame.y = (PuglCoord)((screenHeightPx - view->frame.height) / 2.0); } const NSRect framePx = rectToNsRect(view->frame); diff --git a/src/mac_cairo.m b/src/mac_cairo.m index 33fc89a..e269955 100644 --- a/src/mac_cairo.m +++ b/src/mac_cairo.m @@ -89,7 +89,10 @@ puglMacCairoEnter(PuglView* view, const PuglExposeEvent* expose) const double scale = 1.0 / [[NSScreen mainScreen] backingScaleFactor]; CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - const CGSize sizePx = {view->frame.width, view->frame.height}; + + const CGSize sizePx = {(CGFloat)view->frame.width, + (CGFloat)view->frame.height}; + const CGSize sizePt = CGContextConvertSizeToUserSpace(context, sizePx); // Convert coordinates to standard Cairo space @@ -482,14 +482,14 @@ handleConfigure(PuglView* view, PuglEvent* event) const LONG width = rect.right - rect.left; const LONG height = rect.bottom - rect.top; - view->frame.x = rect.left; - view->frame.y = rect.top; + view->frame.x = (PuglCoord)rect.left; + view->frame.y = (PuglCoord)rect.top; event->configure.type = PUGL_CONFIGURE; - event->configure.x = view->frame.x; - event->configure.y = view->frame.y; - event->configure.width = width; - event->configure.height = height; + event->configure.x = (PuglCoord)view->frame.x; + event->configure.y = (PuglCoord)view->frame.y; + event->configure.width = (PuglSpan)width; + event->configure.height = (PuglSpan)height; return rect; } @@ -638,10 +638,10 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) case WM_PAINT: GetUpdateRect(view->impl->hwnd, &rect, false); event.expose.type = PUGL_EXPOSE; - event.expose.x = rect.left; - event.expose.y = rect.top; - event.expose.width = rect.right - rect.left; - event.expose.height = rect.bottom - rect.top; + event.expose.x = (PuglCoord)rect.left; + event.expose.y = (PuglCoord)rect.top; + event.expose.width = (PuglSpan)(rect.right - rect.left); + event.expose.height = (PuglSpan)(rect.bottom - rect.top); break; case WM_ERASEBKGND: return true; @@ -1200,8 +1200,9 @@ puglWinCreateWindow(PuglView* const view, view->frame.width = defaultSize.width; view->frame.height = defaultSize.height; - view->frame.x = (screenWidth - view->frame.width) / 2.0; - view->frame.y = (screenHeight - view->frame.height) / 2.0; + + view->frame.x = (PuglCoord)((screenWidth - view->frame.width) / 2); + view->frame.y = (PuglCoord)((screenHeight - view->frame.height) / 2); } // The meaning of "parent" depends on the window type (WS_CHILD) @@ -339,12 +339,12 @@ puglRealize(PuglView* const view) } // Center top-level windows if a position has not been set - if (!view->parent && view->frame.x <= 0.0 && view->frame.y <= 0.0) { + if (!view->parent && !view->frame.x && !view->frame.y) { const int screenWidth = DisplayWidth(display, screen); const int screenHeight = DisplayHeight(display, screen); - view->frame.x = screenWidth / 2.0 - view->frame.width / 2.0; - view->frame.y = screenHeight / 2.0 - view->frame.height / 2.0; + view->frame.x = (PuglCoord)((screenWidth - view->frame.width) / 2); + view->frame.y = (PuglCoord)((screenHeight - view->frame.height) / 2); } // Configure the backend to get the visual info @@ -374,10 +374,10 @@ puglRealize(PuglView* const view) // Create the window impl->win = XCreateWindow(display, parent, - (int)view->frame.x, - (int)view->frame.y, - (unsigned)view->frame.width, - (unsigned)view->frame.height, + view->frame.x, + view->frame.y, + view->frame.width, + view->frame.height, 0, impl->vi->depth, InputOutput, @@ -698,17 +698,17 @@ translateEvent(PuglView* const view, XEvent xevent) break; case ConfigureNotify: event.type = PUGL_CONFIGURE; - event.configure.x = xevent.xconfigure.x; - event.configure.y = xevent.xconfigure.y; - event.configure.width = xevent.xconfigure.width; - event.configure.height = xevent.xconfigure.height; + event.configure.x = (PuglCoord)xevent.xconfigure.x; + event.configure.y = (PuglCoord)xevent.xconfigure.y; + event.configure.width = (PuglSpan)xevent.xconfigure.width; + event.configure.height = (PuglSpan)xevent.xconfigure.height; break; case Expose: event.type = PUGL_EXPOSE; - event.expose.x = xevent.xexpose.x; - event.expose.y = xevent.xexpose.y; - event.expose.width = xevent.xexpose.width; - event.expose.height = xevent.xexpose.height; + event.expose.x = (PuglCoord)xevent.xexpose.x; + event.expose.y = (PuglCoord)xevent.xexpose.y; + event.expose.width = (PuglSpan)xevent.xexpose.width; + event.expose.height = (PuglSpan)xevent.xexpose.height; break; case MotionNotify: event.type = PUGL_MOTION; @@ -1031,8 +1031,8 @@ mergeExposeEvents(PuglExposeEvent* const dst, const PuglExposeEvent* const src) dst->x = MIN(dst->x, src->x); dst->y = MIN(dst->y, src->y); - dst->width = max_x - dst->x; - dst->height = max_y - dst->y; + dst->width = (PuglSpan)(max_x - dst->x); + dst->height = (PuglSpan)(max_y - dst->y); } } @@ -1240,10 +1240,10 @@ dispatchX11Events(PuglWorld* const world) // Build an initial configure event in case the WM doesn't send one PuglEvent configureEvent = {{PUGL_CONFIGURE, 0}}; - configureEvent.configure.x = (double)attrs.x; - configureEvent.configure.y = (double)attrs.y; - configureEvent.configure.width = (double)attrs.width; - configureEvent.configure.height = (double)attrs.height; + configureEvent.configure.x = (PuglCoord)attrs.x; + configureEvent.configure.y = (PuglCoord)attrs.y; + configureEvent.configure.width = (PuglSpan)attrs.width; + configureEvent.configure.height = (PuglSpan)attrs.height; // Dispatch an initial configure (if necessary), then the map event st0 = puglDispatchEvent(view, &configureEvent); @@ -1369,10 +1369,10 @@ puglSetFrame(PuglView* const view, const PuglRect frame) if (view->impl->win) { if (!XMoveResizeWindow(view->world->impl->display, view->impl->win, - (int)frame.x, - (int)frame.y, - (unsigned)frame.width, - (unsigned)frame.height)) { + frame.x, + frame.y, + frame.width, + frame.height)) { return PUGL_UNKNOWN_ERROR; } } diff --git a/test/test_size.c b/test/test_size.c index 048bfa5..9597a08 100644 --- a/test/test_size.c +++ b/test/test_size.c @@ -27,7 +27,7 @@ typedef struct { PuglView* view; PuglTestOptions opts; State state; - PuglRect configuredRect; + PuglRect configuredFrame; } PuglTest; static PuglStatus @@ -48,10 +48,10 @@ onEvent(PuglView* view, const PuglEvent* event) if (test->state == CREATED) { test->state = CONFIGURED; } - test->configuredRect.x = event->configure.x; - test->configuredRect.y = event->configure.y; - test->configuredRect.width = event->configure.width; - test->configuredRect.height = event->configure.height; + test->configuredFrame.x = event->configure.x; + test->configuredFrame.y = event->configure.y; + test->configuredFrame.width = event->configure.width; + test->configuredFrame.height = event->configure.height; break; case PUGL_MAP: test->state = MAPPED; @@ -77,7 +77,7 @@ main(int argc, char** argv) NULL, puglParseTestOptions(&argc, &argv), START, - {0.0, 0.0, 0.0, 0.0}}; + {0, 0, 0u, 0u}}; // Set up view with size bounds and an aspect ratio test.view = puglNewView(test.world); @@ -102,10 +102,10 @@ main(int argc, char** argv) // Check that the frame matches the last configure event const PuglRect frame = puglGetFrame(test.view); - assert(frame.x == test.configuredRect.x); - assert(frame.y == test.configuredRect.y); - assert(frame.width == test.configuredRect.width); - assert(frame.height == test.configuredRect.height); + assert(frame.x == test.configuredFrame.x); + assert(frame.y == test.configuredFrame.y); + assert(frame.width == test.configuredFrame.width); + assert(frame.height == test.configuredFrame.height); #if defined(_WIN32) || defined(__APPLE__) /* Some window managers on Linux (particularly tiling ones) just disregard diff --git a/test/test_utils.h b/test/test_utils.h index 0108435..2597537 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -92,8 +92,10 @@ scrollDirectionString(const PuglScrollDirection direction) static inline int printEvent(const PuglEvent* event, const char* prefix, const bool verbose) { -#define FFMT "%6.1f" -#define PFMT FFMT " " FFMT +#define PFFMT "%6.1f %6.1f" +#define PIFMT "%5d %5d" +#define PUFMT "%5u %5u" + #define PRINT(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) switch (event->type) { @@ -125,7 +127,7 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) event->text.string); case PUGL_BUTTON_PRESS: case PUGL_BUTTON_RELEASE: - return (PRINT("%sMouse %u %s at " PFMT " ", + return (PRINT("%sMouse %u %s at " PFFMT " ", prefix, event->button.button, (event->type == PUGL_BUTTON_PRESS) ? "down" : "up ", @@ -133,7 +135,7 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) event->button.y) + printModifiers(event->scroll.state)); case PUGL_SCROLL: - return (PRINT("%sScroll %5.1f %5.1f (%s) at " PFMT " ", + return (PRINT("%sScroll %5.1f %5.1f (%s) at " PFFMT " ", prefix, event->scroll.dx, event->scroll.dy, @@ -142,13 +144,13 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) event->scroll.y) + printModifiers(event->scroll.state)); case PUGL_POINTER_IN: - return PRINT("%sMouse enter at " PFMT " (%s)\n", + return PRINT("%sMouse enter at " PFFMT " (%s)\n", prefix, event->crossing.x, event->crossing.y, crossingModeString(event->crossing.mode)); case PUGL_POINTER_OUT: - return PRINT("%sMouse leave at " PFMT " (%s)\n", + return PRINT("%sMouse leave at " PFFMT " (%s)\n", prefix, event->crossing.x, event->crossing.y, @@ -177,14 +179,14 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) case PUGL_UPDATE: return fprintf(stderr, "%sUpdate\n", prefix); case PUGL_CONFIGURE: - return PRINT("%sConfigure " PFMT " " PFMT "\n", + return PRINT("%sConfigure " PIFMT " " PUFMT "\n", prefix, event->configure.x, event->configure.y, event->configure.width, event->configure.height); case PUGL_EXPOSE: - return PRINT("%sExpose " PFMT " " PFMT "\n", + return PRINT("%sExpose " PIFMT " " PUFMT "\n", prefix, event->expose.x, event->expose.y, @@ -193,7 +195,7 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) case PUGL_CLOSE: return PRINT("%sClose\n", prefix); case PUGL_MOTION: - return PRINT("%sMouse motion at " PFMT "\n", + return PRINT("%sMouse motion at " PFFMT "\n", prefix, event->motion.x, event->motion.y); @@ -205,8 +207,9 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) } #undef PRINT -#undef PFMT -#undef FFMT +#undef PUFMT +#undef PIFMT +#undef PFFMT return 0; } |