implement touch up and touch down

This commit is contained in:
Tony Crisci 2017-08-27 17:35:12 -04:00
parent c914697676
commit 5e06d61e42
7 changed files with 195 additions and 58 deletions

View file

@ -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) {

View file

@ -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.
*

View file

@ -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

View file

@ -4,14 +4,20 @@
#include <wayland-util.h>
#include <stdbool.h>
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

View file

@ -1,6 +1,7 @@
#include <wlr/types/wlr_cursor.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <wlr/util/log.h>
#include <wayland-server.h>
#include <wlr/types/wlr_output.h>
@ -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,30 +144,61 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev,
return false;
}
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);
}
wlr_cursor_warp_unchecked(cur, x, y);
return true;
}
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;
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);
if (wlr_geometry_empty(constraints)) {
goto out;
}
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,
double delta_x, double delta_y) {
assert(cur->state->layout);
@ -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) {

View file

@ -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);

View file

@ -1,16 +1,35 @@
#include <wlr/util/log.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_geometry.h>
#include <limits.h>
#include <stdlib.h>
#include <assert.h>
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
}