diff --git a/include/view.h b/include/view.h index c8640485..d17ebad5 100644 --- a/include/view.h +++ b/include/view.h @@ -388,7 +388,8 @@ void view_adjust_for_layout_change(struct view *view); void view_move_to_edge(struct view *view, enum view_edge direction, bool snap_to_windows); void view_grow_to_edge(struct view *view, enum view_edge direction); void view_shrink_to_edge(struct view *view, enum view_edge direction); -void view_snap_to_edge(struct view *view, enum view_edge direction, bool store_natural_geometry); +void view_snap_to_edge(struct view *view, enum view_edge direction, + bool across_outputs, bool store_natural_geometry); void view_snap_to_region(struct view *view, struct region *region, bool store_natural_geometry); void view_move_to_front(struct view *view); diff --git a/src/action.c b/src/action.c index 6cd809e4..bd0b7051 100644 --- a/src/action.c +++ b/src/action.c @@ -674,7 +674,9 @@ actions_run(struct view *activator, struct server *server, if (view) { /* Config parsing makes sure that direction is a valid direction */ enum view_edge edge = action_get_int(action, "direction", 0); - view_snap_to_edge(view, edge, /*store_natural_geometry*/ true); + view_snap_to_edge(view, edge, + /*across_outputs*/ true, + /*store_natural_geometry*/ true); } break; case ACTION_TYPE_GROW_TO_EDGE: diff --git a/src/interactive.c b/src/interactive.c index d863f569..25139e8b 100644 --- a/src/interactive.c +++ b/src/interactive.c @@ -114,37 +114,45 @@ snap_to_edge(struct view *view) return false; } + struct output *output = output_nearest_to_cursor(view->server); + if (!output_is_usable(output)) { + wlr_log(WLR_ERROR, "output at cursor is unusable"); + return false; + } + /* Translate into output local coordinates */ double cursor_x = view->server->seat.cursor->x; double cursor_y = view->server->seat.cursor->y; wlr_output_layout_output_coords(view->server->output_layout, - view->output->wlr_output, &cursor_x, &cursor_y); + output->wlr_output, &cursor_x, &cursor_y); + struct wlr_box *area = &output->usable_area; + enum view_edge edge; + if (cursor_x <= area->x + snap_range) { + edge = VIEW_EDGE_LEFT; + } else if (cursor_x >= area->x + area->width - snap_range) { + edge = VIEW_EDGE_RIGHT; + } else if (cursor_y <= area->y + snap_range) { + edge = VIEW_EDGE_UP; + } else if (cursor_y >= area->y + area->height - snap_range) { + edge = VIEW_EDGE_DOWN; + } else { + /* Not close to any edge */ + return false; + } + + view_set_output(view, output); /* * Don't store natural geometry here (it was * stored already in interactive_begin()) */ - struct wlr_box *area = &view->output->usable_area; - if (cursor_x <= area->x + snap_range) { - view_snap_to_edge(view, VIEW_EDGE_LEFT, - /*store_natural_geometry*/ false); - } else if (cursor_x >= area->x + area->width - snap_range) { - view_snap_to_edge(view, VIEW_EDGE_RIGHT, - /*store_natural_geometry*/ false); - } else if (cursor_y <= area->y + snap_range) { - if (rc.snap_top_maximize) { - view_maximize(view, VIEW_AXIS_BOTH, - /*store_natural_geometry*/ false); - } else { - view_snap_to_edge(view, VIEW_EDGE_UP, - /*store_natural_geometry*/ false); - } - } else if (cursor_y >= area->y + area->height - snap_range) { - view_snap_to_edge(view, VIEW_EDGE_DOWN, + if (edge == VIEW_EDGE_UP && rc.snap_top_maximize) { + view_maximize(view, VIEW_AXIS_BOTH, /*store_natural_geometry*/ false); } else { - /* Not close to any edge */ - return false; + view_snap_to_edge(view, edge, + /*across_outputs*/ false, + /*store_natural_geometry*/ false); } return true; diff --git a/src/view.c b/src/view.c index b440fb6f..e11c6c14 100644 --- a/src/view.c +++ b/src/view.c @@ -1322,7 +1322,8 @@ view_edge_parse(const char *direction) } void -view_snap_to_edge(struct view *view, enum view_edge edge, bool store_natural_geometry) +view_snap_to_edge(struct view *view, enum view_edge edge, + bool across_outputs, bool store_natural_geometry) { assert(view); if (view->fullscreen) { @@ -1334,7 +1335,7 @@ view_snap_to_edge(struct view *view, enum view_edge edge, bool store_natural_geo return; } - if (view->tiled == edge && view->maximized == VIEW_AXIS_NONE) { + if (across_outputs && view->tiled == edge && view->maximized == VIEW_AXIS_NONE) { /* We are already tiled for this edge and thus should switch outputs */ struct wlr_output *new_output = NULL; struct wlr_output *current_output = output->wlr_output; @@ -1375,13 +1376,6 @@ view_snap_to_edge(struct view *view, enum view_edge edge, bool store_natural_geo * state because the window might have been moved away * (and thus got untiled) and then snapped back to the * original edge. - * - * TODO: The described pattern will cause another bug - * in multi monitor setups: it will snap the - * window to the inverted edge of the nearest - * output. This is the desired behavior when - * caused by a keybind but doesn't make sense - * when caused by mouse movement. */ view_apply_tiled_geometry(view); return;