mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
interactive: allow moving horizontally/vertically maximized window
Applies drag resistance unidirectionally for horizontally/vertically maximized windows, allowing them to be dragged without being untiled immediately. When the distance of cursor movement orthogonal to the maximized direction exceeds <resistance><unMaximizeThreshold>. While dragging a horizontally/vertically maximized window, edge/region snapping is disabled to prevent unintentional snapping and overlays. This commit also includes some refactoring to simplify the logic.
This commit is contained in:
parent
2e19bd4d5b
commit
1f1bdad087
11 changed files with 137 additions and 120 deletions
|
|
@ -330,6 +330,11 @@ this is for compatibility with Openbox.
|
||||||
Sets the movement of cursor in pixel required for a tiled or maximized
|
Sets the movement of cursor in pixel required for a tiled or maximized
|
||||||
window to be moved with an interactive move. Default is 20.
|
window to be moved with an interactive move. Default is 20.
|
||||||
|
|
||||||
|
*<resistance><unMaximizeThreshold>*
|
||||||
|
Sets the one-dimentional movement of cursor in pixel required for a
|
||||||
|
*vertically or horizontally* maximized window to be moved with an
|
||||||
|
interactive move. Default is 150.
|
||||||
|
|
||||||
## FOCUS
|
## FOCUS
|
||||||
|
|
||||||
*<focus><followMouse>* [yes|no]
|
*<focus><followMouse>* [yes|no]
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,10 @@
|
||||||
<resistance>
|
<resistance>
|
||||||
<screenEdgeStrength>20</screenEdgeStrength>
|
<screenEdgeStrength>20</screenEdgeStrength>
|
||||||
<windowEdgeStrength>20</windowEdgeStrength>
|
<windowEdgeStrength>20</windowEdgeStrength>
|
||||||
|
<!-- resistance for maximized/tiled windows -->
|
||||||
<unSnapThreshold>20</unSnapThreshold>
|
<unSnapThreshold>20</unSnapThreshold>
|
||||||
|
<!-- resistance for vertically/horizontally maximized windows -->
|
||||||
|
<unMaximizeThreshold>150</unMaximizeThreshold>
|
||||||
</resistance>
|
</resistance>
|
||||||
|
|
||||||
<resize>
|
<resize>
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,7 @@ struct rcxml {
|
||||||
int screen_edge_strength;
|
int screen_edge_strength;
|
||||||
int window_edge_strength;
|
int window_edge_strength;
|
||||||
int unsnap_threshold;
|
int unsnap_threshold;
|
||||||
|
int unmaximize_threshold;
|
||||||
|
|
||||||
/* window snapping */
|
/* window snapping */
|
||||||
int snap_edge_range;
|
int snap_edge_range;
|
||||||
|
|
|
||||||
|
|
@ -263,13 +263,6 @@ struct server {
|
||||||
/* cursor interactive */
|
/* cursor interactive */
|
||||||
enum input_mode input_mode;
|
enum input_mode input_mode;
|
||||||
struct view *grabbed_view;
|
struct view *grabbed_view;
|
||||||
/*
|
|
||||||
* When an interactive move is requested for tiled/maximized views by CSD
|
|
||||||
* clients or by Drag actions, the actual motion and untiling of the view
|
|
||||||
* can be delayed to prevent the view from being unintentionally untiled.
|
|
||||||
* During this delay, move_pending is set.
|
|
||||||
*/
|
|
||||||
bool move_pending;
|
|
||||||
/* Cursor position when interactive move/resize is requested */
|
/* Cursor position when interactive move/resize is requested */
|
||||||
double grab_x, grab_y;
|
double grab_x, grab_y;
|
||||||
/* View geometry when interactive move/resize is requested */
|
/* View geometry when interactive move/resize is requested */
|
||||||
|
|
@ -506,26 +499,15 @@ void seat_reset_pressed(struct seat *seat);
|
||||||
void seat_output_layout_changed(struct seat *seat);
|
void seat_output_layout_changed(struct seat *seat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* interactive_anchor_to_cursor() - repositions the view to remain
|
* interactive_anchor_to_cursor() - repositions the geometry to remain
|
||||||
* underneath the cursor when its size changes during interactive move.
|
* underneath the cursor when its size changes during interactive move.
|
||||||
|
* This function also resizes server->grab_box and repositions it to remain
|
||||||
|
* underneath server->grab_{x,y}.
|
||||||
*
|
*
|
||||||
* geometry->{width,height} are provided by the caller.
|
* geo->{width,height} are provided by the caller.
|
||||||
* geometry->{x,y} are computed by this function.
|
* geo->{x,y} are computed by this function.
|
||||||
*
|
|
||||||
* @note When <unSnapThreshold> is non-zero, cursor_x/y should be the original
|
|
||||||
* cursor position when the button was pressed.
|
|
||||||
*/
|
*/
|
||||||
void interactive_anchor_to_cursor(struct view *view, struct wlr_box *geometry,
|
void interactive_anchor_to_cursor(struct server *server, struct wlr_box *geo);
|
||||||
int cursor_x, int cursor_y);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* interactive_move_tiled_view_to() - Un-tile the tiled/maximized view at the
|
|
||||||
* start of an interactive move or when an interactive move is pending.
|
|
||||||
* Returns true if the distance of cursor motion exceeds the value of
|
|
||||||
* <resistance><unSnapThreshold> and the view is un-tiled.
|
|
||||||
*/
|
|
||||||
bool interactive_move_tiled_view_to(struct server *server, struct view *view,
|
|
||||||
struct wlr_box *geometry);
|
|
||||||
|
|
||||||
void interactive_begin(struct view *view, enum input_mode mode, uint32_t edges);
|
void interactive_begin(struct view *view, enum input_mode mode, uint32_t edges);
|
||||||
void interactive_finish(struct view *view);
|
void interactive_finish(struct view *view);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,12 @@
|
||||||
#define LABWC_RESISTANCE_H
|
#define LABWC_RESISTANCE_H
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
|
|
||||||
void resistance_move_apply(struct view *view, double *x, double *y);
|
/**
|
||||||
|
* resistance_unsnap_apply() - Apply resistance when dragging a
|
||||||
|
* maximized/tiled window. Returns true when the view needs to be un-tiled.
|
||||||
|
*/
|
||||||
|
bool resistance_unsnap_apply(struct view *view, int *x, int *y);
|
||||||
|
void resistance_move_apply(struct view *view, int *x, int *y);
|
||||||
void resistance_resize_apply(struct view *view, struct wlr_box *new_view_geo);
|
void resistance_resize_apply(struct view *view, struct wlr_box *new_view_geo);
|
||||||
|
|
||||||
#endif /* LABWC_RESISTANCE_H */
|
#endif /* LABWC_RESISTANCE_H */
|
||||||
|
|
|
||||||
|
|
@ -1043,6 +1043,8 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
rc.window_edge_strength = atoi(content);
|
rc.window_edge_strength = atoi(content);
|
||||||
} else if (!strcasecmp(nodename, "unSnapThreshold.resistance")) {
|
} else if (!strcasecmp(nodename, "unSnapThreshold.resistance")) {
|
||||||
rc.unsnap_threshold = atoi(content);
|
rc.unsnap_threshold = atoi(content);
|
||||||
|
} else if (!strcasecmp(nodename, "unMaximizeThreshold.resistance")) {
|
||||||
|
rc.unmaximize_threshold = atoi(content);
|
||||||
} else if (!strcasecmp(nodename, "range.snapping")) {
|
} else if (!strcasecmp(nodename, "range.snapping")) {
|
||||||
rc.snap_edge_range = atoi(content);
|
rc.snap_edge_range = atoi(content);
|
||||||
} else if (!strcasecmp(nodename, "enabled.overlay.snapping")) {
|
} else if (!strcasecmp(nodename, "enabled.overlay.snapping")) {
|
||||||
|
|
@ -1370,6 +1372,7 @@ rcxml_init(void)
|
||||||
rc.screen_edge_strength = 20;
|
rc.screen_edge_strength = 20;
|
||||||
rc.window_edge_strength = 20;
|
rc.window_edge_strength = 20;
|
||||||
rc.unsnap_threshold = 20;
|
rc.unsnap_threshold = 20;
|
||||||
|
rc.unmaximize_threshold = 150;
|
||||||
|
|
||||||
rc.snap_edge_range = 1;
|
rc.snap_edge_range = 1;
|
||||||
rc.snap_overlay_enabled = true;
|
rc.snap_overlay_enabled = true;
|
||||||
|
|
|
||||||
|
|
@ -235,24 +235,34 @@ process_cursor_move(struct server *server, uint32_t time)
|
||||||
{
|
{
|
||||||
struct view *view = server->grabbed_view;
|
struct view *view = server->grabbed_view;
|
||||||
|
|
||||||
/*
|
int x = server->grab_box.x + (server->seat.cursor->x - server->grab_x);
|
||||||
* Un-tile the view when interactive move is delayed and the distance
|
int y = server->grab_box.y + (server->seat.cursor->y - server->grab_y);
|
||||||
* of cursor movement exceeds <resistance><unSnapThreshold>.
|
|
||||||
*/
|
/* Apply resistance for maximized/tiled view */
|
||||||
if (server->move_pending && !interactive_move_tiled_view_to(
|
bool needs_untile = resistance_unsnap_apply(view, &x, &y);
|
||||||
server, server->grabbed_view, &server->grab_box)) {
|
if (needs_untile) {
|
||||||
return;
|
/*
|
||||||
|
* When the view needs to be un-tiled, resize it to natural
|
||||||
|
* geometry while anchoring it to cursor. If the natural
|
||||||
|
* geometry is unknown (possible with xdg-shell views), then
|
||||||
|
* we set a size of 0x0 here and determine the correct geometry
|
||||||
|
* later. See do_late_positioning() in xdg.c.
|
||||||
|
*/
|
||||||
|
struct wlr_box new_geo = {
|
||||||
|
.width = view->natural_geometry.width,
|
||||||
|
.height = view->natural_geometry.height,
|
||||||
|
};
|
||||||
|
interactive_anchor_to_cursor(server, &new_geo);
|
||||||
|
view_set_untiled(view);
|
||||||
|
view_restore_to(view, new_geo);
|
||||||
|
x = new_geo.x;
|
||||||
|
y = new_geo.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
double dx = server->seat.cursor->x - server->grab_x;
|
/* Then apply window & edge resistance */
|
||||||
double dy = server->seat.cursor->y - server->grab_y;
|
resistance_move_apply(view, &x, &y);
|
||||||
|
|
||||||
/* Move the grabbed view to the new position. */
|
|
||||||
dx += server->grab_box.x;
|
|
||||||
dy += server->grab_box.y;
|
|
||||||
resistance_move_apply(view, &dx, &dy);
|
|
||||||
view_move(view, dx, dy);
|
|
||||||
|
|
||||||
|
view_move(view, x, y);
|
||||||
overlay_update(&server->seat);
|
overlay_update(&server->seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,58 +9,47 @@
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "window-rules.h"
|
#include "window-rules.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pos_old pos_cursor
|
||||||
|
* v v
|
||||||
|
* +---------+-------------------+
|
||||||
|
* <-----------size_old---------->
|
||||||
|
*
|
||||||
|
* return value
|
||||||
|
* v
|
||||||
|
* +----+---------+
|
||||||
|
* <---size_new--->
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
max_move_scale(double pos_cursor, double pos_current,
|
max_move_scale(double pos_cursor, double pos_old, double size_old,
|
||||||
double size_current, double size_orig)
|
double size_new)
|
||||||
{
|
{
|
||||||
double anchor_frac = (pos_cursor - pos_current) / size_current;
|
double anchor_frac = (pos_cursor - pos_old) / size_old;
|
||||||
int pos_new = pos_cursor - (size_orig * anchor_frac);
|
int pos_new = pos_cursor - (size_new * anchor_frac);
|
||||||
if (pos_new < pos_current) {
|
if (pos_new < pos_old) {
|
||||||
/* Clamp by using the old offsets of the maximized window */
|
/* Clamp by using the old offsets of the maximized window */
|
||||||
pos_new = pos_current;
|
pos_new = pos_old;
|
||||||
}
|
}
|
||||||
return pos_new;
|
return pos_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
interactive_anchor_to_cursor(struct view *view, struct wlr_box *geometry,
|
interactive_anchor_to_cursor(struct server *server, struct wlr_box *geo)
|
||||||
int cursor_x, int cursor_y)
|
|
||||||
{
|
{
|
||||||
geometry->x = max_move_scale(cursor_x, view->current.x,
|
assert(server->input_mode == LAB_INPUT_STATE_MOVE);
|
||||||
view->current.width, geometry->width);
|
if (wlr_box_empty(geo)) {
|
||||||
geometry->y = max_move_scale(cursor_y, view->current.y,
|
return;
|
||||||
view->current.height, geometry->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
interactive_move_tiled_view_to(struct server *server, struct view *view,
|
|
||||||
struct wlr_box *geometry)
|
|
||||||
{
|
|
||||||
assert(!view_is_floating(view));
|
|
||||||
|
|
||||||
int threshold = rc.unsnap_threshold;
|
|
||||||
|
|
||||||
if (server->input_mode == LAB_INPUT_STATE_MOVE) {
|
|
||||||
/* When called from cursor motion handler */
|
|
||||||
assert(server->move_pending && server->grabbed_view == view);
|
|
||||||
|
|
||||||
double dx = server->seat.cursor->x - server->grab_x;
|
|
||||||
double dy = server->seat.cursor->y - server->grab_y;
|
|
||||||
if (dx * dx + dy * dy < threshold * threshold) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* When called from interactive_begin() */
|
|
||||||
if (threshold > 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* Resize grab_box while anchoring it to grab_box.{x,y} */
|
||||||
|
server->grab_box.x = max_move_scale(server->grab_x, server->grab_box.x,
|
||||||
|
server->grab_box.width, geo->width);
|
||||||
|
server->grab_box.y = max_move_scale(server->grab_y, server->grab_box.y,
|
||||||
|
server->grab_box.height, geo->height);
|
||||||
|
server->grab_box.width = geo->width;
|
||||||
|
server->grab_box.height = geo->height;
|
||||||
|
|
||||||
view_set_untiled(view);
|
geo->x = server->grab_box.x + (server->seat.cursor->x - server->grab_x);
|
||||||
view_restore_to(view, *geometry);
|
geo->y = server->grab_box.y + (server->seat.cursor->y - server->grab_y);
|
||||||
server->move_pending = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -73,7 +62,6 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||||
*/
|
*/
|
||||||
struct server *server = view->server;
|
struct server *server = view->server;
|
||||||
struct seat *seat = &server->seat;
|
struct seat *seat = &server->seat;
|
||||||
struct wlr_box geometry = view->current;
|
|
||||||
|
|
||||||
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -97,31 +85,7 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||||
*/
|
*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!view_is_floating(view)) {
|
if (view_is_floating(view)) {
|
||||||
/*
|
|
||||||
* Un-maximize and restore natural width/height.
|
|
||||||
* If the natural geometry is unknown (possible
|
|
||||||
* with xdg-shell views), then we set a size of
|
|
||||||
* 0x0 here and determine the correct geometry
|
|
||||||
* later. See do_late_positioning() in xdg.c.
|
|
||||||
*/
|
|
||||||
geometry.width = view->natural_geometry.width;
|
|
||||||
geometry.height = view->natural_geometry.height;
|
|
||||||
if (!wlr_box_empty(&geometry)) {
|
|
||||||
interactive_anchor_to_cursor(view, &geometry,
|
|
||||||
seat->cursor->x, seat->cursor->y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If <resistance><unSnapThreshold> is non-zero, the
|
|
||||||
* tiled/maximized view is un-tiled later in cursor
|
|
||||||
* motion handler.
|
|
||||||
*/
|
|
||||||
if (!interactive_move_tiled_view_to(
|
|
||||||
server, view, &geometry)) {
|
|
||||||
server->move_pending = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Store natural geometry at start of move */
|
/* Store natural geometry at start of move */
|
||||||
view_store_natural_geometry(view);
|
view_store_natural_geometry(view);
|
||||||
view_invalidate_last_layout_geometry(view);
|
view_invalidate_last_layout_geometry(view);
|
||||||
|
|
@ -151,7 +115,7 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If tiled or maximized in only one direction, reset
|
* If tiled or maximized in only one direction, reset
|
||||||
* tiled/maximized state but keep the same geometry as
|
* maximized/tiled state but keep the same geometry as
|
||||||
* the starting point for the resize.
|
* the starting point for the resize.
|
||||||
*/
|
*/
|
||||||
view_set_untiled(view);
|
view_set_untiled(view);
|
||||||
|
|
@ -168,8 +132,24 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||||
/* Remember view and cursor positions at start of move/resize */
|
/* Remember view and cursor positions at start of move/resize */
|
||||||
server->grab_x = seat->cursor->x;
|
server->grab_x = seat->cursor->x;
|
||||||
server->grab_y = seat->cursor->y;
|
server->grab_y = seat->cursor->y;
|
||||||
server->grab_box = geometry;
|
server->grab_box = view->current;
|
||||||
server->resize_edges = edges;
|
server->resize_edges = edges;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Un-tile maximized/tiled view immediately if <unSnapThreshold> is
|
||||||
|
* zero. Otherwise, un-tile it later in cursor motion handler.
|
||||||
|
* If the natural geometry is unknown (possible with xdg-shell views),
|
||||||
|
* then we set a size of 0x0 here and determine the correct geometry
|
||||||
|
* later. See do_late_positioning() in xdg.c.
|
||||||
|
*/
|
||||||
|
if (mode == LAB_INPUT_STATE_MOVE && !view_is_floating(view)
|
||||||
|
&& rc.unsnap_threshold <= 0) {
|
||||||
|
struct wlr_box natural_geo = view->natural_geometry;
|
||||||
|
interactive_anchor_to_cursor(server, &natural_geo);
|
||||||
|
view_set_untiled(view);
|
||||||
|
view_restore_to(view, natural_geo);
|
||||||
|
}
|
||||||
|
|
||||||
if (rc.resize_indicator) {
|
if (rc.resize_indicator) {
|
||||||
resize_indicator_show(view);
|
resize_indicator_show(view);
|
||||||
}
|
}
|
||||||
|
|
@ -181,6 +161,10 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||||
enum view_edge
|
enum view_edge
|
||||||
edge_from_cursor(struct seat *seat, struct output **dest_output)
|
edge_from_cursor(struct seat *seat, struct output **dest_output)
|
||||||
{
|
{
|
||||||
|
if (!view_is_floating(seat->server->grabbed_view)) {
|
||||||
|
return VIEW_EDGE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
int snap_range = rc.snap_edge_range;
|
int snap_range = rc.snap_edge_range;
|
||||||
if (!snap_range) {
|
if (!snap_range) {
|
||||||
return VIEW_EDGE_INVALID;
|
return VIEW_EDGE_INVALID;
|
||||||
|
|
@ -296,7 +280,6 @@ interactive_cancel(struct view *view)
|
||||||
|
|
||||||
view->server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
|
view->server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
|
||||||
view->server->grabbed_view = NULL;
|
view->server->grabbed_view = NULL;
|
||||||
view->server->move_pending = false;
|
|
||||||
|
|
||||||
/* Update focus/cursor image */
|
/* Update focus/cursor image */
|
||||||
cursor_update_focus(view->server);
|
cursor_update_focus(view->server);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ regions_should_snap(struct server *server)
|
||||||
{
|
{
|
||||||
if (server->input_mode != LAB_INPUT_STATE_MOVE
|
if (server->input_mode != LAB_INPUT_STATE_MOVE
|
||||||
|| wl_list_empty(&rc.regions)
|
|| wl_list_empty(&rc.regions)
|
||||||
|| server->seat.region_prevent_snap) {
|
|| server->seat.region_prevent_snap
|
||||||
|
|| !view_is_floating(server->grabbed_view)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,38 @@ check_edge_window(int *next, struct edge current, struct edge target,
|
||||||
oppose, align, rc.window_edge_strength, lesser);
|
oppose, align, rc.window_edge_strength, lesser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
resistance_unsnap_apply(struct view *view, int *x, int *y)
|
||||||
|
{
|
||||||
|
if (view_is_floating(view)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dx = *x - view->current.x;
|
||||||
|
int dy = *y - view->current.y;
|
||||||
|
if (view->maximized == VIEW_AXIS_HORIZONTAL) {
|
||||||
|
if (abs(dx) < rc.unmaximize_threshold) {
|
||||||
|
*x = view->current.x;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (view->maximized == VIEW_AXIS_VERTICAL) {
|
||||||
|
if (abs(dy) < rc.unmaximize_threshold) {
|
||||||
|
*y = view->current.y;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dx * dx + dy * dy < rc.unsnap_threshold * rc.unsnap_threshold) {
|
||||||
|
*x = view->current.x;
|
||||||
|
*y = view->current.y;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
resistance_move_apply(struct view *view, double *x, double *y)
|
resistance_move_apply(struct view *view, int *x, int *y)
|
||||||
{
|
{
|
||||||
assert(view);
|
assert(view);
|
||||||
|
|
||||||
|
|
|
||||||
10
src/xdg.c
10
src/xdg.c
|
|
@ -93,14 +93,8 @@ do_late_positioning(struct view *view)
|
||||||
struct server *server = view->server;
|
struct server *server = view->server;
|
||||||
if (server->input_mode == LAB_INPUT_STATE_MOVE
|
if (server->input_mode == LAB_INPUT_STATE_MOVE
|
||||||
&& view == server->grabbed_view) {
|
&& view == server->grabbed_view) {
|
||||||
/* Anchor view to original grab position */
|
/* Reposition the view while anchoring it to cursor */
|
||||||
interactive_anchor_to_cursor(view, &view->pending,
|
interactive_anchor_to_cursor(server, &view->pending);
|
||||||
server->grab_x, server->grab_y);
|
|
||||||
/* Next update grab offsets */
|
|
||||||
server->grab_box = view->pending;
|
|
||||||
/* Finally, move by same distance cursor has moved */
|
|
||||||
view->pending.x += server->seat.cursor->x - server->grab_x;
|
|
||||||
view->pending.y += server->seat.cursor->y - server->grab_y;
|
|
||||||
} else {
|
} else {
|
||||||
/* TODO: smart placement? */
|
/* TODO: smart placement? */
|
||||||
view_compute_centered_position(view, NULL,
|
view_compute_centered_position(view, NULL,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue