diff options
author | David Robillard <d@drobilla.net> | 2023-01-07 19:27:14 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-01-07 20:27:35 -0500 |
commit | 4ad8621ac1d94c8e9cf88f83c46a3a70cd91212b (patch) | |
tree | 63307cb14d43c7391b34f94ca0e532d8e9e01a09 /examples | |
parent | 677e13dcbb5b64ce85093b9ea5c14025964e35b9 (diff) | |
download | pugl-4ad8621ac1d94c8e9cf88f83c46a3a70cd91212b.tar.gz pugl-4ad8621ac1d94c8e9cf88f83c46a3a70cd91212b.tar.bz2 pugl-4ad8621ac1d94c8e9cf88f83c46a3a70cd91212b.zip |
Add support for special view types and styles
Diffstat (limited to 'examples')
-rw-r--r-- | examples/meson.build | 4 | ||||
-rw-r--r-- | examples/pugl_embed_demo.c | 3 | ||||
-rw-r--r-- | examples/pugl_management_demo.app/MacOS/meson.build | 11 | ||||
-rw-r--r-- | examples/pugl_management_demo.app/meson.build | 11 | ||||
-rw-r--r-- | examples/pugl_management_demo.c | 262 | ||||
-rw-r--r-- | examples/pugl_vulkan_cpp_demo.cpp | 3 |
6 files changed, 290 insertions, 4 deletions
diff --git a/examples/meson.build b/examples/meson.build index 70a2384..2b4e5f1 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -18,7 +18,8 @@ gl_examples = [ ] cairo_examples = [ - 'pugl_cairo_demo.c' + 'pugl_cairo_demo.c', + 'pugl_management_demo.c', ] vulkan_examples = [ @@ -89,6 +90,7 @@ if host_machine.system() == 'darwin' if cairo_dep.found() subdir('pugl_cairo_demo.app') + subdir('pugl_management_demo.app') endif if opengl_dep.found() diff --git a/examples/pugl_embed_demo.c b/examples/pugl_embed_demo.c index 94310a5..59d8e2b 100644 --- a/examples/pugl_embed_demo.c +++ b/examples/pugl_embed_demo.c @@ -319,7 +319,8 @@ main(int argc, char** argv) ++framesDrawn; if (!requestedAttention && thisTime > 5.0) { - puglRequestAttention(app.parent); + puglSetViewStyle( + app.parent, puglGetViewStyle(app.parent) | PUGL_VIEW_STYLE_DEMANDING); requestedAttention = true; } diff --git a/examples/pugl_management_demo.app/MacOS/meson.build b/examples/pugl_management_demo.app/MacOS/meson.build new file mode 100644 index 0000000..1ad7b21 --- /dev/null +++ b/examples/pugl_management_demo.app/MacOS/meson.build @@ -0,0 +1,11 @@ +# Copyright 2021-2023 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +executable( + 'pugl_management_demo', + ['../../pugl_management_demo.c'], + c_args: example_defines + example_c_args + cairo_args, + cpp_args: example_defines + example_cpp_args, + dependencies: [pugl_dep, cairo_backend_dep], + include_directories: include_directories('../../..'), +) diff --git a/examples/pugl_management_demo.app/meson.build b/examples/pugl_management_demo.app/meson.build new file mode 100644 index 0000000..380e38d --- /dev/null +++ b/examples/pugl_management_demo.app/meson.build @@ -0,0 +1,11 @@ +# Copyright 2021-2023 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: 0BSD OR ISC + +config = configuration_data() +config.set('NAME', 'pugl_management_demo') + +info_plist = configure_file(configuration: config, + input: files('../../resources/Info.plist.in'), + output: 'Info.plist') + +subdir('MacOS') diff --git a/examples/pugl_management_demo.c b/examples/pugl_management_demo.c new file mode 100644 index 0000000..6a62668 --- /dev/null +++ b/examples/pugl_management_demo.c @@ -0,0 +1,262 @@ +// Copyright 2012-2023 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC + +/* + A demonstration of window types, states, and management. +*/ + +#include "test/test_utils.h" + +#include "pugl/cairo.h" +#include "pugl/pugl.h" + +#include <cairo.h> + +#include <stdbool.h> +#include <stdio.h> + +typedef struct { + PuglView* view; + const char* label; +} LabeledView; + +typedef struct { + PuglWorld* world; + LabeledView mainView; + LabeledView dialogView; + bool quit; + bool verbose; +} DemoApp; + +static PuglStatus +onCommonEvent(PuglView* view, const PuglEvent* event); + +static PuglStatus +onMainEvent(PuglView* view, const PuglEvent* event); + +static PuglStatus +onExpose(PuglView* const view, const PuglExposeEvent* const event) +{ + PuglWorld* const world = puglGetWorld(view); + DemoApp* const app = (DemoApp*)puglGetWorldHandle(world); + const PuglRect frame = puglGetFrame(view); + const PuglViewStyleFlags style = puglGetViewStyle(view); + const PuglCoord cx = (PuglCoord)(frame.width / 2U); + const PuglCoord cy = (PuglCoord)(frame.height / 2U); + cairo_t* const cr = (cairo_t*)puglGetContext(view); + + // Clip to expose region + cairo_rectangle(cr, event->x, event->y, event->width, event->height); + cairo_clip_preserve(cr); + + // Draw background + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 4.0); + cairo_fill(cr); + + // Set up text renering + char buf[128] = {0}; + cairo_text_extents_t extents = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + cairo_set_font_size(cr, 32.0); + + // Draw time label + snprintf(buf, sizeof(buf), "Draw time: %g", puglGetTime(world)); + cairo_text_extents(cr, buf, &extents); + cairo_move_to(cr, cx - extents.width / 2.0, cy + extents.height / 2.0 - 48.0); + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_show_text(cr, buf); + + // Draw style label + snprintf(buf, + sizeof(buf), + "Style:%s%s%s%s%s%s%s%s%s", + style & PUGL_VIEW_STYLE_MODAL ? " modal" : "", + style & PUGL_VIEW_STYLE_TALL ? " tall" : "", + style & PUGL_VIEW_STYLE_WIDE ? " wide" : "", + style & PUGL_VIEW_STYLE_HIDDEN ? " hidden" : "", + style & PUGL_VIEW_STYLE_FULLSCREEN ? " fullscreen" : "", + style & PUGL_VIEW_STYLE_ABOVE ? " above" : "", + style & PUGL_VIEW_STYLE_BELOW ? " below" : "", + style & PUGL_VIEW_STYLE_DEMANDING ? " demanding" : "", + style & PUGL_VIEW_STYLE_RESIZING ? " resizing" : ""); + cairo_text_extents(cr, buf, &extents); + cairo_move_to(cr, cx - extents.width / 2.0, cy + extents.height / 2.0); + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_show_text(cr, buf); + + if (view == app->mainView.view) { + // Draw keyboard help label + snprintf(buf, sizeof(buf), "Keys: Space T W H M F A B D Q"); + cairo_text_extents(cr, buf, &extents); + cairo_move_to( + cr, cx - extents.width / 2.0, cy + extents.height / 2.0 + 48.0); + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_show_text(cr, buf); + } + + return PUGL_SUCCESS; +} + +static PuglStatus +toggleDialog(DemoApp* const app) +{ + if (app->dialogView.view && puglGetVisible(app->dialogView.view)) { + return puglUnrealize(app->dialogView.view); + } + + if (!app->dialogView.view) { + app->dialogView.view = puglNewView(app->world); + + puglSetBackend(app->dialogView.view, puglCairoBackend()); + puglSetEventFunc(app->dialogView.view, onCommonEvent); + puglSetHandle(app->dialogView.view, &app->dialogView); + puglSetTransientParent(app->dialogView.view, + puglGetNativeView(app->mainView.view)); + puglSetSizeHint(app->dialogView.view, PUGL_DEFAULT_SIZE, 320, 240); + puglSetSizeHint(app->dialogView.view, PUGL_MIN_SIZE, 160, 120); + puglSetViewHint(app->dialogView.view, PUGL_IGNORE_KEY_REPEAT, true); + puglSetViewHint(app->dialogView.view, PUGL_RESIZABLE, true); + puglSetViewHint( + app->dialogView.view, PUGL_VIEW_TYPE, PUGL_VIEW_TYPE_DIALOG); + puglSetWindowTitle(app->dialogView.view, "Dialog"); + } + + return puglShow(app->dialogView.view); +} + +static PuglStatus +onKeyPress(PuglView* view, const PuglKeyEvent* event) +{ + PuglWorld* const world = puglGetWorld(view); + DemoApp* const app = (DemoApp*)puglGetWorldHandle(world); + const PuglViewStyleFlags flags = puglGetViewStyle(view); + + switch (event->key) { + case ' ': + toggleDialog(app); + break; + case 't': + return puglSetViewStyle(view, flags ^ PUGL_VIEW_STYLE_TALL); + case 'w': + return puglSetViewStyle(view, flags ^ PUGL_VIEW_STYLE_WIDE); + case 'h': + return puglSetViewStyle(view, flags ^ PUGL_VIEW_STYLE_HIDDEN); + case 'm': + if ((flags & PUGL_VIEW_STYLE_TALL) && (flags & PUGL_VIEW_STYLE_WIDE)) { + return puglSetViewStyle( + view, flags & ~(PUGL_VIEW_STYLE_TALL | PUGL_VIEW_STYLE_WIDE)); + } + + return puglSetViewStyle( + view, flags | PUGL_VIEW_STYLE_TALL | PUGL_VIEW_STYLE_WIDE); + case 'f': + return puglSetViewStyle(view, flags ^ PUGL_VIEW_STYLE_FULLSCREEN); + case 'a': + return puglSetViewStyle(view, flags ^ PUGL_VIEW_STYLE_ABOVE); + case 'b': + return puglSetViewStyle(view, flags ^ PUGL_VIEW_STYLE_BELOW); + case 'd': + return puglSetViewStyle(view, flags ^ PUGL_VIEW_STYLE_DEMANDING); + case 'q': + case PUGL_KEY_ESCAPE: + app->quit = true; + break; + } + + return PUGL_SUCCESS; +} + +static PuglStatus +onCommonEvent(PuglView* view, const PuglEvent* const event) +{ + PuglWorld* const world = puglGetWorld(view); + DemoApp* const app = (DemoApp*)puglGetWorldHandle(world); + LabeledView* const data = (LabeledView*)puglGetHandle(view); + + const char* const prefix = data->label; + printEvent(event, prefix, app->verbose); + + switch (event->type) { + case PUGL_CLOSE: + if (view == app->dialogView.view) { + puglUnrealize(app->dialogView.view); + } + break; + case PUGL_CONFIGURE: + return puglPostRedisplay(view); + case PUGL_EXPOSE: + return onExpose(view, &event->expose); + case PUGL_KEY_PRESS: + return onKeyPress(view, &event->key); + default: + break; + } + + return PUGL_SUCCESS; +} + +static PuglStatus +onMainEvent(PuglView* view, const PuglEvent* const event) +{ + PuglWorld* const world = puglGetWorld(view); + DemoApp* const app = (DemoApp*)puglGetWorldHandle(world); + + switch (event->type) { + case PUGL_CLOSE: + app->quit = true; + return PUGL_SUCCESS; + default: + break; + } + + return onCommonEvent(view, event); +} + +int +main(int argc, char** argv) +{ + DemoApp app = {0}; + + const PuglTestOptions opts = puglParseTestOptions(&argc, &argv); + if (opts.help) { + puglPrintTestUsage(argv[0], ""); + return 1; + } + + app.verbose = opts.verbose; + + app.world = puglNewWorld(PUGL_PROGRAM, 0); + + puglSetWorldHandle(app.world, &app); + puglSetClassName(app.world, "PuglDemoApp"); + + app.mainView.view = puglNewView(app.world); + app.mainView.label = "Main: "; + app.dialogView.label = "Dialog: "; + + // Set up main view + puglSetBackend(app.mainView.view, puglCairoBackend()); + puglSetEventFunc(app.mainView.view, onMainEvent); + puglSetHandle(app.mainView.view, &app.mainView); + puglSetSizeHint(app.mainView.view, PUGL_DEFAULT_SIZE, 640, 480); + puglSetSizeHint(app.mainView.view, PUGL_MIN_SIZE, 320, 240); + puglSetViewHint(app.mainView.view, PUGL_IGNORE_KEY_REPEAT, true); + puglSetViewHint(app.mainView.view, PUGL_RESIZABLE, true); + puglSetViewHint(app.mainView.view, PUGL_VIEW_TYPE, PUGL_VIEW_TYPE_NORMAL); + puglSetWindowTitle(app.mainView.view, "Main Window"); + + PuglStatus st = PUGL_SUCCESS; + if ((st = puglRealize(app.mainView.view))) { + return logError("Failed to realize view (%s)\n", puglStrerror(st)); + } + + puglShow(app.mainView.view); + + while (!app.quit) { + puglUpdate(app.world, -1.0); + } + + puglFreeView(app.mainView.view); + puglFreeWorld(app.world); + return 0; +} diff --git a/examples/pugl_vulkan_cpp_demo.cpp b/examples/pugl_vulkan_cpp_demo.cpp index df0827e..487fab2 100644 --- a/examples/pugl_vulkan_cpp_demo.cpp +++ b/examples/pugl_vulkan_cpp_demo.cpp @@ -1475,6 +1475,7 @@ View::onEvent(const pugl::ConfigureEvent& event) _app.extent = {static_cast<uint32_t>(event.width), static_cast<uint32_t>(event.height)}; + _app.resizing = event.style & PUGL_VIEW_STYLE_RESIZING; return pugl::Status::success; } @@ -1640,7 +1641,6 @@ View::onEvent(const pugl::ExposeEvent&) pugl::Status View::onEvent(const pugl::LoopEnterEvent&) { - _app.resizing = true; startTimer(resizeTimerId, 1.0 / static_cast<double>(getHint(pugl::ViewHint::refreshRate))); @@ -1660,7 +1660,6 @@ View::onEvent(const pugl::LoopLeaveEvent&) // Trigger a swapchain recreation with the normal present mode _app.renderer.swapchain.extent = {}; - _app.resizing = false; return pugl::Status::success; } |