From 4799d07ac1bb08a770ee702eb3fd0ab4654f878a Mon Sep 17 00:00:00 2001
From: "S. Christoffer Eliesen" <christoffer@eliesen.no>
Date: Wed, 28 Oct 2015 00:41:28 +0100
Subject: input_state: Extract 'pointer_position_set' function from handlers.

---
 sway/input_state.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

(limited to 'sway/input_state.c')

diff --git a/sway/input_state.c b/sway/input_state.c
index 2743a9ea..bd46a5ac 100644
--- a/sway/input_state.c
+++ b/sway/input_state.c
@@ -2,6 +2,7 @@
 #include <stdbool.h>
 #include <ctype.h>
 #include "log.h"
+#include "config.h"
 
 #include "input_state.h"
 
@@ -161,6 +162,29 @@ static void reset_initial_sibling(void) {
 	pointer_state.mode = 0;
 }
 
+void pointer_position_set(struct wlc_origin *new_origin, bool force_focus) {
+	pointer_state.delta.x = new_origin->x - pointer_state.origin.x;
+	pointer_state.delta.y = new_origin->y - pointer_state.origin.y;
+	pointer_state.origin.x = new_origin->x;
+	pointer_state.origin.y = new_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();
+	// Otherwise change focus if config is set
+	} else if (force_focus || (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);
+		}
+	}
+
+	wlc_pointer_set_origin(new_origin);
+}
+
 // Mode set left/right click
 
 static void pointer_mode_set_left(void) {
-- 
cgit v1.2.3


From 78ca6197697d4f07eddf0c544daff85603adab90 Mon Sep 17 00:00:00 2001
From: "S. Christoffer Eliesen" <christoffer@eliesen.no>
Date: Mon, 26 Oct 2015 12:20:32 +0100
Subject: commands: Learn mouse_warping.

Place mouse at center of focused view when changing to a workspace on a
different output, if option is enabled. (This replicates existing i3
option.)

This can be triggered in multiple ways:
A) via `workspace <name>` which changes output
B) via `focus <direction>` which changes output
C) via `focus output <name>` which (obviously) changes output
---
 include/commands.h    |  1 +
 include/input_state.h |  1 +
 sway.5.txt            |  4 ++++
 sway/commands.c       | 34 ++++++++++++++++++++++++++++++++--
 sway/focus.c          | 26 +++++++++++++++++++-------
 sway/input_state.c    |  7 +++++++
 6 files changed, 64 insertions(+), 9 deletions(-)

(limited to 'sway/input_state.c')

diff --git a/include/commands.h b/include/commands.h
index 8e53c74d..f6777930 100644
--- a/include/commands.h
+++ b/include/commands.h
@@ -2,6 +2,7 @@
 #define _SWAY_COMMANDS_H
 #include <stdbool.h>
 #include <json-c/json.h>
+#include <wlc/wlc.h>
 #include "config.h"
 
 
diff --git a/include/input_state.h b/include/input_state.h
index dd5d71a8..52759052 100644
--- a/include/input_state.h
+++ b/include/input_state.h
@@ -66,6 +66,7 @@ extern struct pointer_state {
 } pointer_state;
 
 void pointer_position_set(struct wlc_origin *new_origin, bool force_focus);
+void center_pointer_on(swayc_t *view);
 
 // on button release unset mode depending on the button.
 // on button press set mode conditionally depending on the button
diff --git a/sway.5.txt b/sway.5.txt
index dad55c5f..27735db6 100644
--- a/sway.5.txt
+++ b/sway.5.txt
@@ -102,6 +102,10 @@ Commands
 	Moves the focused container to the workspace identified by _name_.
 	_name_ may be a special workspace name. See **workspace**.
 
+**mouse_warping** <output|none>::
+	When _output_: place mouse at center of newly focused window when changing
+	output. When _none_: don't move mouse.
+
 **output** <name> <resolution|res WIDTHxHEIGHT> <position|pos X,Y>::
 	Configures the specified output. It will use the given resolution and be
 	arranged at the given position in the layout tree. You may omit either of
diff --git a/sway/commands.c b/sway/commands.c
index 441b6fd7..00a4d1b0 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -21,6 +21,7 @@
 #include "handlers.h"
 #include "sway.h"
 #include "resize.h"
+#include "input_state.h"
 
 typedef struct cmd_results *sway_cmd(int argc, char **argv);
 
@@ -45,6 +46,7 @@ static sway_cmd cmd_kill;
 static sway_cmd cmd_layout;
 static sway_cmd cmd_log_colors;
 static sway_cmd cmd_mode;
+static sway_cmd cmd_mouse_warping;
 static sway_cmd cmd_move;
 static sway_cmd cmd_output;
 static sway_cmd cmd_reload;
@@ -383,9 +385,13 @@ static struct cmd_results *cmd_focus(int argc, char **argv) {
 		} else if (!workspace_switch(swayc_active_workspace_for(output))) {
 			return cmd_results_new(CMD_FAILURE, "focus output",
 				"Switching to workspace on output '%s' was blocked", argv[1]);
-		} else {
-			return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+		} else if (config->mouse_warping) {
+			swayc_t *focused = get_focused_view(output);
+			if (focused && focused->type == C_VIEW) {
+				center_pointer_on(focused);
+			}
 		}
+		return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 	} else if ((error = checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1))) {
 		return error;
 	}
@@ -528,6 +534,20 @@ static struct cmd_results *cmd_mode(int argc, char **argv) {
 	return cmd_results_new(mode_make ? CMD_BLOCK_MODE : CMD_SUCCESS, NULL, NULL);
 }
 
+static struct cmd_results *cmd_mouse_warping(int argc, char **argv) {
+	struct cmd_results *error = NULL;
+	if ((error = checkarg(argc, "mouse_warping", EXPECTED_EQUAL_TO, 1))) {
+		return error;
+	} else if (strcasecmp(argv[0], "output") == 0) {
+		config->mouse_warping = true;
+	} else if (strcasecmp(argv[0], "none") == 0) {
+		config->mouse_warping = false;
+	} else {
+		return cmd_results_new(CMD_FAILURE, "mouse_warping", "Expected 'mouse_warping output|none'");
+	}
+	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
+
 static struct cmd_results *cmd_move(int argc, char **argv) {
 	struct cmd_results *error = NULL;
 	if (config->reading) return cmd_results_new(CMD_FAILURE, "move", "Can't be used in config file.");
@@ -1165,7 +1185,16 @@ static struct cmd_results *cmd_workspace(int argc, char **argv) {
 				ws = workspace_create(argv[0]);
 			}
 		}
+		swayc_t *old_output = swayc_active_output();
 		workspace_switch(ws);
+		swayc_t *new_output = swayc_active_output();
+
+		if (config->mouse_warping && old_output != new_output) {
+			swayc_t *focused = get_focused_view(ws);
+			if (focused && focused->type == C_VIEW) {
+				center_pointer_on(focused);
+			}
+		}
 	} else {
 		if (strcasecmp(argv[1], "output") == 0) {
 			if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 3))) {
@@ -1217,6 +1246,7 @@ static struct cmd_handler handlers[] = {
 	{ "layout", cmd_layout },
 	{ "log_colors", cmd_log_colors },
 	{ "mode", cmd_mode },
+	{ "mouse_warping", cmd_mouse_warping },
 	{ "move", cmd_move },
 	{ "output", cmd_output },
 	{ "reload", cmd_reload },
diff --git a/sway/focus.c b/sway/focus.c
index 1aa7579b..7f0b1599 100644
--- a/sway/focus.c
+++ b/sway/focus.c
@@ -4,6 +4,8 @@
 #include "log.h"
 #include "workspace.h"
 #include "layout.h"
+#include "config.h"
+#include "input_state.h"
 
 bool locked_container_focus = false;
 bool locked_view_focus = false;
@@ -49,14 +51,24 @@ static void update_focus(swayc_t *c) {
 }
 
 bool move_focus(enum movement_direction direction) {
-	swayc_t *view = get_focused_container(&root_container);
-	view = get_swayc_in_direction(view, direction);
-	if (view) {
-		if (direction == MOVE_PARENT) {
-			return set_focused_container(view);
-		} else {
-			return set_focused_container(get_focused_view(view));
+	swayc_t *old_view = get_focused_container(&root_container);
+	swayc_t *new_view = get_swayc_in_direction(old_view, direction);
+	if (!new_view) {
+		return false;
+	} else if (direction == MOVE_PARENT) {
+		return set_focused_container(new_view);
+	} else if (config->mouse_warping) {
+		swayc_t *old_op = old_view->type == C_OUTPUT ?
+			old_view : swayc_parent_by_type(old_view, C_OUTPUT);
+		swayc_t *focused = get_focused_view(new_view);
+		if (set_focused_container(focused)) {
+			if (old_op != swayc_active_output() && focused && focused->type == C_VIEW) {
+				center_pointer_on(focused);
+			}
+			return true;
 		}
+	} else {
+		return set_focused_container(get_focused_view(new_view));
 	}
 	return false;
 }
diff --git a/sway/input_state.c b/sway/input_state.c
index bd46a5ac..ee3dc7cf 100644
--- a/sway/input_state.c
+++ b/sway/input_state.c
@@ -185,6 +185,13 @@ void pointer_position_set(struct wlc_origin *new_origin, bool force_focus) {
 	wlc_pointer_set_origin(new_origin);
 }
 
+void center_pointer_on(swayc_t *view) {
+	struct wlc_origin new_origin;
+	new_origin.x = view->x + view->width/2;
+	new_origin.y = view->y + view->height/2;
+	pointer_position_set(&new_origin, true);
+}
+
 // Mode set left/right click
 
 static void pointer_mode_set_left(void) {
-- 
cgit v1.2.3


From 5ba47d4a44b21500ed3af2670cb1c807b7fed850 Mon Sep 17 00:00:00 2001
From: "S. Christoffer Eliesen" <christoffer@eliesen.no>
Date: Thu, 29 Oct 2015 18:02:02 +0100
Subject: input_state: Remove mouse_origin (x&y). Query wlc instead.

---
 include/input_state.h |  5 -----
 sway/container.c      |  8 +++++---
 sway/handlers.c       |  4 ----
 sway/input_state.c    | 20 ++++++++++++--------
 4 files changed, 17 insertions(+), 20 deletions(-)

(limited to 'sway/input_state.c')

diff --git a/include/input_state.h b/include/input_state.h
index 52759052..a1f238e1 100644
--- a/include/input_state.h
+++ b/include/input_state.h
@@ -48,11 +48,6 @@ extern struct pointer_state {
 	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;
diff --git a/sway/container.c b/sway/container.c
index 4f9e2b5e..f3e2b3ae 100644
--- a/sway/container.c
+++ b/sway/container.c
@@ -510,7 +510,7 @@ swayc_t *swayc_active_workspace_for(swayc_t *cont) {
 }
 
 static bool pointer_test(swayc_t *view, void *_origin) {
-	const struct mouse_origin *origin = _origin;
+	const struct wlc_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
@@ -531,6 +531,8 @@ swayc_t *container_under_pointer(void) {
 	if (lookup->children == 0) {
 		return NULL;
 	}
+	struct wlc_origin origin;
+	wlc_pointer_get_origin(&origin);
 	while (lookup->type != C_VIEW) {
 		int i;
 		int len;
@@ -545,7 +547,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], &pointer_state.origin)) {
+				if (pointer_test(lookup->floating->items[i], &origin)) {
 					lookup = lookup->floating->items[i];
 					got_floating = true;
 					break;
@@ -558,7 +560,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], &pointer_state.origin)) {
+			if (pointer_test(lookup->children->items[i], &origin)) {
 				lookup = lookup->children->items[i];
 				break;
 			}
diff --git a/sway/handlers.c b/sway/handlers.c
index e1612dc1..510b4261 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -343,10 +343,6 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
 	// 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:
diff --git a/sway/input_state.c b/sway/input_state.c
index ee3dc7cf..9bd8ad4d 100644
--- a/sway/input_state.c
+++ b/sway/input_state.c
@@ -163,10 +163,10 @@ static void reset_initial_sibling(void) {
 }
 
 void pointer_position_set(struct wlc_origin *new_origin, bool force_focus) {
-	pointer_state.delta.x = new_origin->x - pointer_state.origin.x;
-	pointer_state.delta.y = new_origin->y - pointer_state.origin.y;
-	pointer_state.origin.x = new_origin->x;
-	pointer_state.origin.y = new_origin->y;
+	struct wlc_origin origin;
+	wlc_pointer_get_origin(&origin);
+	pointer_state.delta.x = new_origin->x - origin.x;
+	pointer_state.delta.y = new_origin->y - origin.y;
 
 	// Update view under pointer
 	swayc_t *prev_view = pointer_state.view;
@@ -214,8 +214,10 @@ static void pointer_mode_set_right(void) {
 	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;
+	struct wlc_origin origin;
+	wlc_pointer_get_origin(&origin);
+	lock.left = origin.x > midway_x;
+	lock.top = origin.y > midway_y;
 
 	if (initial.ptr->is_floating) {
 		pointer_state.mode = M_RESIZING | M_FLOATING;
@@ -277,8 +279,10 @@ void pointer_mode_update(void) {
 		pointer_state.mode = 0;
 		return;
 	}
-	int dx = pointer_state.origin.x;
-	int dy = pointer_state.origin.y;
+	struct wlc_origin origin;
+	wlc_pointer_get_origin(&origin);
+	int dx = origin.x;
+	int dy = origin.y;
 
 	switch (pointer_state.mode) {
 	case M_FLOATING | M_DRAGGING:
-- 
cgit v1.2.3