From e3d47376dc9a7ffef3823cb2b4db78296e3cf717 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 20 Aug 2017 16:02:39 -0400 Subject: add wlr_cursor basic implementation --- include/wlr/types/wlr_cursor.h | 81 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 include/wlr/types/wlr_cursor.h (limited to 'include') diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h new file mode 100644 index 00000000..1ea089ef --- /dev/null +++ b/include/wlr/types/wlr_cursor.h @@ -0,0 +1,81 @@ +#ifndef _WLR_TYPES_CURSOR_H +#define _WLR_TYPES_CURSOR_H +#include +#include +#include +#include +#include + +struct wlr_cursor_state; +//struct wlr_cursor_impl *; + +struct wlr_cursor { + struct wlr_cursor_state *state; + //struct wlr_cursor_impl *impl; + int x, y; + + struct { + struct wl_signal motion; + struct wl_signal motion_absolute; + struct wl_signal button; + struct wl_signal axis; + } events; +}; + +struct wlr_cursor *wlr_cursor_init(); + +void wlr_cursor_destroy(struct wlr_cursor *cur); + +void wlr_cursor_set_xcursor(struct wlr_cursor *cur, struct wlr_xcursor *xcur); + +void wlr_cursor_warp(struct wlr_cursor *cur, double x, double y); + +void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y); + +/** + * Attaches this input device to this cursor. The input device must be one of: + * + * - WLR_INPUT_DEVICE_POINTER + * - WLR_INPUT_DEVICE_TOUCH + * - WLR_INPUT_DEVICE_TABLET_TOOL + */ +void wlr_cursor_attach_input_device(struct wlr_cursor *cur, + struct wlr_input_device *dev); + +void wlr_cursor_detach_input_device(struct wlr_cursor *cur, + struct wlr_input_device *dev); +/** + * Uses the given layout to establish the boundaries and movement semantics of + * this cursor. Cursors without an output layout allow infinite movement in any + * direction and do not support absolute input events. + */ +void wlr_cursor_attach_output_layout(struct wlr_cursor *cur, + struct wlr_output_layout *l); + +/** + * Attaches this cursor to the given output, which must be among the outputs in + * the current output_layout for this cursor. This call is invalid for a cursor + * without an associated output layout. + */ +void wlr_cursor_map_to_output(struct wlr_cursor *cur, struct wlr_output *output); + +/** + * Maps all input from a specific input device to a given output. The input + * device must be attached to this cursor and the output must be among the + * outputs in the attached output layout. + */ +void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, + struct wlr_input_device *dev, struct wlr_output *output); + +/** + * Maps this cursor to an arbitrary region on the associated wlr_output_layout. + */ +//void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_geometry *geo); + +/** + * Maps inputs from this input device to an arbitrary region on the associated + * wlr_output_layout. + */ +//void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, struct wlr_input_device *dev, struct wlr_geometry *geo); + +#endif -- cgit v1.2.3 From dd68f680e4bda23a723fc68aca9586ae3d3a018a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 24 Aug 2017 10:11:57 -0400 Subject: handle cursor to output edge cases --- include/wlr/types/wlr_output_layout.h | 6 +++++ types/wlr_cursor.c | 34 ++++++++++++++------------ types/wlr_output_layout.c | 46 +++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index f6a1efdd..52cc9423 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -46,4 +46,10 @@ bool wlr_output_layout_contains_point(struct wlr_output_layout *layout, bool wlr_output_layout_intersects(struct wlr_output_layout *layout, struct wlr_output *reference, int x1, int y1, int x2, int y2); +/** + * Get the closest boundary point of this layout from the given point. + */ +void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, + int x, int y, int *dest_x, int *dest_y); + #endif diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index af977632..84224ac9 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -73,7 +73,7 @@ void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) { // TODO handle no layout assert(cur->state->layout); - // TODO handle layout boundaries + double new_x = cur->x + delta_x; double new_y = cur->y + delta_y; int hotspot_x = 0; @@ -85,24 +85,28 @@ void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) { hotspot_y = image->hotspot_y; } - if (wlr_output_layout_output_at(cur->state->layout, new_x, new_y)) { - //struct wlr_output *output; - //output = wlr_output_layout_output_at(cur->state->layout, new_x, new_y); - struct wlr_output_layout_output *l_output; - wl_list_for_each(l_output, &cur->state->layout->outputs, link) { - int output_x = new_x; - int output_y = new_y; + if (!wlr_output_layout_output_at(cur->state->layout, new_x, new_y)) { + int closest_x, closest_y; + wlr_output_layout_closest_boundary(cur->state->layout, new_x, new_y, + &closest_x, &closest_y); + new_x = closest_x; + new_y = closest_y; + } + + struct wlr_output_layout_output *l_output; + wl_list_for_each(l_output, &cur->state->layout->outputs, link) { + int output_x = new_x; + int output_y = new_y; - // TODO fix double to int rounding issues - wlr_output_layout_output_coords(cur->state->layout, + // TODO fix double to int rounding issues + wlr_output_layout_output_coords(cur->state->layout, l_output->output, &output_x, &output_y); - wlr_output_move_cursor(l_output->output, output_x - hotspot_x, + wlr_output_move_cursor(l_output->output, output_x - hotspot_x, output_y - hotspot_y); - } - - cur->x = new_x; - cur->y = new_y; } + + cur->x = new_x; + cur->y = new_y; } static void handle_pointer_motion(struct wl_listener *listener, void *data) { diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 2e2032b3..3593eae6 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -126,3 +127,48 @@ void wlr_output_layout_output_coords(struct wlr_output_layout *layout, } } } + +static double get_distance(double x1, double y1, double x2, double y2) { + double distance; + distance = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + return distance; +} + +void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, + int x, int y, int *dest_x, int *dest_y) { + int min_x = INT_MAX, min_y = INT_MAX, min_distance = INT_MAX; + struct wlr_output_layout_output *l_output; + wl_list_for_each(l_output, &layout->outputs, link) { + int width, height, output_x, output_y, output_distance; + wlr_output_effective_resolution(l_output->output, &width, &height); + + // find the closest x point + if (x < l_output->x) { + output_x = l_output->x; + } else if (x > l_output->x + width) { + output_x = l_output->x + width; + } else { + output_x = x; + } + + // find closest y point + if (y < l_output->y) { + output_y = l_output->y; + } else if (y > l_output->y + height) { + output_y = l_output->y + height; + } else { + output_y = y; + } + + // calculate distance + output_distance = get_distance(output_x, output_y, x, y); + if (output_distance < min_distance) { + min_x = output_x; + min_y = output_y; + min_distance = output_distance; + } + } + + *dest_x = min_x; + *dest_y = min_y; +} -- cgit v1.2.3 From 0cba06dcef791d8dc1702270cae2915936380a46 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 24 Aug 2017 10:42:05 -0400 Subject: implement wlr_cursor_warp --- include/wlr/types/wlr_cursor.h | 11 ++++++++- types/wlr_cursor.c | 54 +++++++++++++++++++++++------------------- 2 files changed, 40 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 1ea089ef..380d8a6f 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -28,8 +28,17 @@ void wlr_cursor_destroy(struct wlr_cursor *cur); void wlr_cursor_set_xcursor(struct wlr_cursor *cur, struct wlr_xcursor *xcur); -void wlr_cursor_warp(struct wlr_cursor *cur, double x, double y); +/** + * Warp the cursor to the given x and y in layout coordinates. If x and y are + * out of the layout boundaries or constraints, no warp will happen. + * + * Returns true when the mouse warp was successful. + */ +bool wlr_cursor_warp(struct wlr_cursor *cur, double x, double y); +/** + * Move the cursor in the direction of the given x and y coordinates. + */ void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y); /** diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 84224ac9..948ab550 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -64,18 +64,11 @@ void wlr_cursor_set_xcursor(struct wlr_cursor *cur, struct wlr_xcursor *xcur) { cur->state->xcursor = xcur; } -void wlr_cursor_warp(struct wlr_cursor *cur, double x, double y) { -} - -void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) { - //struct wlr_output *current_output; - //current_output = wlr_output_layout_output_at(cur->state->layout, cur->x, cur->y); - - // TODO handle no layout - assert(cur->state->layout); +bool wlr_cursor_warp(struct wlr_cursor *cur, double x, double y) { + if (!wlr_output_layout_output_at(cur->state->layout, x, y)) { + return false; + } - double new_x = cur->x + delta_x; - double new_y = cur->y + delta_y; int hotspot_x = 0; int hotspot_y = 0; @@ -85,28 +78,41 @@ void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) { hotspot_y = image->hotspot_y; } - if (!wlr_output_layout_output_at(cur->state->layout, new_x, new_y)) { - int closest_x, closest_y; - wlr_output_layout_closest_boundary(cur->state->layout, new_x, new_y, - &closest_x, &closest_y); - new_x = closest_x; - new_y = closest_y; - } struct wlr_output_layout_output *l_output; wl_list_for_each(l_output, &cur->state->layout->outputs, link) { - int output_x = new_x; - int output_y = new_y; + int output_x = x; + int output_y = y; // TODO fix double to int rounding issues wlr_output_layout_output_coords(cur->state->layout, - l_output->output, &output_x, &output_y); + l_output->output, &output_x, &output_y); wlr_output_move_cursor(l_output->output, output_x - hotspot_x, - output_y - hotspot_y); + output_y - hotspot_y); + } + + return true; +} + +void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) { + // TODO handle no layout + assert(cur->state->layout); + + int x = cur->x + delta_x; + int y = cur->y + delta_y; + + if (!wlr_output_layout_output_at(cur->state->layout, x, y)) { + int closest_x, closest_y; + wlr_output_layout_closest_boundary(cur->state->layout, x, y, &closest_x, + &closest_y); + x = closest_x; + y = closest_y; } - cur->x = new_x; - cur->y = new_y; + if (wlr_cursor_warp(cur, x, y)) { + cur->x = x; + cur->y = y; + } } static void handle_pointer_motion(struct wl_listener *listener, void *data) { -- cgit v1.2.3 From a4810203ccfcdba2460331b46d7be4d9535f904a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 24 Aug 2017 11:46:40 -0400 Subject: change output layout coords to double type --- examples/output-layout.c | 4 ++-- include/wlr/types/wlr_output_layout.h | 2 +- types/wlr_cursor.c | 5 ++--- types/wlr_output_layout.c | 10 +++++----- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/examples/output-layout.c b/examples/output-layout.c index 0dcbc1f8..041d5788 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -49,8 +49,8 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts float matrix[16]; // transform global coordinates to local coordinates - int local_x = sample->x_offs; - int local_y = sample->y_offs; + double local_x = sample->x_offs; + double local_y = sample->y_offs; wlr_output_layout_output_coords(sample->layout, output->output, &local_x, &local_y); diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index 52cc9423..9094f02f 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -38,7 +38,7 @@ void wlr_output_layout_remove(struct wlr_output_layout *layout, * coordinates relative to the given reference output. */ void wlr_output_layout_output_coords(struct wlr_output_layout *layout, - struct wlr_output *reference, int *x, int *y); + struct wlr_output *reference, double *x, double *y); bool wlr_output_layout_contains_point(struct wlr_output_layout *layout, struct wlr_output *reference, int x, int y); diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 9a303d37..c9937c73 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -82,10 +82,9 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, double x, double y) { struct wlr_output_layout_output *l_output; wl_list_for_each(l_output, &cur->state->layout->outputs, link) { - int output_x = x; - int output_y = y; + double output_x = x; + double output_y = y; - // TODO fix double to int rounding issues wlr_output_layout_output_coords(cur->state->layout, l_output->output, &output_x, &output_y); wlr_output_move_cursor(l_output->output, output_x - hotspot_x, diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 3593eae6..a26a4794 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -113,16 +113,16 @@ void wlr_output_layout_remove(struct wlr_output_layout *layout, } void wlr_output_layout_output_coords(struct wlr_output_layout *layout, - struct wlr_output *reference, int *x, int *y) { + struct wlr_output *reference, double *x, double *y) { assert(layout && reference); - int src_x = *x; - int src_y = *y; + double src_x = *x; + double src_y = *y; struct wlr_output_layout_output *_output; wl_list_for_each(_output, &layout->outputs, link) { if (_output->output == reference) { - *x = src_x - _output->x; - *y = src_y - _output->y; + *x = src_x - (double)_output->x; + *y = src_y - (double)_output->y; return; } } -- cgit v1.2.3 From 13e895d943eca5e86f68230c5ca503090866aafc Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 24 Aug 2017 12:30:34 -0400 Subject: implement wlr_cursor_map_to_output --- include/wlr/types/wlr_output_layout.h | 7 +++++-- types/wlr_cursor.c | 31 +++++++++++++++++++++++-------- types/wlr_output_layout.c | 12 +++++++++--- 3 files changed, 37 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index 9094f02f..144c2d5a 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -47,9 +47,12 @@ bool wlr_output_layout_intersects(struct wlr_output_layout *layout, struct wlr_output *reference, int x1, int y1, int x2, int y2); /** - * Get the closest boundary point of this layout from the given point. + * Get the closest boundary point of this layout from the given point from the + * reference output. If reference is NULL, gets the closest boundary point from + * the entire layout. */ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, - int x, int y, int *dest_x, int *dest_y); + struct wlr_output *reference, double x, double y, double *dest_x, + double *dest_y); #endif diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index c9937c73..affdcdeb 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -22,6 +22,7 @@ struct wlr_cursor_state { struct wl_list devices; struct wlr_output_layout *layout; struct wlr_xcursor *xcursor; + struct wlr_output *mapped_output; }; struct wlr_cursor *wlr_cursor_init() { @@ -37,6 +38,8 @@ struct wlr_cursor *wlr_cursor_init() { return NULL; } + cur->state->mapped_output = NULL; + wl_list_init(&cur->state->devices); wl_signal_init(&cur->events.motion); @@ -66,7 +69,16 @@ void wlr_cursor_set_xcursor(struct wlr_cursor *cur, struct wlr_xcursor *xcur) { bool wlr_cursor_warp(struct wlr_cursor *cur, double x, double y) { assert(cur->state->layout); - if (!wlr_output_layout_output_at(cur->state->layout, x, y)) { + struct wlr_output *output; + output = wlr_output_layout_output_at(cur->state->layout, x, y); + + if (!output) { + return false; + } + + if (cur->state->mapped_output && + !wlr_output_layout_contains_point(cur->state->layout, + cur->state->mapped_output, x, y)) { return false; } @@ -97,13 +109,16 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, double x, double y) { void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) { assert(cur->state->layout); - int x = cur->x + delta_x; - int y = cur->y + delta_y; + double x = cur->x + delta_x; + double y = cur->y + delta_y; + + struct wlr_output *output; + output = wlr_output_layout_output_at(cur->state->layout, x, y); - if (!wlr_output_layout_output_at(cur->state->layout, x, y)) { - int closest_x, closest_y; - wlr_output_layout_closest_boundary(cur->state->layout, x, y, &closest_x, - &closest_y); + if (!output || (cur->state->mapped_output && cur->state->mapped_output != output)) { + double closest_x, closest_y; + wlr_output_layout_closest_boundary(cur->state->layout, + cur->state->mapped_output, x, y, &closest_x, &closest_y); x = closest_x; y = closest_y; } @@ -210,7 +225,7 @@ void wlr_cursor_attach_output_layout(struct wlr_cursor *cur, void wlr_cursor_map_to_output(struct wlr_cursor *cur, struct wlr_output *output) { - wlr_log(L_DEBUG, "TODO: map to output"); + cur->state->mapped_output = output; } void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index a26a4794..5e2067da 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -135,11 +135,17 @@ static double get_distance(double x1, double y1, double x2, double y2) { } void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, - int x, int y, int *dest_x, int *dest_y) { - int min_x = INT_MAX, min_y = INT_MAX, min_distance = INT_MAX; + struct wlr_output *reference, double x, double y, double *dest_x, + double *dest_y) { + double min_x = INT_MAX, min_y = INT_MAX, min_distance = INT_MAX; struct wlr_output_layout_output *l_output; wl_list_for_each(l_output, &layout->outputs, link) { - int width, height, output_x, output_y, output_distance; + if (reference != NULL && reference != l_output->output) { + continue; + } + + int width, height; + double output_x, output_y, output_distance; wlr_output_effective_resolution(l_output->output, &width, &height); // find the closest x point -- cgit v1.2.3 From 98f4cdfccb7d2ace2929bca45f0479b3472b96ac Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 24 Aug 2017 14:35:55 -0400 Subject: implement wlr_cursor_map_input_to_output --- backend/libinput/pointer.c | 4 +++ backend/wayland/wl_seat.c | 3 ++ examples/pointer.c | 33 ++++++++++++++++++++- include/wlr/types/wlr_cursor.h | 12 ++++++-- include/wlr/types/wlr_pointer.h | 4 +++ types/wlr_cursor.c | 63 +++++++++++++++++++++++++++++++++-------- 6 files changed, 104 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 8bda205d..005c9516 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -30,6 +30,7 @@ void handle_pointer_motion(struct libinput_event *event, struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); struct wlr_event_pointer_motion wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_pointer_get_time(pevent); wlr_event.time_usec = libinput_event_pointer_get_time_usec(pevent); wlr_event.delta_x = libinput_event_pointer_get_dx(pevent); @@ -48,6 +49,7 @@ void handle_pointer_motion_abs(struct libinput_event *event, struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); struct wlr_event_pointer_motion_absolute wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_pointer_get_time(pevent); wlr_event.time_usec = libinput_event_pointer_get_time_usec(pevent); wlr_event.x_mm = libinput_event_pointer_get_absolute_x(pevent); @@ -67,6 +69,7 @@ void handle_pointer_button(struct libinput_event *event, struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); struct wlr_event_pointer_button wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_pointer_get_time(pevent); wlr_event.time_usec = libinput_event_pointer_get_time_usec(pevent); wlr_event.button = libinput_event_pointer_get_button(pevent); @@ -92,6 +95,7 @@ void handle_pointer_axis(struct libinput_event *event, struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); struct wlr_event_pointer_axis wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_pointer_get_time(pevent); wlr_event.time_usec = libinput_event_pointer_get_time_usec(pevent); switch (libinput_event_pointer_get_axis_source(pevent)) { diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c index a4cc0ba5..3e6982a0 100644 --- a/backend/wayland/wl_seat.c +++ b/backend/wayland/wl_seat.c @@ -51,6 +51,7 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, wl_egl_window_get_attached_size(wlr_wl_pointer->current_output->egl_window, &width, &height); struct wlr_event_pointer_motion_absolute wlr_event; + wlr_event.device = dev; wlr_event.time_sec = time / 1000; wlr_event.time_usec = time * 1000; wlr_event.width_mm = width; @@ -66,6 +67,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, assert(dev && dev->pointer); struct wlr_event_pointer_button wlr_event; + wlr_event.device = dev; wlr_event.button = button; wlr_event.state = state; wlr_event.time_sec = time / 1000; @@ -80,6 +82,7 @@ static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, struct wlr_wl_pointer *wlr_wl_pointer = (struct wlr_wl_pointer *)dev->pointer; struct wlr_event_pointer_axis wlr_event; + wlr_event.device = dev; wlr_event.delta = value; wlr_event.orientation = axis; wlr_event.time_sec = time / 1000; diff --git a/examples/pointer.c b/examples/pointer.c index 0092c633..95e28bb2 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -24,6 +24,11 @@ #include "shared.h" #include "cat.h" +struct sample_input_device { + struct wlr_input_device *device; + struct wl_list link; +}; + struct sample_state { struct compositor_state *compositor; struct example_config *config; @@ -33,6 +38,7 @@ struct sample_state { float default_color[4]; float clear_color[4]; struct wlr_output_layout *layout; + struct wl_list devices; struct wl_listener cursor_motion; struct wl_listener cursor_motion_absolute; @@ -63,6 +69,16 @@ static void handle_output_add(struct output_state *ostate) { sample->layout = configure_layout(sample->config, &ostate->compositor->outputs); wlr_cursor_attach_output_layout(sample->cursor, sample->layout); + /* + // TODO configuration + if (strcmp("DP-1", ostate->output->name) == 0) { + struct sample_input_device *dev; + wl_list_for_each(dev, &sample->devices, link) { + wlr_cursor_map_input_to_output(sample->cursor, dev->device, ostate->output); + } + } + */ + if (!wlr_output_set_cursor(wlr_output, image->buffer, image->width, image->width, image->height)) { wlr_log(L_DEBUG, "Failed to set hardware cursor"); @@ -94,6 +110,20 @@ static void handle_input_add(struct compositor_state *state, struct // TODO handle other input devices if (device->type == WLR_INPUT_DEVICE_POINTER) { + struct sample_input_device *s_device = calloc(1, sizeof(struct sample_input_device)); + s_device->device = device; + wl_list_insert(&sample->devices, &s_device->link); + + /* + // TODO configuration + struct output_state *ostate; + wl_list_for_each(ostate, &sample->compositor->outputs, link) { + if (strcmp(ostate->output->name, "DP-1") == 0) { + wlr_cursor_map_input_to_output(sample->cursor, device, ostate->output); + } + } + */ + wlr_cursor_attach_input_device(sample->cursor, device); } } @@ -101,7 +131,7 @@ static void handle_input_add(struct compositor_state *state, struct static void handle_cursor_motion(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, cursor_motion); struct wlr_event_pointer_motion *event = data; - wlr_cursor_move(sample->cursor, event->delta_x, event->delta_y); + wlr_cursor_move(sample->cursor, event->device, event->delta_x, event->delta_y); } static void handle_cursor_motion_absolute(struct wl_listener *listener, void *data) { @@ -163,6 +193,7 @@ int main(int argc, char *argv[]) { state.config = parse_args(argc, argv); state.cursor = wlr_cursor_init(); + wl_list_init(&state.devices); wl_signal_add(&state.cursor->events.motion, &state.cursor_motion); state.cursor_motion.notify = handle_cursor_motion; diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 380d8a6f..64a75e4f 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -32,14 +32,22 @@ void wlr_cursor_set_xcursor(struct wlr_cursor *cur, struct wlr_xcursor *xcur); * Warp the cursor to the given x and y in layout coordinates. If x and y are * out of the layout boundaries or constraints, no warp will happen. * + * `dev` may be passed to respect device mapping constraints. If `dev` is NULL, + * device mapping constraints will be ignored. + * * Returns true when the mouse warp was successful. */ -bool wlr_cursor_warp(struct wlr_cursor *cur, double x, double y); +bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, + double x, double y); /** * Move the cursor in the direction of the given x and y coordinates. + * + * `dev` may be passed to respect device mapping constraints. If `dev` is NULL, + * device mapping constraints will be ignored. */ -void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y); +void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, + double delta_x, double delta_y); /** * Attaches this input device to this cursor. The input device must be one of: diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index 13a2d045..9153963a 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -20,12 +20,14 @@ struct wlr_pointer { }; struct wlr_event_pointer_motion { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; double delta_x, delta_y; }; struct wlr_event_pointer_motion_absolute { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; double x_mm, y_mm; @@ -33,6 +35,7 @@ struct wlr_event_pointer_motion_absolute { }; struct wlr_event_pointer_button { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; uint32_t button; @@ -52,6 +55,7 @@ enum wlr_axis_orientation { }; struct wlr_event_pointer_axis { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; enum wlr_axis_source source; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index affdcdeb..6917526e 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -11,6 +11,7 @@ struct wlr_cursor_device { struct wlr_cursor *cursor; struct wlr_input_device *device; struct wl_list link; + struct wlr_output *mapped_output; struct wl_listener motion; struct wl_listener motion_absolute; @@ -54,8 +55,8 @@ struct wlr_cursor *wlr_cursor_init() { } void wlr_cursor_destroy(struct wlr_cursor *cur) { - struct wlr_cursor_device *device, *tmp = NULL; - wl_list_for_each_safe(device, tmp, &cur->state->devices, link) { + struct wlr_cursor_device *device, *device_tmp = NULL; + wl_list_for_each_safe(device, device_tmp, &cur->state->devices, link) { wl_list_remove(&device->link); free(device); } @@ -67,18 +68,41 @@ void wlr_cursor_set_xcursor(struct wlr_cursor *cur, struct wlr_xcursor *xcur) { cur->state->xcursor = xcur; } -bool wlr_cursor_warp(struct wlr_cursor *cur, double x, double y) { +static struct wlr_cursor_device *get_cursor_device(struct wlr_cursor *cur, + struct wlr_input_device *device) { + struct wlr_cursor_device *c_device, *ret = NULL; + wl_list_for_each(c_device, &cur->state->devices, link) { + if (c_device->device == device) { + ret = c_device; + break; + } + } + + return ret; +} + +bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, + double x, double y) { assert(cur->state->layout); struct wlr_output *output; output = wlr_output_layout_output_at(cur->state->layout, x, y); + struct wlr_output *mapped_output = NULL; + struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); + + if (c_device && c_device->mapped_output) { + mapped_output = c_device->mapped_output; + } else { + mapped_output = cur->state->mapped_output; + } + if (!output) { return false; } - if (cur->state->mapped_output && - !wlr_output_layout_contains_point(cur->state->layout, - cur->state->mapped_output, x, y)) { + if (mapped_output && + !wlr_output_layout_contains_point(cur->state->layout, mapped_output, + x, y)) { return false; } @@ -106,8 +130,17 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, double x, double y) { return true; } -void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) { +void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, + double delta_x, double delta_y) { assert(cur->state->layout); + struct wlr_output *mapped_output = NULL; + struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); + + if (c_device && c_device->mapped_output) { + mapped_output = c_device->mapped_output; + } else { + mapped_output = cur->state->mapped_output; + } double x = cur->x + delta_x; double y = cur->y + delta_y; @@ -115,15 +148,15 @@ void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) { struct wlr_output *output; output = wlr_output_layout_output_at(cur->state->layout, x, y); - if (!output || (cur->state->mapped_output && cur->state->mapped_output != output)) { + if (!output || (mapped_output && mapped_output != output)) { double closest_x, closest_y; - wlr_output_layout_closest_boundary(cur->state->layout, - cur->state->mapped_output, x, y, &closest_x, &closest_y); + wlr_output_layout_closest_boundary(cur->state->layout, mapped_output, x, + y, &closest_x, &closest_y); x = closest_x; y = closest_y; } - if (wlr_cursor_warp(cur, x, y)) { + if (wlr_cursor_warp(cur, dev, x, y)) { cur->x = x; cur->y = y; } @@ -230,5 +263,11 @@ void wlr_cursor_map_to_output(struct wlr_cursor *cur, void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, struct wlr_input_device *dev, struct wlr_output *output) { - wlr_log(L_DEBUG, "TODO map input to output"); + struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); + if (!c_device) { + wlr_log(L_ERROR, "Cannot map device \"%s\" to output (not found in this cursor)", dev->name); + return; + } + + c_device->mapped_output = output; } -- cgit v1.2.3 From 0a97b68278a621882c712b55ffe851101e5902d0 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 25 Aug 2017 13:26:13 -0400 Subject: implement cursor and device geometry mapping --- examples/config.c | 75 ++++++++++++++++++++++++++++++++++++++++ examples/config.h | 2 ++ examples/pointer.c | 15 ++++++-- examples/wlr-example.ini.example | 8 +++++ include/wlr/types/wlr_cursor.h | 6 ++-- include/wlr/types/wlr_geometry.h | 12 +++++++ types/meson.build | 1 + types/wlr_cursor.c | 35 +++++++++++++++++++ types/wlr_geometry.c | 36 +++++++++++++++++++ types/wlr_output_layout.c | 1 + 10 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 include/wlr/types/wlr_geometry.h create mode 100644 types/wlr_geometry.c (limited to 'include') diff --git a/examples/config.c b/examples/config.c index 31aaa6d7..829350c1 100644 --- a/examples/config.c +++ b/examples/config.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "shared.h" #include "config.h" #include "ini.h" @@ -21,6 +22,64 @@ static void usage(const char *name, int ret) { exit(ret); } +static struct wlr_geometry *parse_geometry(const char *str) { + // format: {width}x{height}+{x}+{y} + if (strlen(str) > 255l) { + wlr_log(L_ERROR, "cannot parse geometry string, too long"); + return NULL; + } + + char *buf = strdup(str); + struct wlr_geometry *geo = calloc(1, sizeof(struct wlr_geometry)); + + bool has_width, has_height, has_x, has_y; + char *pch = strtok(buf, "x+"); + while (pch != NULL) { + errno = 0; + char *endptr; + long val = strtol(pch, &endptr, 0); + + if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) + || (errno != 0 && val == 0)) { + goto invalid_input; + } + + if (endptr == pch) { + goto invalid_input; + } + + if (!has_width) { + geo->width = val; + has_width = true; + } else if (!has_height) { + geo->height = val; + has_height = true; + } else if (!has_x) { + geo->x = val; + has_x = true; + } else if (!has_y) { + geo->y = val; + has_y = true; + } else { + goto invalid_input; + } + pch = strtok(NULL, "x+"); + } + + if (!has_width || !has_height || !has_x || !has_y) { + goto invalid_input; + } + + free(buf); + return geo; + +invalid_input: + wlr_log(L_ERROR, "could not parse geometry string: %s", str); + free(buf); + free(geo); + return NULL; +} + static const char *output_prefix = "output:"; static const char *device_prefix = "device:"; @@ -71,6 +130,11 @@ static int config_ini_handler(void *user, const char *section, const char *name, } else if (strcmp(section, "cursor") == 0) { if (strcmp(name, "map-to-output") == 0) { config->cursor.mapped_output = strdup(value); + } else if (strcmp(name, "geometry") == 0) { + if (config->cursor.mapped_geo) { + free(config->cursor.mapped_geo); + } + config->cursor.mapped_geo = parse_geometry(value); } else { wlr_log(L_ERROR, "got unknown cursor config: %s", name); } @@ -97,6 +161,11 @@ static int config_ini_handler(void *user, const char *section, const char *name, free(dc->mapped_output); } dc->mapped_output = strdup(value); + } else if (strcmp(name, "geometry") == 0) { + if (dc->mapped_geo) { + free(dc->mapped_geo); + } + dc->mapped_geo = parse_geometry(value); } else { wlr_log(L_ERROR, "got unknown device config: %s", name); } @@ -166,6 +235,9 @@ void example_config_destroy(struct example_config *config) { if (dc->mapped_output) { free(dc->mapped_output); } + if (dc->mapped_geo) { + free(dc->mapped_geo); + } free(dc); } @@ -175,6 +247,9 @@ void example_config_destroy(struct example_config *config) { if (config->cursor.mapped_output) { free(config->cursor.mapped_output); } + if (config->cursor.mapped_geo) { + free(config->cursor.mapped_geo); + } free(config); } diff --git a/examples/config.h b/examples/config.h index e1765c57..cd19dc5e 100644 --- a/examples/config.h +++ b/examples/config.h @@ -15,12 +15,14 @@ struct output_config { struct device_config { char *name; char *mapped_output; + struct wlr_geometry *mapped_geo; struct wl_list link; }; struct example_config { struct { char *mapped_output; + struct wlr_geometry *mapped_geo; } cursor; struct wl_list outputs; diff --git a/examples/pointer.c b/examples/pointer.c index bec71dff..9492adab 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -63,14 +63,21 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts static void configure_devices(struct sample_state *sample) { struct sample_input_device *dev; - // reset device to output mappings + struct device_config *dc; + + // reset device mappings wl_list_for_each(dev, &sample->devices, link) { wlr_cursor_map_input_to_output(sample->cursor, dev->device, NULL); + wl_list_for_each(dc, &sample->config->devices, link) { + if (strcmp(dev->device->name, dc->name) == 0) { + wlr_cursor_map_input_to_region(sample->cursor, dev->device, + dc->mapped_geo); + } + } } struct output_state *ostate; wl_list_for_each(ostate, &sample->compositor->outputs, link) { - struct device_config *dc; wl_list_for_each(dc, &sample->config->devices, link) { // configure device to output mappings if (dc->mapped_output && @@ -123,7 +130,8 @@ static void handle_output_remove(struct output_state *ostate) { configure_devices(sample); - if (strcmp(sample->config->cursor.mapped_output, ostate->output->name) == 0) { + char *mapped_output = sample->config->cursor.mapped_output; + if (mapped_output && strcmp(mapped_output, ostate->output->name) == 0) { wlr_cursor_map_to_output(sample->cursor, NULL); } } @@ -216,6 +224,7 @@ int main(int argc, char *argv[]) { state.config = parse_args(argc, argv); state.cursor = wlr_cursor_init(); + wlr_cursor_map_to_region(state.cursor, state.config->cursor.mapped_geo); wl_list_init(&state.devices); wl_signal_add(&state.cursor->events.motion, &state.cursor_motion); diff --git a/examples/wlr-example.ini.example b/examples/wlr-example.ini.example index ffb6229e..1698e0c6 100644 --- a/examples/wlr-example.ini.example +++ b/examples/wlr-example.ini.example @@ -34,8 +34,12 @@ y=232 # ~~~~~~~~~~~~~~~~~~~~ # Value "map-to-output" specifies the output to which the cursor is # constrained. +# +# Value "geometry" specifies the geometry (widthxheight+x+y) to which the cursor +# is constrained. [cursor] map-to-output=HDMI-A-1 +geometry=500x700+50+50 # Device Configuration # ~~~~~~~~~~~~~~~~~~~~ @@ -43,7 +47,11 @@ map-to-output=HDMI-A-1 # name given to this device. See a log file for device names. # # Value "map-to-output" specifies the output to which the device is constrained. +# +# Value "geometry" specifies the geometry (widthxheight+x+y) to which the device +# is constrained. [device:Razer Razer DeathAdder 2013] map-to-output=DP-1 +geometry=500x700+50+50 # vim:filetype=dosini diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 64a75e4f..30495d44 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -4,6 +4,7 @@ #include #include #include +#include #include struct wlr_cursor_state; @@ -87,12 +88,13 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, /** * Maps this cursor to an arbitrary region on the associated wlr_output_layout. */ -//void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_geometry *geo); +void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_geometry *geo); /** * Maps inputs from this input device to an arbitrary region on the associated * wlr_output_layout. */ -//void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, struct wlr_input_device *dev, struct wlr_geometry *geo); +void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, + struct wlr_input_device *dev, struct wlr_geometry *geo); #endif diff --git a/include/wlr/types/wlr_geometry.h b/include/wlr/types/wlr_geometry.h new file mode 100644 index 00000000..3e218bed --- /dev/null +++ b/include/wlr/types/wlr_geometry.h @@ -0,0 +1,12 @@ +#ifndef _WLR_TYPES_GEOMETRY_H +#define _WLR_TYPES_GEOMETRY_H + +struct wlr_geometry { + int x, y; + int width, height; +}; + +void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, + int *dest_x, int *dest_y, double *distance); + +#endif diff --git a/types/meson.build b/types/meson.build index 3992c6e9..d0ed85fe 100644 --- a/types/meson.build +++ b/types/meson.build @@ -16,6 +16,7 @@ lib_wlr_types = static_library('wlr_types', files( 'wlr_xdg_shell_v6.c', 'wlr_wl_shell.c', 'wlr_compositor.c', + 'wlr_geometry.c', ), include_directories: wlr_inc, dependencies: [wayland_server, pixman, wlr_protos]) diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 6917526e..c0b2b6ae 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -12,6 +12,7 @@ struct wlr_cursor_device { struct wlr_input_device *device; struct wl_list link; struct wlr_output *mapped_output; + struct wlr_geometry *mapped_geometry; struct wl_listener motion; struct wl_listener motion_absolute; @@ -24,6 +25,7 @@ struct wlr_cursor_state { struct wlr_output_layout *layout; struct wlr_xcursor *xcursor; struct wlr_output *mapped_output; + struct wlr_geometry *mapped_geometry; }; struct wlr_cursor *wlr_cursor_init() { @@ -145,6 +147,25 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, double x = cur->x + delta_x; double y = cur->y + delta_y; + // cursor geometry constraints + if (cur->state->mapped_geometry) { + int closest_x, closest_y; + wlr_geometry_closest_boundary(cur->state->mapped_geometry, x, y, + &closest_x, &closest_y, NULL); + x = closest_x; + y = closest_y; + } + + // device constraints + if (c_device->mapped_geometry) { + int closest_x, closest_y; + wlr_geometry_closest_boundary(c_device->mapped_geometry, x, y, + &closest_x, &closest_y, NULL); + x = closest_x; + y = closest_y; + } + + // layout constraints struct wlr_output *output; output = wlr_output_layout_output_at(cur->state->layout, x, y); @@ -271,3 +292,17 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, c_device->mapped_output = output; } + +void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_geometry *geo) { + cur->state->mapped_geometry = geo; +} + +void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, + struct wlr_input_device *dev, struct wlr_geometry *geo) { + struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); + if (!c_device) { + wlr_log(L_ERROR, "Cannot map device \"%s\" to geometry (not found in this cursor)", dev->name); + return; + } + c_device->mapped_geometry = geo; +} diff --git a/types/wlr_geometry.c b/types/wlr_geometry.c new file mode 100644 index 00000000..8358d887 --- /dev/null +++ b/types/wlr_geometry.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +static double get_distance(double x1, double y1, double x2, double y2) { + double distance; + distance = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + return distance; +} + +void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, + int *dest_x, int *dest_y, double *distance) { + // find the closest x point + if (x < geo->x) { + *dest_x = geo->x; + } else if (x > geo->x + geo->width) { + *dest_x = geo->x + geo->width; + } else { + *dest_x = x; + } + + // find closest y point + if (y < geo->y) { + *dest_y = geo->y; + } else if (y > geo->y + geo->height) { + *dest_y = geo->y + geo->height; + } else { + *dest_y = y; + } + + // calculate distance + if (distance) { + *distance = get_distance(*dest_x, *dest_y, x, y); + } +} diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 5e2067da..7dcb4651 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -149,6 +149,7 @@ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, wlr_output_effective_resolution(l_output->output, &width, &height); // find the closest x point + // TODO use wlr_geometry_closest_boundary if (x < l_output->x) { output_x = l_output->x; } else if (x > l_output->x + width) { -- cgit v1.2.3 From ac503a47a71e2ab5d149a1bb9184d424609c7da7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 26 Aug 2017 11:55:24 -0400 Subject: intersect cursor and device regions --- include/wlr/types/wlr_geometry.h | 6 +++++ types/wlr_cursor.c | 33 ++++++++++++++++-------- types/wlr_geometry.c | 54 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/include/wlr/types/wlr_geometry.h b/include/wlr/types/wlr_geometry.h index 3e218bed..7ac2f843 100644 --- a/include/wlr/types/wlr_geometry.h +++ b/include/wlr/types/wlr_geometry.h @@ -1,5 +1,6 @@ #ifndef _WLR_TYPES_GEOMETRY_H #define _WLR_TYPES_GEOMETRY_H +#include struct wlr_geometry { int x, y; @@ -9,4 +10,9 @@ struct wlr_geometry { void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, int *dest_x, int *dest_y, double *distance); +bool wlr_geometry_intersection(struct wlr_geometry *geo_a, + struct wlr_geometry *geo_b, struct wlr_geometry **dest); + +bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y); + #endif diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index c0b2b6ae..28d9f8c9 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -147,19 +147,20 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, double x = cur->x + delta_x; double y = cur->y + delta_y; - // cursor geometry constraints - if (cur->state->mapped_geometry) { - int closest_x, closest_y; - wlr_geometry_closest_boundary(cur->state->mapped_geometry, x, y, - &closest_x, &closest_y, NULL); - x = closest_x; - y = closest_y; - } + // geometry constraints + struct wlr_geometry *constraints = NULL; + if (cur->state->mapped_geometry != NULL || + c_device->mapped_geometry != NULL) { + constraints = calloc(1, sizeof(struct wlr_geometry)); + + if (!wlr_geometry_intersection(cur->state->mapped_geometry, + c_device->mapped_geometry, &constraints)) { + // TODO handle no possible movement + goto out; + } - // device constraints - if (c_device->mapped_geometry) { int closest_x, closest_y; - wlr_geometry_closest_boundary(c_device->mapped_geometry, x, y, + wlr_geometry_closest_boundary(constraints, x, y, &closest_x, &closest_y, NULL); x = closest_x; y = closest_y; @@ -177,10 +178,20 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, y = closest_y; } + if (constraints && !wlr_geometry_contains_point(constraints, x, y)) { + // TODO handle no possible movement + goto out; + } + if (wlr_cursor_warp(cur, dev, x, y)) { cur->x = x; cur->y = y; } + +out: + if (constraints) { + free(constraints); + } } static void handle_pointer_motion(struct wl_listener *listener, void *data) { diff --git a/types/wlr_geometry.c b/types/wlr_geometry.c index 8358d887..be4a80eb 100644 --- a/types/wlr_geometry.c +++ b/types/wlr_geometry.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include static double get_distance(double x1, double y1, double x2, double y2) { double distance; @@ -34,3 +36,55 @@ void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, *distance = get_distance(*dest_x, *dest_y, x, y); } } + +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static bool wlr_geometry_empty(struct wlr_geometry *geo) { + return geo == NULL || geo->width < 0 || geo->height < 0; +} + +bool wlr_geometry_intersection(struct wlr_geometry *geo_a, + struct wlr_geometry *geo_b, struct wlr_geometry **geo_dest) { + struct wlr_geometry *dest = *geo_dest; + bool a_empty = wlr_geometry_empty(geo_a); + bool b_empty = wlr_geometry_empty(geo_b); + + if (a_empty && b_empty) { + return false; + } else if (a_empty) { + dest->x = geo_b->x; + dest->y = geo_b->y; + dest->height = geo_b->height; + dest->width = geo_b->width; + return true; + } else if (b_empty) { + dest->x = geo_a->x; + dest->y = geo_a->y; + dest->height = geo_a->height; + dest->width = geo_a->width; + return true; + } + + int x1 = max(geo_a->x, geo_b->x); + int y1 = max(geo_a->y, geo_b->y); + int x2 = min(geo_a->x + geo_a->width, geo_b->x + geo_b->width); + int y2 = min(geo_a->y + geo_a->height, geo_b->y + geo_b->height); + + dest->x = x1; + dest->y = y1; + dest->width = x2 - x1; + dest->height = y2 - y1; + + return !wlr_geometry_empty(dest); +} + +bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y) { + return x >= geo->x && x <= geo->x + geo->width && + y >= geo->y && y <= geo->y + geo->height; +} -- cgit v1.2.3 From ed126b0881413dc3c855abf313c62e2f3abad4aa Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 27 Aug 2017 11:34:25 -0400 Subject: add touch events --- examples/pointer.c | 91 ++++++++++++++++++++++++++++++++++++++++-- include/wlr/types/wlr_cursor.h | 5 +++ types/wlr_cursor.c | 83 ++++++++++++++++++++++++++++++++------ 3 files changed, 163 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/examples/pointer.c b/examples/pointer.c index 9492adab..bae205f5 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -45,8 +45,27 @@ struct sample_state { struct wl_listener cursor_motion_absolute; struct wl_listener cursor_button; struct wl_listener cursor_axis; + + struct wl_listener touch_motion; + struct wl_listener touch_up; + struct wl_listener touch_down; + struct wl_listener touch_cancel; + list_t *touch_points; +}; + +struct touch_point { + int32_t slot; + double x, y; }; +static void warp_to_touch(struct sample_state *sample) { + wlr_log(L_DEBUG, "TODO: warp to touch"); + for (size_t i = 0; i < sample->touch_points->length; ++i) { + struct touch_point *point = sample->touch_points->items[i]; + wlr_log(L_DEBUG, "have point x=%f,y=%f", point->x, point->y); + } +} + static void handle_output_frame(struct output_state *output, struct timespec *ts) { struct compositor_state *state = output->compositor; struct sample_state *sample = state->data; @@ -149,8 +168,10 @@ static void handle_input_add(struct compositor_state *state, struct struct sample_state *sample = state->data; // TODO handle other input devices - if (device->type == WLR_INPUT_DEVICE_POINTER) { - struct sample_input_device *s_device = calloc(1, sizeof(struct sample_input_device)); + if (device->type == WLR_INPUT_DEVICE_POINTER || + device->type == WLR_INPUT_DEVICE_TOUCH) { + struct sample_input_device *s_device; + s_device = calloc(1, sizeof(struct sample_input_device)); s_device->device = device; wl_list_insert(&sample->devices, &s_device->link); @@ -216,10 +237,60 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) { sizeof(sample->clear_color)); } +static void handle_touch_up(struct wl_listener *listener, void *data) { + struct sample_state *sample = wl_container_of(listener, sample, touch_up); + struct wlr_event_touch_up *event = data; + for (size_t i = 0; i < sample->touch_points->length; ++i) { + struct touch_point *point = sample->touch_points->items[i]; + if (point->slot == event->slot) { + list_del(sample->touch_points, i); + break; + } + } + + warp_to_touch(sample); +} + +static void handle_touch_down(struct wl_listener *listener, void *data) { + struct sample_state *sample = wl_container_of(listener, sample, touch_down); + struct wlr_event_touch_down *event = data; + struct touch_point *point = calloc(1, sizeof(struct touch_state)); + point->slot = event->slot; + point->x = event->x_mm / event->width_mm; + point->y = event->y_mm / event->height_mm; + if (list_add(sample->touch_points, point) == -1) { + free(point); + } + + warp_to_touch(sample); +} + +static void handle_touch_motion(struct wl_listener *listener, void *data) { + struct sample_state *sample = wl_container_of(listener, sample, touch_motion); + struct wlr_event_touch_motion *event = data; + for (size_t i = 0; i < sample->touch_points->length; ++i) { + struct touch_point *point = sample->touch_points->items[i]; + if (point->slot == event->slot) { + point->x = event->x_mm / event->width_mm; + point->y = event->y_mm / event->height_mm; + break; + } + } + + warp_to_touch(sample); +} + +static void handle_touch_cancel(struct wl_listener *listener, void *data) { + //struct sample_state *sample = wl_container_of(listener, sample, touch_cancel); + //struct wlr_event_touch_cancel *event = data; + wlr_log(L_DEBUG, "TODO: touch cancel"); +} + int main(int argc, char *argv[]) { struct sample_state state = { .default_color = { 0.25f, 0.25f, 0.25f, 1 }, - .clear_color = { 0.25f, 0.25f, 0.25f, 1 } + .clear_color = { 0.25f, 0.25f, 0.25f, 1 }, + .touch_points = list_create(), }; state.config = parse_args(argc, argv); @@ -227,6 +298,7 @@ int main(int argc, char *argv[]) { wlr_cursor_map_to_region(state.cursor, state.config->cursor.mapped_geo); wl_list_init(&state.devices); + // pointer events wl_signal_add(&state.cursor->events.motion, &state.cursor_motion); state.cursor_motion.notify = handle_cursor_motion; @@ -239,6 +311,19 @@ int main(int argc, char *argv[]) { wl_signal_add(&state.cursor->events.axis, &state.cursor_axis); state.cursor_axis.notify = handle_cursor_axis; + // touch events + wl_signal_add(&state.cursor->events.touch_up, &state.touch_up); + state.touch_up.notify = handle_touch_up; + + wl_signal_add(&state.cursor->events.touch_down, &state.touch_down); + state.touch_down.notify = handle_touch_down; + + wl_signal_add(&state.cursor->events.touch_motion, &state.touch_motion); + state.touch_motion.notify = handle_touch_motion; + + wl_signal_add(&state.cursor->events.touch_cancel, &state.touch_cancel); + state.touch_cancel.notify = handle_touch_cancel; + struct compositor_state compositor = { 0 }; compositor.data = &state; compositor.output_add_cb = handle_output_add; diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 30495d44..ad5c52a4 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -20,6 +20,11 @@ struct wlr_cursor { struct wl_signal motion_absolute; struct wl_signal button; struct wl_signal axis; + + struct wl_signal touch_up; + struct wl_signal touch_down; + struct wl_signal touch_motion; + struct wl_signal touch_cancel; } events; }; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 28d9f8c9..f9e1fcc9 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -18,6 +18,11 @@ struct wlr_cursor_device { struct wl_listener motion_absolute; struct wl_listener button; struct wl_listener axis; + + struct wl_listener touch_down; + struct wl_listener touch_up; + struct wl_listener touch_motion; + struct wl_listener touch_cancel; }; struct wlr_cursor_state { @@ -45,11 +50,18 @@ struct wlr_cursor *wlr_cursor_init() { wl_list_init(&cur->state->devices); + // pointer signals wl_signal_init(&cur->events.motion); wl_signal_init(&cur->events.motion_absolute); wl_signal_init(&cur->events.button); wl_signal_init(&cur->events.axis); + // touch signals + wl_signal_init(&cur->events.touch_up); + wl_signal_init(&cur->events.touch_down); + wl_signal_init(&cur->events.touch_motion); + wl_signal_init(&cur->events.touch_cancel); + cur->x = 100; cur->y = 100; @@ -218,19 +230,48 @@ static void handle_pointer_axis(struct wl_listener *listener, void *data) { wl_signal_emit(&device->cursor->events.axis, event); } +static void handle_touch_up(struct wl_listener *listener, void *data) { + struct wlr_event_touch_up *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, touch_up); + wl_signal_emit(&device->cursor->events.touch_up, event); +} + +static void handle_touch_down(struct wl_listener *listener, void *data) { + struct wlr_event_touch_down *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, touch_down); + wl_signal_emit(&device->cursor->events.touch_down, event); +} + +static void handle_touch_motion(struct wl_listener *listener, void *data) { + struct wlr_event_touch_motion *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, touch_motion); + wl_signal_emit(&device->cursor->events.touch_motion, event); +} + +static void handle_touch_cancel(struct wl_listener *listener, void *data) { + struct wlr_event_touch_cancel *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, touch_cancel); + wl_signal_emit(&device->cursor->events.touch_cancel, event); +} + void wlr_cursor_attach_input_device(struct wlr_cursor *cur, struct wlr_input_device *dev) { if (dev->type != WLR_INPUT_DEVICE_POINTER && dev->type != WLR_INPUT_DEVICE_TOUCH && dev->type != WLR_INPUT_DEVICE_TABLET_TOOL) { - wlr_log(L_ERROR, "only device types of pointer, touch or tablet tool are" - "supported"); + wlr_log(L_ERROR, "only device types of pointer, touch or tablet tool" + "are supported"); return; } // TODO support other device types - if (dev->type != WLR_INPUT_DEVICE_POINTER) { - wlr_log(L_ERROR, "TODO: support touch and tablet tool devices"); + if (dev->type != WLR_INPUT_DEVICE_POINTER && + dev->type != WLR_INPUT_DEVICE_TOUCH) { + wlr_log(L_ERROR, "TODO: support tablet tool devices"); return; } @@ -242,7 +283,8 @@ void wlr_cursor_attach_input_device(struct wlr_cursor *cur, } } - struct wlr_cursor_device *device = calloc(1, sizeof(struct wlr_cursor_device)); + struct wlr_cursor_device *device; + device = calloc(1, sizeof(struct wlr_cursor_device)); if (!device) { wlr_log(L_ERROR, "Failed to allocate wlr_cursor_device"); return; @@ -252,17 +294,32 @@ void wlr_cursor_attach_input_device(struct wlr_cursor *cur, device->device = dev; // listen to events - wl_signal_add(&dev->pointer->events.motion, &device->motion); - device->motion.notify = handle_pointer_motion; - wl_signal_add(&dev->pointer->events.motion_absolute, &device->motion_absolute); - device->motion_absolute.notify = handle_pointer_motion_absolute; + if (dev->type == WLR_INPUT_DEVICE_POINTER) { + wl_signal_add(&dev->pointer->events.motion, &device->motion); + device->motion.notify = handle_pointer_motion; + + wl_signal_add(&dev->pointer->events.motion_absolute, &device->motion_absolute); + device->motion_absolute.notify = handle_pointer_motion_absolute; - wl_signal_add(&dev->pointer->events.button, &device->button); - device->button.notify = handle_pointer_button; + wl_signal_add(&dev->pointer->events.button, &device->button); + device->button.notify = handle_pointer_button; - wl_signal_add(&dev->pointer->events.axis, &device->axis); - device->axis.notify = handle_pointer_axis; + wl_signal_add(&dev->pointer->events.axis, &device->axis); + device->axis.notify = handle_pointer_axis; + } else if (dev->type == WLR_INPUT_DEVICE_TOUCH) { + wl_signal_add(&dev->touch->events.motion, &device->touch_motion); + device->touch_motion.notify = handle_touch_motion; + + wl_signal_add(&dev->touch->events.down, &device->touch_down); + device->touch_down.notify = handle_touch_down; + + wl_signal_add(&dev->touch->events.up, &device->touch_up); + device->touch_up.notify = handle_touch_up; + + wl_signal_add(&dev->touch->events.cancel, &device->touch_cancel); + device->touch_cancel.notify = handle_touch_cancel; + } wl_list_insert(&cur->state->devices, &device->link); } -- cgit v1.2.3 From c91469767631c84375678f3428a43c355d2c9742 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 27 Aug 2017 11:44:55 -0400 Subject: add device to touch events --- backend/libinput/touch.c | 4 ++++ include/wlr/types/wlr_touch.h | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'include') diff --git a/backend/libinput/touch.c b/backend/libinput/touch.c index 9e08d028..2f300482 100644 --- a/backend/libinput/touch.c +++ b/backend/libinput/touch.c @@ -30,6 +30,7 @@ void handle_touch_down(struct libinput_event *event, struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); struct wlr_event_touch_down wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_touch_get_time(tevent); wlr_event.time_usec = libinput_event_touch_get_time_usec(tevent); wlr_event.slot = libinput_event_touch_get_slot(tevent); @@ -50,6 +51,7 @@ void handle_touch_up(struct libinput_event *event, struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); struct wlr_event_touch_up wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_touch_get_time(tevent); wlr_event.time_usec = libinput_event_touch_get_time_usec(tevent); wlr_event.slot = libinput_event_touch_get_slot(tevent); @@ -67,6 +69,7 @@ void handle_touch_motion(struct libinput_event *event, struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); struct wlr_event_touch_motion wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_touch_get_time(tevent); wlr_event.time_usec = libinput_event_touch_get_time_usec(tevent); wlr_event.slot = libinput_event_touch_get_slot(tevent); @@ -87,6 +90,7 @@ void handle_touch_cancel(struct libinput_event *event, struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); struct wlr_event_touch_cancel wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_touch_get_time(tevent); wlr_event.time_usec = libinput_event_touch_get_time_usec(tevent); wlr_event.slot = libinput_event_touch_get_slot(tevent); diff --git a/include/wlr/types/wlr_touch.h b/include/wlr/types/wlr_touch.h index 93069fcb..1a27cad3 100644 --- a/include/wlr/types/wlr_touch.h +++ b/include/wlr/types/wlr_touch.h @@ -19,6 +19,7 @@ struct wlr_touch { }; struct wlr_event_touch_down { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; int32_t slot; @@ -27,12 +28,14 @@ struct wlr_event_touch_down { }; struct wlr_event_touch_up { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; int32_t slot; }; struct wlr_event_touch_motion { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; int32_t slot; @@ -41,6 +44,7 @@ struct wlr_event_touch_motion { }; struct wlr_event_touch_cancel { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; int32_t slot; -- cgit v1.2.3 From 5e06d61e4238f7e2ebc9ac4750ff477423b02279 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 27 Aug 2017 17:35:12 -0400 Subject: implement touch up and touch down --- examples/pointer.c | 20 +++++--- include/wlr/types/wlr_cursor.h | 3 ++ include/wlr/types/wlr_geometry.h | 2 + include/wlr/types/wlr_output_layout.h | 13 +++++ types/wlr_cursor.c | 92 +++++++++++++++++++++++++++-------- types/wlr_geometry.c | 22 +++------ types/wlr_output_layout.c | 89 ++++++++++++++++++++++++++++----- 7 files changed, 189 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/examples/pointer.c b/examples/pointer.c index bae205f5..98b4735a 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -58,12 +58,20 @@ struct touch_point { double x, y; }; -static void warp_to_touch(struct sample_state *sample) { - wlr_log(L_DEBUG, "TODO: warp to touch"); +static void warp_to_touch(struct sample_state *sample, struct wlr_input_device *dev) { + if (sample->touch_points->length == 0) { + return; + } + + double x = 0, y = 0; for (size_t i = 0; i < sample->touch_points->length; ++i) { struct touch_point *point = sample->touch_points->items[i]; - wlr_log(L_DEBUG, "have point x=%f,y=%f", point->x, point->y); + x += point->x; + y += point->y; } + x /= sample->touch_points->length; + y /= sample->touch_points->length; + wlr_cursor_warp_absolute(sample->cursor, dev, x, y); } static void handle_output_frame(struct output_state *output, struct timespec *ts) { @@ -248,7 +256,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { } } - warp_to_touch(sample); + warp_to_touch(sample, event->device); } static void handle_touch_down(struct wl_listener *listener, void *data) { @@ -262,7 +270,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { free(point); } - warp_to_touch(sample); + warp_to_touch(sample, event->device); } static void handle_touch_motion(struct wl_listener *listener, void *data) { @@ -277,7 +285,7 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { } } - warp_to_touch(sample); + warp_to_touch(sample, event->device); } static void handle_touch_cancel(struct wl_listener *listener, void *data) { diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index ad5c52a4..4ba7b25f 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -46,6 +46,9 @@ void wlr_cursor_set_xcursor(struct wlr_cursor *cur, struct wlr_xcursor *xcur); bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, double x, double y); +void wlr_cursor_warp_absolute(struct wlr_cursor *cur, + struct wlr_input_device *dev, double x_mm, double y_mm); + /** * Move the cursor in the direction of the given x and y coordinates. * diff --git a/include/wlr/types/wlr_geometry.h b/include/wlr/types/wlr_geometry.h index 7ac2f843..cac75431 100644 --- a/include/wlr/types/wlr_geometry.h +++ b/include/wlr/types/wlr_geometry.h @@ -15,4 +15,6 @@ bool wlr_geometry_intersection(struct wlr_geometry *geo_a, bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y); +bool wlr_geometry_empty(struct wlr_geometry *geo); + #endif diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index 144c2d5a..0d157f56 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -4,14 +4,20 @@ #include #include +struct wlr_output_layout_state; + struct wlr_output_layout { struct wl_list outputs; + struct wlr_output_layout_state *state; }; +struct wlr_output_layout_output_state; + struct wlr_output_layout_output { struct wlr_output *output; int x, y; struct wl_list link; + struct wlr_output_layout_output_state *state; }; struct wlr_output_layout *wlr_output_layout_init(); @@ -55,4 +61,11 @@ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, struct wlr_output *reference, double x, double y, double *dest_x, double *dest_y); +/** + * Get the geometry of the layout for the given reference output. If `reference` + * is NULL, the geometry will be for the extents of the entire layout. + */ +struct wlr_geometry *wlr_output_layout_get_geometry( + struct wlr_output_layout *layout, struct wlr_output *reference); + #endif diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index f9e1fcc9..f315727f 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,29 @@ static struct wlr_cursor_device *get_cursor_device(struct wlr_cursor *cur, return ret; } +static void wlr_cursor_warp_unchecked(struct wlr_cursor *cur, double x, double y) { + int hotspot_x = 0; + int hotspot_y = 0; + + if (cur->state->xcursor && cur->state->xcursor->image_count > 0) { + struct wlr_xcursor_image *image = cur->state->xcursor->images[0]; + hotspot_x = image->hotspot_x; + hotspot_y = image->hotspot_y; + } + + + struct wlr_output_layout_output *l_output; + wl_list_for_each(l_output, &cur->state->layout->outputs, link) { + double output_x = x; + double output_y = y; + + wlr_output_layout_output_coords(cur->state->layout, + l_output->output, &output_x, &output_y); + wlr_output_move_cursor(l_output->output, output_x - hotspot_x, + output_y - hotspot_y); + } +} + bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, double x, double y) { assert(cur->state->layout); @@ -120,28 +144,59 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, return false; } - int hotspot_x = 0; - int hotspot_y = 0; + wlr_cursor_warp_unchecked(cur, x, y); + return true; +} - if (cur->state->xcursor && cur->state->xcursor->image_count > 0) { - struct wlr_xcursor_image *image = cur->state->xcursor->images[0]; - hotspot_x = image->hotspot_x; - hotspot_y = image->hotspot_y; +void wlr_cursor_warp_absolute(struct wlr_cursor *cur, + struct wlr_input_device *dev, double x_mm, double y_mm) { + // convert from absolute to global coordinates + assert(cur->state->layout); + struct wlr_output *mapped_output = NULL; + struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); + + if (c_device && c_device->mapped_output) { + mapped_output = c_device->mapped_output; + } else { + mapped_output = cur->state->mapped_output; } + struct wlr_geometry *constraints = calloc(1, sizeof(struct wlr_geometry)); + // XXX how do we express infinite regions? + constraints->x = INT_MIN / 2; + constraints->y = INT_MIN / 2; + constraints->width = INT_MAX; + constraints->height = INT_MAX; - struct wlr_output_layout_output *l_output; - wl_list_for_each(l_output, &cur->state->layout->outputs, link) { - double output_x = x; - double output_y = y; + if (cur->state->mapped_geometry) { + wlr_geometry_intersection(cur->state->mapped_geometry, constraints, + &constraints); + } + if (c_device->mapped_geometry) { + wlr_geometry_intersection(c_device->mapped_geometry, constraints, + &constraints); + } + struct wlr_geometry *geo; + if (mapped_output) { + geo = wlr_output_layout_get_geometry(cur->state->layout, mapped_output); + wlr_geometry_intersection(geo, constraints, &constraints); + } + geo = wlr_output_layout_get_geometry(cur->state->layout, NULL); + wlr_geometry_intersection(geo, constraints, &constraints); - wlr_output_layout_output_coords(cur->state->layout, - l_output->output, &output_x, &output_y); - wlr_output_move_cursor(l_output->output, output_x - hotspot_x, - output_y - hotspot_y); + if (wlr_geometry_empty(constraints)) { + goto out; } - return true; + double x = constraints->width * x_mm + constraints->x; + double y = constraints->height * y_mm + constraints->y; + + wlr_cursor_warp_unchecked(cur, x, y); + +out: + if (constraints) { + free(constraints); + } } void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, @@ -195,10 +250,9 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, goto out; } - if (wlr_cursor_warp(cur, dev, x, y)) { - cur->x = x; - cur->y = y; - } + wlr_cursor_warp_unchecked(cur, x, y); + cur->x = x; + cur->y = y; out: if (constraints) { diff --git a/types/wlr_geometry.c b/types/wlr_geometry.c index be4a80eb..32dbb81f 100644 --- a/types/wlr_geometry.c +++ b/types/wlr_geometry.c @@ -45,8 +45,8 @@ void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, #define min(a,b) ((a) < (b) ? (a) : (b)) #endif -static bool wlr_geometry_empty(struct wlr_geometry *geo) { - return geo == NULL || geo->width < 0 || geo->height < 0; +bool wlr_geometry_empty(struct wlr_geometry *geo) { + return geo == NULL || geo->width <= 0 || geo->height <= 0; } bool wlr_geometry_intersection(struct wlr_geometry *geo_a, @@ -55,20 +55,12 @@ bool wlr_geometry_intersection(struct wlr_geometry *geo_a, bool a_empty = wlr_geometry_empty(geo_a); bool b_empty = wlr_geometry_empty(geo_b); - if (a_empty && b_empty) { + if (a_empty || b_empty) { + dest->x = 0; + dest->y = 0; + dest->width = -100; + dest->height = -100; return false; - } else if (a_empty) { - dest->x = geo_b->x; - dest->y = geo_b->y; - dest->height = geo_b->height; - dest->width = geo_b->width; - return true; - } else if (b_empty) { - dest->x = geo_a->x; - dest->y = geo_a->y; - dest->height = geo_a->height; - dest->width = geo_a->width; - return true; } int x1 = max(geo_a->x, geo_b->x); diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 7dcb4651..0b5e0411 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -1,16 +1,35 @@ #include #include #include +#include #include #include #include +struct wlr_output_layout_state { + struct wlr_geometry *_geo; +}; + +struct wlr_output_layout_output_state { + struct wlr_geometry *_geo; +}; + struct wlr_output_layout *wlr_output_layout_init() { struct wlr_output_layout *layout = calloc(1, sizeof(struct wlr_output_layout)); + layout->state = calloc(1, sizeof(struct wlr_output_layout_state)); + layout->state->_geo = calloc(1, sizeof(struct wlr_geometry)); wl_list_init(&layout->outputs); return layout; } +static void wlr_output_layout_output_destroy( + struct wlr_output_layout_output *l_output) { + wl_list_remove(&l_output->link); + free(l_output->state->_geo); + free(l_output->state); + free(l_output); +} + void wlr_output_layout_destroy(struct wlr_output_layout *layout) { if (!layout) { return; @@ -18,20 +37,24 @@ void wlr_output_layout_destroy(struct wlr_output_layout *layout) { struct wlr_output_layout_output *_output, *temp = NULL; wl_list_for_each_safe(_output, temp, &layout->outputs, link) { - wl_list_remove(&_output->link); - free(_output); + wlr_output_layout_output_destroy(_output); } + free(layout->state->_geo); + free(layout->state); free(layout); } void wlr_output_layout_add(struct wlr_output_layout *layout, struct wlr_output *output, int x, int y) { - struct wlr_output_layout_output *layout_output = calloc(1, sizeof(struct wlr_output_layout_output)); - layout_output->output = output; - layout_output->x = x; - layout_output->y = y; - wl_list_insert(&layout->outputs, &layout_output->link); + struct wlr_output_layout_output *l_output; + l_output= calloc(1, sizeof(struct wlr_output_layout_output)); + l_output->state = calloc(1, sizeof(struct wlr_output_layout_output_state)); + l_output->state->_geo = calloc(1, sizeof(struct wlr_geometry)); + l_output->output = output; + l_output->x = x; + l_output->y = y; + wl_list_insert(&layout->outputs, &l_output->link); } struct wlr_output_layout_output *wlr_output_layout_get( @@ -104,11 +127,10 @@ void wlr_output_layout_move(struct wlr_output_layout *layout, void wlr_output_layout_remove(struct wlr_output_layout *layout, struct wlr_output *output) { - struct wlr_output_layout_output *layout_output = - wlr_output_layout_get(layout, output); - if (layout_output) { - wl_list_remove(&layout_output->link); - free(layout_output); + struct wlr_output_layout_output *l_output; + l_output= wlr_output_layout_get(layout, output); + if (l_output) { + wlr_output_layout_output_destroy(l_output); } } @@ -179,3 +201,46 @@ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, *dest_x = min_x; *dest_y = min_y; } + +struct wlr_geometry *wlr_output_layout_get_geometry( + struct wlr_output_layout *layout, struct wlr_output *reference) { + struct wlr_output_layout_output *l_output; + if (reference) { + // output extents + l_output= wlr_output_layout_get(layout, reference); + l_output->state->_geo->x = l_output->x; + l_output->state->_geo->y = l_output->y; + wlr_output_effective_resolution(reference, + &l_output->state->_geo->width, &l_output->state->_geo->height); + return l_output->state->_geo; + } else { + // layout extents + int min_x = INT_MAX, min_y = INT_MAX; + int max_x = INT_MIN, max_y = INT_MIN; + wl_list_for_each(l_output, &layout->outputs, link) { + int width, height; + wlr_output_effective_resolution(l_output->output, &width, &height); + if (l_output->x < min_x) { + min_x = l_output->x; + } + if (l_output->y < min_y) { + min_y = l_output->y; + } + if (l_output->x + width > max_x) { + max_x = l_output->x + width; + } + if (l_output->y + height > max_y) { + max_y = l_output->y + height; + } + } + + layout->state->_geo->x = min_x; + layout->state->_geo->y = min_y; + layout->state->_geo->width = max_x - min_x; + layout->state->_geo->height = max_y - min_y; + + return layout->state->_geo; + } + + // not reached +} -- cgit v1.2.3 From df0ee7f25ff628360f38d87b8a74daaa2cc742a8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 28 Aug 2017 08:42:39 -0400 Subject: implement tablet tool devices --- backend/libinput/tablet_tool.c | 4 +++ examples/pointer.c | 4 +-- include/wlr/types/wlr_cursor.h | 5 +++ include/wlr/types/wlr_tablet_tool.h | 4 +++ types/wlr_cursor.c | 61 ++++++++++++++++++++++++++++++++----- 5 files changed, 69 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/backend/libinput/tablet_tool.c b/backend/libinput/tablet_tool.c index 8b3d34ed..472e8506 100644 --- a/backend/libinput/tablet_tool.c +++ b/backend/libinput/tablet_tool.c @@ -30,6 +30,7 @@ void handle_tablet_tool_axis(struct libinput_event *event, struct libinput_event_tablet_tool *tevent = libinput_event_get_tablet_tool_event(event); struct wlr_event_tablet_tool_axis wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_tablet_tool_get_time(tevent); wlr_event.time_usec = libinput_event_tablet_tool_get_time_usec(tevent); libinput_device_get_size(libinput_dev, &wlr_event.width_mm, &wlr_event.height_mm); @@ -83,6 +84,7 @@ void handle_tablet_tool_proximity(struct libinput_event *event, struct libinput_event_tablet_tool *tevent = libinput_event_get_tablet_tool_event(event); struct wlr_event_tablet_tool_proximity wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_tablet_tool_get_time(tevent); wlr_event.time_usec = libinput_event_tablet_tool_get_time_usec(tevent); switch (libinput_event_tablet_tool_get_proximity_state(tevent)) { @@ -109,6 +111,7 @@ void handle_tablet_tool_tip(struct libinput_event *event, struct libinput_event_tablet_tool *tevent = libinput_event_get_tablet_tool_event(event); struct wlr_event_tablet_tool_tip wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_tablet_tool_get_time(tevent); wlr_event.time_usec = libinput_event_tablet_tool_get_time_usec(tevent); switch (libinput_event_tablet_tool_get_tip_state(tevent)) { @@ -134,6 +137,7 @@ void handle_tablet_tool_button(struct libinput_event *event, struct libinput_event_tablet_tool *tevent = libinput_event_get_tablet_tool_event(event); struct wlr_event_tablet_tool_button wlr_event = { 0 }; + wlr_event.device = wlr_dev; wlr_event.time_sec = libinput_event_tablet_tool_get_time(tevent); wlr_event.time_usec = libinput_event_tablet_tool_get_time_usec(tevent); wlr_event.button = libinput_event_tablet_tool_get_button(tevent); diff --git a/examples/pointer.c b/examples/pointer.c index 98b4735a..3863c0e8 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -175,9 +175,9 @@ static void handle_input_add(struct compositor_state *state, struct wlr_input_device *device) { struct sample_state *sample = state->data; - // TODO handle other input devices if (device->type == WLR_INPUT_DEVICE_POINTER || - device->type == WLR_INPUT_DEVICE_TOUCH) { + device->type == WLR_INPUT_DEVICE_TOUCH || + device->type == WLR_INPUT_DEVICE_TABLET_TOOL) { struct sample_input_device *s_device; s_device = calloc(1, sizeof(struct sample_input_device)); s_device->device = device; diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 4ba7b25f..35c2ff8e 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -25,6 +25,11 @@ struct wlr_cursor { struct wl_signal touch_down; struct wl_signal touch_motion; struct wl_signal touch_cancel; + + struct wl_signal tablet_tool_axis; + struct wl_signal tablet_tool_proximity; + struct wl_signal tablet_tool_tip; + struct wl_signal tablet_tool_button; } events; }; diff --git a/include/wlr/types/wlr_tablet_tool.h b/include/wlr/types/wlr_tablet_tool.h index dcb9c191..98fd82c0 100644 --- a/include/wlr/types/wlr_tablet_tool.h +++ b/include/wlr/types/wlr_tablet_tool.h @@ -32,6 +32,7 @@ enum wlr_tablet_tool_axes { }; struct wlr_event_tablet_tool_axis { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; uint32_t updated_axes; @@ -51,6 +52,7 @@ enum wlr_tablet_tool_proximity_state { }; struct wlr_event_tablet_tool_proximity { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; double x, y; @@ -64,6 +66,7 @@ enum wlr_tablet_tool_tip_state { }; struct wlr_event_tablet_tool_tip { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; double x, y; @@ -72,6 +75,7 @@ struct wlr_event_tablet_tool_tip { }; struct wlr_event_tablet_tool_button { + struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; uint32_t button; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index f183e64a..c62fba9b 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -24,6 +24,11 @@ struct wlr_cursor_device { struct wl_listener touch_up; struct wl_listener touch_motion; struct wl_listener touch_cancel; + + struct wl_listener tablet_tool_axis; + struct wl_listener tablet_tool_proximity; + struct wl_listener tablet_tool_tip; + struct wl_listener tablet_tool_button; }; struct wlr_cursor_state { @@ -63,6 +68,12 @@ struct wlr_cursor *wlr_cursor_init() { wl_signal_init(&cur->events.touch_motion); wl_signal_init(&cur->events.touch_cancel); + // tablet tool signals + wl_signal_init(&cur->events.tablet_tool_tip); + wl_signal_init(&cur->events.tablet_tool_axis); + wl_signal_init(&cur->events.tablet_tool_button); + wl_signal_init(&cur->events.tablet_tool_proximity); + cur->x = 100; cur->y = 100; @@ -279,6 +290,34 @@ static void handle_touch_cancel(struct wl_listener *listener, void *data) { wl_signal_emit(&device->cursor->events.touch_cancel, event); } +static void handle_tablet_tool_tip(struct wl_listener *listener, void *data) { + struct wlr_event_tablet_tool_tip *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, tablet_tool_tip); + wl_signal_emit(&device->cursor->events.tablet_tool_tip, event); +} + +static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { + struct wlr_event_tablet_tool_axis *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, tablet_tool_axis); + wl_signal_emit(&device->cursor->events.tablet_tool_axis, event); +} + +static void handle_tablet_tool_button(struct wl_listener *listener, void *data) { + struct wlr_event_tablet_tool_button *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, tablet_tool_button); + wl_signal_emit(&device->cursor->events.tablet_tool_button, event); +} + +static void handle_tablet_tool_proximity(struct wl_listener *listener, void *data) { + struct wlr_event_tablet_tool_proximity *event = data; + struct wlr_cursor_device *device; + device = wl_container_of(listener, device, tablet_tool_proximity); + wl_signal_emit(&device->cursor->events.tablet_tool_proximity, event); +} + void wlr_cursor_attach_input_device(struct wlr_cursor *cur, struct wlr_input_device *dev) { if (dev->type != WLR_INPUT_DEVICE_POINTER && @@ -289,13 +328,6 @@ void wlr_cursor_attach_input_device(struct wlr_cursor *cur, return; } - // TODO support other device types - if (dev->type != WLR_INPUT_DEVICE_POINTER && - dev->type != WLR_INPUT_DEVICE_TOUCH) { - wlr_log(L_ERROR, "TODO: support tablet tool devices"); - return; - } - // make sure it is not already attached struct wlr_cursor_device *_dev; wl_list_for_each(_dev, &cur->state->devices, link) { @@ -340,6 +372,21 @@ void wlr_cursor_attach_input_device(struct wlr_cursor *cur, wl_signal_add(&dev->touch->events.cancel, &device->touch_cancel); device->touch_cancel.notify = handle_touch_cancel; + } else if (dev->type == WLR_INPUT_DEVICE_TABLET_TOOL) { + wl_signal_add(&dev->tablet_tool->events.tip, &device->tablet_tool_tip); + device->tablet_tool_tip.notify = handle_tablet_tool_tip; + + wl_signal_add(&dev->tablet_tool->events.proximity, + &device->tablet_tool_proximity); + device->tablet_tool_proximity.notify = handle_tablet_tool_proximity; + + wl_signal_add(&dev->tablet_tool->events.axis, + &device->tablet_tool_axis); + device->tablet_tool_axis.notify = handle_tablet_tool_axis; + + wl_signal_add(&dev->tablet_tool->events.button, + &device->tablet_tool_button); + device->tablet_tool_button.notify = handle_tablet_tool_button; } wl_list_insert(&cur->state->devices, &device->link); -- cgit v1.2.3 From 5c845f14ed72bcdbd45a2e719223c441846f62ad Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 28 Aug 2017 10:29:53 -0400 Subject: handle input device destroy --- examples/pointer.c | 15 +++++++++++++-- examples/shared.c | 5 +++++ examples/shared.h | 2 ++ include/wlr/types/wlr_input_device.h | 4 ++++ types/wlr_cursor.c | 11 +++++++++++ types/wlr_input_device.c | 4 ++++ 6 files changed, 39 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/examples/pointer.c b/examples/pointer.c index 3863c0e8..8ad18442 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -188,6 +188,18 @@ static void handle_input_add(struct compositor_state *state, struct } } +static void handle_input_remove(struct compositor_state *state, struct + wlr_input_device *device) { + struct sample_state *sample = state->data; + struct sample_input_device *s_device, *tmp = NULL; + wl_list_for_each_safe(s_device, tmp, &sample->devices, link) { + if (s_device->device == device) { + wl_list_remove(&s_device->link); + free(s_device); + } + } +} + static void handle_cursor_motion(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, cursor_motion); struct wlr_event_pointer_motion *event = data; @@ -339,8 +351,7 @@ int main(int argc, char *argv[]) { compositor.output_resolution_cb = handle_output_resolution; compositor.output_frame_cb = handle_output_frame; compositor.input_add_cb = handle_input_add; - // TODO input_remove_cb - //compositor.input_remove_cb = handle_input_add; + compositor.input_remove_cb = handle_input_remove; state.compositor = &compositor; diff --git a/examples/shared.c b/examples/shared.c index f9d687e3..0346c96d 100644 --- a/examples/shared.c +++ b/examples/shared.c @@ -401,6 +401,11 @@ static void tablet_pad_remove(struct wlr_input_device *device, struct compositor static void input_remove_notify(struct wl_listener *listener, void *data) { struct wlr_input_device *device = data; struct compositor_state *state = wl_container_of(listener, state, input_remove); + + if (state->input_remove_cb) { + state->input_remove_cb(state, device); + } + switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD: keyboard_remove(device, state); diff --git a/examples/shared.h b/examples/shared.h index 06108494..7cf4db63 100644 --- a/examples/shared.h +++ b/examples/shared.h @@ -77,6 +77,8 @@ struct tablet_pad_state { struct compositor_state { void (*input_add_cb)(struct compositor_state *compositor, struct wlr_input_device *device); + void (*input_remove_cb)(struct compositor_state *compositor, + struct wlr_input_device *device); void (*output_add_cb)(struct output_state *s); void (*keyboard_add_cb)(struct keyboard_state *s); void (*output_frame_cb)(struct output_state *s, struct timespec *ts); diff --git a/include/wlr/types/wlr_input_device.h b/include/wlr/types/wlr_input_device.h index 642892ff..5a41ce9d 100644 --- a/include/wlr/types/wlr_input_device.h +++ b/include/wlr/types/wlr_input_device.h @@ -40,6 +40,10 @@ struct wlr_input_device { struct wlr_tablet_pad *tablet_pad; }; + struct { + struct wl_signal destroy; + } events; + void *data; }; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index c62fba9b..ff19bb2b 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -29,6 +29,8 @@ struct wlr_cursor_device { struct wl_listener tablet_tool_proximity; struct wl_listener tablet_tool_tip; struct wl_listener tablet_tool_button; + + struct wl_listener destroy; }; struct wlr_cursor_state { @@ -318,6 +320,12 @@ static void handle_tablet_tool_proximity(struct wl_listener *listener, void *dat wl_signal_emit(&device->cursor->events.tablet_tool_proximity, event); } +static void handle_device_destroy(struct wl_listener *listener, void *data) { + struct wlr_cursor_device *c_device; + c_device = wl_container_of(listener, c_device, destroy); + wlr_cursor_detach_input_device(c_device->cursor, c_device->device); +} + void wlr_cursor_attach_input_device(struct wlr_cursor *cur, struct wlr_input_device *dev) { if (dev->type != WLR_INPUT_DEVICE_POINTER && @@ -348,6 +356,9 @@ void wlr_cursor_attach_input_device(struct wlr_cursor *cur, // listen to events + wl_signal_add(&dev->events.destroy, &device->destroy); + device->destroy.notify = handle_device_destroy; + if (dev->type == WLR_INPUT_DEVICE_POINTER) { wl_signal_add(&dev->pointer->events.motion, &device->motion); device->motion.notify = handle_pointer_motion; diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 409e8bd1..002c2b54 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -20,12 +20,16 @@ void wlr_input_device_init(struct wlr_input_device *dev, dev->name = strdup(name); dev->vendor = vendor; dev->product = product; + + wl_signal_init(&dev->events.destroy); } void wlr_input_device_destroy(struct wlr_input_device *dev) { if (!dev) { return; } + + wl_signal_emit(&dev->events.destroy, dev); if (dev->_device) { switch (dev->type) { -- cgit v1.2.3 From 30611894f2c411830a57e813c441e901068ff033 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 28 Aug 2017 22:12:35 -0400 Subject: Implement tablet_tool support in pointer example --- examples/pointer.c | 20 ++++++++++++++++++++ include/wlr/types/wlr_tablet_tool.h | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/examples/pointer.c b/examples/pointer.c index 936bfb6a..f808d9ab 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -51,6 +51,11 @@ struct sample_state { struct wl_listener touch_down; struct wl_listener touch_cancel; list_t *touch_points; + + struct wl_listener tablet_tool_axis; + struct wl_listener tablet_tool_proxmity; + struct wl_listener tablet_tool_tip; + struct wl_listener tablet_tool_button; }; struct touch_point { @@ -306,6 +311,17 @@ static void handle_touch_cancel(struct wl_listener *listener, void *data) { wlr_log(L_DEBUG, "TODO: touch cancel"); } +static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { + struct sample_state *sample = wl_container_of(listener, sample, tablet_tool_axis); + struct wlr_event_tablet_tool_axis *event = data; + if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) + && (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { + wlr_cursor_warp_absolute(sample->cursor, event->device, + event->x_mm / event->width_mm, + event->y_mm / event->height_mm); + } +} + int main(int argc, char *argv[]) { struct sample_state state = { .default_color = { 0.25f, 0.25f, 0.25f, 1 }, @@ -344,6 +360,10 @@ int main(int argc, char *argv[]) { wl_signal_add(&state.cursor->events.touch_cancel, &state.touch_cancel); state.touch_cancel.notify = handle_touch_cancel; + // tool events + wl_signal_add(&state.cursor->events.tablet_tool_axis, &state.tablet_tool_axis); + state.tablet_tool_axis.notify = handle_tablet_tool_axis; + struct compositor_state compositor = { 0 }; compositor.data = &state; compositor.output_add_cb = handle_output_add; diff --git a/include/wlr/types/wlr_tablet_tool.h b/include/wlr/types/wlr_tablet_tool.h index 98fd82c0..9090828a 100644 --- a/include/wlr/types/wlr_tablet_tool.h +++ b/include/wlr/types/wlr_tablet_tool.h @@ -55,7 +55,7 @@ struct wlr_event_tablet_tool_proximity { struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; - double x, y; + double x_mm, y_mm; double width_mm, height_mm; enum wlr_tablet_tool_proximity_state state; }; @@ -69,7 +69,7 @@ struct wlr_event_tablet_tool_tip { struct wlr_input_device *device; uint32_t time_sec; uint64_t time_usec; - double x, y; + double x_mm, y_mm; double width_mm, height_mm; enum wlr_tablet_tool_tip_state state; }; -- cgit v1.2.3 From 3449777a8d3fec597c40b29540800d6addd7a05e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 29 Aug 2017 09:59:03 -0400 Subject: wlr_output_layout.c: fix style --- include/wlr/types/wlr_output_layout.h | 8 ++--- types/wlr_output_layout.c | 59 ++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index 0d157f56..dfb5234d 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -7,16 +7,16 @@ struct wlr_output_layout_state; struct wlr_output_layout { - struct wl_list outputs; + struct wl_list outputs; struct wlr_output_layout_state *state; }; struct wlr_output_layout_output_state; struct wlr_output_layout_output { - struct wlr_output *output; - int x, y; - struct wl_list link; + struct wlr_output *output; + int x, y; + struct wl_list link; struct wlr_output_layout_output_state *state; }; diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 4062c107..b097b1b8 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -15,7 +15,8 @@ struct wlr_output_layout_output_state { }; struct wlr_output_layout *wlr_output_layout_init() { - struct wlr_output_layout *layout = calloc(1, sizeof(struct wlr_output_layout)); + struct wlr_output_layout *layout = + calloc(1, sizeof(struct wlr_output_layout)); layout->state = calloc(1, sizeof(struct wlr_output_layout_state)); layout->state->_geo = calloc(1, sizeof(struct wlr_geometry)); wl_list_init(&layout->outputs); @@ -24,10 +25,10 @@ struct wlr_output_layout *wlr_output_layout_init() { static void wlr_output_layout_output_destroy( struct wlr_output_layout_output *l_output) { - wl_list_remove(&l_output->link); - free(l_output->state->_geo); - free(l_output->state); - free(l_output); + wl_list_remove(&l_output->link); + free(l_output->state->_geo); + free(l_output->state); + free(l_output); } void wlr_output_layout_destroy(struct wlr_output_layout *layout) { @@ -59,10 +60,10 @@ void wlr_output_layout_add(struct wlr_output_layout *layout, struct wlr_output_layout_output *wlr_output_layout_get( struct wlr_output_layout *layout, struct wlr_output *reference) { - struct wlr_output_layout_output *_output; - wl_list_for_each(_output, &layout->outputs, link) { - if (_output->output == reference) { - return _output; + struct wlr_output_layout_output *l_output; + wl_list_for_each(l_output, &layout->outputs, link) { + if (l_output->output == reference) { + return l_output; } } return NULL; @@ -77,7 +78,8 @@ static bool output_contains_point( struct wlr_output_layout_output *l_output, bool wlr_output_layout_contains_point(struct wlr_output_layout *layout, struct wlr_output *reference, int x, int y) { if (reference) { - struct wlr_output_layout_output *layout_output = wlr_output_layout_get(layout, reference); + struct wlr_output_layout_output *layout_output = + wlr_output_layout_get(layout, reference); int width, height; wlr_output_effective_resolution(layout_output->output, &width, &height); return output_contains_point(layout_output, x, y, width, height); @@ -88,7 +90,8 @@ bool wlr_output_layout_contains_point(struct wlr_output_layout *layout, bool wlr_output_layout_intersects(struct wlr_output_layout *layout, struct wlr_output *reference, int x1, int y1, int x2, int y2) { - struct wlr_output_layout_output *l_output = wlr_output_layout_get(layout, reference); + struct wlr_output_layout_output *l_output = + wlr_output_layout_get(layout, reference); if (!l_output) { return false; } @@ -104,15 +107,15 @@ bool wlr_output_layout_intersects(struct wlr_output_layout *layout, struct wlr_output *wlr_output_layout_output_at(struct wlr_output_layout *layout, double x, double y) { - struct wlr_output_layout_output *_output; - wl_list_for_each(_output, &layout->outputs, link) { - if (_output->output) { + struct wlr_output_layout_output *l_output; + wl_list_for_each(l_output, &layout->outputs, link) { + if (l_output->output) { int width, height; - wlr_output_effective_resolution(_output->output, &width, &height); - bool has_x = x >= _output->x && x <= _output->x + width; - bool has_y = y >= _output->y && y <= _output->y + height; + wlr_output_effective_resolution(l_output->output, &width, &height); + bool has_x = x >= l_output->x && x <= l_output->x + width; + bool has_y = y >= l_output->y && y <= l_output->y + height; if (has_x && has_y) { - return _output->output; + return l_output->output; } } } @@ -121,11 +124,11 @@ struct wlr_output *wlr_output_layout_output_at(struct wlr_output_layout *layout, void wlr_output_layout_move(struct wlr_output_layout *layout, struct wlr_output *output, int x, int y) { - struct wlr_output_layout_output *layout_output = - wlr_output_layout_get(layout, output); - if (layout_output) { - layout_output->x = x; - layout_output->y = y; + struct wlr_output_layout_output *l_output = + wlr_output_layout_get(layout, output); + if (l_output) { + l_output->x = x; + l_output->y = y; } } @@ -144,11 +147,11 @@ void wlr_output_layout_output_coords(struct wlr_output_layout *layout, double src_x = *x; double src_y = *y; - struct wlr_output_layout_output *_output; - wl_list_for_each(_output, &layout->outputs, link) { - if (_output->output == reference) { - *x = src_x - (double)_output->x; - *y = src_y - (double)_output->y; + struct wlr_output_layout_output *l_output; + wl_list_for_each(l_output, &layout->outputs, link) { + if (l_output->output == reference) { + *x = src_x - (double)l_output->x; + *y = src_y - (double)l_output->y; return; } } -- cgit v1.2.3 From 1fb8bc9340d157dffd354ea18f8521e279021750 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 29 Aug 2017 10:31:39 -0400 Subject: wlr_cursor.c: fix formatting --- include/wlr/types/wlr_cursor.h | 23 +++++++++++------------ types/wlr_cursor.c | 35 +++++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 35c2ff8e..b91c195e 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -8,15 +8,13 @@ #include struct wlr_cursor_state; -//struct wlr_cursor_impl *; struct wlr_cursor { - struct wlr_cursor_state *state; - //struct wlr_cursor_impl *impl; - int x, y; + struct wlr_cursor_state *state; + int x, y; - struct { - struct wl_signal motion; + struct { + struct wl_signal motion; struct wl_signal motion_absolute; struct wl_signal button; struct wl_signal axis; @@ -30,7 +28,7 @@ struct wlr_cursor { struct wl_signal tablet_tool_proximity; struct wl_signal tablet_tool_tip; struct wl_signal tablet_tool_button; - } events; + } events; }; struct wlr_cursor *wlr_cursor_init(); @@ -71,24 +69,25 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, * - WLR_INPUT_DEVICE_TABLET_TOOL */ void wlr_cursor_attach_input_device(struct wlr_cursor *cur, - struct wlr_input_device *dev); + struct wlr_input_device *dev); void wlr_cursor_detach_input_device(struct wlr_cursor *cur, - struct wlr_input_device *dev); + struct wlr_input_device *dev); /** * Uses the given layout to establish the boundaries and movement semantics of * this cursor. Cursors without an output layout allow infinite movement in any * direction and do not support absolute input events. */ void wlr_cursor_attach_output_layout(struct wlr_cursor *cur, - struct wlr_output_layout *l); + struct wlr_output_layout *l); /** * Attaches this cursor to the given output, which must be among the outputs in * the current output_layout for this cursor. This call is invalid for a cursor * without an associated output layout. */ -void wlr_cursor_map_to_output(struct wlr_cursor *cur, struct wlr_output *output); +void wlr_cursor_map_to_output(struct wlr_cursor *cur, + struct wlr_output *output); /** * Maps all input from a specific input device to a given output. The input @@ -96,7 +95,7 @@ void wlr_cursor_map_to_output(struct wlr_cursor *cur, struct wlr_output *output) * outputs in the attached output layout. */ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, - struct wlr_input_device *dev, struct wlr_output *output); + struct wlr_input_device *dev, struct wlr_output *output); /** * Maps this cursor to an arbitrary region on the associated wlr_output_layout. diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 9f93d0d7..9a9a28b8 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -110,7 +110,8 @@ static struct wlr_cursor_device *get_cursor_device(struct wlr_cursor *cur, return ret; } -static void wlr_cursor_warp_unchecked(struct wlr_cursor *cur, double x, double y) { +static void wlr_cursor_warp_unchecked(struct wlr_cursor *cur, + double x, double y) { assert(cur->state->layout); int hotspot_x = 0; int hotspot_y = 0; @@ -166,7 +167,7 @@ static struct wlr_geometry *get_mapping(struct wlr_cursor *cur, if (cur->state->mapped_geometry) { return cur->state->mapped_geometry; } - if(cur->state->mapped_output) { + if (cur->state->mapped_output) { return wlr_output_layout_get_geometry(cur->state->layout, cur->state->mapped_output); } @@ -186,7 +187,8 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, wlr_cursor_warp_unchecked(cur, x, y); result = true; } - } else if (wlr_output_layout_contains_point(cur->state->layout, NULL, x, y)) { + } else if (wlr_output_layout_contains_point(cur->state->layout, NULL, + x, y)) { wlr_cursor_warp_unchecked(cur, x, y); result = true; } @@ -243,19 +245,23 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, static void handle_pointer_motion(struct wl_listener *listener, void *data) { struct wlr_event_pointer_motion *event = data; - struct wlr_cursor_device *device = wl_container_of(listener, device, motion); + struct wlr_cursor_device *device = + wl_container_of(listener, device, motion); wl_signal_emit(&device->cursor->events.motion, event); } -static void handle_pointer_motion_absolute(struct wl_listener *listener, void *data) { +static void handle_pointer_motion_absolute(struct wl_listener *listener, + void *data) { struct wlr_event_pointer_motion_absolute *event = data; - struct wlr_cursor_device *device = wl_container_of(listener, device, motion_absolute); + struct wlr_cursor_device *device = + wl_container_of(listener, device, motion_absolute); wl_signal_emit(&device->cursor->events.motion_absolute, event); } static void handle_pointer_button(struct wl_listener *listener, void *data) { struct wlr_event_pointer_button *event = data; - struct wlr_cursor_device *device = wl_container_of(listener, device, button); + struct wlr_cursor_device *device = + wl_container_of(listener, device, button); wl_signal_emit(&device->cursor->events.button, event); } @@ -307,14 +313,16 @@ static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { wl_signal_emit(&device->cursor->events.tablet_tool_axis, event); } -static void handle_tablet_tool_button(struct wl_listener *listener, void *data) { +static void handle_tablet_tool_button(struct wl_listener *listener, + void *data) { struct wlr_event_tablet_tool_button *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, tablet_tool_button); wl_signal_emit(&device->cursor->events.tablet_tool_button, event); } -static void handle_tablet_tool_proximity(struct wl_listener *listener, void *data) { +static void handle_tablet_tool_proximity(struct wl_listener *listener, + void *data) { struct wlr_event_tablet_tool_proximity *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, tablet_tool_proximity); @@ -364,7 +372,8 @@ void wlr_cursor_attach_input_device(struct wlr_cursor *cur, wl_signal_add(&dev->pointer->events.motion, &device->motion); device->motion.notify = handle_pointer_motion; - wl_signal_add(&dev->pointer->events.motion_absolute, &device->motion_absolute); + wl_signal_add(&dev->pointer->events.motion_absolute, + &device->motion_absolute); device->motion_absolute.notify = handle_pointer_motion_absolute; wl_signal_add(&dev->pointer->events.button, &device->button); @@ -434,14 +443,16 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, struct wlr_input_device *dev, struct wlr_output *output) { struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); if (!c_device) { - wlr_log(L_ERROR, "Cannot map device \"%s\" to output (not found in this cursor)", dev->name); + wlr_log(L_ERROR, "Cannot map device \"%s\" to output" + "(not found in this cursor)", dev->name); return; } c_device->mapped_output = output; } -void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_geometry *geo) { +void wlr_cursor_map_to_region(struct wlr_cursor *cur, + struct wlr_geometry *geo) { if (geo && wlr_geometry_empty(geo)) { wlr_log(L_ERROR, "cannot map cursor to an empty region"); return; -- cgit v1.2.3 From a51b76083e589214320f30c8792d6b2666ef21d2 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 29 Aug 2017 10:42:23 -0400 Subject: rename wlr_cursor_init to wlr_cursor_create --- examples/pointer.c | 2 +- include/wlr/types/wlr_cursor.h | 2 +- types/wlr_cursor.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/examples/pointer.c b/examples/pointer.c index 100feccc..5341c72c 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -340,7 +340,7 @@ int main(int argc, char *argv[]) { }; state.config = parse_args(argc, argv); - state.cursor = wlr_cursor_init(); + state.cursor = wlr_cursor_create(); wlr_cursor_map_to_region(state.cursor, state.config->cursor.mapped_geo); wl_list_init(&state.devices); diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index b91c195e..ef3b8dbb 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -31,7 +31,7 @@ struct wlr_cursor { } events; }; -struct wlr_cursor *wlr_cursor_init(); +struct wlr_cursor *wlr_cursor_create(); void wlr_cursor_destroy(struct wlr_cursor *cur); diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 9a9a28b8..4bbf897b 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -41,7 +41,7 @@ struct wlr_cursor_state { struct wlr_geometry *mapped_geometry; }; -struct wlr_cursor *wlr_cursor_init() { +struct wlr_cursor *wlr_cursor_create() { struct wlr_cursor *cur = calloc(1, sizeof(struct wlr_cursor)); if (!cur) { wlr_log(L_ERROR, "Failed to allocate wlr_cursor"); -- cgit v1.2.3 From 9b65d0b3f0030bf2103cd7d65448f727c62de468 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 29 Aug 2017 12:08:49 -0400 Subject: refactor and rename wlr_geometry to wlr_box --- examples/config.c | 34 +++++++------- examples/config.h | 4 +- examples/pointer.c | 4 +- include/wlr/types/wlr_box.h | 20 ++++++++ include/wlr/types/wlr_cursor.h | 6 +-- include/wlr/types/wlr_geometry.h | 20 -------- include/wlr/types/wlr_output_layout.h | 6 +-- types/meson.build | 2 +- types/wlr_box.c | 67 +++++++++++++++++++++++++++ types/wlr_cursor.c | 52 ++++++++++----------- types/wlr_geometry.c | 86 ----------------------------------- types/wlr_output_layout.c | 36 +++++++-------- 12 files changed, 159 insertions(+), 178 deletions(-) create mode 100644 include/wlr/types/wlr_box.h delete mode 100644 include/wlr/types/wlr_geometry.h create mode 100644 types/wlr_box.c delete mode 100644 types/wlr_geometry.c (limited to 'include') diff --git a/examples/config.c b/examples/config.c index b99f130d..a1ed5d5a 100644 --- a/examples/config.c +++ b/examples/config.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "shared.h" #include "config.h" #include "ini.h" @@ -25,7 +25,7 @@ static void usage(const char *name, int ret) { exit(ret); } -static struct wlr_geometry *parse_geometry(const char *str) { +static struct wlr_box *parse_geometry(const char *str) { // format: {width}x{height}+{x}+{y} if (strlen(str) > 255) { wlr_log(L_ERROR, "cannot parse geometry string, too long"); @@ -33,7 +33,7 @@ static struct wlr_geometry *parse_geometry(const char *str) { } char *buf = strdup(str); - struct wlr_geometry *geo = calloc(1, sizeof(struct wlr_geometry)); + struct wlr_box *box = calloc(1, sizeof(struct wlr_box)); bool has_width = false; bool has_height = false; @@ -56,16 +56,16 @@ static struct wlr_geometry *parse_geometry(const char *str) { } if (!has_width) { - geo->width = val; + box->width = val; has_width = true; } else if (!has_height) { - geo->height = val; + box->height = val; has_height = true; } else if (!has_x) { - geo->x = val; + box->x = val; has_x = true; } else if (!has_y) { - geo->y = val; + box->y = val; has_y = true; } else { break; @@ -78,12 +78,12 @@ static struct wlr_geometry *parse_geometry(const char *str) { } free(buf); - return geo; + return box; invalid_input: wlr_log(L_ERROR, "could not parse geometry string: %s", str); free(buf); - free(geo); + free(box); return NULL; } @@ -140,8 +140,8 @@ static int config_ini_handler(void *user, const char *section, const char *name, free(config->cursor.mapped_output); config->cursor.mapped_output = strdup(value); } else if (strcmp(name, "geometry") == 0) { - free(config->cursor.mapped_geo); - config->cursor.mapped_geo = parse_geometry(value); + free(config->cursor.mapped_box); + config->cursor.mapped_box = parse_geometry(value); } else { wlr_log(L_ERROR, "got unknown cursor config: %s", name); } @@ -167,8 +167,8 @@ static int config_ini_handler(void *user, const char *section, const char *name, free(dc->mapped_output); dc->mapped_output = strdup(value); } else if (strcmp(name, "geometry") == 0) { - free(dc->mapped_geo); - dc->mapped_geo = parse_geometry(value); + free(dc->mapped_box); + dc->mapped_box = parse_geometry(value); } else { wlr_log(L_ERROR, "got unknown device config: %s", name); } @@ -239,8 +239,8 @@ void example_config_destroy(struct example_config *config) { if (dc->mapped_output) { free(dc->mapped_output); } - if (dc->mapped_geo) { - free(dc->mapped_geo); + if (dc->mapped_box) { + free(dc->mapped_box); } free(dc); } @@ -251,8 +251,8 @@ void example_config_destroy(struct example_config *config) { if (config->cursor.mapped_output) { free(config->cursor.mapped_output); } - if (config->cursor.mapped_geo) { - free(config->cursor.mapped_geo); + if (config->cursor.mapped_box) { + free(config->cursor.mapped_box); } free(config); } diff --git a/examples/config.h b/examples/config.h index cd19dc5e..2a69c4f4 100644 --- a/examples/config.h +++ b/examples/config.h @@ -15,14 +15,14 @@ struct output_config { struct device_config { char *name; char *mapped_output; - struct wlr_geometry *mapped_geo; + struct wlr_box *mapped_box; struct wl_list link; }; struct example_config { struct { char *mapped_output; - struct wlr_geometry *mapped_geo; + struct wlr_box *mapped_box; } cursor; struct wl_list outputs; diff --git a/examples/pointer.c b/examples/pointer.c index 5341c72c..d9a06339 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -105,7 +105,7 @@ static void configure_devices(struct sample_state *sample) { wl_list_for_each(dc, &sample->config->devices, link) { if (strcmp(dev->device->name, dc->name) == 0) { wlr_cursor_map_input_to_region(sample->cursor, dev->device, - dc->mapped_geo); + dc->mapped_box); } } } @@ -341,7 +341,7 @@ int main(int argc, char *argv[]) { state.config = parse_args(argc, argv); state.cursor = wlr_cursor_create(); - wlr_cursor_map_to_region(state.cursor, state.config->cursor.mapped_geo); + wlr_cursor_map_to_region(state.cursor, state.config->cursor.mapped_box); wl_list_init(&state.devices); // pointer events diff --git a/include/wlr/types/wlr_box.h b/include/wlr/types/wlr_box.h new file mode 100644 index 00000000..e2b1ab4e --- /dev/null +++ b/include/wlr/types/wlr_box.h @@ -0,0 +1,20 @@ +#ifndef _WLR_TYPES_GEOMETRY_H +#define _WLR_TYPES_GEOMETRY_H +#include + +struct wlr_box { + int x, y; + int width, height; +}; + +void wlr_box_closest_point(struct wlr_box *box, double x, double y, + double *dest_x, double *dest_y); + +bool wlr_box_intersection(struct wlr_box *box_a, + struct wlr_box *box_b, struct wlr_box **dest); + +bool wlr_box_contains_point(struct wlr_box *box, double x, double y); + +bool wlr_box_empty(struct wlr_box *box); + +#endif diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index ef3b8dbb..5fc0ec76 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include struct wlr_cursor_state; @@ -100,13 +100,13 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, /** * Maps this cursor to an arbitrary region on the associated wlr_output_layout. */ -void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_geometry *geo); +void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_box *box); /** * Maps inputs from this input device to an arbitrary region on the associated * wlr_output_layout. */ void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, - struct wlr_input_device *dev, struct wlr_geometry *geo); + struct wlr_input_device *dev, struct wlr_box *box); #endif diff --git a/include/wlr/types/wlr_geometry.h b/include/wlr/types/wlr_geometry.h deleted file mode 100644 index cac75431..00000000 --- a/include/wlr/types/wlr_geometry.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _WLR_TYPES_GEOMETRY_H -#define _WLR_TYPES_GEOMETRY_H -#include - -struct wlr_geometry { - int x, y; - int width, height; -}; - -void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, - int *dest_x, int *dest_y, double *distance); - -bool wlr_geometry_intersection(struct wlr_geometry *geo_a, - struct wlr_geometry *geo_b, struct wlr_geometry **dest); - -bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y); - -bool wlr_geometry_empty(struct wlr_geometry *geo); - -#endif diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index dfb5234d..794fc491 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -62,10 +62,10 @@ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, double *dest_y); /** - * Get the geometry of the layout for the given reference output. If `reference` - * is NULL, the geometry will be for the extents of the entire layout. + * Get the box of the layout for the given reference output. If `reference` + * is NULL, the box will be for the extents of the entire layout. */ -struct wlr_geometry *wlr_output_layout_get_geometry( +struct wlr_box *wlr_output_layout_get_box( struct wlr_output_layout *layout, struct wlr_output *reference); #endif diff --git a/types/meson.build b/types/meson.build index 8b8b215b..56390475 100644 --- a/types/meson.build +++ b/types/meson.build @@ -16,7 +16,7 @@ lib_wlr_types = static_library('wlr_types', files( 'wlr_xdg_shell_v6.c', 'wlr_wl_shell.c', 'wlr_compositor.c', - 'wlr_geometry.c', + 'wlr_box.c', ), include_directories: wlr_inc, dependencies: [wayland_server, pixman, wlr_protos]) diff --git a/types/wlr_box.c b/types/wlr_box.c new file mode 100644 index 00000000..7e981833 --- /dev/null +++ b/types/wlr_box.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include + +void wlr_box_closest_point(struct wlr_box *box, double x, double y, + double *dest_x, double *dest_y) { + // find the closest x point + if (x < box->x) { + *dest_x = box->x; + } else if (x > box->x + box->width) { + *dest_x = box->x + box->width; + } else { + *dest_x = x; + } + + // find closest y point + if (y < box->y) { + *dest_y = box->y; + } else if (y > box->y + box->height) { + *dest_y = box->y + box->height; + } else { + *dest_y = y; + } +} + +bool wlr_box_empty(struct wlr_box *box) { + return box == NULL || box->width <= 0 || box->height <= 0; +} + +bool wlr_box_intersection(struct wlr_box *box_a, + struct wlr_box *box_b, struct wlr_box **box_dest) { + struct wlr_box *dest = *box_dest; + bool a_empty = wlr_box_empty(box_a); + bool b_empty = wlr_box_empty(box_b); + + if (a_empty || b_empty) { + dest->x = 0; + dest->y = 0; + dest->width = -100; + dest->height = -100; + return false; + } + + int x1 = fmax(box_a->x, box_b->x); + int y1 = fmax(box_a->y, box_b->y); + int x2 = fmin(box_a->x + box_a->width, box_b->x + box_b->width); + int y2 = fmin(box_a->y + box_a->height, box_b->y + box_b->height); + + dest->x = x1; + dest->y = y1; + dest->width = x2 - x1; + dest->height = y2 - y1; + + return !wlr_box_empty(dest); +} + +bool wlr_box_contains_point(struct wlr_box *box, double x, double y) { + if (wlr_box_empty(box)) { + return false; + } else { + return x >= box->x && x <= box->x + box->width && + y >= box->y && y <= box->y + box->height; + } +} diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 4bbf897b..bc546b15 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -13,7 +13,7 @@ struct wlr_cursor_device { struct wlr_input_device *device; struct wl_list link; struct wlr_output *mapped_output; - struct wlr_geometry *mapped_geometry; + struct wlr_box *mapped_box; struct wl_listener motion; struct wl_listener motion_absolute; @@ -38,7 +38,7 @@ struct wlr_cursor_state { struct wlr_output_layout *layout; struct wlr_xcursor *xcursor; struct wlr_output *mapped_output; - struct wlr_geometry *mapped_geometry; + struct wlr_box *mapped_box; }; struct wlr_cursor *wlr_cursor_create() { @@ -149,26 +149,26 @@ static void wlr_cursor_warp_unchecked(struct wlr_cursor *cur, * If none of these are set, returns NULL and absolute movement should be * relative to the extents of the layout. */ -static struct wlr_geometry *get_mapping(struct wlr_cursor *cur, +static struct wlr_box *get_mapping(struct wlr_cursor *cur, struct wlr_input_device *dev) { assert(cur->state->layout); struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); if (c_device) { - if (c_device->mapped_geometry) { - return c_device->mapped_geometry; + if (c_device->mapped_box) { + return c_device->mapped_box; } if (c_device->mapped_output) { - return wlr_output_layout_get_geometry(cur->state->layout, + return wlr_output_layout_get_box(cur->state->layout, c_device->mapped_output); } } - if (cur->state->mapped_geometry) { - return cur->state->mapped_geometry; + if (cur->state->mapped_box) { + return cur->state->mapped_box; } if (cur->state->mapped_output) { - return wlr_output_layout_get_geometry(cur->state->layout, + return wlr_output_layout_get_box(cur->state->layout, cur->state->mapped_output); } @@ -180,10 +180,10 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev, assert(cur->state->layout); bool result = false; - struct wlr_geometry *mapping = get_mapping(cur, dev); + struct wlr_box *mapping = get_mapping(cur, dev); if (mapping) { - if (wlr_geometry_contains_point(mapping, x, y)) { + if (wlr_box_contains_point(mapping, x, y)) { wlr_cursor_warp_unchecked(cur, x, y); result = true; } @@ -200,9 +200,9 @@ void wlr_cursor_warp_absolute(struct wlr_cursor *cur, struct wlr_input_device *dev, double x_mm, double y_mm) { assert(cur->state->layout); - struct wlr_geometry *mapping = get_mapping(cur, dev); + struct wlr_box *mapping = get_mapping(cur, dev); if (!mapping) { - mapping = wlr_output_layout_get_geometry(cur->state->layout, NULL); + mapping = wlr_output_layout_get_box(cur->state->layout, NULL); } double x = mapping->width * x_mm + mapping->x; @@ -218,15 +218,15 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, double x = cur->x + delta_x; double y = cur->y + delta_y; - struct wlr_geometry *mapping = get_mapping(cur, dev); + struct wlr_box *mapping = get_mapping(cur, dev); if (mapping) { - int boundary_x, boundary_y; - if (!wlr_geometry_contains_point(mapping, x, y)) { - wlr_geometry_closest_boundary(mapping, x, y, &boundary_x, - &boundary_y, NULL); - x = boundary_x; - y = boundary_y; + double closest_x, closest_y; + if (!wlr_box_contains_point(mapping, x, y)) { + wlr_box_closest_point(mapping, x, y, &closest_x, + &closest_y); + x = closest_x; + y = closest_y; } } else { if (!wlr_output_layout_contains_point(cur->state->layout, NULL, x, y)) { @@ -452,18 +452,18 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, } void wlr_cursor_map_to_region(struct wlr_cursor *cur, - struct wlr_geometry *geo) { - if (geo && wlr_geometry_empty(geo)) { + struct wlr_box *box) { + if (box && wlr_box_empty(box)) { wlr_log(L_ERROR, "cannot map cursor to an empty region"); return; } - cur->state->mapped_geometry = geo; + cur->state->mapped_box = box; } void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, - struct wlr_input_device *dev, struct wlr_geometry *geo) { - if (geo && wlr_geometry_empty(geo)) { + struct wlr_input_device *dev, struct wlr_box *box) { + if (box && wlr_box_empty(box)) { wlr_log(L_ERROR, "cannot map device \"%s\" input to an empty region", dev->name); return; @@ -476,5 +476,5 @@ void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, return; } - c_device->mapped_geometry = geo; + c_device->mapped_box = box; } diff --git a/types/wlr_geometry.c b/types/wlr_geometry.c deleted file mode 100644 index 4f532d6f..00000000 --- a/types/wlr_geometry.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include -#include -#include -#include - -static double get_distance(double x1, double y1, double x2, double y2) { - double distance; - distance = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); - return distance; -} - -void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, - int *dest_x, int *dest_y, double *distance) { - // find the closest x point - if (x < geo->x) { - *dest_x = geo->x; - } else if (x > geo->x + geo->width) { - *dest_x = geo->x + geo->width; - } else { - *dest_x = x; - } - - // find closest y point - if (y < geo->y) { - *dest_y = geo->y; - } else if (y > geo->y + geo->height) { - *dest_y = geo->y + geo->height; - } else { - *dest_y = y; - } - - // calculate distance - if (distance) { - *distance = get_distance(*dest_x, *dest_y, x, y); - } -} - -#ifndef max -#define max(a,b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -bool wlr_geometry_empty(struct wlr_geometry *geo) { - return geo == NULL || geo->width <= 0 || geo->height <= 0; -} - -bool wlr_geometry_intersection(struct wlr_geometry *geo_a, - struct wlr_geometry *geo_b, struct wlr_geometry **geo_dest) { - struct wlr_geometry *dest = *geo_dest; - bool a_empty = wlr_geometry_empty(geo_a); - bool b_empty = wlr_geometry_empty(geo_b); - - if (a_empty || b_empty) { - dest->x = 0; - dest->y = 0; - dest->width = -100; - dest->height = -100; - return false; - } - - int x1 = max(geo_a->x, geo_b->x); - int y1 = max(geo_a->y, geo_b->y); - int x2 = min(geo_a->x + geo_a->width, geo_b->x + geo_b->width); - int y2 = min(geo_a->y + geo_a->height, geo_b->y + geo_b->height); - - dest->x = x1; - dest->y = y1; - dest->width = x2 - x1; - dest->height = y2 - y1; - - return !wlr_geometry_empty(dest); -} - -bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y) { - if (wlr_geometry_empty(geo)) { - return false; - } else { - return x >= geo->x && x <= geo->x + geo->width && - y >= geo->y && y <= geo->y + geo->height; - } -} diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index b097b1b8..ba2c158a 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -1,24 +1,24 @@ #include #include #include -#include +#include #include #include #include struct wlr_output_layout_state { - struct wlr_geometry *_geo; + struct wlr_box *_box; }; struct wlr_output_layout_output_state { - struct wlr_geometry *_geo; + struct wlr_box *_box; }; struct wlr_output_layout *wlr_output_layout_init() { struct wlr_output_layout *layout = calloc(1, sizeof(struct wlr_output_layout)); layout->state = calloc(1, sizeof(struct wlr_output_layout_state)); - layout->state->_geo = calloc(1, sizeof(struct wlr_geometry)); + layout->state->_box = calloc(1, sizeof(struct wlr_box)); wl_list_init(&layout->outputs); return layout; } @@ -26,7 +26,7 @@ struct wlr_output_layout *wlr_output_layout_init() { static void wlr_output_layout_output_destroy( struct wlr_output_layout_output *l_output) { wl_list_remove(&l_output->link); - free(l_output->state->_geo); + free(l_output->state->_box); free(l_output->state); free(l_output); } @@ -41,7 +41,7 @@ void wlr_output_layout_destroy(struct wlr_output_layout *layout) { wlr_output_layout_output_destroy(_output); } - free(layout->state->_geo); + free(layout->state->_box); free(layout->state); free(layout); } @@ -51,7 +51,7 @@ void wlr_output_layout_add(struct wlr_output_layout *layout, struct wlr_output_layout_output *l_output; l_output= calloc(1, sizeof(struct wlr_output_layout_output)); l_output->state = calloc(1, sizeof(struct wlr_output_layout_output_state)); - l_output->state->_geo = calloc(1, sizeof(struct wlr_geometry)); + l_output->state->_box = calloc(1, sizeof(struct wlr_box)); l_output->output = output; l_output->x = x; l_output->y = y; @@ -178,7 +178,7 @@ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, wlr_output_effective_resolution(l_output->output, &width, &height); // find the closest x point - // TODO use wlr_geometry_closest_boundary + // TODO use wlr_box_closest_boundary if (x < l_output->x) { output_x = l_output->x; } else if (x > l_output->x + width) { @@ -209,17 +209,17 @@ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, *dest_y = min_y; } -struct wlr_geometry *wlr_output_layout_get_geometry( +struct wlr_box *wlr_output_layout_get_box( struct wlr_output_layout *layout, struct wlr_output *reference) { struct wlr_output_layout_output *l_output; if (reference) { // output extents l_output= wlr_output_layout_get(layout, reference); - l_output->state->_geo->x = l_output->x; - l_output->state->_geo->y = l_output->y; + l_output->state->_box->x = l_output->x; + l_output->state->_box->y = l_output->y; wlr_output_effective_resolution(reference, - &l_output->state->_geo->width, &l_output->state->_geo->height); - return l_output->state->_geo; + &l_output->state->_box->width, &l_output->state->_box->height); + return l_output->state->_box; } else { // layout extents int min_x = INT_MAX, min_y = INT_MAX; @@ -241,12 +241,12 @@ struct wlr_geometry *wlr_output_layout_get_geometry( } } - layout->state->_geo->x = min_x; - layout->state->_geo->y = min_y; - layout->state->_geo->width = max_x - min_x; - layout->state->_geo->height = max_y - min_y; + layout->state->_box->x = min_x; + layout->state->_box->y = min_y; + layout->state->_box->width = max_x - min_x; + layout->state->_box->height = max_y - min_y; - return layout->state->_geo; + return layout->state->_box; } // not reached -- cgit v1.2.3 From b6031d106525706db6eef03d2a500259357ecb69 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 29 Aug 2017 12:32:17 -0400 Subject: refactor wlr_output_layout_closest_point --- include/wlr/types/wlr_output_layout.h | 7 +++-- types/wlr_cursor.c | 10 +++---- types/wlr_output_layout.c | 49 ++++++++++++----------------------- 3 files changed, 24 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index 794fc491..b1253eb1 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -53,11 +53,10 @@ bool wlr_output_layout_intersects(struct wlr_output_layout *layout, struct wlr_output *reference, int x1, int y1, int x2, int y2); /** - * Get the closest boundary point of this layout from the given point from the - * reference output. If reference is NULL, gets the closest boundary point from - * the entire layout. + * Get the closest point on this layout from the given point from the reference + * output. If reference is NULL, gets the closest point from the entire layout. */ -void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, +void wlr_output_layout_closest_point(struct wlr_output_layout *layout, struct wlr_output *reference, double x, double y, double *dest_x, double *dest_y); diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index bc546b15..f9be0a7a 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -230,11 +230,11 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, } } else { if (!wlr_output_layout_contains_point(cur->state->layout, NULL, x, y)) { - double boundary_x, boundary_y; - wlr_output_layout_closest_boundary(cur->state->layout, NULL, x, y, - &boundary_x, &boundary_y); - x = boundary_x; - y = boundary_y; + double layout_x, layout_y; + wlr_output_layout_closest_point(cur->state->layout, NULL, x, y, + &layout_x, &layout_y); + x = layout_x; + y = layout_y; } } diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index ba2c158a..7c98837d 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -157,47 +158,33 @@ void wlr_output_layout_output_coords(struct wlr_output_layout *layout, } } -static double get_distance(double x1, double y1, double x2, double y2) { - double distance; - distance = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); - return distance; +static struct wlr_box *wlr_output_layout_output_get_box( + struct wlr_output_layout_output *l_output) { + l_output->state->_box->x = l_output->x; + l_output->state->_box->y = l_output->y; + wlr_output_effective_resolution(l_output->output, + &l_output->state->_box->width, &l_output->state->_box->height); + return l_output->state->_box; } -void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout, +void wlr_output_layout_closest_point(struct wlr_output_layout *layout, struct wlr_output *reference, double x, double y, double *dest_x, double *dest_y) { - double min_x = INT_MAX, min_y = INT_MAX, min_distance = INT_MAX; + double min_x = DBL_MAX, min_y = DBL_MAX, min_distance = DBL_MAX; struct wlr_output_layout_output *l_output; wl_list_for_each(l_output, &layout->outputs, link) { if (reference != NULL && reference != l_output->output) { continue; } - int width, height; double output_x, output_y, output_distance; - wlr_output_effective_resolution(l_output->output, &width, &height); - - // find the closest x point - // TODO use wlr_box_closest_boundary - if (x < l_output->x) { - output_x = l_output->x; - } else if (x > l_output->x + width) { - output_x = l_output->x + width; - } else { - output_x = x; - } + struct wlr_box *box = wlr_output_layout_output_get_box(l_output); + wlr_box_closest_point(box, x, y, &output_x, &output_y); - // find closest y point - if (y < l_output->y) { - output_y = l_output->y; - } else if (y > l_output->y + height) { - output_y = l_output->y + height; - } else { - output_y = y; - } + // calculate squared distance suitable for comparison + output_distance = + (x - output_x) * (x - output_x) + (y - output_y) * (y - output_y); - // calculate distance - output_distance = get_distance(output_x, output_y, x, y); if (output_distance < min_distance) { min_x = output_x; min_y = output_y; @@ -215,11 +202,7 @@ struct wlr_box *wlr_output_layout_get_box( if (reference) { // output extents l_output= wlr_output_layout_get(layout, reference); - l_output->state->_box->x = l_output->x; - l_output->state->_box->y = l_output->y; - wlr_output_effective_resolution(reference, - &l_output->state->_box->width, &l_output->state->_box->height); - return l_output->state->_box; + return wlr_output_layout_output_get_box(l_output); } else { // layout extents int min_x = INT_MAX, min_y = INT_MAX; -- cgit v1.2.3