diff options
| author | emersion <contact@emersion.fr> | 2018-04-24 19:39:29 +0100 | 
|---|---|---|
| committer | emersion <contact@emersion.fr> | 2018-04-26 10:53:47 +0100 | 
| commit | ff61df17ffd358b03663a35fe7140e51e1ee98fc (patch) | |
| tree | 3736887591d8464f577d2ad4a753a404d38d77ae /sway | |
| parent | d94bb78ff3ade39cc848d0acfd571b9ac6917868 (diff) | |
| download | sway-ff61df17ffd358b03663a35fe7140e51e1ee98fc.tar.xz | |
Add map_from_region command
Diffstat (limited to 'sway')
| -rw-r--r-- | sway/commands.c | 1 | ||||
| -rw-r--r-- | sway/commands/input/map_from_region.c | 79 | ||||
| -rw-r--r-- | sway/commands/input/map_to_output.c | 2 | ||||
| -rw-r--r-- | sway/config/input.c | 13 | ||||
| -rw-r--r-- | sway/input/cursor.c | 60 | ||||
| -rw-r--r-- | sway/input/input-manager.c | 1 | ||||
| -rw-r--r-- | sway/input/seat.c | 4 | ||||
| -rw-r--r-- | sway/meson.build | 1 | ||||
| -rw-r--r-- | sway/sway-input.5.txt | 14 | 
9 files changed, 151 insertions, 24 deletions
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[] = {  	{ "dwt", input_cmd_dwt },  	{ "events", input_cmd_events },  	{ "left_handed", input_cmd_left_handed }, +	{ "map_from_region", input_cmd_map_from_region },  	{ "map_to_output", input_cmd_map_to_output },  	{ "middle_emulation", input_cmd_middle_emulation },  	{ "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 @@ +#define _POSIX_C_SOURCE 200809L +#include <stdbool.h> +#include <string.h> +#include <strings.h> +#include "log.h" +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/input/input-manager.h" + +static bool parse_coords(const char *str, double *x, double *y, bool *mm) { +	*mm = false; + +	char *end; +	*x = strtod(str, &end); +	if (end[0] != 'x') { +		return false; +	} +	++end; + +	*y = strtod(end, &end); +	if (end[0] == 'm') { +		// Expect mm +		if (end[1] != 'm') { +			return false; +		} +		*mm = true; +		end = &end[2]; +	} +	if (end[0] != '\0') { +		return false; +	} + +	return true; +} + +struct cmd_results *input_cmd_map_from_region(int argc, char **argv) { +	struct cmd_results *error = NULL; +	if ((error = checkarg(argc, "map_from_region", EXPECTED_EQUAL_TO, 2))) { +		return error; +	} +	struct input_config *current_input_config = +		config->handler_context.input_config; +	if (!current_input_config) { +		return cmd_results_new(CMD_FAILURE, "map_from_region", +			"No input device defined"); +	} + +	struct input_config *new_config = +		new_input_config(current_input_config->identifier); + +	new_config->mapped_from_region = +		calloc(1, sizeof(struct input_config_mapped_from_region)); + +	bool mm1, mm2; +	if (!parse_coords(argv[0], &new_config->mapped_from_region->x1, +			&new_config->mapped_from_region->y1, &mm1)) { +		return cmd_results_new(CMD_FAILURE, "map_from_region", +			"Invalid top-left coordinates"); +	} +	if (!parse_coords(argv[1], &new_config->mapped_from_region->x2, +			&new_config->mapped_from_region->y2, &mm2)) { +		return cmd_results_new(CMD_FAILURE, "map_from_region", +			"Invalid bottom-right coordinates"); +	} +	if (new_config->mapped_from_region->x1 > new_config->mapped_from_region->x2 || +			new_config->mapped_from_region->y1 > new_config->mapped_from_region->y2) { +		return cmd_results_new(CMD_FAILURE, "map_from_region", +			"Invalid rectangle"); +	} +	if (mm1 != mm2) { +		return cmd_results_new(CMD_FAILURE, "map_from_region", +			"Both coordinates must be in the same unit"); +	} +	new_config->mapped_from_region->mm = mm1; + +	apply_input_config(new_config); + +	return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} 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) {  	struct input_config *new_config =  		new_input_config(current_input_config->identifier); -	new_config->mapped_output = strdup(argv[0]); +	new_config->mapped_to_output = strdup(argv[0]);  	apply_input_config(new_config);  	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) {  		free(dst->xkb_variant);  		dst->xkb_variant = strdup(src->xkb_variant);  	} -	if (src->mapped_output) { -		free(dst->mapped_output); -		dst->mapped_output = strdup(src->mapped_output); +	if (src->mapped_from_region) { +		free(dst->mapped_from_region); +		dst->mapped_from_region = +			malloc(sizeof(struct input_config_mapped_from_region)); +		memcpy(dst->mapped_from_region, src->mapped_from_region, +			sizeof(struct input_config_mapped_from_region)); +	} +	if (src->mapped_to_output) { +		free(dst->mapped_to_output); +		dst->mapped_to_output = strdup(src->mapped_to_output);  	}  } 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) {  	wlr_log(L_DEBUG, "TODO: handle touch motion event: %p", event);  } +static double apply_mapping_from_coord(double low, double high, double value) { +	if (value == -1) { +		return value; +	} + +	value = (value - low) / (high - low); +	if (value < 0) { +		return 0; +	} else if (value > 1) { +		return 1; +	} else { +		return value; +	} +} + +static void apply_mapping_from_region(struct wlr_input_device *device, +		struct input_config_mapped_from_region *region, double *x, double *y) { +	double x1 = region->x1, x2 = region->x2; +	double y1 = region->y1, y2 = region->y2; + +	if (region->mm) { +		if (device->width_mm == 0 || device->height_mm == 0) { +			return; +		} +		x1 /= device->width_mm; +		x2 /= device->width_mm; +		y1 /= device->height_mm; +		y2 /= device->height_mm; +	} + +	*x = apply_mapping_from_coord(x1, x2, *x); +	*y = apply_mapping_from_coord(y1, y2, *y); +} +  static void handle_tool_axis(struct wl_listener *listener, void *data) {  	struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis);  	struct wlr_event_tablet_tool_axis *event = data; +	struct sway_input_device *input_device = event->device->data; -	if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) && -			(event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { -		wlr_cursor_warp_absolute(cursor->cursor, event->device, -			event->x, event->y); -		cursor_send_pointer_motion(cursor, event->time_msec); -	} else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) { -		wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, -1); -		cursor_send_pointer_motion(cursor, event->time_msec); -	} else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { -		wlr_cursor_warp_absolute(cursor->cursor, event->device, -1, event->y); -		cursor_send_pointer_motion(cursor, event->time_msec); +	double x = -1, y = -1; +	if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) { +		x = event->x; +	} +	if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { +		y = event->y;  	} + +	struct input_config *ic = input_device_get_config(input_device); +	if (ic != NULL && ic->mapped_from_region != NULL) { +		apply_mapping_from_region(event->device, ic->mapped_from_region, &x, &y); +	} + +	wlr_cursor_warp_absolute(cursor->cursor, event->device, x, y); +	cursor_send_pointer_motion(cursor, event->time_msec);  }  static 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) {  	if (!sway_assert(input_device, "could not allocate input device")) {  		return;  	} +	device->data = input_device;  	input_device->wlr_device = device;  	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,  	}  	wlr_log(L_DEBUG, "Applying input config to %s",  			sway_device->input_device->identifier); -	if (ic->mapped_output) { +	if (ic->mapped_to_output) {  		struct sway_container *output = NULL;  		for (int i = 0; i < root_container.children->length; ++i) {  			struct sway_container *_output = root_container.children->items[i]; -			if (strcasecmp(_output->name, ic->mapped_output) == 0) { +			if (strcasecmp(_output->name, ic->mapped_to_output) == 0) {  				output = _output;  				break;  			} 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(  	'commands/input/dwt.c',  	'commands/input/events.c',  	'commands/input/left_handed.c', +	'commands/input/map_from_region.c',  	'commands/input/map_to_output.c',  	'commands/input/middle_emulation.c',  	'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  	layout. Only meaningful if the device is a pointer, touch, or drawing tablet  	device. -**input** <identifier> map_region <WxH\@X,Y>:: -	Ignores inputs from this device that do not occur within the specified region. -	Can be in millimeters (e.g. 10mmx20mm\@10mm,20mm) or in terms of 0..1 (e.g. -	0.5x0.5\@0,0). Not all devices support millimeters. Only meaningful if the -	device is not a keyboard an provides events in absolute terms (such as a -	drawing tablet or touch screen - most pointers provide events relative to the -	previous frame). +**input** <identifier> map_from_region <X1xY1> <X2xY2>:: +	Ignores inputs from this device that do not occur within the specified +	region. Can be in millimeters (e.g. 10x20mm 20x40mm) or in terms of 0..1 +	(e.g. 0.5x0.5 0.7x0.7). Not all devices support millimeters. Only meaningful +	if the device is not a keyboard an provides events in absolute terms (such +	as a drawing tablet or touch screen - most pointers provide events relative +	to the previous frame).  Libinput Configuration  ~~~~~~~~~~~~~~~~~~~~~~  | 
