aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2015-08-23 15:38:51 -0400
committerDrew DeVault <sir@cmpwn.com>2015-08-23 15:38:51 -0400
commit9a7f48f87272dea8cb1e678673b2fe95dc993d68 (patch)
tree1a9e633ead0ff50f55987310621dab39531d2305
parent1ac0c8cd47f734809c20bf6a6a0a7278680ed597 (diff)
parent51ab3c918030565cefbb82dc8e899f324e6c5a21 (diff)
Merge pull request #121 from taiyu-len/pointer_mod
Pointer mode clean and fix.
-rw-r--r--include/input_state.h72
-rw-r--r--include/layout.h2
-rw-r--r--include/resize.h3
-rw-r--r--sway/handlers.c247
-rw-r--r--sway/input_state.c281
-rw-r--r--sway/layout.c140
-rw-r--r--sway/resize.c261
7 files changed, 508 insertions, 498 deletions
diff --git a/include/input_state.h b/include/input_state.h
index 29064fd0..d87ae18c 100644
--- a/include/input_state.h
+++ b/include/input_state.h
@@ -15,6 +15,7 @@ void press_key(uint32_t key_sym, uint32_t key_code);
// unsets a key as pressed
void release_key(uint32_t key_sym, uint32_t key_code);
+
/* Pointer state */
enum pointer_values {
@@ -25,34 +26,55 @@ enum pointer_values {
M_SCROLL_DOWN = 276,
};
+enum pointer_mode {
+ // Target
+ M_FLOATING = 1,
+ M_TILING = 2,
+ // Action
+ M_DRAGGING = 4,
+ M_RESIZING = 8,
+};
+
+struct pointer_button_state {
+ bool held;
+ // state at the point it was pressed
+ int x, y;
+ swayc_t *view;
+};
+
extern struct pointer_state {
- bool l_held;
- bool r_held;
- struct pointer_floating {
- bool drag;
- bool resize;
- } floating;
- struct pointer_tiling {
- bool resize;
- swayc_t *init_view;
- struct wlc_origin lock_pos;
- } tiling;
- struct pointer_lock {
- // Lock movement for certain edges
- bool left;
- bool right;
- bool top;
- bool bottom;
- // Lock movement in certain directions
- bool temp_left;
- bool temp_right;
- bool temp_up;
- bool temp_down;
- } lock;
+ // mouse clicks
+ struct pointer_button_state left;
+ struct pointer_button_state right;
+ struct pointer_button_state scroll;
+
+ // pointer position
+ struct mouse_origin{
+ int x, y;
+ } origin;
+
+ // change in pointer position
+ struct {
+ int x, y;
+ } delta;
+
+ // view pointer is currently over
+ swayc_t *view;
+
+ // Pointer mode
+ int mode;
} pointer_state;
-void start_floating(swayc_t *view);
-void reset_floating(swayc_t *view);
+// on button release unset mode depending on the button.
+// on button press set mode conditionally depending on the button
+void pointer_mode_set(uint32_t button, bool condition);
+
+// Update mode in mouse motion
+void pointer_mode_update(void);
+
+// Reset mode on any keypress;
+void pointer_mode_reset(void);
+
void input_init(void);
#endif
diff --git a/include/layout.h b/include/layout.h
index f8aebe0a..8f269607 100644
--- a/include/layout.h
+++ b/include/layout.h
@@ -19,10 +19,12 @@ void add_floating(swayc_t *ws, swayc_t *child);
swayc_t *add_sibling(swayc_t *sibling, swayc_t *child);
swayc_t *replace_child(swayc_t *child, swayc_t *new_child);
swayc_t *remove_child(swayc_t *child);
+void swap_container(swayc_t *a, swayc_t *b);
void move_container(swayc_t* container,swayc_t* root,enum movement_direction direction);
// Layout
+void update_geometry(swayc_t *view);
void arrange_windows(swayc_t *container, double width, double height);
swayc_t *get_focused_container(swayc_t *parent);
diff --git a/include/resize.h b/include/resize.h
index 4ace1815..8d205d3b 100644
--- a/include/resize.h
+++ b/include/resize.h
@@ -1,8 +1,7 @@
#ifndef _SWAY_RESIZE_H
#define _SWAY_RESIZE_H
+#include <stdbool.h>
-bool mouse_resize_tiled(struct wlc_origin prev_pos);
-bool resize_floating(struct wlc_origin prev_pos);
bool resize_tiled(int amount, bool use_width);
#endif
diff --git a/sway/handlers.c b/sway/handlers.c
index acf3e6a4..27f6d294 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -17,10 +17,14 @@
#include "input_state.h"
#include "resize.h"
-struct wlc_origin mouse_origin;
+// Event should be sent to client
+#define EVENT_PASSTHROUGH false
+
+// Event handled by sway and should not be sent to client
+#define EVENT_HANDLED true
static bool pointer_test(swayc_t *view, void *_origin) {
- const struct wlc_origin *origin = _origin;
+ const struct mouse_origin *origin = _origin;
// Determine the output that the view is under
swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT);
if (origin->x >= view->x && origin->y >= view->y
@@ -55,7 +59,7 @@ swayc_t *container_under_pointer(void) {
i = len = lookup->floating->length;
bool got_floating = false;
while (--i > -1) {
- if (pointer_test(lookup->floating->items[i], &mouse_origin)) {
+ if (pointer_test(lookup->floating->items[i], &pointer_state.origin)) {
lookup = lookup->floating->items[i];
got_floating = true;
break;
@@ -68,7 +72,7 @@ swayc_t *container_under_pointer(void) {
// search children
len = lookup->children->length;
for (i = 0; i < len; ++i) {
- if (pointer_test(lookup->children->items[i], &mouse_origin)) {
+ if (pointer_test(lookup->children->items[i], &pointer_state.origin)) {
lookup = lookup->children->items[i];
break;
}
@@ -284,13 +288,12 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
uint32_t key, uint32_t sym, enum wlc_key_state state) {
if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) {
- return false;
+ return EVENT_PASSTHROUGH;
}
- // Revert floating container back to original position on keypress
- if (state == WLC_KEY_STATE_PRESSED &&
- (pointer_state.floating.drag || pointer_state.floating.resize)) {
- reset_floating(get_focused_view(&root_container));
+ // reset pointer mode on keypress
+ if (state == WLC_KEY_STATE_PRESSED && pointer_state.mode) {
+ pointer_mode_reset();
}
struct sway_mode *mode = config->current_mode;
@@ -319,125 +322,119 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
if (match) {
if (state == WLC_KEY_STATE_PRESSED) {
handle_command(config, binding->command);
- return true;
+ return EVENT_HANDLED;
} else if (state == WLC_KEY_STATE_RELEASED) {
// TODO: --released
}
}
}
}
- return false;
+ return EVENT_PASSTHROUGH;
}
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) {
- static struct wlc_origin prev_pos;
- static wlc_handle prev_handle = 0;
- mouse_origin = *origin;
- bool changed_floating = false;
- bool changed_tiling = false;
- if (!swayc_active_workspace()) {
- return false;
- }
- // Do checks to determine if proper keys are being held
- swayc_t *view = container_under_pointer();
- if (pointer_state.floating.drag && view) {
- if (view->is_floating) {
- int dx = mouse_origin.x - prev_pos.x;
- int dy = mouse_origin.y - prev_pos.y;
- view->x += dx;
- view->y += dy;
- struct wlc_geometry geometry = {
- .origin = {
- .x = view->x,
- .y = view->y
- },
- .size = {
- .w = view->width,
- .h = view->height
- }
- };
- wlc_view_set_geometry(view->handle, 0, &geometry);
- changed_floating = true;
- } else {
- swayc_t *init_view = pointer_state.tiling.init_view;
- if (view != init_view && view->type == C_VIEW) {
- changed_tiling = true;
- int i, j;
- for (i = 0; i < view->parent->children->length; i++) {
- if (view->parent->children->items[i] == view) {
- for (j = 0; j < init_view->parent->children->length; j++) {
- if (init_view->parent->children->items[j] == init_view) {
- double temp_w = view->width;
- double temp_h = view->height;
- view->width = init_view->width;
- view->height = init_view->height;
- init_view->width = temp_w;
- init_view->height = temp_h;
-
- init_view->parent->children->items[j] = view;
- view->parent->children->items[i] = init_view;
-
- swayc_t *temp = view->parent;
- view->parent = init_view->parent;
- init_view->parent = temp;
-
- arrange_windows(&root_container, -1, -1);
- break;
- }
- }
- break;
- }
- }
- }
- }
- } else if (pointer_state.floating.resize && view) {
- changed_floating = resize_floating(prev_pos);
- } else if (pointer_state.tiling.resize && view) {
- changed_tiling = mouse_resize_tiled(prev_pos);
+ // Update pointer origin
+ pointer_state.delta.x = origin->x - pointer_state.origin.x;
+ pointer_state.delta.y = origin->y - pointer_state.origin.y;
+ pointer_state.origin.x = origin->x;
+ pointer_state.origin.y = origin->y;
+
+ // Update view under pointer
+ swayc_t *prev_view = pointer_state.view;
+ pointer_state.view = container_under_pointer();
+
+ // If pointer is in a mode, update it
+ if (pointer_state.mode) {
+ pointer_mode_update();
}
- if (config->focus_follows_mouse && prev_handle != handle) {
- // Dont change focus if fullscreen
- swayc_t *focused = get_focused_view(view);
- if (!swayc_is_fullscreen(focused)
- && !(pointer_state.l_held || pointer_state.r_held)) {
- set_focused_container(container_under_pointer());
+ // Otherwise change focus if config is set an
+ else if (prev_view != pointer_state.view && config->focus_follows_mouse) {
+ if (pointer_state.view && pointer_state.view->type == C_VIEW) {
+ set_focused_container(pointer_state.view);
}
}
- prev_handle = handle;
- prev_pos = mouse_origin;
- if (changed_tiling || changed_floating) {
- return true;
- }
- return false;
+ return EVENT_PASSTHROUGH;
}
static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers,
uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) {
- swayc_t *focused = get_focused_container(&root_container);
- // dont change focus if fullscreen
- if (swayc_is_fullscreen(focused)) {
- return false;
- }
- if (state == WLC_BUTTON_STATE_PRESSED) {
- sway_log(L_DEBUG, "Mouse button %u pressed", button);
- if (button == M_LEFT_CLICK) {
- pointer_state.l_held = true;
+
+ // Update view pointer is on
+ pointer_state.view = container_under_pointer();
+
+ // Update pointer origin
+ pointer_state.origin.x = origin->x;
+ pointer_state.origin.y = origin->y;
+
+ // Update pointer_state
+ switch (button) {
+ case M_LEFT_CLICK:
+ if (state == WLC_BUTTON_STATE_PRESSED) {
+ pointer_state.left.held = true;
+ pointer_state.left.x = origin->x;
+ pointer_state.left.y = origin->y;
+ pointer_state.left.view = pointer_state.view;
+ } else {
+ pointer_state.left.held = false;
}
- if (button == M_RIGHT_CLICK) {
- pointer_state.r_held = true;
+ break;
+
+ case M_RIGHT_CLICK:
+ if (state == WLC_BUTTON_STATE_PRESSED) {
+ pointer_state.right.held = true;
+ pointer_state.right.x = origin->x;
+ pointer_state.right.y = origin->y;
+ pointer_state.right.view = pointer_state.view;
+ } else {
+ pointer_state.right.held = false;
}
- swayc_t *pointer = container_under_pointer();
- if (pointer) {
- set_focused_container(pointer);
- int midway_x = pointer->x + pointer->width/2;
- int midway_y = pointer->y + pointer->height/2;
- pointer_state.lock.bottom = origin->y < midway_y;
- pointer_state.lock.top = !pointer_state.lock.bottom;
- pointer_state.lock.right = origin->x < midway_x;
- pointer_state.lock.left = !pointer_state.lock.right;
+ break;
+
+ case M_SCROLL_CLICK:
+ if (state == WLC_BUTTON_STATE_PRESSED) {
+ pointer_state.scroll.held = true;
+ pointer_state.scroll.x = origin->x;
+ pointer_state.scroll.y = origin->y;
+ pointer_state.scroll.view = pointer_state.view;
+ } else {
+ pointer_state.scroll.held = false;
}
+ break;
+
+ //TODO scrolling behavior
+ case M_SCROLL_UP:
+ case M_SCROLL_DOWN:
+ break;
+ }
+
+ // get focused window and check if to change focus on mouse click
+ swayc_t *focused = get_focused_container(&root_container);
+
+ // dont change focus or mode if fullscreen
+ if (swayc_is_fullscreen(focused)) {
+ return EVENT_PASSTHROUGH;
+ }
+
+ // set pointer mode
+ pointer_mode_set(button,
+ (modifiers->mods & config->floating_mod) == config->floating_mod);
+ // Return if mode has been set
+ if (pointer_state.mode) {
+ return EVENT_HANDLED;
+ }
+
+ // Always send mouse release
+ if (state == WLC_BUTTON_STATE_RELEASED) {
+ return EVENT_PASSTHROUGH;
+ }
+
+ // Check whether to change focus
+ swayc_t *pointer = pointer_state.view;
+ if (pointer && focused != pointer) {
+ set_focused_container(pointer_state.view);
+ // Send to front if floating
if (pointer->is_floating) {
int i;
for (i = 0; i < pointer->parent->floating->length; i++) {
@@ -447,40 +444,12 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
break;
}
}
- arrange_windows(pointer->parent, -1, -1);
- if (modifiers->mods & config->floating_mod) {
- pointer_state.floating.drag = pointer_state.l_held;
- pointer_state.floating.resize = pointer_state.r_held;
- start_floating(pointer);
- }
- // Dont want pointer sent to window while dragging or resizing
- return (pointer_state.floating.drag || pointer_state.floating.resize);
- } else {
- if (modifiers->mods & config->floating_mod) {
- pointer_state.floating.drag = pointer_state.l_held;
- pointer_state.tiling.resize = pointer_state.r_held;
- pointer_state.tiling.init_view = pointer;
- // Dont want pointer sent when resizing
- return (pointer_state.tiling.resize);
- }
- }
- return (pointer && pointer != focused);
- } else {
- sway_log(L_DEBUG, "Mouse button %u released", button);
- if (button == M_LEFT_CLICK) {
- pointer_state.l_held = false;
- pointer_state.floating.drag = false;
- pointer_state.tiling.init_view = NULL;
- }
- if (button == M_RIGHT_CLICK) {
- pointer_state.r_held = false;
- pointer_state.floating.resize = false;
- pointer_state.tiling.resize = false;
- pointer_state.tiling.init_view = NULL;
- pointer_state.lock = (struct pointer_lock){false ,false ,false ,false, false, false, false, false};
+ wlc_view_bring_to_front(view);
}
}
- return false;
+
+ // Finally send click
+ return EVENT_PASSTHROUGH;
}
static void handle_wlc_ready(void) {
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};
}
diff --git a/sway/layout.c b/sway/layout.c
index 035fea34..bc12b9b1 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -20,7 +20,8 @@ void init_layout(void) {
root_container.handle = -1;
}
-static int index_child(swayc_t *parent, swayc_t *child) {
+static int index_child(swayc_t *child) {
+ swayc_t *parent = child->parent;
int i;
for (i = 0; i < parent->children->length; ++i) {
if (parent->children->items[i] == child) {
@@ -54,7 +55,7 @@ void add_floating(swayc_t *ws, swayc_t *child) {
swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) {
swayc_t *parent = sibling->parent;
- int i = index_child(parent, sibling);
+ int i = index_child(sibling);
if (i == parent->children->length) {
--i;
}
@@ -68,17 +69,65 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child) {
if (parent == NULL) {
return NULL;
}
- int i = index_child(parent, child);
+ int i = index_child(child);
parent->children->items[i] = new_child;
new_child->parent = child->parent;
+ // Set parent for new child
if (child->parent->focused == child) {
child->parent->focused = new_child;
}
child->parent = NULL;
+ // Set geometry for new child
+ new_child->x = child->x;
+ new_child->y = child->y;
+ new_child->width = child->width;
+ new_child->height = child->height;
+ // set child geometry to 0
+ child->x = 0;
+ child->y = 0;
+ child->width = 0;
+ child->height = 0;
return parent;
}
+void swap_container(swayc_t *a, swayc_t *b) {
+ //TODO doesnt handle floating <-> tiling swap
+ if (!sway_assert(a&&b, "%s: parameters must be non null",__func__) ||
+ !sway_assert(a->parent && b->parent, "%s: containers must have parents",__func__)) {
+ return;
+ }
+ size_t a_index = index_child(a);
+ size_t b_index = index_child(b);
+ swayc_t *a_parent = a->parent;
+ swayc_t *b_parent = b->parent;
+ // Swap the pointers
+ a_parent->children->items[a_index] = b;
+ b_parent->children->items[b_index] = a;
+ a->parent = b_parent;
+ b->parent = a_parent;
+ if (a_parent->focused == a) {
+ a_parent->focused = b;
+ }
+ // dont want to double switch
+ if (b_parent->focused == b && a_parent != b_parent) {
+ b_parent->focused = a;
+ }
+ // and their geometry
+ double x = a->x;
+ double y = a->y;
+ double w = a->width;
+ double h = a->height;
+ a->x = b->x;
+ a->y = b->y;
+ a->width = b->width;
+ a->height = b->height;
+ b->x = x;
+ b->y = y;
+ b->width = w;
+ b->height = h;
+}
+
swayc_t *remove_child(swayc_t *child) {
int i;
swayc_t *parent = child->parent;
@@ -154,6 +203,30 @@ void move_container(swayc_t *container,swayc_t* root,enum movement_direction dir
}
+void update_geometry(swayc_t *container) {
+ if (container->type != C_VIEW) {
+ return;
+ }
+ struct wlc_geometry geometry = {
+ .origin = {
+ .x = container->x + (container->is_floating ? 0 : container->gaps / 2),
+ .y = container->y + (container->is_floating ? 0 : container->gaps / 2)
+ },
+ .size = {
+ .w = container->width - (container->is_floating ? 0 : container->gaps),
+ .h = container->height - (container->is_floating ? 0 : container->gaps)
+ }
+ };
+ if (swayc_is_fullscreen(container)) {
+ swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT);
+ geometry.origin.x = 0;
+ geometry.origin.y = 0;
+ geometry.size.w = parent->width;
+ geometry.size.h = parent->height;
+ }
+ wlc_view_set_geometry(container->handle, 0, &geometry);
+ return;
+}
void arrange_windows(swayc_t *container, double width, double height) {
int i;
@@ -189,31 +262,11 @@ void arrange_windows(swayc_t *container, double width, double height) {
return;
case C_VIEW:
{
- struct wlc_geometry geometry = {
- .origin = {
- .x = container->x + container->gaps / 2,
- .y = container->y + container->gaps / 2
- },
- .size = {
- .w = width - container->gaps,
- .h = height - container->gaps
- }
- };
- if (swayc_is_fullscreen(container)) {
- swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT);
- geometry.origin.x = 0;
- geometry.origin.y = 0;
- geometry.size.w = parent->width;
- geometry.size.h = parent->height;
- wlc_view_set_geometry(container->handle, 0, &geometry);
- wlc_view_bring_to_front(container->handle);
- } else {
- wlc_view_set_geometry(container->handle, 0, &geometry);
- container->width = width;
- container->height = height;
- }
- sway_log(L_DEBUG, "Set view to %d x %d @ %d, %d", geometry.size.w, geometry.size.h,
- geometry.origin.x, geometry.origin.y);
+ container->width = width;
+ container->height = height;
+ update_geometry(container);
+ sway_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", container->width,
+ container->height, container->x, container->y);
}
return;
default:
@@ -287,35 +340,12 @@ void arrange_windows(swayc_t *container, double width, double height) {
for (i = 0; i < container->floating->length; ++i) {
swayc_t *view = container->floating->items[i];
if (view->type == C_VIEW) {
- // Set the geometry
- struct wlc_geometry geometry = {
- .origin = {
- .x = view->x,
- .y = view->y
- },
- .size = {
- .w = view->width,
- .h = view->height
- }
- };
+ update_geometry(view);
if (swayc_is_fullscreen(view)) {
- swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT);
- geometry.origin.x = 0;
- geometry.origin.y = 0;
- geometry.size.w = parent->width;
- geometry.size.h = parent->height;
- wlc_view_set_geometry(view->handle, 0, &geometry);
wlc_view_bring_to_front(view->handle);
- } else {
- wlc_view_set_geometry(view->handle, 0, &geometry);
- // Bring the views to the front in order of the list, the list
- // will be kept up to date so that more recently focused views
- // have higher indexes
- // This is conditional on there not being a fullscreen view in the workspace
- if (!container->focused
- || !swayc_is_fullscreen(container->focused)) {
- wlc_view_bring_to_front(view->handle);
- }
+ } else if (!container->focused
+ || !swayc_is_fullscreen(container->focused)) {
+ wlc_view_bring_to_front(view->handle);
}
}
}
diff --git a/sway/resize.c b/sway/resize.c
index a08ef4a1..22d520af 100644
--- a/sway/resize.c
+++ b/sway/resize.c
@@ -6,267 +6,6 @@
#include "input_state.h"
#include "handlers.h"
-bool mouse_resize_tiled(struct wlc_origin prev_pos) {
- swayc_t *view = container_under_pointer();
- bool valid = true;
- bool changed_tiling = false;
- double dx = mouse_origin.x - prev_pos.x;
- double dy = mouse_origin.y - prev_pos.y;
- if (view != pointer_state.tiling.init_view) {
- changed_tiling = true;
- valid = false;
- if (view->type != C_WORKSPACE) {
- if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_LEFT) == view) {
- pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
- pointer_state.lock.temp_left = true;
- } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_RIGHT) == view) {
- pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
- pointer_state.lock.temp_right = true;
- } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_UP) == view) {
- pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
- pointer_state.lock.temp_up = true;
- } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_DOWN) == view) {
- pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
- pointer_state.lock.temp_down = true;
- }
- }
- }
-
- if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) {
- changed_tiling = true;
- valid = false;
- } else if (dx > 0 && pointer_state.lock.temp_left) {
- pointer_state.lock.temp_left = false;
- pointer_state.tiling.lock_pos.x = 0;
- }
-
- if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) {
- changed_tiling = true;
- valid = false;
- } else if (dx < 0 && pointer_state.lock.temp_right) {
- pointer_state.lock.temp_right = false;
- pointer_state.tiling.lock_pos.x = 0;
- }
-
- if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) {
- changed_tiling = true;
- valid = false;
- } else if (dy > 0 && pointer_state.lock.temp_up) {
- pointer_state.lock.temp_up = false;
- pointer_state.tiling.lock_pos.y = 0;
- }
-
- if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) {
- changed_tiling = true;
- valid = false;
- } else if (dy < 0 && pointer_state.lock.temp_down) {
- pointer_state.lock.temp_down = false;
- pointer_state.tiling.lock_pos.y = 0;
- }
-
- if (!view->is_floating && valid) {
- // Handle layout resizes -- Find the biggest parent container then apply resizes to that
- // and its bordering siblings
- swayc_t *parent = view;
- if (!pointer_state.lock.bottom) {
- while (parent->type != C_WORKSPACE) {
- // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better
- // way of doing this.
- if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) {
- parent = parent->parent;
- } else {
- break;
- }
- }
- if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
- swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN);
- if (sibling) {
- if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) {
- recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM);
- recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP);
- changed_tiling = true;
- } else {
- if (parent->height < min_sane_h) {
- //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
- pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
- pointer_state.lock.temp_up = true;
- } else if (sibling->height < min_sane_h) {
- pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
- pointer_state.lock.temp_down = true;
- }
- }
- }
- }
- } else if (!pointer_state.lock.top) {
- while (parent->type != C_WORKSPACE) {
- if (fabs(parent->parent->y - view->y) <= 1) {
- parent = parent->parent;
- } else {
- break;
- }
- }
- if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
- swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP);
- if (sibling) {
- if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) {
- recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP);
- recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM);
- changed_tiling = true;
- } else {
- if (parent->height < min_sane_h) {
- //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
- pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
- pointer_state.lock.temp_down = true;
- } else if (sibling->height < min_sane_h) {
- pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
- pointer_state.lock.temp_up = true;
- }
- }
- }
- }
- }
-
- parent = view;
- if (!pointer_state.lock.right) {
- while (parent->type != C_WORKSPACE) {
- if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) {
- parent = parent->parent;
- } else {
- sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width);
- break;
- }
- }
- if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
- swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT);
- if (sibling) {
- if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) {
- recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT);
- recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT);
- changed_tiling = true;
- } else {
- if (parent->width < min_sane_w) {
- pointer_state.lock.temp_left = true;
- pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
- } else if (sibling->width < min_sane_w) {
- pointer_state.lock.temp_right = true;
- pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
- }
- }
- }
- }
- } else if (!pointer_state.lock.left) {
- while (parent->type != C_WORKSPACE) {
- if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) {
- parent = parent->parent;
- } else {
- break;
- }
- }
- if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
- swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT);
- if (sibling) {
- if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) {
- recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT);
- recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT);
- changed_tiling = true;
- } else {
- if (parent->width < min_sane_w) {
- pointer_state.lock.temp_right = true;
- pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
- } else if (sibling->width < min_sane_w) {
- pointer_state.lock.temp_left = true;
- pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
- }
- }
- }
- }
- }
- arrange_windows(swayc_active_workspace(), -1, -1);
- }
- return changed_tiling;
-}
-
-bool resize_floating(struct wlc_origin prev_pos) {
- bool changed = false;
- swayc_t *view = container_under_pointer();
- uint32_t edge = 0;
- int dx = mouse_origin.x - prev_pos.x;
- int dy = mouse_origin.y - prev_pos.y;
-
- // Move and resize the view based on the dx/dy and mouse position
- int midway_x = view->x + view->width/2;
- int midway_y = view->y + view->height/2;
- if (dx < 0) {
- if (!pointer_state.lock.right) {
- if (view->width > min_sane_w) {
- changed = true;
- view->width += dx;
- edge += WLC_RESIZE_EDGE_RIGHT;
- }
- } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) {
- changed = true;
- view->x += dx;
- view->width -= dx;
- edge += WLC_RESIZE_EDGE_LEFT;
- }
- } else if (dx > 0) {
- if (mouse_origin.x > midway_x && !pointer_state.lock.right) {
- changed = true;
- view->width += dx;
- edge += WLC_RESIZE_EDGE_RIGHT;
- } else if (!pointer_state.lock.left) {
- if (view->width > min_sane_w) {
- changed = true;
- view->x += dx;
- view->width -= dx;
- edge += WLC_RESIZE_EDGE_LEFT;
- }
- }
- }
-
- if (dy < 0) {
- if (!pointer_state.lock.bottom) {
- if (view->height > min_sane_h) {
- changed = true;
- view->height += dy;
- edge += WLC_RESIZE_EDGE_BOTTOM;
- }
- } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) {
- changed = true;
- view->y += dy;
- view->height -= dy;
- edge += WLC_RESIZE_EDGE_TOP;
- }
- } else if (dy > 0) {
- if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) {
- changed = true;
- view->height += dy;
- edge += WLC_RESIZE_EDGE_BOTTOM;
- } else if (!pointer_state.lock.top) {
- if (view->height > min_sane_h) {
- changed = true;
- view->y += dy;
- view->height -= dy;
- edge += WLC_RESIZE_EDGE_TOP;
- }
- }
- }
- if (changed) {
- struct wlc_geometry geometry = {
- .origin = {
- .x = view->x,
- .y = view->y
- },
- .size = {
- .w = view->width,
- .h = view->height
- }
- };
- wlc_view_set_geometry(view->handle, edge, &geometry);
- }
- return changed;
-}
-
bool resize_tiled(int amount, bool use_width) {
swayc_t *parent = get_focused_view(swayc_active_workspace());
swayc_t *focused = parent;