From fcddc7933dbff47754b8e4acea7406b77df1bf21 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 1 Apr 2020 19:35:58 +0200 Subject: Replace puglShowWindow() with puglRealize() --- doc/mainpage.md | 2 +- examples/pugl_cairo_demo.c | 5 +++-- examples/pugl_embed_demo.c | 7 +++++-- examples/pugl_gl3_demo.c | 3 ++- examples/pugl_print_events.c | 3 ++- examples/pugl_window_demo.c | 6 +++--- pugl/detail/mac.m | 29 +++++++++++++------------ pugl/detail/win.c | 18 ++++++++-------- pugl/detail/x11.c | 28 ++++++++++++++++++------- pugl/pugl.h | 50 +++++++++++++++++++++++++++++++------------- test/test_redisplay.c | 2 +- test/test_show_hide.c | 2 +- test/test_timer.c | 2 +- test/test_update.c | 2 +- 14 files changed, 101 insertions(+), 58 deletions(-) diff --git a/doc/mainpage.md b/doc/mainpage.md index d7a96fa..aa6f925 100644 --- a/doc/mainpage.md +++ b/doc/mainpage.md @@ -33,7 +33,7 @@ as well as a [stub](@ref stub) backend that creates a native window with no draw Once the view is configured, -it can be [created](@ref puglCreateWindow) and [shown](@ref puglShowWindow). +it can be [realized](@ref puglRealize) and [shown](@ref puglShowWindow). By default a view will correspond to a top-level system window. To create a view within another window, it must have a [parent window set](@ref puglSetParentWindow) before being created. diff --git a/examples/pugl_cairo_demo.c b/examples/pugl_cairo_demo.c index 6b43cb0..483446f 100644 --- a/examples/pugl_cairo_demo.c +++ b/examples/pugl_cairo_demo.c @@ -237,16 +237,17 @@ main(int argc, char** argv) PuglRect frame = { 0, 0, 512, 512 }; PuglView* view = puglNewView(app.world); + + puglSetWindowTitle(view, "Pugl Cairo Demo"); puglSetFrame(view, frame); puglSetMinSize(view, 256, 256); puglSetViewHint(view, PUGL_RESIZABLE, app.opts.resizable); puglSetHandle(view, &app); puglSetBackend(view, puglCairoBackend()); - puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, app.opts.ignoreKeyRepeat); puglSetEventFunc(view, onEvent); - PuglStatus st = puglCreateWindow(view, "Pugl Test"); + PuglStatus st = puglRealize(view); if (st) { return logError("Failed to create window (%s)\n", puglStrerror(st)); } diff --git a/examples/pugl_embed_demo.c b/examples/pugl_embed_demo.c index 313a92c..6152648 100644 --- a/examples/pugl_embed_demo.c +++ b/examples/pugl_embed_demo.c @@ -302,7 +302,10 @@ main(int argc, char** argv) PuglStatus st = PUGL_SUCCESS; const uint8_t title[] = { 'P', 'u', 'g', 'l', ' ', 'P', 'r', 0xC3, 0xBC, 'f', 'u', 'n', 'g', 0 }; - if ((st = puglCreateWindow(app.parent, (const char*)title))) { + + puglSetWindowTitle(app.parent, (const char*)title); + + if ((st = puglRealize(app.parent))) { return logError("Failed to create parent window (%s)\n", puglStrerror(st)); } @@ -319,7 +322,7 @@ main(int argc, char** argv) puglSetHandle(app.child, &app); puglSetEventFunc(app.child, onEvent); - if ((st = puglCreateWindow(app.child, NULL))) { + if ((st = puglRealize(app.child))) { return logError("Failed to create child window (%s)\n", puglStrerror(st)); } diff --git a/examples/pugl_gl3_demo.c b/examples/pugl_gl3_demo.c index 210d27f..3a9503c 100644 --- a/examples/pugl_gl3_demo.c +++ b/examples/pugl_gl3_demo.c @@ -271,6 +271,7 @@ setupPugl(PuglTestApp* app, const PuglRect frame) // Set up world and view puglSetClassName(app->world, "PuglGL3Demo"); + puglSetWindowTitle(app->view, "Pugl OpenGL 3"); puglSetFrame(app->view, frame); puglSetMinSize(app->view, defaultWidth / 4, defaultHeight / 4); puglSetAspectRatio(app->view, 1, 1, 16, 9); @@ -405,7 +406,7 @@ main(int argc, char** argv) setupPugl(&app, frame); // Create window (which will send a PUGL_CREATE event) - const PuglStatus st = puglCreateWindow(app.view, "Pugl OpenGL 3"); + const PuglStatus st = puglRealize(app.view); if (st) { return logError("Failed to create window (%s)\n", puglStrerror(st)); } diff --git a/examples/pugl_print_events.c b/examples/pugl_print_events.c index 9c81033..52b58c4 100644 --- a/examples/pugl_print_events.c +++ b/examples/pugl_print_events.c @@ -57,11 +57,12 @@ main(void) app.view = puglNewView(app.world); puglSetClassName(app.world, "Pugl Print Events"); + puglSetWindowTitle(app.view, "Pugl Event Printer"); puglSetBackend(app.view, puglStubBackend()); puglSetHandle(app.view, &app); puglSetEventFunc(app.view, onEvent); - if (puglCreateWindow(app.view, "Pugl Event Printer")) { + if (puglRealize(app.view)) { return logError("Failed to create window\n"); } diff --git a/examples/pugl_window_demo.c b/examples/pugl_window_demo.c index 7beb330..39f50c8 100644 --- a/examples/pugl_window_demo.c +++ b/examples/pugl_window_demo.c @@ -205,6 +205,7 @@ main(int argc, char** argv) cube->dist = 10; + puglSetWindowTitle(view, "Pugl Window Demo"); puglSetFrame(view, frame); puglSetMinSize(view, 128, 128); puglSetBackend(view, puglGlBackend()); @@ -218,9 +219,8 @@ main(int argc, char** argv) puglSetHandle(view, cube); puglSetEventFunc(view, onEvent); - if ((st = puglCreateWindow(view, "Pugl"))) { - return logError("Failed to create window window (%s)\n", - puglStrerror(st)); + if ((st = puglRealize(view))) { + return logError("Failed to create window (%s)\n", puglStrerror(st)); } puglShowWindow(view); diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m index f8ab084..43dca9e 100644 --- a/pugl/detail/mac.m +++ b/pugl/detail/mac.m @@ -753,7 +753,7 @@ puglConstraint(id item, NSLayoutAttribute attribute, float constant) } PuglStatus -puglCreateWindow(PuglView* view, const char* title) +puglRealize(PuglView* view) { PuglInternals* impl = view->impl; @@ -788,11 +788,6 @@ puglCreateWindow(PuglView* view, const char* title) [impl->drawView setHidden:NO]; [[impl->drawView window] makeFirstResponder:impl->wrapperView]; } else { - NSString* titleString = [[NSString alloc] - initWithBytes:title - length:strlen(title) - encoding:NSUTF8StringEncoding]; - const NSRect frame = rectToScreen( NSMakeRect(view->frame.x, view->frame.y, view->minWidth, view->minHeight)); @@ -811,13 +806,21 @@ puglCreateWindow(PuglView* view, const char* title) defer:NO ] retain]; [window setPuglview:view]; - [window setTitle:titleString]; + + if (view->title) { + NSString* titleString = [[NSString alloc] + initWithBytes:view->title + length:strlen(view->title) + encoding:NSUTF8StringEncoding]; + + [window setTitle:titleString]; + } + if (view->minWidth || view->minHeight) { [window setContentMinSize:NSMakeSize(view->minWidth, view->minHeight)]; } impl->window = window; - puglSetWindowTitle(view, title); ((NSWindow*)window).delegate = [[PuglWindowDelegate alloc] initWithPuglWindow:window]; @@ -1080,12 +1083,12 @@ puglSetWindowTitle(PuglView* view, const char* title) { puglSetString(&view->title, title); - NSString* titleString = [[NSString alloc] - initWithBytes:title - length:strlen(title) - encoding:NSUTF8StringEncoding]; - if (view->impl->window) { + NSString* titleString = [[NSString alloc] + initWithBytes:title + length:strlen(title) + encoding:NSUTF8StringEncoding]; + [view->impl->window setTitle:titleString]; } diff --git a/pugl/detail/win.c b/pugl/detail/win.c index 4606d60..6d8a99e 100644 --- a/pugl/detail/win.c +++ b/pugl/detail/win.c @@ -160,12 +160,10 @@ puglPollWinEvents(PuglWorld* world, const double timeout) } PuglStatus -puglCreateWindow(PuglView* view, const char* title) +puglRealize(PuglView* view) { PuglInternals* impl = view->impl; - title = title ? title : view->world->className; - // Get refresh rate for resize draw timer DEVMODEA devMode = {0}; EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devMode); @@ -187,8 +185,8 @@ puglCreateWindow(PuglView* view, const char* title) return PUGL_CREATE_CONTEXT_FAILED; } - if (title) { - puglSetWindowTitle(view, title); + if (view->title) { + puglSetWindowTitle(view, view->title); } puglSetFrame(view, view->frame); @@ -919,10 +917,12 @@ puglSetWindowTitle(PuglView* view, const char* title) { puglSetString(&view->title, title); - wchar_t* wtitle = puglUtf8ToWideChar(title); - if (wtitle) { - SetWindowTextW(view->impl->hwnd, wtitle); - free(wtitle); + if (view->impl->hwnd) { + wchar_t* wtitle = puglUtf8ToWideChar(title); + if (wtitle) { + SetWindowTextW(view->impl->hwnd, wtitle); + free(wtitle); + } } return PUGL_SUCCESS; diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c index 3f43a8f..59850c5 100644 --- a/pugl/detail/x11.c +++ b/pugl/detail/x11.c @@ -221,7 +221,7 @@ getSizeHints(const PuglView* view) } PuglStatus -puglCreateWindow(PuglView* view, const char* title) +puglRealize(PuglView* view) { PuglInternals* const impl = view->impl; PuglWorld* const world = view->world; @@ -268,8 +268,8 @@ puglCreateWindow(PuglView* view, const char* title) XClassHint classHint = { world->className, world->className }; XSetClassHint(display, win, &classHint); - if (title) { - puglSetWindowTitle(view, title); + if (view->title) { + puglSetWindowTitle(view, view->title); } if (!view->parent) { @@ -300,9 +300,18 @@ puglCreateWindow(PuglView* view, const char* title) PuglStatus puglShowWindow(PuglView* view) { + PuglStatus st = PUGL_SUCCESS; + + if (!view->impl->win) { + if ((st = puglRealize(view))) { + return st; + } + } + XMapRaised(view->impl->display, view->impl->win); puglPostRedisplay(view); - return PUGL_SUCCESS; + + return st; } PuglStatus @@ -1065,10 +1074,13 @@ puglSetWindowTitle(PuglView* view, const char* title) const PuglX11Atoms* const atoms = &view->world->impl->atoms; puglSetString(&view->title, title); - XStoreName(display, view->impl->win, title); - XChangeProperty(display, view->impl->win, atoms->NET_WM_NAME, - atoms->UTF8_STRING, 8, PropModeReplace, - (const uint8_t*)title, (int)strlen(title)); + + if (view->impl->win) { + XStoreName(display, view->impl->win, title); + XChangeProperty(display, view->impl->win, atoms->NET_WM_NAME, + atoms->UTF8_STRING, 8, PropModeReplace, + (const uint8_t*)title, (int)strlen(title)); + } return PUGL_SUCCESS; } diff --git a/pugl/pugl.h b/pugl/pugl.h index f1ddfdb..b09d883 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -776,7 +776,8 @@ typedef PuglStatus (*PuglEventFunc)(PuglView* view, const PuglEvent* event); Create a new view. A newly created view does not correspond to a real system view or window. - It must first be configured, then be realised by calling puglCreateWindow(). + It must first be configured, then the system view can be created with + puglRealize(). */ PUGL_API PuglView* puglNewView(PuglWorld* world); @@ -815,7 +816,7 @@ puglGetHandle(PuglView* view); Set the graphics backend to use for a view. This must be called once to set the graphics backend before calling - puglCreateWindow(). + puglRealize(). Pugl includes the following backends: @@ -839,7 +840,7 @@ puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc); /** Set a hint to configure window properties. - This only has an effect when called before puglCreateWindow(). + This only has an effect when called before puglRealize(). */ PUGL_API PuglStatus puglSetViewHint(PuglView* view, PuglViewHint hint, int value); @@ -872,8 +873,7 @@ puglSetFrame(PuglView* view, PuglRect frame); Set the minimum size of the view. If an initial minimum size is known, this should be called before - puglCreateWindow() to avoid stutter, though it can be called afterwards as - well. + puglRealize() to avoid stutter, though it can be called afterwards as well. */ PUGL_API PuglStatus puglSetMinSize(PuglView* view, int width, int height); @@ -889,8 +889,7 @@ puglSetMinSize(PuglView* view, int width, int height); ratio works properly across all platforms. If an initial aspect ratio is known, this should be called before - puglCreateWindow() to avoid stutter, though it can be called afterwards as - well. + puglRealize() to avoid stutter, though it can be called afterwards as well. */ PUGL_API PuglStatus puglSetAspectRatio(PuglView* view, int minX, int minY, int maxX, int maxY); @@ -915,7 +914,7 @@ puglSetWindowTitle(PuglView* view, const char* title); /** Set the parent window for embedding a view in an existing window. - This must be called before puglCreateWindow(), reparenting is not supported. + This must be called before puglRealize(), reparenting is not supported. */ PUGL_API PuglStatus puglSetParentWindow(PuglView* view, PuglNativeWindow parent); @@ -925,7 +924,7 @@ puglSetParentWindow(PuglView* view, PuglNativeWindow parent); Set this for transient children like dialogs, to have them properly associated with their parent window. This should be called before - puglCreateWindow(). + puglRealize(). */ PUGL_API PuglStatus puglSetTransientFor(PuglView* view, PuglNativeWindow parent); @@ -933,17 +932,25 @@ puglSetTransientFor(PuglView* view, PuglNativeWindow parent); /** Realise a view by creating a corresponding system view or window. + After this call, the (initially invisible) underlying system view exists and + can be accessed with puglGetNativeWindow(). There is currently no + corresponding unrealize function, the system view will be destroyed along + with the view when puglFreeView() is called. + The view should be fully configured using the above functions before this is called. This function may only be called once per view. */ PUGL_API PuglStatus -puglCreateWindow(PuglView* view, const char* title); +puglRealize(PuglView* view); /** - Show the current window. + Show the view. + + If the view has not yet been realized, the first call to this function will + do so automatically. - If the window is currently hidden, it will be shown and possibly raised to - the top depending on the platform. + If the view is currently hidden, it will be shown and possibly raised to the + top depending on the platform. */ PUGL_API PuglStatus puglShowWindow(PuglView* view); @@ -1135,7 +1142,7 @@ puglSendEvent(PuglView* view, const PuglEvent* event); Create a Pugl application and view. To create a window, call the various puglInit* functions as necessary, then - call puglCreateWindow(). + call puglRealize(). @deprecated Use puglNewApp() and puglNewView(). @@ -1302,6 +1309,21 @@ puglInitBackend(PuglView* view, const PuglBackend* backend) return (int)puglSetBackend(view, backend); } +/** + Realise a view by creating a corresponding system view or window. + + The view should be fully configured using the above functions before this is + called. This function may only be called once per view. + + @deprecated Use puglRealize(), or just show the view. +*/ +static inline PUGL_DEPRECATED_BY("puglRealize") PuglStatus +puglCreateWindow(PuglView* view, const char* title) +{ + puglSetWindowTitle(view, title); + return puglRealize(view); +} + /** Block and wait for an event to be ready. diff --git a/test/test_redisplay.c b/test/test_redisplay.c index 6ec5bb8..75006cb 100644 --- a/test/test_redisplay.c +++ b/test/test_redisplay.c @@ -107,7 +107,7 @@ main(int argc, char** argv) puglSetEventFunc(app.view, onEvent); // Create and show window - assert(!puglCreateWindow(app.view, "Pugl Test")); + assert(!puglRealize(app.view)); assert(!puglShowWindow(app.view)); while (app.state != EXPOSED) { assert(!puglUpdate(app.world, timeout)); diff --git a/test/test_show_hide.c b/test/test_show_hide.c index ed5ede7..cc2c972 100644 --- a/test/test_show_hide.c +++ b/test/test_show_hide.c @@ -117,7 +117,7 @@ main(int argc, char** argv) puglSetEventFunc(test.view, onEvent); // Create initially invisible window - assert(!puglCreateWindow(test.view, "Pugl Test")); + assert(!puglRealize(test.view)); assert(!puglGetVisible(test.view)); while (test.state < CREATED) { tick(test.world); diff --git a/test/test_timer.c b/test/test_timer.c index 11666ec..58d0652 100644 --- a/test/test_timer.c +++ b/test/test_timer.c @@ -111,7 +111,7 @@ main(int argc, char** argv) puglSetEventFunc(app.view, onEvent); // Create and show window - assert(!puglCreateWindow(app.view, "Pugl Test")); + assert(!puglRealize(app.view)); assert(!puglShowWindow(app.view)); while (app.state != EXPOSED) { assert(!puglUpdate(app.world, timeout)); diff --git a/test/test_update.c b/test/test_update.c index ada3da8..081fb9b 100644 --- a/test/test_update.c +++ b/test/test_update.c @@ -103,7 +103,7 @@ main(int argc, char** argv) puglSetEventFunc(app.view, onEvent); // Create and show window - assert(!puglCreateWindow(app.view, "Pugl Test")); + assert(!puglRealize(app.view)); assert(!puglShowWindow(app.view)); // Tick until an expose happens -- cgit v1.2.1