diff options
| -rw-r--r-- | include/yasl/yasl.h | 9 | ||||
| -rw-r--r-- | src/common/surface.c | 8 | ||||
| -rw-r--r-- | tests/common/test_surface_integration.c | 31 |
3 files changed, 44 insertions, 4 deletions
diff --git a/include/yasl/yasl.h b/include/yasl/yasl.h index 931cf7f..d68bcc9 100644 --- a/include/yasl/yasl.h +++ b/include/yasl/yasl.h @@ -81,7 +81,10 @@ struct yasl_surface_options { void *userdata; /** Called when the window needs drawing while the system blocks the event * loop, as during a macOS live resize; draw and present before returning. - * REFRESH events cover every other case. Must not wait, create or destroy. */ + * REFRESH events cover every other case. Events stay queued meanwhile, so + * apply the size from yasl_surface_get_info, already current here; one + * WINDOW event reports the final size once the system's loop returns. + * Waiting, creating and destroying fail with EBUSY. */ void (*refresh)(yasl_surface *surface); struct yasl_gl_options gl; }; @@ -201,7 +204,9 @@ enum yasl_event_type { YASL_EVENT_CLOSE, /**< The user asked to close the window; destroy it to comply. */ YASL_EVENT_QUIT, /**< The system asked the app to quit; exit to comply. */ YASL_EVENT_REOPEN, /**< macOS: the app was activated with no window open. */ - YASL_EVENT_WINDOW, /**< window: size, scale or state changed. */ + YASL_EVENT_WINDOW, /**< window: size, scale or state changed. It reports the + * current geometry, so changes made since the last + * one fold into it. */ YASL_EVENT_REFRESH, /**< Draw now: once sized, after every resize, and on expose. */ YASL_EVENT_KEY, /**< key; action is a yasl_key_action. */ YASL_EVENT_TEXT, /**< text: typed text to insert. */ diff --git a/src/common/surface.c b/src/common/surface.c index 683bbaa..1dc30d1 100644 --- a/src/common/surface.c +++ b/src/common/surface.c @@ -814,8 +814,12 @@ static bool convert_event(const struct yasl_private_event *p, yasl_event *e) return p->surface && window_event(p->surface, p->surface->reported_size, p->surface->reported_scale_120, p->state.flags, e); case YASL_PRIVATE_EVENT_WINDOW_RESIZE: - return p->surface && window_event(p->surface, p->resize.geometry.size, - p->resize.geometry.scale_120, p->surface->reported_state, e); + /* The current geometry, not the queued one: resizes made while the + * application was away, as during a macOS live resize, fold into one + * event, and an application that applied yasl_surface_get_info in its + * refresh callback never steps back through older sizes. */ + return p->surface && window_event(p->surface, p->surface->size, p->surface->scale_120, + p->surface->reported_state, e); case YASL_PRIVATE_EVENT_KEY: e->type = YASL_EVENT_KEY; e->action = (unsigned)p->key.action; diff --git a/tests/common/test_surface_integration.c b/tests/common/test_surface_integration.c index 74c1574..662b26a 100644 --- a/tests/common/test_surface_integration.c +++ b/tests/common/test_surface_integration.c @@ -190,6 +190,18 @@ static void push(yasl_surface *s, struct yasl_private_event event) event.surface = s; assert(yasl_private_events_push(s->display, s, &event)); } +/* Drains the queue; returns how many WINDOW events came, each of this pixel size. */ +static int windows_of(int pixel_width, int pixel_height) +{ + yasl_event e; + int n = 0; + while (yasl_wait_event(&e, 0) > 0) + if (e.type == YASL_EVENT_WINDOW) { + assert(e.window.pixel_width == pixel_width && e.window.pixel_height == pixel_height); + n++; + } + return n; +} static int refreshes; /* Whether the display still lists the surface with this address; compared, never dereferenced. */ static bool listed(struct yasl_private_display *d, uintptr_t id) @@ -210,8 +222,11 @@ static void refresh(yasl_surface *s) assert(!yasl_surface_create(&options) && errno == EBUSY); options.type = YASL_SURFACE_GL; assert(!yasl_surface_create(&options) && errno == EBUSY); + /* The geometry being drawn is already current; its WINDOW event comes later. */ + struct yasl_surface_info info = yasl_surface_get_info(s); int w, h; assert(yasl_cpu_pixels(s, &w, &h) && yasl_cpu_present(s) == 0); + assert(w == info.pixel_width && h == info.pixel_height); } int main(int argc, char **argv) { @@ -415,6 +430,22 @@ int main(int argc, char **argv) #endif s->refresh = NULL; + /* WINDOW events report the current geometry: resizes queued while the + * application was away fold into one, and a size it already has reports + * nothing. */ + drain(); + struct yasl_private_geometry real = {s->size, s->scale_120}; + struct yasl_private_geometry wider = {{real.size.x + 8, real.size.y}, real.scale_120}; + struct yasl_private_geometry larger = {{real.size.x + 16, real.size.y + 8}, real.scale_120}; + yasl_private_surface_notify_configure(s, wider); + yasl_private_surface_notify_configure(s, larger); + assert(windows_of(larger.size.x, larger.size.y) == 1); + yasl_private_surface_notify_configure(s, wider); + yasl_private_surface_notify_configure(s, larger); + assert(windows_of(0, 0) == 0); + yasl_private_surface_notify_configure(s, real); + assert(windows_of(real.size.x, real.size.y) == 1); + /* Title and window requests: each either works or reports ENOTSUP. */ assert(yasl_surface_set_title(s, "CPU contract renamed") == 0); /* Weston configures a minimized fullscreen window at 0 x 0, then rejects |
