aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/config.h9
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/input/map_from_region.c79
-rw-r--r--sway/commands/input/map_to_output.c2
-rw-r--r--sway/config/input.c13
-rw-r--r--sway/input/cursor.c60
-rw-r--r--sway/input/input-manager.c1
-rw-r--r--sway/input/seat.c4
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway-input.5.txt14
11 files changed, 160 insertions, 25 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 75534163..0732a90a 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -193,6 +193,7 @@ sway_cmd input_cmd_drag_lock;
193sway_cmd input_cmd_dwt; 193sway_cmd input_cmd_dwt;
194sway_cmd input_cmd_events; 194sway_cmd input_cmd_events;
195sway_cmd input_cmd_left_handed; 195sway_cmd input_cmd_left_handed;
196sway_cmd input_cmd_map_from_region;
196sway_cmd input_cmd_map_to_output; 197sway_cmd input_cmd_map_to_output;
197sway_cmd input_cmd_middle_emulation; 198sway_cmd input_cmd_middle_emulation;
198sway_cmd input_cmd_natural_scroll; 199sway_cmd input_cmd_natural_scroll;
diff --git a/include/sway/config.h b/include/sway/config.h
index 085f7b92..87123289 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -51,6 +51,12 @@ struct sway_mode {
51 list_t *keycode_bindings; 51 list_t *keycode_bindings;
52}; 52};
53 53
54struct input_config_mapped_from_region {
55 double x1, y1;
56 double x2, y2;
57 bool mm;
58};
59
54/** 60/**
55 * options for input devices 61 * options for input devices
56 */ 62 */
@@ -77,7 +83,8 @@ struct input_config {
77 char *xkb_rules; 83 char *xkb_rules;
78 char *xkb_variant; 84 char *xkb_variant;
79 85
80 char *mapped_output; 86 struct input_config_mapped_from_region *mapped_from_region;
87 char *mapped_to_output;
81 88
82 bool capturable; 89 bool capturable;
83 struct wlr_box region; 90 struct wlr_box region;
diff --git a/sway/commands.c b/sway/commands.c
index 5827fc13..a67bc127 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -191,6 +191,7 @@ static struct cmd_handler input_handlers[] = {
191 { "dwt", input_cmd_dwt }, 191 { "dwt", input_cmd_dwt },
192 { "events", input_cmd_events }, 192 { "events", input_cmd_events },
193 { "left_handed", input_cmd_left_handed }, 193 { "left_handed", input_cmd_left_handed },
194 { "map_from_region", input_cmd_map_from_region },
194 { "map_to_output", input_cmd_map_to_output }, 195 { "map_to_output", input_cmd_map_to_output },
195 { "middle_emulation", input_cmd_middle_emulation }, 196 { "middle_emulation", input_cmd_middle_emulation },
196 { "natural_scroll", input_cmd_natural_scroll }, 197 { "natural_scroll", input_cmd_natural_scroll },
diff --git a/sway/commands/input/map_from_region.c b/sway/commands/input/map_from_region.c
new file mode 100644
index 00000000..80bb856d
--- /dev/null
+++ b/sway/commands/input/map_from_region.c
@@ -0,0 +1,79 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h>
3#include <string.h>
4#include <strings.h>
5#include "log.h"
6#include "sway/commands.h"
7#include "sway/config.h"
8#include "sway/input/input-manager.h"
9
10static bool parse_coords(const char *str, double *x, double *y, bool *mm) {
11 *mm = false;
12
13 char *end;
14 *x = strtod(str, &end);
15 if (end[0] != 'x') {
16 return false;
17 }
18 ++end;
19
20 *y = strtod(end, &end);
21 if (end[0] == 'm') {
22 // Expect mm
23 if (end[1] != 'm') {
24 return false;
25 }
26 *mm = true;
27 end = &end[2];
28 }
29 if (end[0] != '\0') {
30 return false;
31 }
32
33 return true;
34}
35
36struct cmd_results *input_cmd_map_from_region(int argc, char **argv) {
37 struct cmd_results *error = NULL;
38 if ((error = checkarg(argc, "map_from_region", EXPECTED_EQUAL_TO, 2))) {
39 return error;
40 }
41 struct input_config *current_input_config =
42 config->handler_context.input_config;
43 if (!current_input_config) {
44 return cmd_results_new(CMD_FAILURE, "map_from_region",
45 "No input device defined");
46 }
47
48 struct input_config *new_config =
49 new_input_config(current_input_config->identifier);
50
51 new_config->mapped_from_region =
52 calloc(1, sizeof(struct input_config_mapped_from_region));
53
54 bool mm1, mm2;
55 if (!parse_coords(argv[0], &new_config->mapped_from_region->x1,
56 &new_config->mapped_from_region->y1, &mm1)) {
57 return cmd_results_new(CMD_FAILURE, "map_from_region",
58 "Invalid top-left coordinates");
59 }
60 if (!parse_coords(argv[1], &new_config->mapped_from_region->x2,
61 &new_config->mapped_from_region->y2, &mm2)) {
62 return cmd_results_new(CMD_FAILURE, "map_from_region",
63 "Invalid bottom-right coordinates");
64 }
65 if (new_config->mapped_from_region->x1 > new_config->mapped_from_region->x2 ||
66 new_config->mapped_from_region->y1 > new_config->mapped_from_region->y2) {
67 return cmd_results_new(CMD_FAILURE, "map_from_region",
68 "Invalid rectangle");
69 }
70 if (mm1 != mm2) {
71 return cmd_results_new(CMD_FAILURE, "map_from_region",
72 "Both coordinates must be in the same unit");
73 }
74 new_config->mapped_from_region->mm = mm1;
75
76 apply_input_config(new_config);
77
78 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
79}
diff --git a/sway/commands/input/map_to_output.c b/sway/commands/input/map_to_output.c
index 60e4608e..68439bec 100644
--- a/sway/commands/input/map_to_output.c
+++ b/sway/commands/input/map_to_output.c
@@ -20,7 +20,7 @@ struct cmd_results *input_cmd_map_to_output(int argc, char **argv) {
20 struct input_config *new_config = 20 struct input_config *new_config =
21 new_input_config(current_input_config->identifier); 21 new_input_config(current_input_config->identifier);
22 22
23 new_config->mapped_output = strdup(argv[0]); 23 new_config->mapped_to_output = strdup(argv[0]);
24 apply_input_config(new_config); 24 apply_input_config(new_config);
25 25
26 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 26 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/config/input.c b/sway/config/input.c
index a9f20723..17303ccc 100644
--- a/sway/config/input.c
+++ b/sway/config/input.c
@@ -96,9 +96,16 @@ void merge_input_config(struct input_config *dst, struct input_config *src) {
96 free(dst->xkb_variant); 96 free(dst->xkb_variant);
97 dst->xkb_variant = strdup(src->xkb_variant); 97 dst->xkb_variant = strdup(src->xkb_variant);
98 } 98 }
99 if (src->mapped_output) { 99 if (src->mapped_from_region) {
100 free(dst->mapped_output); 100 free(dst->mapped_from_region);
101 dst->mapped_output = strdup(src->mapped_output); 101 dst->mapped_from_region =
102 malloc(sizeof(struct input_config_mapped_from_region));
103 memcpy(dst->mapped_from_region, src->mapped_from_region,
104 sizeof(struct input_config_mapped_from_region));
105 }
106 if (src->mapped_to_output) {
107 free(dst->mapped_to_output);
108 dst->mapped_to_output = strdup(src->mapped_to_output);
102 } 109 }
103} 110}
104 111
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 831109dc..944ad8eb 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -261,22 +261,60 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) {
261 wlr_log(L_DEBUG, "TODO: handle touch motion event: %p", event); 261 wlr_log(L_DEBUG, "TODO: handle touch motion event: %p", event);
262} 262}
263 263
264static double apply_mapping_from_coord(double low, double high, double value) {
265 if (value == -1) {
266 return value;
267 }
268
269 value = (value - low) / (high - low);
270 if (value < 0) {
271 return 0;
272 } else if (value > 1) {
273 return 1;
274 } else {
275 return value;
276 }
277}
278
279static void apply_mapping_from_region(struct wlr_input_device *device,
280 struct input_config_mapped_from_region *region, double *x, double *y) {
281 double x1 = region->x1, x2 = region->x2;
282 double y1 = region->y1, y2 = region->y2;
283
284 if (region->mm) {
285 if (device->width_mm == 0 || device->height_mm == 0) {
286 return;
287 }
288 x1 /= device->width_mm;
289 x2 /= device->width_mm;
290 y1 /= device->height_mm;
291 y2 /= device->height_mm;
292 }
293
294 *x = apply_mapping_from_coord(x1, x2, *x);
295 *y = apply_mapping_from_coord(y1, y2, *y);
296}
297
264static void handle_tool_axis(struct wl_listener *listener, void *data) { 298static void handle_tool_axis(struct wl_listener *listener, void *data) {
265 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); 299 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis);
266 struct wlr_event_tablet_tool_axis *event = data; 300 struct wlr_event_tablet_tool_axis *event = data;
301 struct sway_input_device *input_device = event->device->data;
267 302
268 if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) && 303 double x = -1, y = -1;
269 (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { 304 if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) {
270 wlr_cursor_warp_absolute(cursor->cursor, event->device, 305 x = event->x;
271 event->x, event->y); 306 }
272 cursor_send_pointer_motion(cursor, event->time_msec); 307 if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) {
273 } else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) { 308 y = event->y;
274 wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, -1);
275 cursor_send_pointer_motion(cursor, event->time_msec);
276 } else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) {
277 wlr_cursor_warp_absolute(cursor->cursor, event->device, -1, event->y);
278 cursor_send_pointer_motion(cursor, event->time_msec);
279 } 309 }
310
311 struct input_config *ic = input_device_get_config(input_device);
312 if (ic != NULL && ic->mapped_from_region != NULL) {
313 apply_mapping_from_region(event->device, ic->mapped_from_region, &x, &y);
314 }
315
316 wlr_cursor_warp_absolute(cursor->cursor, event->device, x, y);
317 cursor_send_pointer_motion(cursor, event->time_msec);
280} 318}
281 319
282static void handle_tool_tip(struct wl_listener *listener, void *data) { 320static void handle_tool_tip(struct wl_listener *listener, void *data) {
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index ae55d2a1..29b47a7b 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -211,6 +211,7 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
211 if (!sway_assert(input_device, "could not allocate input device")) { 211 if (!sway_assert(input_device, "could not allocate input device")) {
212 return; 212 return;
213 } 213 }
214 device->data = input_device;
214 215
215 input_device->wlr_device = device; 216 input_device->wlr_device = device;
216 input_device->identifier = get_device_identifier(device); 217 input_device->identifier = get_device_identifier(device);
diff --git a/sway/input/seat.c b/sway/input/seat.c
index e88bcfd1..963d38b2 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -269,11 +269,11 @@ static void seat_apply_input_config(struct sway_seat *seat,
269 } 269 }
270 wlr_log(L_DEBUG, "Applying input config to %s", 270 wlr_log(L_DEBUG, "Applying input config to %s",
271 sway_device->input_device->identifier); 271 sway_device->input_device->identifier);
272 if (ic->mapped_output) { 272 if (ic->mapped_to_output) {
273 struct sway_container *output = NULL; 273 struct sway_container *output = NULL;
274 for (int i = 0; i < root_container.children->length; ++i) { 274 for (int i = 0; i < root_container.children->length; ++i) {
275 struct sway_container *_output = root_container.children->items[i]; 275 struct sway_container *_output = root_container.children->items[i];
276 if (strcasecmp(_output->name, ic->mapped_output) == 0) { 276 if (strcasecmp(_output->name, ic->mapped_to_output) == 0) {
277 output = _output; 277 output = _output;
278 break; 278 break;
279 } 279 }
diff --git a/sway/meson.build b/sway/meson.build
index a8107e4e..c9bb8f83 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -90,6 +90,7 @@ sway_sources = files(
90 'commands/input/dwt.c', 90 'commands/input/dwt.c',
91 'commands/input/events.c', 91 'commands/input/events.c',
92 'commands/input/left_handed.c', 92 'commands/input/left_handed.c',
93 'commands/input/map_from_region.c',
93 'commands/input/map_to_output.c', 94 'commands/input/map_to_output.c',
94 'commands/input/middle_emulation.c', 95 'commands/input/middle_emulation.c',
95 'commands/input/natural_scroll.c', 96 'commands/input/natural_scroll.c',
diff --git a/sway/sway-input.5.txt b/sway/sway-input.5.txt
index 948b4b6f..c7305503 100644
--- a/sway/sway-input.5.txt
+++ b/sway/sway-input.5.txt
@@ -52,13 +52,13 @@ Mapping Configuration
52 layout. Only meaningful if the device is a pointer, touch, or drawing tablet 52 layout. Only meaningful if the device is a pointer, touch, or drawing tablet
53 device. 53 device.
54 54
55**input** <identifier> map_region <WxH\@X,Y>:: 55**input** <identifier> map_from_region <X1xY1> <X2xY2>::
56 Ignores inputs from this device that do not occur within the specified region. 56 Ignores inputs from this device that do not occur within the specified
57 Can be in millimeters (e.g. 10mmx20mm\@10mm,20mm) or in terms of 0..1 (e.g. 57 region. Can be in millimeters (e.g. 10x20mm 20x40mm) or in terms of 0..1
58 0.5x0.5\@0,0). Not all devices support millimeters. Only meaningful if the 58 (e.g. 0.5x0.5 0.7x0.7). Not all devices support millimeters. Only meaningful
59 device is not a keyboard an provides events in absolute terms (such as a 59 if the device is not a keyboard an provides events in absolute terms (such
60 drawing tablet or touch screen - most pointers provide events relative to the 60 as a drawing tablet or touch screen - most pointers provide events relative
61 previous frame). 61 to the previous frame).
62 62
63Libinput Configuration 63Libinput Configuration
64~~~~~~~~~~~~~~~~~~~~~~ 64~~~~~~~~~~~~~~~~~~~~~~