diff options
Diffstat (limited to 'src/platform/wayland/surface.c')
| -rw-r--r-- | src/platform/wayland/surface.c | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/src/platform/wayland/surface.c b/src/platform/wayland/surface.c index 2b72317..cc0c715 100644 --- a/src/platform/wayland/surface.c +++ b/src/platform/wayland/surface.c @@ -45,7 +45,7 @@ static void display_lose(struct wayland_display *c) return; c->lost = true; c->stale = true; - c->base.offline = true; + atomic_store(&c->base.offline, true); report_display_error(c); display_cancel_read(c); if (c->loop && c->watch > 0) @@ -195,6 +195,7 @@ void wayland_display_flush(struct wayland_display *c) c->depth++; for (struct wayland_surface *w = c->surfaces, *next; w; w = next) { next = w->conn_next; + surface_arm_deferred(w); surface_draw_frame(w); } if (!c->lost && c->wl) { @@ -290,6 +291,10 @@ static void display_rebuild(struct wayland_display *c) if (w->base.presenter == YASL_PRIVATE_PRESENTER_GL && !w->closed && !w->gl_built && !surface_build_gl(w)) surface_fail(w); #endif + /* Seats announced their pointers before these surfaces existed, so lock them now. */ + for (struct wayland_surface *w = c->surfaces; w && !c->lost; w = w->conn_next) + if (!w->closed && w->base.pointer_mode == YASL_PRIVATE_POINTER_RELATIVE) + surface_lock_preferred(w); for (struct wayland_surface *w = c->surfaces; w && !c->lost; w = w->conn_next) if (!w->closed) yasl_private_surface_notify_refresh(&w->base); } @@ -312,9 +317,11 @@ static uint64_t reconnect_tick(void *ud, yasl_private_timer_id id, uint64_t inte } c->reconnect_timer = 0; c->lost = false; - c->base.offline = false; yasl_private_display_notify_event(&c->base, YASL_PRIVATE_EVENT_DISPLAY_RESTORED); display_rebuild(c); + /* Windows exist again only after the rebuild; a loss during it stays offline. */ + if (!c->lost) + atomic_store(&c->base.offline, false); display_leave(c); return 0; } @@ -337,6 +344,7 @@ struct wayland_display *wayland_display_open(struct yasl_private_loop *loop, con { struct wayland_display *c = calloc(1, sizeof(*c)); if (!c) return NULL; + c->owner = pthread_self(); c->base.ops = &yasl_private_wayland_backend; if (!loop) { c->loop = yasl_private_loop_create(); @@ -499,6 +507,7 @@ void surface_release_native(struct wayland_surface *w) w->base.presenter = YASL_PRIVATE_PRESENTER_NONE; w->configured = w->has_pending_serial = w->has_shown = false; w->frame_active = w->want_draw = false; + atomic_store(&w->frame_deferred, false); w->outputs = 0; } @@ -520,10 +529,10 @@ struct wayland_surface *wayland_surface_create_toplevel(struct wayland_display * w->base.presenter = (spec->external_gpu && !(spec->flags & YASL_PRIVATE_SURFACE_CPU)) ? YASL_PRIVATE_PRESENTER_NONE : YASL_PRIVATE_PRESENTER_CPU; wayland_surface_set_callbacks(w, NULL, NULL); - wayland_surface_set_title(w, spec->title ? spec->title : "yasl_private_app"); + wayland_surface_set_title(w, spec->title ? spec->title : "YASL"); w->cursor = YASL_PRIVATE_CURSOR_TEXT; - w->req_width = width; - w->req_height = height; + w->floating_width = width; + w->floating_height = height; w->logical_width = width; w->logical_height = height; w->scale_120 = YASL_PRIVATE_SCALE_UNIT; @@ -613,31 +622,55 @@ void wayland_surface_set_background_color(struct wayland_surface *w, uint32_t bg (void)w; (void)bg; } +/* The serial of the press a window request cites; it must still be held. */ +static uint32_t held_press_serial(struct wayland_surface *s, struct seat **seat) +{ + *seat = s->conn->active_seat ? s->conn->active_seat : s->conn->seats; + uint32_t serial = seat_held_press_serial(*seat); + if (!serial || !(*seat)->proxy) { + errno = ESTALE; + return 0; + } + return serial; +} + bool wayland_surface_start_interactive_move(struct wayland_surface *s) { - if (!s || !s->toplevel || !s->conn) return false; - struct seat *seat = s->conn->active_seat ? s->conn->active_seat : s->conn->seats; - if (!seat || !seat->proxy || !seat->press_serial) return false; - xdg_toplevel_move(s->toplevel, seat->proxy, seat->press_serial); + if (!s || !s->toplevel || !s->conn) { + errno = EINVAL; + return false; + } + struct seat *seat; + uint32_t serial = held_press_serial(s, &seat); + if (!serial) return false; + xdg_toplevel_move(s->toplevel, seat->proxy, serial); return true; } bool wayland_surface_start_interactive_resize(struct wayland_surface *s, enum yasl_private_resize_edge edge) { - if (!s || !s->toplevel || !s->conn || edge == YASL_PRIVATE_EDGE_NONE) return false; - struct seat *seat = s->conn->active_seat ? s->conn->active_seat : s->conn->seats; - if (!seat || !seat->proxy || !seat->press_serial) return false; - xdg_toplevel_resize(s->toplevel, seat->proxy, seat->press_serial, (uint32_t)edge); + if (!s || !s->toplevel || !s->conn || edge == YASL_PRIVATE_EDGE_NONE) { + errno = EINVAL; + return false; + } + struct seat *seat; + uint32_t serial = held_press_serial(s, &seat); + if (!serial) return false; + xdg_toplevel_resize(s->toplevel, seat->proxy, serial, (uint32_t)edge); return true; } bool wayland_surface_show_window_menu(struct wayland_surface *s, struct yasl_private_vector2i pos) { - if (!s || !s->toplevel || !s->conn) return false; - struct seat *seat = s->conn->active_seat ? s->conn->active_seat : s->conn->seats; - if (!seat || !seat->proxy || !seat->press_serial) return false; + if (!s || !s->toplevel || !s->conn) { + errno = EINVAL; + return false; + } + struct seat *seat; + uint32_t serial = held_press_serial(s, &seat); + if (!serial) return false; uint32_t scale = s->scale_120 ? s->scale_120 : YASL_PRIVATE_SCALE_UNIT; - xdg_toplevel_show_window_menu(s->toplevel, seat->proxy, seat->press_serial, + xdg_toplevel_show_window_menu(s->toplevel, seat->proxy, serial, yasl_private_scale_to_logical(pos.x, scale), yasl_private_scale_to_logical(pos.y, scale)); return true; |
