diff options
Diffstat (limited to 'sway/input/seatop_default.c')
-rw-r--r-- | sway/input/seatop_default.c | 236 |
1 files changed, 143 insertions, 93 deletions
diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 875426bf..0c6f7c5e 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c | |||
@@ -1,7 +1,7 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <float.h> | 1 | #include <float.h> |
3 | #include <libevdev/libevdev.h> | 2 | #include <libevdev/libevdev.h> |
4 | #include <wlr/types/wlr_cursor.h> | 3 | #include <wlr/types/wlr_cursor.h> |
4 | #include <wlr/types/wlr_subcompositor.h> | ||
5 | #include <wlr/types/wlr_tablet_v2.h> | 5 | #include <wlr/types/wlr_tablet_v2.h> |
6 | #include <wlr/types/wlr_xcursor_manager.h> | 6 | #include <wlr/types/wlr_xcursor_manager.h> |
7 | #include "gesture.h" | 7 | #include "gesture.h" |
@@ -9,7 +9,9 @@ | |||
9 | #include "sway/input/cursor.h" | 9 | #include "sway/input/cursor.h" |
10 | #include "sway/input/seat.h" | 10 | #include "sway/input/seat.h" |
11 | #include "sway/input/tablet.h" | 11 | #include "sway/input/tablet.h" |
12 | #include "sway/layers.h" | ||
12 | #include "sway/output.h" | 13 | #include "sway/output.h" |
14 | #include "sway/scene_descriptor.h" | ||
13 | #include "sway/tree/view.h" | 15 | #include "sway/tree/view.h" |
14 | #include "sway/tree/workspace.h" | 16 | #include "sway/tree/workspace.h" |
15 | #include "log.h" | 17 | #include "log.h" |
@@ -53,6 +55,9 @@ static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) { | |||
53 | while (cont) { | 55 | while (cont) { |
54 | if (container_parent_layout(cont) == layout) { | 56 | if (container_parent_layout(cont) == layout) { |
55 | list_t *siblings = container_get_siblings(cont); | 57 | list_t *siblings = container_get_siblings(cont); |
58 | if (!siblings) { | ||
59 | return false; | ||
60 | } | ||
56 | int index = list_find(siblings, cont); | 61 | int index = list_find(siblings, cont); |
57 | if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) { | 62 | if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) { |
58 | return false; | 63 | return false; |
@@ -228,14 +233,15 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, | |||
228 | struct sway_container *cont = node && node->type == N_CONTAINER ? | 233 | struct sway_container *cont = node && node->type == N_CONTAINER ? |
229 | node->sway_container : NULL; | 234 | node->sway_container : NULL; |
230 | 235 | ||
231 | if (wlr_surface_is_layer_surface(surface)) { | 236 | struct wlr_layer_surface_v1 *layer; |
237 | #if HAVE_XWAYLAND | ||
238 | struct wlr_xwayland_surface *xsurface; | ||
239 | #endif | ||
240 | if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface)) && | ||
241 | layer->current.keyboard_interactive) { | ||
232 | // Handle tapping a layer surface | 242 | // Handle tapping a layer surface |
233 | struct wlr_layer_surface_v1 *layer = | 243 | seat_set_focus_layer(seat, layer); |
234 | wlr_layer_surface_v1_from_wlr_surface(surface); | 244 | transaction_commit_dirty(); |
235 | if (layer->current.keyboard_interactive) { | ||
236 | seat_set_focus_layer(seat, layer); | ||
237 | transaction_commit_dirty(); | ||
238 | } | ||
239 | } else if (cont) { | 245 | } else if (cont) { |
240 | bool is_floating_or_child = container_is_floating_or_child(cont); | 246 | bool is_floating_or_child = container_is_floating_or_child(cont); |
241 | bool is_fullscreen_or_child = container_is_fullscreen_or_child(cont); | 247 | bool is_fullscreen_or_child = container_is_fullscreen_or_child(cont); |
@@ -260,20 +266,17 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, | |||
260 | 266 | ||
261 | // Handle tapping on a container surface | 267 | // Handle tapping on a container surface |
262 | seat_set_focus_container(seat, cont); | 268 | seat_set_focus_container(seat, cont); |
263 | seatop_begin_down(seat, node->sway_container, time_msec, sx, sy); | 269 | seatop_begin_down(seat, node->sway_container, sx, sy); |
264 | } | 270 | } |
265 | #if HAVE_XWAYLAND | 271 | #if HAVE_XWAYLAND |
266 | // Handle tapping on an xwayland unmanaged view | 272 | // Handle tapping on an xwayland unmanaged view |
267 | else if (wlr_surface_is_xwayland_surface(surface)) { | 273 | else if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) && |
268 | struct wlr_xwayland_surface *xsurface = | 274 | xsurface->override_redirect && |
269 | wlr_xwayland_surface_from_wlr_surface(surface); | 275 | wlr_xwayland_or_surface_wants_focus(xsurface)) { |
270 | if (xsurface->override_redirect && | 276 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; |
271 | wlr_xwayland_or_surface_wants_focus(xsurface)) { | 277 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
272 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; | 278 | seat_set_focus_surface(seat, xsurface->surface, false); |
273 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 279 | transaction_commit_dirty(); |
274 | seat_set_focus_surface(seat, xsurface->surface, false); | ||
275 | transaction_commit_dirty(); | ||
276 | } | ||
277 | } | 280 | } |
278 | #endif | 281 | #endif |
279 | 282 | ||
@@ -287,7 +290,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, | |||
287 | 290 | ||
288 | static bool trigger_pointer_button_binding(struct sway_seat *seat, | 291 | static bool trigger_pointer_button_binding(struct sway_seat *seat, |
289 | struct wlr_input_device *device, uint32_t button, | 292 | struct wlr_input_device *device, uint32_t button, |
290 | enum wlr_button_state state, uint32_t modifiers, | 293 | enum wl_pointer_button_state state, uint32_t modifiers, |
291 | bool on_titlebar, bool on_border, bool on_contents, bool on_workspace) { | 294 | bool on_titlebar, bool on_border, bool on_contents, bool on_workspace) { |
292 | // We can reach this for non-pointer devices if we're currently emulating | 295 | // We can reach this for non-pointer devices if we're currently emulating |
293 | // pointer input for one. Emulated input should not trigger bindings. The | 296 | // pointer input for one. Emulated input should not trigger bindings. The |
@@ -301,7 +304,7 @@ static bool trigger_pointer_button_binding(struct sway_seat *seat, | |||
301 | char *device_identifier = device ? input_device_get_identifier(device) | 304 | char *device_identifier = device ? input_device_get_identifier(device) |
302 | : strdup("*"); | 305 | : strdup("*"); |
303 | struct sway_binding *binding = NULL; | 306 | struct sway_binding *binding = NULL; |
304 | if (state == WLR_BUTTON_PRESSED) { | 307 | if (state == WL_POINTER_BUTTON_STATE_PRESSED) { |
305 | state_add_button(e, button); | 308 | state_add_button(e, button); |
306 | binding = get_active_mouse_binding(e, | 309 | binding = get_active_mouse_binding(e, |
307 | config->current_mode->mouse_bindings, modifiers, false, | 310 | config->current_mode->mouse_bindings, modifiers, false, |
@@ -326,7 +329,7 @@ static bool trigger_pointer_button_binding(struct sway_seat *seat, | |||
326 | 329 | ||
327 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 330 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
328 | struct wlr_input_device *device, uint32_t button, | 331 | struct wlr_input_device *device, uint32_t button, |
329 | enum wlr_button_state state) { | 332 | enum wl_pointer_button_state state) { |
330 | struct sway_cursor *cursor = seat->cursor; | 333 | struct sway_cursor *cursor = seat->cursor; |
331 | 334 | ||
332 | // Determine what's under the cursor | 335 | // Determine what's under the cursor |
@@ -359,7 +362,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
359 | 362 | ||
360 | // Handle clicking an empty workspace | 363 | // Handle clicking an empty workspace |
361 | if (node && node->type == N_WORKSPACE) { | 364 | if (node && node->type == N_WORKSPACE) { |
362 | if (state == WLR_BUTTON_PRESSED) { | 365 | if (state == WL_POINTER_BUTTON_STATE_PRESSED) { |
363 | seat_set_focus(seat, node); | 366 | seat_set_focus(seat, node); |
364 | transaction_commit_dirty(); | 367 | transaction_commit_dirty(); |
365 | } | 368 | } |
@@ -367,16 +370,15 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
367 | return; | 370 | return; |
368 | } | 371 | } |
369 | 372 | ||
370 | // Handle clicking a layer surface | 373 | // Handle clicking a layer surface and its popups/subsurfaces |
371 | if (surface && wlr_surface_is_layer_surface(surface)) { | 374 | struct wlr_layer_surface_v1 *layer = NULL; |
372 | struct wlr_layer_surface_v1 *layer = | 375 | if ((layer = toplevel_layer_surface_from_surface(surface))) { |
373 | wlr_layer_surface_v1_from_wlr_surface(surface); | ||
374 | if (layer->current.keyboard_interactive) { | 376 | if (layer->current.keyboard_interactive) { |
375 | seat_set_focus_layer(seat, layer); | 377 | seat_set_focus_layer(seat, layer); |
376 | transaction_commit_dirty(); | 378 | transaction_commit_dirty(); |
377 | } | 379 | } |
378 | if (state == WLR_BUTTON_PRESSED) { | 380 | if (state == WL_POINTER_BUTTON_STATE_PRESSED) { |
379 | seatop_begin_down_on_surface(seat, surface, time_msec, sx, sy); | 381 | seatop_begin_down_on_surface(seat, surface, sx, sy); |
380 | } | 382 | } |
381 | seat_pointer_notify_button(seat, time_msec, button, state); | 383 | seat_pointer_notify_button(seat, time_msec, button, state); |
382 | return; | 384 | return; |
@@ -384,7 +386,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
384 | 386 | ||
385 | // Handle tiling resize via border | 387 | // Handle tiling resize via border |
386 | if (cont && resize_edge && button == BTN_LEFT && | 388 | if (cont && resize_edge && button == BTN_LEFT && |
387 | state == WLR_BUTTON_PRESSED && !is_floating) { | 389 | state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating) { |
388 | // If a resize is triggered on a tabbed or stacked container, change | 390 | // If a resize is triggered on a tabbed or stacked container, change |
389 | // focus to the tab which already had inactive focus -- otherwise, we'd | 391 | // focus to the tab which already had inactive focus -- otherwise, we'd |
390 | // change the active tab when the user probably just wanted to resize. | 392 | // change the active tab when the user probably just wanted to resize. |
@@ -402,7 +404,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
402 | // Handle tiling resize via mod | 404 | // Handle tiling resize via mod |
403 | bool mod_pressed = modifiers & config->floating_mod; | 405 | bool mod_pressed = modifiers & config->floating_mod; |
404 | if (cont && !is_floating_or_child && mod_pressed && | 406 | if (cont && !is_floating_or_child && mod_pressed && |
405 | state == WLR_BUTTON_PRESSED) { | 407 | state == WL_POINTER_BUTTON_STATE_PRESSED) { |
406 | uint32_t btn_resize = config->floating_mod_inverse ? | 408 | uint32_t btn_resize = config->floating_mod_inverse ? |
407 | BTN_LEFT : BTN_RIGHT; | 409 | BTN_LEFT : BTN_RIGHT; |
408 | if (button == btn_resize) { | 410 | if (button == btn_resize) { |
@@ -429,13 +431,31 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
429 | } | 431 | } |
430 | } | 432 | } |
431 | 433 | ||
434 | // Handle changing focus when clicking on a container | ||
435 | if (cont && state == WL_POINTER_BUTTON_STATE_PRESSED) { | ||
436 | // Default case: focus the container that was just clicked. | ||
437 | node = &cont->node; | ||
438 | |||
439 | // If the container is a tab/stacked container and the click happened | ||
440 | // on a tab, switch to the tab. If the tab contents were already | ||
441 | // focused, focus the tab container itself. If the tab container was | ||
442 | // already focused, cycle back to focusing the tab contents. | ||
443 | if (on_titlebar) { | ||
444 | struct sway_container *focus = seat_get_focused_container(seat); | ||
445 | if (focus == cont || !container_has_ancestor(focus, cont)) { | ||
446 | node = seat_get_focus_inactive(seat, &cont->node); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | seat_set_focus(seat, node); | ||
451 | transaction_commit_dirty(); | ||
452 | } | ||
453 | |||
432 | // Handle beginning floating move | 454 | // Handle beginning floating move |
433 | if (cont && is_floating_or_child && !is_fullscreen_or_child && | 455 | if (cont && is_floating_or_child && !is_fullscreen_or_child && |
434 | state == WLR_BUTTON_PRESSED) { | 456 | state == WL_POINTER_BUTTON_STATE_PRESSED) { |
435 | uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; | 457 | uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; |
436 | if (button == btn_move && (mod_pressed || on_titlebar)) { | 458 | if (button == btn_move && (mod_pressed || on_titlebar)) { |
437 | seat_set_focus_container(seat, | ||
438 | seat_get_focus_inactive_view(seat, &cont->node)); | ||
439 | seatop_begin_move_floating(seat, container_toplevel_ancestor(cont)); | 459 | seatop_begin_move_floating(seat, container_toplevel_ancestor(cont)); |
440 | return; | 460 | return; |
441 | } | 461 | } |
@@ -443,9 +463,10 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
443 | 463 | ||
444 | // Handle beginning floating resize | 464 | // Handle beginning floating resize |
445 | if (cont && is_floating_or_child && !is_fullscreen_or_child && | 465 | if (cont && is_floating_or_child && !is_fullscreen_or_child && |
446 | state == WLR_BUTTON_PRESSED) { | 466 | state == WL_POINTER_BUTTON_STATE_PRESSED) { |
447 | // Via border | 467 | // Via border |
448 | if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) { | 468 | if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) { |
469 | seat_set_focus_container(seat, cont); | ||
449 | seatop_begin_resize_floating(seat, cont, resize_edge); | 470 | seatop_begin_resize_floating(seat, cont, resize_edge); |
450 | return; | 471 | return; |
451 | } | 472 | } |
@@ -460,6 +481,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
460 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; | 481 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; |
461 | edge |= cursor->cursor->y > floater->pending.y + floater->pending.height / 2 ? | 482 | edge |= cursor->cursor->y > floater->pending.y + floater->pending.height / 2 ? |
462 | WLR_EDGE_BOTTOM : WLR_EDGE_TOP; | 483 | WLR_EDGE_BOTTOM : WLR_EDGE_TOP; |
484 | seat_set_focus_container(seat, floater); | ||
463 | seatop_begin_resize_floating(seat, floater, edge); | 485 | seatop_begin_resize_floating(seat, floater, edge); |
464 | return; | 486 | return; |
465 | } | 487 | } |
@@ -467,55 +489,43 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
467 | 489 | ||
468 | // Handle moving a tiling container | 490 | // Handle moving a tiling container |
469 | if (config->tiling_drag && (mod_pressed || on_titlebar) && | 491 | if (config->tiling_drag && (mod_pressed || on_titlebar) && |
470 | state == WLR_BUTTON_PRESSED && !is_floating_or_child && | 492 | state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child && |
471 | cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { | 493 | cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { |
472 | struct sway_container *focus = seat_get_focused_container(seat); | ||
473 | bool focused = focus == cont || container_has_ancestor(focus, cont); | ||
474 | if (on_titlebar && !focused) { | ||
475 | node = seat_get_focus_inactive(seat, &cont->node); | ||
476 | seat_set_focus(seat, node); | ||
477 | } | ||
478 | |||
479 | // If moving a container by its title bar, use a threshold for the drag | 494 | // If moving a container by its title bar, use a threshold for the drag |
480 | if (!mod_pressed && config->tiling_drag_threshold > 0) { | 495 | if (!mod_pressed && config->tiling_drag_threshold > 0) { |
481 | seatop_begin_move_tiling_threshold(seat, cont); | 496 | seatop_begin_move_tiling_threshold(seat, cont); |
482 | } else { | 497 | } else { |
483 | seatop_begin_move_tiling(seat, cont); | 498 | seatop_begin_move_tiling(seat, cont); |
484 | } | 499 | } |
500 | |||
485 | return; | 501 | return; |
486 | } | 502 | } |
487 | 503 | ||
488 | // Handle mousedown on a container surface | 504 | // Handle mousedown on a container surface |
489 | if (surface && cont && state == WLR_BUTTON_PRESSED) { | 505 | if (surface && cont && state == WL_POINTER_BUTTON_STATE_PRESSED) { |
490 | seat_set_focus_container(seat, cont); | 506 | seatop_begin_down(seat, cont, sx, sy); |
491 | seatop_begin_down(seat, cont, time_msec, sx, sy); | 507 | seat_pointer_notify_button(seat, time_msec, button, WL_POINTER_BUTTON_STATE_PRESSED); |
492 | seat_pointer_notify_button(seat, time_msec, button, WLR_BUTTON_PRESSED); | ||
493 | return; | 508 | return; |
494 | } | 509 | } |
495 | 510 | ||
496 | // Handle clicking a container surface or decorations | 511 | // Handle clicking a container surface or decorations |
497 | if (cont && state == WLR_BUTTON_PRESSED) { | 512 | if (cont && state == WL_POINTER_BUTTON_STATE_PRESSED) { |
498 | node = seat_get_focus_inactive(seat, &cont->node); | ||
499 | seat_set_focus(seat, node); | ||
500 | transaction_commit_dirty(); | ||
501 | seat_pointer_notify_button(seat, time_msec, button, state); | 513 | seat_pointer_notify_button(seat, time_msec, button, state); |
502 | return; | 514 | return; |
503 | } | 515 | } |
504 | 516 | ||
505 | #if HAVE_XWAYLAND | 517 | #if HAVE_XWAYLAND |
506 | // Handle clicking on xwayland unmanaged view | 518 | // Handle clicking on xwayland unmanaged view |
507 | if (surface && wlr_surface_is_xwayland_surface(surface)) { | 519 | struct wlr_xwayland_surface *xsurface; |
508 | struct wlr_xwayland_surface *xsurface = | 520 | if (surface && |
509 | wlr_xwayland_surface_from_wlr_surface(surface); | 521 | (xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) && |
510 | if (xsurface->override_redirect && | 522 | xsurface->override_redirect && |
511 | wlr_xwayland_or_surface_wants_focus(xsurface)) { | 523 | wlr_xwayland_or_surface_wants_focus(xsurface)) { |
512 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; | 524 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; |
513 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 525 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
514 | seat_set_focus_surface(seat, xsurface->surface, false); | 526 | seat_set_focus_surface(seat, xsurface->surface, false); |
515 | transaction_commit_dirty(); | 527 | transaction_commit_dirty(); |
516 | seat_pointer_notify_button(seat, time_msec, button, state); | 528 | seat_pointer_notify_button(seat, time_msec, button, state); |
517 | return; | ||
518 | } | ||
519 | } | 529 | } |
520 | #endif | 530 | #endif |
521 | 531 | ||
@@ -538,6 +548,21 @@ static void check_focus_follows_mouse(struct sway_seat *seat, | |||
538 | if (wlr_output == NULL) { | 548 | if (wlr_output == NULL) { |
539 | return; | 549 | return; |
540 | } | 550 | } |
551 | |||
552 | struct wlr_surface *surface = NULL; | ||
553 | double sx, sy; | ||
554 | node_at_coords(seat, seat->cursor->cursor->x, seat->cursor->cursor->y, | ||
555 | &surface, &sx, &sy); | ||
556 | |||
557 | // Focus topmost layer surface | ||
558 | struct wlr_layer_surface_v1 *layer = NULL; | ||
559 | if ((layer = toplevel_layer_surface_from_surface(surface)) && | ||
560 | layer->current.keyboard_interactive) { | ||
561 | seat_set_focus_layer(seat, layer); | ||
562 | transaction_commit_dirty(); | ||
563 | return; | ||
564 | } | ||
565 | |||
541 | struct sway_output *hovered_output = wlr_output->data; | 566 | struct sway_output *hovered_output = wlr_output->data; |
542 | if (focus && hovered_output != node_get_output(focus)) { | 567 | if (focus && hovered_output != node_get_output(focus)) { |
543 | struct sway_workspace *ws = output_get_active_workspace(hovered_output); | 568 | struct sway_workspace *ws = output_get_active_workspace(hovered_output); |
@@ -598,12 +623,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { | |||
598 | wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); | 623 | wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); |
599 | } | 624 | } |
600 | 625 | ||
601 | struct sway_drag_icon *drag_icon; | 626 | drag_icons_update_position(seat); |
602 | wl_list_for_each(drag_icon, &root->drag_icons, link) { | ||
603 | if (drag_icon->seat == seat) { | ||
604 | drag_icon_update_position(drag_icon); | ||
605 | } | ||
606 | } | ||
607 | 627 | ||
608 | e->previous_node = node; | 628 | e->previous_node = node; |
609 | } | 629 | } |
@@ -633,25 +653,50 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, | |||
633 | wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); | 653 | wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); |
634 | } | 654 | } |
635 | 655 | ||
636 | struct sway_drag_icon *drag_icon; | 656 | drag_icons_update_position(seat); |
637 | wl_list_for_each(drag_icon, &root->drag_icons, link) { | ||
638 | if (drag_icon->seat == seat) { | ||
639 | drag_icon_update_position(drag_icon); | ||
640 | } | ||
641 | } | ||
642 | 657 | ||
643 | e->previous_node = node; | 658 | e->previous_node = node; |
644 | } | 659 | } |
645 | 660 | ||
661 | static void handle_touch_down(struct sway_seat *seat, | ||
662 | struct wlr_touch_down_event *event, double lx, double ly) { | ||
663 | struct wlr_surface *surface = NULL; | ||
664 | struct wlr_seat *wlr_seat = seat->wlr_seat; | ||
665 | struct sway_cursor *cursor = seat->cursor; | ||
666 | double sx, sy; | ||
667 | node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy); | ||
668 | |||
669 | if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { | ||
670 | if (seat_is_input_allowed(seat, surface)) { | ||
671 | cursor->simulating_pointer_from_touch = false; | ||
672 | seatop_begin_touch_down(seat, surface, event, sx, sy, lx, ly); | ||
673 | } | ||
674 | } else if (!cursor->simulating_pointer_from_touch && | ||
675 | (!surface || seat_is_input_allowed(seat, surface))) { | ||
676 | // Fallback to cursor simulation. | ||
677 | // The pointer_touch_id state is needed, so drags are not aborted when over | ||
678 | // a surface supporting touch and multi touch events don't interfere. | ||
679 | cursor->simulating_pointer_from_touch = true; | ||
680 | cursor->pointer_touch_id = seat->touch_id; | ||
681 | double dx, dy; | ||
682 | dx = seat->touch_x - cursor->cursor->x; | ||
683 | dy = seat->touch_y - cursor->cursor->y; | ||
684 | pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, | ||
685 | dx, dy); | ||
686 | dispatch_cursor_button(cursor, &event->touch->base, event->time_msec, | ||
687 | BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); | ||
688 | } | ||
689 | } | ||
690 | |||
646 | /*----------------------------------------\ | 691 | /*----------------------------------------\ |
647 | * Functions used by handle_pointer_axis / | 692 | * Functions used by handle_pointer_axis / |
648 | *--------------------------------------*/ | 693 | *--------------------------------------*/ |
649 | 694 | ||
650 | static uint32_t wl_axis_to_button(struct wlr_pointer_axis_event *event) { | 695 | static uint32_t wl_axis_to_button(struct wlr_pointer_axis_event *event) { |
651 | switch (event->orientation) { | 696 | switch (event->orientation) { |
652 | case WLR_AXIS_ORIENTATION_VERTICAL: | 697 | case WL_POINTER_AXIS_VERTICAL_SCROLL: |
653 | return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN; | 698 | return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN; |
654 | case WLR_AXIS_ORIENTATION_HORIZONTAL: | 699 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: |
655 | return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT; | 700 | return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT; |
656 | default: | 701 | default: |
657 | sway_log(SWAY_DEBUG, "Unknown axis orientation"); | 702 | sway_log(SWAY_DEBUG, "Unknown axis orientation"); |
@@ -708,6 +753,7 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
708 | 753 | ||
709 | // Scrolling on a tabbed or stacked title bar (handled as press event) | 754 | // Scrolling on a tabbed or stacked title bar (handled as press event) |
710 | if (!handled && (on_titlebar || on_titlebar_border)) { | 755 | if (!handled && (on_titlebar || on_titlebar_border)) { |
756 | struct sway_node *new_focus; | ||
711 | enum sway_container_layout layout = container_parent_layout(cont); | 757 | enum sway_container_layout layout = container_parent_layout(cont); |
712 | if (layout == L_TABBED || layout == L_STACKED) { | 758 | if (layout == L_TABBED || layout == L_STACKED) { |
713 | struct sway_node *tabcontainer = node_get_parent(node); | 759 | struct sway_node *tabcontainer = node_get_parent(node); |
@@ -715,7 +761,7 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
715 | seat_get_active_tiling_child(seat, tabcontainer); | 761 | seat_get_active_tiling_child(seat, tabcontainer); |
716 | list_t *siblings = container_get_siblings(cont); | 762 | list_t *siblings = container_get_siblings(cont); |
717 | int desired = list_find(siblings, active->sway_container) + | 763 | int desired = list_find(siblings, active->sway_container) + |
718 | round(scroll_factor * event->delta_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); | 764 | roundf(scroll_factor * event->delta_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); |
719 | if (desired < 0) { | 765 | if (desired < 0) { |
720 | desired = 0; | 766 | desired = 0; |
721 | } else if (desired >= siblings->length) { | 767 | } else if (desired >= siblings->length) { |
@@ -724,14 +770,16 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
724 | 770 | ||
725 | struct sway_container *new_sibling_con = siblings->items[desired]; | 771 | struct sway_container *new_sibling_con = siblings->items[desired]; |
726 | struct sway_node *new_sibling = &new_sibling_con->node; | 772 | struct sway_node *new_sibling = &new_sibling_con->node; |
727 | struct sway_node *new_focus = | ||
728 | seat_get_focus_inactive(seat, new_sibling); | ||
729 | // Use the focused child of the tabbed/stacked container, not the | 773 | // Use the focused child of the tabbed/stacked container, not the |
730 | // container the user scrolled on. | 774 | // container the user scrolled on. |
731 | seat_set_focus(seat, new_focus); | 775 | new_focus = seat_get_focus_inactive(seat, new_sibling); |
732 | transaction_commit_dirty(); | 776 | } else { |
733 | handled = true; | 777 | new_focus = seat_get_focus_inactive(seat, &cont->node); |
734 | } | 778 | } |
779 | |||
780 | seat_set_focus(seat, new_focus); | ||
781 | transaction_commit_dirty(); | ||
782 | handled = true; | ||
735 | } | 783 | } |
736 | 784 | ||
737 | // Handle mouse bindings - x11 mouse buttons 4-7 - release event | 785 | // Handle mouse bindings - x11 mouse buttons 4-7 - release event |
@@ -747,8 +795,9 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
747 | 795 | ||
748 | if (!handled) { | 796 | if (!handled) { |
749 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, | 797 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, |
750 | event->orientation, scroll_factor * event->delta, | 798 | event->orientation, scroll_factor * event->delta, |
751 | round(scroll_factor * event->delta_discrete), event->source); | 799 | roundf(scroll_factor * event->delta_discrete), event->source, |
800 | event->relative_direction); | ||
752 | } | 801 | } |
753 | } | 802 | } |
754 | 803 | ||
@@ -894,7 +943,7 @@ static void handle_hold_begin(struct sway_seat *seat, | |||
894 | // ... otherwise forward to client | 943 | // ... otherwise forward to client |
895 | struct sway_cursor *cursor = seat->cursor; | 944 | struct sway_cursor *cursor = seat->cursor; |
896 | wlr_pointer_gestures_v1_send_hold_begin( | 945 | wlr_pointer_gestures_v1_send_hold_begin( |
897 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 946 | server.input->pointer_gestures, cursor->seat->wlr_seat, |
898 | event->time_msec, event->fingers); | 947 | event->time_msec, event->fingers); |
899 | } | 948 | } |
900 | } | 949 | } |
@@ -906,7 +955,7 @@ static void handle_hold_end(struct sway_seat *seat, | |||
906 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_HOLD)) { | 955 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_HOLD)) { |
907 | struct sway_cursor *cursor = seat->cursor; | 956 | struct sway_cursor *cursor = seat->cursor; |
908 | wlr_pointer_gestures_v1_send_hold_end( | 957 | wlr_pointer_gestures_v1_send_hold_end( |
909 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 958 | server.input->pointer_gestures, cursor->seat->wlr_seat, |
910 | event->time_msec, event->cancelled); | 959 | event->time_msec, event->cancelled); |
911 | return; | 960 | return; |
912 | } | 961 | } |
@@ -939,7 +988,7 @@ static void handle_pinch_begin(struct sway_seat *seat, | |||
939 | // ... otherwise forward to client | 988 | // ... otherwise forward to client |
940 | struct sway_cursor *cursor = seat->cursor; | 989 | struct sway_cursor *cursor = seat->cursor; |
941 | wlr_pointer_gestures_v1_send_pinch_begin( | 990 | wlr_pointer_gestures_v1_send_pinch_begin( |
942 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 991 | server.input->pointer_gestures, cursor->seat->wlr_seat, |
943 | event->time_msec, event->fingers); | 992 | event->time_msec, event->fingers); |
944 | } | 993 | } |
945 | } | 994 | } |
@@ -955,7 +1004,7 @@ static void handle_pinch_update(struct sway_seat *seat, | |||
955 | // ... otherwise forward to client | 1004 | // ... otherwise forward to client |
956 | struct sway_cursor *cursor = seat->cursor; | 1005 | struct sway_cursor *cursor = seat->cursor; |
957 | wlr_pointer_gestures_v1_send_pinch_update( | 1006 | wlr_pointer_gestures_v1_send_pinch_update( |
958 | cursor->pointer_gestures, | 1007 | server.input->pointer_gestures, |
959 | cursor->seat->wlr_seat, | 1008 | cursor->seat->wlr_seat, |
960 | event->time_msec, event->dx, event->dy, | 1009 | event->time_msec, event->dx, event->dy, |
961 | event->scale, event->rotation); | 1010 | event->scale, event->rotation); |
@@ -969,7 +1018,7 @@ static void handle_pinch_end(struct sway_seat *seat, | |||
969 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) { | 1018 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) { |
970 | struct sway_cursor *cursor = seat->cursor; | 1019 | struct sway_cursor *cursor = seat->cursor; |
971 | wlr_pointer_gestures_v1_send_pinch_end( | 1020 | wlr_pointer_gestures_v1_send_pinch_end( |
972 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 1021 | server.input->pointer_gestures, cursor->seat->wlr_seat, |
973 | event->time_msec, event->cancelled); | 1022 | event->time_msec, event->cancelled); |
974 | return; | 1023 | return; |
975 | } | 1024 | } |
@@ -1002,7 +1051,7 @@ static void handle_swipe_begin(struct sway_seat *seat, | |||
1002 | // ... otherwise forward to client | 1051 | // ... otherwise forward to client |
1003 | struct sway_cursor *cursor = seat->cursor; | 1052 | struct sway_cursor *cursor = seat->cursor; |
1004 | wlr_pointer_gestures_v1_send_swipe_begin( | 1053 | wlr_pointer_gestures_v1_send_swipe_begin( |
1005 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 1054 | server.input->pointer_gestures, cursor->seat->wlr_seat, |
1006 | event->time_msec, event->fingers); | 1055 | event->time_msec, event->fingers); |
1007 | } | 1056 | } |
1008 | } | 1057 | } |
@@ -1019,7 +1068,7 @@ static void handle_swipe_update(struct sway_seat *seat, | |||
1019 | // ... otherwise forward to client | 1068 | // ... otherwise forward to client |
1020 | struct sway_cursor *cursor = seat->cursor; | 1069 | struct sway_cursor *cursor = seat->cursor; |
1021 | wlr_pointer_gestures_v1_send_swipe_update( | 1070 | wlr_pointer_gestures_v1_send_swipe_update( |
1022 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 1071 | server.input->pointer_gestures, cursor->seat->wlr_seat, |
1023 | event->time_msec, event->dx, event->dy); | 1072 | event->time_msec, event->dx, event->dy); |
1024 | } | 1073 | } |
1025 | } | 1074 | } |
@@ -1030,7 +1079,7 @@ static void handle_swipe_end(struct sway_seat *seat, | |||
1030 | struct seatop_default_event *seatop = seat->seatop_data; | 1079 | struct seatop_default_event *seatop = seat->seatop_data; |
1031 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) { | 1080 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) { |
1032 | struct sway_cursor *cursor = seat->cursor; | 1081 | struct sway_cursor *cursor = seat->cursor; |
1033 | wlr_pointer_gestures_v1_send_swipe_end(cursor->pointer_gestures, | 1082 | wlr_pointer_gestures_v1_send_swipe_end(server.input->pointer_gestures, |
1034 | cursor->seat->wlr_seat, event->time_msec, event->cancelled); | 1083 | cursor->seat->wlr_seat, event->time_msec, event->cancelled); |
1035 | return; | 1084 | return; |
1036 | } | 1085 | } |
@@ -1087,6 +1136,7 @@ static const struct sway_seatop_impl seatop_impl = { | |||
1087 | .swipe_begin = handle_swipe_begin, | 1136 | .swipe_begin = handle_swipe_begin, |
1088 | .swipe_update = handle_swipe_update, | 1137 | .swipe_update = handle_swipe_update, |
1089 | .swipe_end = handle_swipe_end, | 1138 | .swipe_end = handle_swipe_end, |
1139 | .touch_down = handle_touch_down, | ||
1090 | .rebase = handle_rebase, | 1140 | .rebase = handle_rebase, |
1091 | .allow_set_cursor = true, | 1141 | .allow_set_cursor = true, |
1092 | }; | 1142 | }; |