aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-03-09 21:49:53 +0100
committerDavid Robillard <d@drobilla.net>2020-03-09 21:49:53 +0100
commita7cb0cb1506792d6893556bc976822e254a89106 (patch)
treec6ea552a3fb0fbf711ecbfafc699030eda3f8158
parented301f0548438692269481096e6ef51c3ead01dc (diff)
Add create, destroy, map, and unmap events
These can be used to do things when a view is created or destroyed, in particular set up the GL context in a more controlled way. Map and unmap events are also added for when views are shown and hidden so application can react to this as well. Towards the deprecation of puglEnterContext() and puglLeaveContext(), which are prone to abuse. squash! Remove client event stuff
-rw-r--r--pugl/detail/implementation.c5
-rw-r--r--pugl/detail/mac.m39
-rw-r--r--pugl/detail/win.c13
-rw-r--r--pugl/detail/x11.c15
-rw-r--r--pugl/pugl.h10
-rw-r--r--test/test_utils.h8
6 files changed, 74 insertions, 16 deletions
diff --git a/pugl/detail/implementation.c b/pugl/detail/implementation.c
index e9e1ae9..5c3da62 100644
--- a/pugl/detail/implementation.c
+++ b/pugl/detail/implementation.c
@@ -159,6 +159,9 @@ puglNewView(PuglWorld* const world)
void
puglFreeView(PuglView* view)
{
+ const PuglEvent destroyEvent = {{PUGL_DESTROY, 0}};
+ puglDispatchEvent(view, &destroyEvent);
+
// Remove from world view list
PuglWorld* world = view->world;
for (size_t i = 0; i < world->numViews; ++i) {
@@ -309,6 +312,8 @@ puglDispatchEvent(PuglView* view, const PuglEvent* event)
switch (event->type) {
case PUGL_NOTHING:
break;
+ case PUGL_CREATE:
+ case PUGL_DESTROY:
case PUGL_CONFIGURE:
view->backend->enter(view, NULL);
view->eventFunc(view, event);
diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m
index da1ab35..c083919 100644
--- a/pugl/detail/mac.m
+++ b/pugl/detail/mac.m
@@ -98,6 +98,21 @@ updateViewRect(PuglView* view)
return YES;
}
+- (void) setIsVisible:(BOOL)flag
+{
+ if (flag && !puglview->visible) {
+ const PuglEvent map = {{PUGL_MAP, 0}};
+ puglview->eventFunc(puglview, &map);
+ } else if (!flag && puglview->visible) {
+ const PuglEvent unmap = {{PUGL_UNMAP, 0}};
+ puglview->eventFunc(puglview, &unmap);
+ }
+
+ puglview->visible = flag;
+
+ [super setIsVisible:flag];
+}
+
@end
@implementation PuglWrapperView
@@ -817,15 +832,32 @@ puglCreateWindow(PuglView* view, const char* title)
[impl->wrapperView updateTrackingAreas];
+ const PuglEvent createEvent = {{PUGL_CREATE, 0}};
+ puglDispatchEvent(view, &createEvent);
+
+ const PuglEventConfigure ev = {
+ PUGL_CONFIGURE,
+ 0,
+ view->frame.x,
+ view->frame.y,
+ view->frame.width,
+ view->frame.height,
+ };
+
+ puglDispatchEvent(view, (const PuglEvent*)&ev);
+
return 0;
}
PuglStatus
puglShowWindow(PuglView* view)
{
- [view->impl->window setIsVisible:YES];
- updateViewRect(view);
- view->visible = true;
+ if (![view->impl->window isVisible]) {
+ [view->impl->window setIsVisible:YES];
+ [view->impl->drawView setNeedsDisplay: YES];
+ updateViewRect(view);
+ }
+
return PUGL_SUCCESS;
}
@@ -833,7 +865,6 @@ PuglStatus
puglHideWindow(PuglView* view)
{
[view->impl->window setIsVisible:NO];
- view->visible = false;
return PUGL_SUCCESS;
}
diff --git a/pugl/detail/win.c b/pugl/detail/win.c
index b7f03a3..2e0cd96 100644
--- a/pugl/detail/win.c
+++ b/pugl/detail/win.c
@@ -193,6 +193,9 @@ puglCreateWindow(PuglView* view, const char* title)
puglSetFrame(view, view->frame);
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
+ const PuglEvent createEvent = {{PUGL_CREATE, 0}};
+ view->eventFunc(view, &createEvent);
+
return PUGL_SUCCESS;
}
@@ -203,7 +206,6 @@ puglShowWindow(PuglView* view)
ShowWindow(impl->hwnd, SW_SHOWNORMAL);
SetFocus(impl->hwnd);
- view->visible = true;
return PUGL_SUCCESS;
}
@@ -213,7 +215,6 @@ puglHideWindow(PuglView* view)
PuglInternals* impl = view->impl;
ShowWindow(impl->hwnd, SW_HIDE);
- view->visible = false;
return PUGL_SUCCESS;
}
@@ -554,9 +555,17 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam)
case WM_SHOWWINDOW:
if (wParam) {
handleConfigure(view, &event);
+ puglDispatchEvent(view, &event);
+ event.type = PUGL_NOTHING;
+
RedrawWindow(view->impl->hwnd, NULL, NULL,
RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_INTERNALPAINT);
}
+
+ if ((bool)wParam != view->visible) {
+ view->visible = wParam;
+ event.any.type = wParam ? PUGL_MAP : PUGL_UNMAP;
+ }
break;
case WM_SIZE:
handleConfigure(view, &event);
diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c
index cc77f29..d3e4195 100644
--- a/pugl/detail/x11.c
+++ b/pugl/detail/x11.c
@@ -254,6 +254,9 @@ puglCreateWindow(PuglView* view, const char* title)
fprintf(stderr, "warning: XCreateIC failed\n");
}
+ const PuglEvent createEvent = {{PUGL_CREATE, 0}};
+ puglDispatchEvent(view, &createEvent);
+
return PUGL_SUCCESS;
}
@@ -425,17 +428,11 @@ translateEvent(PuglView* view, XEvent xevent)
case VisibilityNotify:
view->visible = xevent.xvisibility.state != VisibilityFullyObscured;
break;
- case MapNotify: {
- XWindowAttributes attrs = {0};
- XGetWindowAttributes(view->impl->display, view->impl->win, &attrs);
- event.type = PUGL_CONFIGURE;
- event.configure.x = attrs.x;
- event.configure.y = attrs.y;
- event.configure.width = attrs.width;
- event.configure.height = attrs.height;
+ case MapNotify:
+ event.type = PUGL_MAP;
break;
- }
case UnmapNotify:
+ event.type = PUGL_UNMAP;
view->visible = false;
break;
case ConfigureNotify:
diff --git a/pugl/pugl.h b/pugl/pugl.h
index d14c086..04f5343 100644
--- a/pugl/pugl.h
+++ b/pugl/pugl.h
@@ -168,7 +168,11 @@ typedef enum {
PUGL_NOTHING, ///< No event
PUGL_BUTTON_PRESS, ///< Mouse button pressed, a #PuglEventButton
PUGL_BUTTON_RELEASE, ///< Mouse button released, a #PuglEventButton
- PUGL_CONFIGURE, ///< View moved and/or resized, a #PuglEventConfigure
+ PUGL_CREATE, ///< View created, a #PuglEventAny
+ PUGL_DESTROY, ///< View destroyed, a #PuglEventAny
+ PUGL_MAP, ///< View made visible, a #PuglEventAny
+ PUGL_UNMAP, ///< View made invisible, a #PuglEventAny
+ PUGL_CONFIGURE, ///< View moved/resized, a #PuglEventConfigure
PUGL_EXPOSE, ///< View must be drawn, a #PuglEventExpose
PUGL_CLOSE, ///< View will be closed, a #PuglEventAny
PUGL_KEY_PRESS, ///< Key pressed, a #PuglEventKey
@@ -390,6 +394,10 @@ typedef struct {
This is a union of all event types. The #type must be checked to determine
which fields are safe to access. A pointer to PuglEvent can either be cast
to the appropriate type, or the union members used.
+
+ The graphics system may only be accessed when handling certain events. The
+ graphics context is active for #PUGL_CREATE, #PUGL_DESTROY, #PUGL_CONFIGURE,
+ and #PUGL_EXPOSE, but only enabled for drawing for #PUGL_EXPOSE.
*/
typedef union {
PuglEventAny any; ///< Valid for all event types
diff --git a/test/test_utils.h b/test/test_utils.h
index 80d279b..aca3376 100644
--- a/test/test_utils.h
+++ b/test/test_utils.h
@@ -124,6 +124,14 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose)
if (verbose) {
switch (event->type) {
+ case PUGL_CREATE:
+ return fprintf(stderr, "%sCreate\n", prefix);
+ case PUGL_DESTROY:
+ return fprintf(stderr, "%sDestroy\n", prefix);
+ case PUGL_MAP:
+ return fprintf(stderr, "%sMap\n", prefix);
+ case PUGL_UNMAP:
+ return fprintf(stderr, "%sUnmap\n", prefix);
case PUGL_CONFIGURE:
return PRINT("%sConfigure " PFMT " " PFMT "\n",
prefix,