diff --git a/include/labwc.h b/include/labwc.h index 6212a09f..b8d839e6 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -345,6 +345,7 @@ void xdg_toplevel_decoration(struct wl_listener *listener, void *data); void xdg_surface_new(struct wl_listener *listener, void *data); void foreign_toplevel_handle_create(struct view *view); +void foreign_toplevel_update_outputs(struct view *view); /* * desktop.c routines deal with a collection of views diff --git a/include/view.h b/include/view.h index 1fb9d911..d00c9a98 100644 --- a/include/view.h +++ b/include/view.h @@ -121,8 +121,6 @@ void view_move_resize(struct view *view, struct wlr_box geo); void view_move(struct view *view, int x, int y); void view_moved(struct view *view); void view_minimize(struct view *view, bool minimized); -/* view_wlr_output - return the output that a view is mostly on */ -struct wlr_output *view_wlr_output(struct view *view); void view_store_natural_geometry(struct view *view); void view_center(struct view *view); void view_restore_to(struct view *view, struct wlr_box geometry); diff --git a/src/foreign.c b/src/foreign.c index 1a1f376e..86ff27f0 100644 --- a/src/foreign.c +++ b/src/foreign.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only +#include #include "labwc.h" #include "view.h" #include "workspaces.h" @@ -74,14 +75,6 @@ foreign_toplevel_handle_create(struct view *view) return; } - struct wlr_output *wlr_output = view_wlr_output(view); - if (!wlr_output) { - wlr_log(WLR_ERROR, "no wlr_output for (%s)", - view_get_string_prop(view, "title")); - return; - } - wlr_foreign_toplevel_handle_v1_output_enter(toplevel->handle, wlr_output); - toplevel->maximize.notify = handle_request_maximize; wl_signal_add(&toplevel->handle->events.request_maximize, &toplevel->maximize); @@ -105,3 +98,33 @@ foreign_toplevel_handle_create(struct view *view) toplevel->destroy.notify = handle_destroy; wl_signal_add(&toplevel->handle->events.destroy, &toplevel->destroy); } + +/* + * Loop over all outputs and notify foreign_toplevel clients about changes. + * wlr_foreign_toplevel_handle_v1_output_xxx() keeps track of the active + * outputs internally and merges the events. It also listens to output + * destroy events so its fine to just relay the current state and let + * wlr_foreign_toplevel handle the rest. + */ +void +foreign_toplevel_update_outputs(struct view *view) +{ + assert(view->toplevel.handle); + + struct wlr_box view_geo = { view->x, view->y, view->w, view->h }; + struct wlr_output_layout *layout = view->server->output_layout; + + struct output *output; + wl_list_for_each(output, &view->server->outputs, link) { + if (output->wlr_output->enabled && !output->leased) { + if (wlr_output_layout_intersects(layout, + output->wlr_output, &view_geo)) { + wlr_foreign_toplevel_handle_v1_output_enter( + view->toplevel.handle, output->wlr_output); + continue; + } + } + wlr_foreign_toplevel_handle_v1_output_leave( + view->toplevel.handle, output->wlr_output); + } +} diff --git a/src/view.c b/src/view.c index d9108b2b..956514d8 100644 --- a/src/view.c +++ b/src/view.c @@ -156,6 +156,9 @@ view_moved(struct view *view) view_discover_output(view); ssd_update_geometry(view->ssd); cursor_update_focus(view->server); + if (view->toplevel.handle) { + foreign_toplevel_update_outputs(view); + } } /* N.B. Use view_move() if not resizing. */ @@ -217,7 +220,7 @@ view_minimize(struct view *view, bool minimized) } /* view_wlr_output - return the output that a view is mostly on */ -struct wlr_output * +static struct wlr_output * view_wlr_output(struct view *view) { assert(view); @@ -754,23 +757,8 @@ view_adjust_for_layout_change(struct view *view) view_center(view); } } -} - -static void -view_output_enter(struct view *view, struct wlr_output *wlr_output) -{ if (view->toplevel.handle) { - wlr_foreign_toplevel_handle_v1_output_enter( - view->toplevel.handle, wlr_output); - } -} - -static void -view_output_leave(struct view *view, struct wlr_output *wlr_output) -{ - if (view->toplevel.handle) { - wlr_foreign_toplevel_handle_v1_output_leave( - view->toplevel.handle, wlr_output); + foreign_toplevel_update_outputs(view); } } @@ -783,24 +771,13 @@ void view_discover_output(struct view *view) { assert(view); - struct output *old_output = view->output; - struct output *new_output = view_output(view); - if (old_output != new_output) { - view->output = new_output; - if (new_output) { - view_output_enter(view, new_output->wlr_output); - } - if (old_output) { - view_output_leave(view, old_output->wlr_output); - } - } + view->output = view_output(view); } void view_on_output_destroy(struct view *view) { assert(view); - view_output_leave(view, view->output->wlr_output); view->output = NULL; }