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);
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:
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);
- /*
- * Don't store natural geometry here (it was
- * stored already in interactive_begin())
- */
- struct wlr_box *area = &view->output->usable_area;
+ struct wlr_box *area = &output->usable_area;
+ enum view_edge edge;
if (cursor_x <= area->x + snap_range) {
- view_snap_to_edge(view, VIEW_EDGE_LEFT,
- /*store_natural_geometry*/ false);
+ edge = VIEW_EDGE_LEFT;
} else if (cursor_x >= area->x + area->width - snap_range) {
- view_snap_to_edge(view, VIEW_EDGE_RIGHT,
- /*store_natural_geometry*/ false);
+ edge = VIEW_EDGE_RIGHT;
} 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);
- }
+ edge = VIEW_EDGE_UP;
} else if (cursor_y >= area->y + area->height - snap_range) {
- view_snap_to_edge(view, VIEW_EDGE_DOWN,
- /*store_natural_geometry*/ false);
+ 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())
+ */
+ if (edge == VIEW_EDGE_UP && rc.snap_top_maximize) {
+ view_maximize(view, VIEW_AXIS_BOTH,
+ /*store_natural_geometry*/ false);
+ } else {
+ view_snap_to_edge(view, edge,
+ /*across_outputs*/ false,
+ /*store_natural_geometry*/ false);
+ }
+
return true;
}
}
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) {
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;
* 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;