[wip] src/view.c: add view_move_to_output()

This allows moving a view to another output.
The way we currently do this is pretty much a hack and should be
replaced with a better approach. This function now confines this
hack in a single place and allows future enhancements.

Initially implemented for only defining the output to use for
unmapped surfaces, this implementation now also allows moving
usual views to different outputs by supplying the apply_layout
argument.

This patch also replaces usages of the output selection hack with
the new function.
This commit is contained in:
Consolatis 2023-02-12 07:53:34 +01:00
parent e6bfcdb815
commit 03dbdc10f2
5 changed files with 72 additions and 8 deletions

View file

@ -146,6 +146,8 @@ bool view_is_always_on_top(struct view *view);
bool view_is_tiled(struct view *view);
bool view_is_floating(struct view *view);
void view_move_to_workspace(struct view *view, struct workspace *workspace);
void view_move_to_output(struct view *view, struct output *output, bool apply_layout);
void view_set_decorations(struct view *view, bool decorations);
void view_toggle_fullscreen(struct view *view);
void view_adjust_for_layout_change(struct view *view);

View file

@ -303,6 +303,10 @@ actions_run(struct view *activator, struct server *server,
break;
case ACTION_TYPE_DEBUG:
debug_dump_scene(server);
if (view) {
wlr_log(WLR_ERROR, "moving to cursor output");
view_move_to_output(view, NULL, /* apply_layout */ true);
}
break;
case ACTION_TYPE_EXECUTE:
if (!arg) {

View file

@ -630,6 +630,67 @@ view_move_to_workspace(struct view *view, struct workspace *workspace)
}
}
void
view_move_to_output(struct view *view, struct output *output, bool apply_layout)
{
assert(view);
if (!output) {
/* Get the output where the cursor is currently on */
struct wlr_output *wlr_output = wlr_output_layout_output_at(
view->server->output_layout,
view->server->seat.cursor->x,
view->server->seat.cursor->y);
output = output_from_wlr_output(view->server, wlr_output);
}
if (!output) {
wlr_log(WLR_ERROR, "Can't move view to output: No outputs available");
return;
} else if (output == view->output || output->wlr_output == view->fullscreen) {
wlr_log(WLR_ERROR, "Refusing to move view to same output");
return;
}
/*
* TODO:
* This is a pretty horrible hack which forces
* view_discover() to select a specific output.
*
* This should be replaced by a better alternative
* which preserves the automatic fallover property
* of discover_output() being used in the various
* view_apply_xxx_geometry() functions.
*/
struct wlr_box layout_usable = output_usable_area_in_layout_coords(output);
view->current.x = layout_usable.x;
view->current.y = layout_usable.y;
/* Handle fullscreen */
if (view->fullscreen) {
view->fullscreen = output->wlr_output;
}
/* Adjust natural geometry so we restore to the new output */
if (!view_is_floating(view)) {
view_compute_centered_position(view,
view->natural_geometry.width,
view->natural_geometry.height,
&view->natural_geometry.x,
&view->natural_geometry.y);
}
if (apply_layout) {
if (view->fullscreen) {
view_apply_fullscreen_geometry(view, view->fullscreen);
} else if (!view_apply_special_geometry(view)) {
/*
* This could be enhanced to use approximately
* the same position as on the old output.
*/
view_center(view);
}
}
}
static void
decorate(struct view *view)
{

View file

@ -298,10 +298,8 @@ position_xdg_toplevel_view(struct view *view)
xdg_toplevel_from_view(view)->parent;
if (!parent_xdg_toplevel) {
struct wlr_box box =
output_usable_area_from_cursor_coords(view->server);
view->current.x = box.x;
view->current.y = box.y;
/* Move view to the output where the cursor is currently on */
view_move_to_output(view, NULL, /* apply_layout */ false);
view_center(view);
} else {
/*
@ -345,6 +343,7 @@ xdg_toplevel_view_map(struct view *view)
}
view->mapped = true;
struct wlr_xdg_surface *xdg_surface = xdg_surface_from_view(view);
view->surface = xdg_surface->surface;
wlr_scene_node_set_enabled(&view->scene_tree->node, true);
if (!view->been_mapped) {

View file

@ -470,10 +470,8 @@ set_initial_position(struct view *view,
/* Just make sure the view is on-screen */
view_adjust_for_layout_change(view);
} else {
struct wlr_box box =
output_usable_area_from_cursor_coords(view->server);
view->current.x = box.x;
view->current.y = box.y;
/* Move view to the output where the cursor is currently on */
view_move_to_output(view, NULL, /* apply_layout */ false);
view_center(view);
}
}