diff --git a/include/view.h b/include/view.h index 3b6844a8..623aff91 100644 --- a/include/view.h +++ b/include/view.h @@ -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); diff --git a/src/action.c b/src/action.c index 5c36e00b..716e08ea 100644 --- a/src/action.c +++ b/src/action.c @@ -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) { diff --git a/src/view.c b/src/view.c index eeb768f2..07dd4f43 100644 --- a/src/view.c +++ b/src/view.c @@ -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) { diff --git a/src/xdg.c b/src/xdg.c index 89b1f4c3..f4991853 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -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) { diff --git a/src/xwayland.c b/src/xwayland.c index 09ca3cc1..e266eb74 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -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); } }