aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/swaybar/bar.h1
-rw-r--r--include/swaybar/input.h13
-rw-r--r--swaybar/input.c139
3 files changed, 138 insertions, 15 deletions
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h
index 2518d5aa..dfadc200 100644
--- a/include/swaybar/bar.h
+++ b/include/swaybar/bar.h
@@ -34,6 +34,7 @@ struct swaybar {
struct swaybar_config *config;
struct swaybar_pointer pointer;
+ struct swaybar_touch touch;
struct status_line *status;
struct loop *eventloop;
diff --git a/include/swaybar/input.h b/include/swaybar/input.h
index d76cd551..88e5abc5 100644
--- a/include/swaybar/input.h
+++ b/include/swaybar/input.h
@@ -22,6 +22,19 @@ struct swaybar_pointer {
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 {
HOTSPOT_IGNORE,
HOTSPOT_PROCESS,
diff --git a/swaybar/input.c b/swaybar/input.c
index e416f6e7..d443c777 100644
--- a/swaybar/input.c
+++ b/swaybar/input.c
@@ -123,6 +123,23 @@ static bool check_bindings(struct swaybar *bar, uint32_t button,
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,
uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
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) {
return;
}
- struct swaybar_hotspot *hotspot;
- 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;
- }
- }
- }
+ process_hotspots(output, pointer->x, pointer->y, button);
}
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
}
-struct wl_pointer_listener pointer_listener = {
+static struct wl_pointer_listener pointer_listener = {
.enter = wl_pointer_enter,
.leave = wl_pointer_leave,
.motion = wl_pointer_motion,
@@ -267,6 +271,107 @@ struct wl_pointer_listener pointer_listener = {
.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,
enum wl_seat_capability caps) {
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);
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,