diff options
author | Martin Dørum <martid0311@gmail.com> | 2020-04-23 23:07:04 +0200 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2020-04-28 21:46:37 +0200 |
commit | 4492e493e62d51e6cd3340af622eef934f1c88cd (patch) | |
tree | b57fb5901caae42fb167438985a471af2556b04b /swaybar | |
parent | Add each view's shell to JSON description (diff) | |
download | sway-4492e493e62d51e6cd3340af622eef934f1c88cd.tar.gz sway-4492e493e62d51e6cd3340af622eef934f1c88cd.tar.zst sway-4492e493e62d51e6cd3340af622eef934f1c88cd.zip |
swaybar: Fix scrolling with precise trackpads
Diffstat (limited to 'swaybar')
-rw-r--r-- | swaybar/bar.c | 2 | ||||
-rw-r--r-- | swaybar/input.c | 90 |
2 files changed, 80 insertions, 12 deletions
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 | ||
217 | static 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 | ||
222 | static 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 | ||
254 | static 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 | |||
270 | static 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 | |||
255 | static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { | 294 | static 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 | ||
259 | static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, | 322 | static 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 | ||
269 | static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, | 332 | static 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 | ||
274 | static struct wl_pointer_listener pointer_listener = { | 342 | static struct wl_pointer_listener pointer_listener = { |