swaybar: process hotspots on touch tap

This commit is contained in:
Drew DeVault 2019-02-17 10:13:11 -05:00 committed by emersion
parent 512619a9a1
commit 4599907de7
3 changed files with 138 additions and 15 deletions

View file

@ -34,6 +34,7 @@ struct swaybar {
struct swaybar_config *config; struct swaybar_config *config;
struct swaybar_pointer pointer; struct swaybar_pointer pointer;
struct swaybar_touch touch;
struct status_line *status; struct status_line *status;
struct loop *eventloop; struct loop *eventloop;

View file

@ -22,6 +22,19 @@ struct swaybar_pointer {
uint32_t serial; uint32_t serial;
}; };
struct touch_slot {
int32_t id;
uint32_t time;
struct swaybar_output *output;
double start_x, start_y;
double x, y;
};
struct swaybar_touch {
struct wl_touch *touch;
struct touch_slot slots[16];
};
enum hotspot_event_handling { enum hotspot_event_handling {
HOTSPOT_IGNORE, HOTSPOT_IGNORE,
HOTSPOT_PROCESS, HOTSPOT_PROCESS,

View file

@ -123,6 +123,23 @@ static bool check_bindings(struct swaybar *bar, uint32_t button,
return false; return false;
} }
static void process_hotspots(struct swaybar_output *output,
double x, double y, uint32_t button) {
x *= output->scale;
y *= output->scale;
struct swaybar_hotspot *hotspot;
wl_list_for_each(hotspot, &output->hotspots, link) {
if (x >= hotspot->x && y >= hotspot->y
&& x < hotspot->x + hotspot->width
&& y < hotspot->y + hotspot->height) {
if (HOTSPOT_IGNORE == hotspot->callback(output, hotspot,
x / output->scale, y / output->scale, button, hotspot->data)) {
return;
}
}
}
}
static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
struct swaybar *bar = data; struct swaybar *bar = data;
@ -139,20 +156,7 @@ static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
if (state != WL_POINTER_BUTTON_STATE_PRESSED) { if (state != WL_POINTER_BUTTON_STATE_PRESSED) {
return; return;
} }
struct swaybar_hotspot *hotspot; process_hotspots(output, pointer->x, pointer->y, button);
wl_list_for_each(hotspot, &output->hotspots, link) {
double x = pointer->x * output->scale;
double y = pointer->y * output->scale;
if (x >= hotspot->x
&& y >= hotspot->y
&& x < hotspot->x + hotspot->width
&& y < hotspot->y + hotspot->height) {
if (HOTSPOT_IGNORE == hotspot->callback(output, hotspot,
pointer->x, pointer->y, button, hotspot->data)) {
return;
}
}
}
} }
static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
@ -255,7 +259,7 @@ static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
// Who cares // Who cares
} }
struct wl_pointer_listener pointer_listener = { static struct wl_pointer_listener pointer_listener = {
.enter = wl_pointer_enter, .enter = wl_pointer_enter,
.leave = wl_pointer_leave, .leave = wl_pointer_leave,
.motion = wl_pointer_motion, .motion = wl_pointer_motion,
@ -267,6 +271,107 @@ struct wl_pointer_listener pointer_listener = {
.axis_discrete = wl_pointer_axis_discrete, .axis_discrete = wl_pointer_axis_discrete,
}; };
static struct touch_slot *get_touch_slot(struct swaybar_touch *touch, int32_t id) {
int next = -1;
for (size_t i = 0; i < sizeof(touch->slots) / sizeof(*touch->slots); ++i) {
if (touch->slots[i].id == id) {
return &touch->slots[i];
}
if (next == -1 && !touch->slots[i].output) {
next = i;
}
}
if (next == -1) {
sway_log(SWAY_ERROR, "Ran out of touch slots");
return NULL;
}
return &touch->slots[next];
}
static void wl_touch_down(void *data, struct wl_touch *wl_touch,
uint32_t serial, uint32_t time, struct wl_surface *surface,
int32_t id, wl_fixed_t _x, wl_fixed_t _y) {
struct swaybar *bar = data;
struct swaybar_output *_output, *output;
wl_list_for_each(_output, &bar->outputs, link) {
if (_output->surface == surface) {
output = _output;
break;
}
}
if (!output) {
sway_log(SWAY_DEBUG, "Got touch event for unknown surface");
return;
}
struct touch_slot *slot = get_touch_slot(&bar->touch, id);
if (!slot) {
return;
}
slot->id = id;
slot->output = output;
slot->x = slot->start_x = wl_fixed_to_double(_x);
slot->y = slot->start_y = wl_fixed_to_double(_y);
slot->time = time;
}
static void wl_touch_up(void *data, struct wl_touch *wl_touch,
uint32_t serial, uint32_t time, int32_t id) {
struct swaybar *bar = data;
struct touch_slot *slot = get_touch_slot(&bar->touch, id);
if (!slot) {
return;
}
if (time - slot->time < 500) {
// Tap, treat it like a pointer click
process_hotspots(slot->output, slot->x, slot->y, BTN_LEFT);
}
slot->output = NULL;
}
static void wl_touch_motion(void *data, struct wl_touch *wl_touch,
uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) {
struct swaybar *bar = data;
struct touch_slot *slot = get_touch_slot(&bar->touch, id);
if (!slot) {
return;
}
slot->x = wl_fixed_to_double(x);
slot->y = wl_fixed_to_double(y);
// TODO: Slide gestures
}
static void wl_touch_frame(void *data, struct wl_touch *wl_touch) {
// Who cares
}
static void wl_touch_cancel(void *data, struct wl_touch *wl_touch) {
struct swaybar *bar = data;
struct swaybar_touch *touch = &bar->touch;
for (size_t i = 0; i < sizeof(touch->slots) / sizeof(*touch->slots); ++i) {
touch->slots[i].output = NULL;
}
}
static void wl_touch_shape(void *data, struct wl_touch *wl_touch, int32_t id,
wl_fixed_t major, wl_fixed_t minor) {
// Who cares
}
static void wl_touch_orientation(void *data, struct wl_touch *wl_touch,
int32_t id, wl_fixed_t orientation) {
// Who cares
}
static struct wl_touch_listener touch_listener = {
.down = wl_touch_down,
.up = wl_touch_up,
.motion = wl_touch_motion,
.frame = wl_touch_frame,
.cancel = wl_touch_cancel,
.shape = wl_touch_shape,
.orientation = wl_touch_orientation,
};
static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
enum wl_seat_capability caps) { enum wl_seat_capability caps) {
struct swaybar *bar = data; struct swaybar *bar = data;
@ -278,6 +383,10 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
bar->pointer.pointer = wl_seat_get_pointer(wl_seat); bar->pointer.pointer = wl_seat_get_pointer(wl_seat);
wl_pointer_add_listener(bar->pointer.pointer, &pointer_listener, bar); wl_pointer_add_listener(bar->pointer.pointer, &pointer_listener, bar);
} }
if ((caps & WL_SEAT_CAPABILITY_TOUCH)) {
bar->touch.touch = wl_seat_get_touch(wl_seat);
wl_touch_add_listener(bar->touch.touch, &touch_listener, bar);
}
} }
static void seat_handle_name(void *data, struct wl_seat *wl_seat, static void seat_handle_name(void *data, struct wl_seat *wl_seat,