aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Martin Dørum <martid0311@gmail.com>2020-04-23 23:07:04 +0200
committerLibravatar Drew DeVault <sir@cmpwn.com>2020-04-28 21:46:37 +0200
commit4492e493e62d51e6cd3340af622eef934f1c88cd (patch)
treeb57fb5901caae42fb167438985a471af2556b04b
parentAdd each view's shell to JSON description (diff)
downloadsway-4492e493e62d51e6cd3340af622eef934f1c88cd.tar.gz
sway-4492e493e62d51e6cd3340af622eef934f1c88cd.tar.zst
sway-4492e493e62d51e6cd3340af622eef934f1c88cd.zip
swaybar: Fix scrolling with precise trackpads
-rw-r--r--include/swaybar/input.h11
-rw-r--r--swaybar/bar.c2
-rw-r--r--swaybar/input.c90
3 files changed, 91 insertions, 12 deletions
diff --git a/include/swaybar/input.h b/include/swaybar/input.h
index 65e49218..e8735d88 100644
--- a/include/swaybar/input.h
+++ b/include/swaybar/input.h
@@ -2,6 +2,7 @@
2#define _SWAYBAR_INPUT_H 2#define _SWAYBAR_INPUT_H
3 3
4#include <wayland-client.h> 4#include <wayland-client.h>
5#include <stdbool.h>
5#include "list.h" 6#include "list.h"
6 7
7#define SWAY_SCROLL_UP KEY_MAX + 1 8#define SWAY_SCROLL_UP KEY_MAX + 1
@@ -9,6 +10,9 @@
9#define SWAY_SCROLL_LEFT KEY_MAX + 3 10#define SWAY_SCROLL_LEFT KEY_MAX + 3
10#define SWAY_SCROLL_RIGHT KEY_MAX + 4 11#define SWAY_SCROLL_RIGHT KEY_MAX + 4
11 12
13#define SWAY_CONTINUOUS_SCROLL_TIMEOUT 1000
14#define SWAY_CONTINUOUS_SCROLL_THRESHOLD 10000
15
12struct swaybar; 16struct swaybar;
13struct swaybar_output; 17struct swaybar_output;
14 18
@@ -50,6 +54,12 @@ struct swaybar_hotspot {
50 void *data; 54 void *data;
51}; 55};
52 56
57struct swaybar_scroll_axis {
58 wl_fixed_t value;
59 uint32_t discrete_steps;
60 uint32_t update_time;
61};
62
53struct swaybar_seat { 63struct swaybar_seat {
54 struct swaybar *bar; 64 struct swaybar *bar;
55 uint32_t wl_name; 65 uint32_t wl_name;
@@ -57,6 +67,7 @@ struct swaybar_seat {
57 struct swaybar_pointer pointer; 67 struct swaybar_pointer pointer;
58 struct swaybar_touch touch; 68 struct swaybar_touch touch;
59 struct wl_list link; // swaybar_seat:link 69 struct wl_list link; // swaybar_seat:link
70 struct swaybar_scroll_axis axis[2];
60}; 71};
61 72
62extern const struct wl_seat_listener seat_listener; 73extern const struct wl_seat_listener seat_listener;
diff --git a/swaybar/bar.c b/swaybar/bar.c
index efd0da4b..f4dd4405 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -340,7 +340,7 @@ static void handle_global(void *data, struct wl_registry *registry,
340 } 340 }
341 seat->bar = bar; 341 seat->bar = bar;
342 seat->wl_name = name; 342 seat->wl_name = name;
343 seat->wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, 3); 343 seat->wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, 5);
344 wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); 344 wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
345 wl_list_insert(&bar->seats, &seat->link); 345 wl_list_insert(&bar->seats, &seat->link);
346 } else if (strcmp(interface, wl_shm_interface.name) == 0) { 346 } else if (strcmp(interface, wl_shm_interface.name) == 0) {
diff --git a/swaybar/input.c b/swaybar/input.c
index f768cd40..4fe6dd93 100644
--- a/swaybar/input.c
+++ b/swaybar/input.c
@@ -211,18 +211,17 @@ static void workspace_next(struct swaybar *bar, struct swaybar_output *output,
211 211
212 if (new) { 212 if (new) {
213 ipc_send_workspace_command(bar, new->name); 213 ipc_send_workspace_command(bar, new->name);
214 }
215}
216 214
217static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, 215 // Since we're asking Sway to switch to 'new', it should become visible.
218 uint32_t time, uint32_t axis, wl_fixed_t value) { 216 // Marking it visible right now allows calling workspace_next in a loop.
219 struct swaybar_seat *seat = data; 217 new->visible = true;
220 struct swaybar_pointer *pointer = &seat->pointer; 218 active->visible = false;
221 struct swaybar_output *output = pointer->current;
222 if (!sway_assert(output, "axis with no active output")) {
223 return;
224 } 219 }
220}
225 221
222static void process_discrete_scroll(struct swaybar_seat *seat,
223 struct swaybar_output *output, struct swaybar_pointer *pointer,
224 uint32_t axis, wl_fixed_t value) {
226 // If there is a button press binding, execute it, skip default behavior, 225 // If there is a button press binding, execute it, skip default behavior,
227 // and check button release bindings 226 // and check button release bindings
228 uint32_t button = wl_axis_to_button(axis, value); 227 uint32_t button = wl_axis_to_button(axis, value);
@@ -252,8 +251,72 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
252 check_bindings(seat->bar, button, WL_POINTER_BUTTON_STATE_RELEASED); 251 check_bindings(seat->bar, button, WL_POINTER_BUTTON_STATE_RELEASED);
253} 252}
254 253
254static void process_continuous_scroll(struct swaybar_seat *seat,
255 struct swaybar_output *output, struct swaybar_pointer *pointer,
256 uint32_t axis) {
257 while (abs(seat->axis[axis].value) > SWAY_CONTINUOUS_SCROLL_THRESHOLD) {
258 if (seat->axis[axis].value > 0) {
259 process_discrete_scroll(seat, output, pointer, axis,
260 SWAY_CONTINUOUS_SCROLL_THRESHOLD);
261 seat->axis[axis].value -= SWAY_CONTINUOUS_SCROLL_THRESHOLD;
262 } else {
263 process_discrete_scroll(seat, output, pointer, axis,
264 -SWAY_CONTINUOUS_SCROLL_THRESHOLD);
265 seat->axis[axis].value += SWAY_CONTINUOUS_SCROLL_THRESHOLD;
266 }
267 }
268}
269
270static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
271 uint32_t time, uint32_t axis, wl_fixed_t value) {
272 struct swaybar_seat *seat = data;
273 struct swaybar_pointer *pointer = &seat->pointer;
274 struct swaybar_output *output = pointer->current;
275 if (!sway_assert(output, "axis with no active output")) {
276 return;
277 }
278
279 if (!sway_assert(axis < 2, "axis out of range")) {
280 return;
281 }
282
283 // If there's a while since the last scroll event,
284 // set 'value' to zero as if to reset the "virtual scroll wheel"
285 if (seat->axis[axis].discrete_steps == 0 &&
286 time - seat->axis[axis].update_time > SWAY_CONTINUOUS_SCROLL_TIMEOUT) {
287 seat->axis[axis].value = 0;
288 }
289
290 seat->axis[axis].value += value;
291 seat->axis[axis].update_time = time;
292}
293
255static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { 294static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) {
256 // Who cares 295 struct swaybar_seat *seat = data;
296 struct swaybar_pointer *pointer = &seat->pointer;
297 struct swaybar_output *output = pointer->current;
298
299 if (output == NULL) {
300 return;
301 }
302
303 for (uint32_t axis = 0; axis < 2; ++axis) {
304 if (seat->axis[axis].discrete_steps) {
305 for (uint32_t step = 0; step < seat->axis[axis].discrete_steps; ++step) {
306 // Honestly, it would probabyl make sense to pass in
307 // 'seat->axis[axis].value / seat->axis[axi].discrete_steps' here,
308 // but it's only used to check whether it's positive or negative
309 // so I don't think it's worth the risk of rounding errors.
310 process_discrete_scroll(seat, output, pointer, axis,
311 seat->axis[axis].value);
312 }
313
314 seat->axis[axis].value = 0;
315 seat->axis[axis].discrete_steps = 0;
316 } else {
317 process_continuous_scroll(seat, output, pointer, axis);
318 }
319 }
257} 320}
258 321
259static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, 322static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer,
@@ -268,7 +331,12 @@ static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
268 331
269static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, 332static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
270 uint32_t axis, int32_t discrete) { 333 uint32_t axis, int32_t discrete) {
271 // Who cares 334 struct swaybar_seat *seat = data;
335 if (!sway_assert(axis < 2, "axis out of range")) {
336 return;
337 }
338
339 seat->axis[axis].discrete_steps += abs(discrete);
272} 340}
273 341
274static struct wl_pointer_listener pointer_listener = { 342static struct wl_pointer_listener pointer_listener = {