aboutsummaryrefslogtreecommitdiff
path: root/sway/input_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input_state.c')
-rw-r--r--sway/input_state.c281
1 files changed, 265 insertions, 16 deletions
diff --git a/sway/input_state.c b/sway/input_state.c
index 9e065e60..e911d9cf 100644
--- a/sway/input_state.c
+++ b/sway/input_state.c
@@ -74,27 +74,276 @@ void release_key(uint32_t key_sym, uint32_t key_code) {
}
}
+// Pointer state and mode
+
struct pointer_state pointer_state;
-static struct wlc_geometry saved_floating;
+static struct mode_state {
+ // initial view state
+ double x, y, w, h;
+ swayc_t *ptr;
+ // Containers used for resizing horizontally
+ struct {
+ double w;
+ swayc_t *ptr;
+ struct {
+ double w;
+ swayc_t *ptr;
+ } parent;
+ } horiz;
+ // Containers used for resizing vertically
+ struct {
+ double h;
+ swayc_t *ptr;
+ struct {
+ double h;
+ swayc_t *ptr;
+ } parent;
+ } vert;
+} initial;
+
+static struct {
+ bool left;
+ bool top;
+} lock;
+
+// initial set/unset
+
+static void set_initial_view(swayc_t *view) {
+ initial.ptr = view;
+ initial.x = view->x;
+ initial.y = view->y;
+ initial.w = view->width;
+ initial.h = view->height;
+}
+
+static void set_initial_sibling(void) {
+ bool reset = true;
+ if ((initial.horiz.ptr = get_swayc_in_direction(initial.ptr, lock.left ? MOVE_RIGHT: MOVE_LEFT))) {
+ initial.horiz.w = initial.horiz.ptr->width;
+ initial.horiz.parent.ptr = get_swayc_in_direction(initial.horiz.ptr, lock.left ? MOVE_LEFT : MOVE_RIGHT);
+ initial.horiz.parent.w = initial.horiz.parent.ptr->width;
+ reset = false;
+ }
+ if ((initial.vert.ptr = get_swayc_in_direction(initial.ptr, lock.top ? MOVE_DOWN: MOVE_UP))) {
+ initial.vert.h = initial.vert.ptr->height;
+ initial.vert.parent.ptr = get_swayc_in_direction(initial.vert.ptr, lock.top ? MOVE_UP : MOVE_DOWN);
+ initial.vert.parent.h = initial.vert.parent.ptr->height;
+ reset = false;
+ }
+ // If nothing will change just undo the mode
+ if (reset) {
+ pointer_state.mode = 0;
+ }
+}
+
+static void reset_initial_view(void) {
+ initial.ptr->x = initial.x;
+ initial.ptr->y = initial.y;
+ initial.ptr->width = initial.w;
+ initial.ptr->height = initial.h;
+ arrange_windows(initial.ptr, -1, -1);
+ pointer_state.mode = 0;
+}
+
+static void reset_initial_sibling(void) {
+ initial.horiz.ptr->width = initial.horiz.w;
+ initial.horiz.parent.ptr->width = initial.horiz.parent.w;
+ initial.vert.ptr->height = initial.vert.h;
+ initial.vert.parent.ptr->height = initial.vert.parent.h;
+ arrange_windows(initial.horiz.ptr->parent, -1, -1);
+ arrange_windows(initial.vert.ptr->parent, -1, -1);
+ pointer_state.mode = 0;
+}
+
+// Mode set left/right click
+
+static void pointer_mode_set_left(void) {
+ set_initial_view(pointer_state.left.view);
+ if (initial.ptr->is_floating) {
+ pointer_state.mode = M_DRAGGING | M_FLOATING;
+ } else {
+ pointer_state.mode = M_DRAGGING | M_TILING;
+ }
+}
+
+static void pointer_mode_set_right(void) {
+ set_initial_view(pointer_state.right.view);
+ // Setup locking information
+ int midway_x = initial.ptr->x + initial.ptr->width/2;
+ int midway_y = initial.ptr->y + initial.ptr->height/2;
+
+ lock.left = pointer_state.origin.x > midway_x;
+ lock.top = pointer_state.origin.y > midway_y;
+
+ if (initial.ptr->is_floating) {
+ pointer_state.mode = M_RESIZING | M_FLOATING;
+ } else {
+ pointer_state.mode = M_RESIZING | M_TILING;
+ set_initial_sibling();
+ }
+}
+
+// Mode set/update/reset
+
+void pointer_mode_set(uint32_t button, bool condition) {
+ // switch on drag/resize mode
+ switch (pointer_state.mode & (M_DRAGGING | M_RESIZING)) {
+ case M_DRAGGING:
+ // end drag mode when left click is unpressed
+ if (!pointer_state.left.held) {
+ pointer_state.mode = 0;
+ }
+ break;
+
+ case M_RESIZING:
+ // end resize mode when right click is unpressed
+ if (!pointer_state.right.held) {
+ pointer_state.mode = 0;
+ }
+ break;
+
+ // No mode case
+ default:
+ // return if failed condition, or no view
+ if (!condition || !pointer_state.view) {
+ break;
+ }
-void start_floating(swayc_t *view) {
- if (view->is_floating) {
- saved_floating.origin.x = view->x;
- saved_floating.origin.y = view->y;
- saved_floating.size.w = view->width;
- saved_floating.size.h = view->height;
+ // Set mode depending on current button press
+ switch (button) {
+ // Start dragging mode
+ case M_LEFT_CLICK:
+ // if button release dont do anything
+ if (pointer_state.left.held) {
+ pointer_mode_set_left();
+ }
+ break;
+
+ // Start resize mode
+ case M_RIGHT_CLICK:
+ // if button release dont do anyhting
+ if (pointer_state.right.held) {
+ pointer_mode_set_right();
+ }
+ break;
+ }
}
}
-void reset_floating(swayc_t *view) {
- if (view->is_floating) {
- view->x = saved_floating.origin.x;
- view->y = saved_floating.origin.y;
- view->width = saved_floating.size.w;
- view->height = saved_floating.size.h;
- arrange_windows(view->parent, -1, -1);
+void pointer_mode_update(void) {
+ if (initial.ptr->type != C_VIEW) {
+ pointer_state.mode = 0;
+ return;
+ }
+ int dx = pointer_state.origin.x;
+ int dy = pointer_state.origin.y;
+
+ switch (pointer_state.mode) {
+ case M_FLOATING | M_DRAGGING:
+ // Update position
+ dx -= pointer_state.left.x;
+ dy -= pointer_state.left.y;
+ if (initial.x + dx != initial.ptr->x) {
+ initial.ptr->x = initial.x + dx;
+ }
+ if (initial.y + dy != initial.ptr->y) {
+ initial.ptr->y = initial.y + dy;
+ }
+ update_geometry(initial.ptr);
+ break;
+
+ case M_FLOATING | M_RESIZING:
+ dx -= pointer_state.right.x;
+ dy -= pointer_state.right.y;
+ initial.ptr = pointer_state.right.view;
+ if (lock.left) {
+ if (initial.w + dx > min_sane_w) {
+ initial.ptr->width = initial.w + dx;
+ }
+ } else { // lock.right
+ if (initial.w - dx > min_sane_w) {
+ initial.ptr->width = initial.w - dx;
+ initial.ptr->x = initial.x + dx;
+ }
+ }
+ if (lock.top) {
+ if (initial.h + dy > min_sane_h) {
+ initial.ptr->height = initial.h + dy;
+ }
+ } else { // lock.bottom
+ if (initial.h - dy > min_sane_h) {
+ initial.ptr->height = initial.h - dy;
+ initial.ptr->y = initial.y + dy;
+ }
+ }
+ update_geometry(initial.ptr);
+ break;
+
+ case M_TILING | M_DRAGGING:
+ // swap current view under pointer with dragged view
+ if (pointer_state.view && pointer_state.view->type == C_VIEW
+ && pointer_state.view != initial.ptr) {
+ // Swap them around
+ swap_container(pointer_state.view, initial.ptr);
+ update_geometry(pointer_state.view);
+ update_geometry(initial.ptr);
+ // Set focus back to initial view
+ set_focused_container(initial.ptr);
+ }
+ break;
+
+ case M_TILING | M_RESIZING:
+ dx -= pointer_state.right.x;
+ dy -= pointer_state.right.y;
+ // resize if we can
+ if (initial.horiz.ptr) {
+ if (lock.left) {
+ // Check whether its fine to resize
+ if (initial.w + dx > min_sane_w && initial.horiz.w - dx > min_sane_w) {
+ initial.horiz.ptr->width = initial.horiz.w - dx;
+ initial.horiz.parent.ptr->width = initial.horiz.parent.w + dx;
+ }
+ } else { // lock.right
+ if (initial.w - dx > min_sane_w && initial.horiz.w + dx > min_sane_w) {
+ initial.horiz.ptr->width = initial.horiz.w + dx;
+ initial.horiz.parent.ptr->width = initial.horiz.parent.w - dx;
+ }
+ }
+ arrange_windows(initial.horiz.ptr->parent, -1, -1);
+ }
+ if (initial.vert.ptr) {
+ if (lock.top) {
+ if (initial.h + dy > min_sane_h && initial.vert.h - dy > min_sane_h) {
+ initial.vert.ptr->height = initial.vert.h - dy;
+ initial.vert.parent.ptr->height = initial.vert.parent.h + dy;
+ }
+ } else { // lock.bottom
+ if (initial.h - dy > min_sane_h && initial.vert.h + dy > min_sane_h) {
+ initial.vert.ptr->height = initial.vert.h + dy;
+ initial.vert.parent.ptr->height = initial.vert.parent.h - dy;
+ }
+ }
+ arrange_windows(initial.vert.ptr->parent, -1, -1);
+ }
+ default:
+ return;
+ }
+}
+
+void pointer_mode_reset(void) {
+ switch (pointer_state.mode) {
+ case M_FLOATING | M_RESIZING:
+ case M_FLOATING | M_DRAGGING:
+ reset_initial_view();
+ break;
+
+ case M_TILING | M_RESIZING:
+ (void) reset_initial_sibling;
+ break;
+
+ case M_TILING | M_DRAGGING:
+ default:
+ break;
}
- pointer_state.floating = (struct pointer_floating){0, 0};
- pointer_state.lock = (struct pointer_lock){0, 0, 0, 0, 0, 0, 0, 0};
}