diff --git a/include/labwc.h b/include/labwc.h index da07a3e1..b60d7647 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -160,7 +160,6 @@ struct seat { struct wlr_scene_tree *icons; } drag; - /* Private use by overlay.c */ struct overlay overlay; /* Used to prevent region snapping when starting a move with A-Left */ bool region_prevent_snap; diff --git a/include/overlay.h b/include/overlay.h index bd9b0050..963da8e7 100644 --- a/include/overlay.h +++ b/include/overlay.h @@ -14,23 +14,23 @@ struct overlay { struct multi_rect *pixman_rect; }; - /* For caching previously shown overlay */ + /* Represents currently shown or delayed overlay */ struct { + /* Region overlay */ struct region *region; + + /* Snap-to-edge overlay */ enum view_edge edge; + struct output *output; } active; /* For delayed snap-to-edge overlay */ struct wl_event_source *timer; - struct { - struct view *view; - struct wlr_box box; - } pending; }; -/* Calls overlay_hide() internally if the view is not to be snapped */ -void overlay_show(struct seat *seat, struct view *view); -/* This function must be called when grabbed view is destroyed */ +/* Calls overlay_hide() internally if there's no overlay to show */ +void overlay_show(struct seat *seat); +/* This function must be called when server->grabbed_view is destroyed */ void overlay_hide(struct seat *seat); #endif diff --git a/src/input/cursor.c b/src/input/cursor.c index 04334389..23309f0e 100644 --- a/src/input/cursor.c +++ b/src/input/cursor.c @@ -225,7 +225,7 @@ process_cursor_move(struct server *server, uint32_t time) resistance_move_apply(view, &dx, &dy); view_move(view, dx, dy); - overlay_show(&server->seat, view); + overlay_show(&server->seat); } static void diff --git a/src/input/keyboard.c b/src/input/keyboard.c index fb7ac204..08d5a4b3 100644 --- a/src/input/keyboard.c +++ b/src/input/keyboard.c @@ -80,6 +80,8 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data) if (server->input_mode == LAB_INPUT_STATE_MOVE) { /* Any change to the modifier state re-enable region snap */ seat->region_prevent_snap = false; + /* Pressing/releasing modifier key may show/hide region overlay */ + overlay_show(seat); } if (server->osd_state.cycle_view @@ -97,10 +99,6 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data) } } } - /* Pressing/releasing modifier key may show/hide region overlay */ - if (server->grabbed_view) { - overlay_show(seat, server->grabbed_view); - } if (!input_method_keyboard_grab_forward_modifiers(keyboard)) { wlr_seat_keyboard_notify_modifiers(seat->seat, diff --git a/src/output.c b/src/output.c index 605b3acb..e81abaee 100644 --- a/src/output.c +++ b/src/output.c @@ -102,13 +102,17 @@ static void output_destroy_notify(struct wl_listener *listener, void *data) { struct output *output = wl_container_of(listener, output, destroy); + struct seat *seat = &output->server->seat; regions_evacuate_output(output); - regions_destroy(&output->server->seat, &output->regions); + regions_destroy(seat, &output->regions); + if (seat->overlay.active.output == output) { + overlay_hide(seat); + } wl_list_remove(&output->link); wl_list_remove(&output->frame.link); wl_list_remove(&output->destroy.link); wl_list_remove(&output->request_state.link); - seat_output_layout_changed(&output->server->seat); + seat_output_layout_changed(seat); for (size_t i = 0; i < ARRAY_SIZE(output->layer_tree); i++) { wlr_scene_node_destroy(&output->layer_tree[i]->node); diff --git a/src/overlay.c b/src/overlay.c index f2bc373a..3f517744 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -32,24 +32,16 @@ create_overlay(struct seat *seat) } static void -cancel_pending_overlay(struct overlay *overlay) +show_overlay(struct seat *seat, struct wlr_box *box) { - if (overlay->timer) { - wl_event_source_timer_update(overlay->timer, 0); - } - overlay->pending.view = NULL; - overlay->pending.box = (struct wlr_box){0}; -} + struct server *server = seat->server; + struct view *view = server->grabbed_view; + assert(view); -static void -show_overlay(struct seat *seat, struct view *view, struct wlr_box *box) -{ if (!seat->overlay.tree) { create_overlay(seat); } - /* Update overlay */ - struct server *server = seat->server; struct wlr_scene_node *node = &seat->overlay.tree->node; if (!wlr_renderer_is_pixman(server->renderer)) { /* Hardware assisted rendering: Half transparent overlay */ @@ -66,19 +58,22 @@ show_overlay(struct seat *seat, struct view *view, struct wlr_box *box) } wlr_scene_node_set_position(node, box->x, box->y); wlr_scene_node_set_enabled(node, true); - - cancel_pending_overlay(&seat->overlay); } static void -show_region_overlay(struct seat *seat, struct view *view, struct region *region) +show_region_overlay(struct seat *seat, struct region *region) { if (region == seat->overlay.active.region) { return; } seat->overlay.active.region = region; seat->overlay.active.edge = VIEW_EDGE_INVALID; - show_overlay(seat, view, ®ion->geo); + seat->overlay.active.output = NULL; + if (seat->overlay.timer) { + wl_event_source_timer_update(seat->overlay.timer, 0); + } + + show_overlay(seat, ®ion->geo); } /* TODO: share logic with view_get_edge_snap_box() */ @@ -109,37 +104,40 @@ static struct wlr_box get_edge_snap_box(enum view_edge edge, struct output *outp } static int -handle_overlay_timeout(void *data) +handle_edge_overlay_timeout(void *data) { struct seat *seat = data; - show_overlay(seat, seat->overlay.pending.view, - &seat->overlay.pending.box); + assert(seat->overlay.active.edge != VIEW_EDGE_INVALID + && seat->overlay.active.output); + struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge, + seat->overlay.active.output); + show_overlay(seat, &box); return 0; } static void -show_edge_overlay_delayed(struct seat *seat, struct view *view, - enum view_edge edge, struct output *output) +show_edge_overlay_delayed(struct seat *seat, enum view_edge edge, + struct output *output) { - if (seat->overlay.active.edge == edge) { + if (seat->overlay.active.edge == edge + && seat->overlay.active.output == output) { return; } - seat->overlay.active.edge = edge; seat->overlay.active.region = NULL; + seat->overlay.active.edge = edge; + seat->overlay.active.output = output; - seat->overlay.pending.view = view; - seat->overlay.pending.box = get_edge_snap_box(edge, output); if (!seat->overlay.timer) { seat->overlay.timer = wl_event_loop_add_timer( seat->server->wl_event_loop, - handle_overlay_timeout, seat); + handle_edge_overlay_timeout, seat); } /* Delay for 150ms */ wl_event_source_timer_update(seat->overlay.timer, 150); } void -overlay_show(struct seat *seat, struct view *view) +overlay_show(struct seat *seat) { struct server *server = seat->server; @@ -147,7 +145,7 @@ overlay_show(struct seat *seat, struct view *view) if (regions_should_snap(server)) { struct region *region = regions_from_cursor(server); if (region) { - show_region_overlay(seat, view, region); + show_region_overlay(seat, region); return; } } @@ -161,7 +159,7 @@ overlay_show(struct seat *seat, struct view *view) * flickering when dragging view across output edges in * multi-monitor setup. */ - show_edge_overlay_delayed(seat, view, edge, output); + show_edge_overlay_delayed(seat, edge, output); return; } @@ -171,9 +169,12 @@ overlay_show(struct seat *seat, struct view *view) void overlay_hide(struct seat *seat) { - cancel_pending_overlay(&seat->overlay); - seat->overlay.active.edge = VIEW_EDGE_INVALID; seat->overlay.active.region = NULL; + seat->overlay.active.edge = VIEW_EDGE_INVALID; + seat->overlay.active.output = NULL; + if (seat->overlay.timer) { + wl_event_source_timer_update(seat->overlay.timer, 0); + } if (!seat->overlay.tree) { return; diff --git a/src/regions.c b/src/regions.c index 159d82d9..1b265fe3 100644 --- a/src/regions.c +++ b/src/regions.c @@ -164,7 +164,7 @@ regions_destroy(struct seat *seat, struct wl_list *regions) wl_list_for_each_safe(region, region_tmp, regions, link) { wl_list_remove(®ion->link); if (seat && seat->overlay.active.region == region) { - seat->overlay.active.region = NULL; + overlay_hide(seat); } zfree(region->name); zfree(region);