diff options
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r-- | sway/input/cursor.c | 323 |
1 files changed, 225 insertions, 98 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 3f417e96..3b70b471 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "list.h" | 12 | #include "list.h" |
13 | #include "log.h" | 13 | #include "log.h" |
14 | #include "config.h" | 14 | #include "config.h" |
15 | #include "sway/commands.h" | ||
15 | #include "sway/desktop.h" | 16 | #include "sway/desktop.h" |
16 | #include "sway/desktop/transaction.h" | 17 | #include "sway/desktop/transaction.h" |
17 | #include "sway/input/cursor.h" | 18 | #include "sway/input/cursor.h" |
@@ -136,7 +137,45 @@ static struct sway_container *container_at_coords( | |||
136 | return output->swayc; | 137 | return output->swayc; |
137 | } | 138 | } |
138 | 139 | ||
139 | static enum wlr_edges find_resize_edge(struct sway_container *cont, | 140 | /** |
141 | * Determine if the edge of the given container is on the edge of the | ||
142 | * workspace/output. | ||
143 | */ | ||
144 | static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) { | ||
145 | enum sway_container_layout layout = L_NONE; | ||
146 | switch (edge) { | ||
147 | case WLR_EDGE_TOP: | ||
148 | case WLR_EDGE_BOTTOM: | ||
149 | layout = L_VERT; | ||
150 | break; | ||
151 | case WLR_EDGE_LEFT: | ||
152 | case WLR_EDGE_RIGHT: | ||
153 | layout = L_HORIZ; | ||
154 | break; | ||
155 | case WLR_EDGE_NONE: | ||
156 | sway_assert(false, "Never reached"); | ||
157 | return false; | ||
158 | } | ||
159 | |||
160 | // Iterate the parents until we find one with the layout we want, | ||
161 | // then check if the child has siblings between it and the edge. | ||
162 | while (cont->type != C_OUTPUT) { | ||
163 | if (cont->parent->layout == layout) { | ||
164 | int index = list_find(cont->parent->children, cont); | ||
165 | if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) { | ||
166 | return false; | ||
167 | } | ||
168 | if (index < cont->parent->children->length - 1 && | ||
169 | (edge == WLR_EDGE_RIGHT || edge == WLR_EDGE_BOTTOM)) { | ||
170 | return false; | ||
171 | } | ||
172 | } | ||
173 | cont = cont->parent; | ||
174 | } | ||
175 | return true; | ||
176 | } | ||
177 | |||
178 | static enum wlr_edges find_edge(struct sway_container *cont, | ||
140 | struct sway_cursor *cursor) { | 179 | struct sway_cursor *cursor) { |
141 | if (cont->type != C_VIEW) { | 180 | if (cont->type != C_VIEW) { |
142 | return WLR_EDGE_NONE; | 181 | return WLR_EDGE_NONE; |
@@ -159,6 +198,20 @@ static enum wlr_edges find_resize_edge(struct sway_container *cont, | |||
159 | if (cursor->cursor->y >= cont->y + cont->height - view->border_thickness) { | 198 | if (cursor->cursor->y >= cont->y + cont->height - view->border_thickness) { |
160 | edge |= WLR_EDGE_BOTTOM; | 199 | edge |= WLR_EDGE_BOTTOM; |
161 | } | 200 | } |
201 | |||
202 | return edge; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * If the cursor is over a _resizable_ edge, return the edge. | ||
207 | * Edges that can't be resized are edges of the workspace. | ||
208 | */ | ||
209 | static enum wlr_edges find_resize_edge(struct sway_container *cont, | ||
210 | struct sway_cursor *cursor) { | ||
211 | enum wlr_edges edge = find_edge(cont, cursor); | ||
212 | if (edge && !container_is_floating(cont) && edge_is_external(cont, edge)) { | ||
213 | return WLR_EDGE_NONE; | ||
214 | } | ||
162 | return edge; | 215 | return edge; |
163 | } | 216 | } |
164 | 217 | ||
@@ -209,7 +262,7 @@ static void calculate_floating_constraints(struct sway_container *con, | |||
209 | } | 262 | } |
210 | } | 263 | } |
211 | 264 | ||
212 | static void handle_resize_motion(struct sway_seat *seat, | 265 | static void handle_resize_floating_motion(struct sway_seat *seat, |
213 | struct sway_cursor *cursor) { | 266 | struct sway_cursor *cursor) { |
214 | struct sway_container *con = seat->op_container; | 267 | struct sway_container *con = seat->op_container; |
215 | enum wlr_edges edge = seat->op_resize_edge; | 268 | enum wlr_edges edge = seat->op_resize_edge; |
@@ -301,6 +354,39 @@ static void handle_resize_motion(struct sway_seat *seat, | |||
301 | arrange_windows(con); | 354 | arrange_windows(con); |
302 | } | 355 | } |
303 | 356 | ||
357 | static void handle_resize_tiling_motion(struct sway_seat *seat, | ||
358 | struct sway_cursor *cursor) { | ||
359 | int amount_x = 0; | ||
360 | int amount_y = 0; | ||
361 | int moved_x = cursor->cursor->x - seat->op_ref_lx; | ||
362 | int moved_y = cursor->cursor->y - seat->op_ref_ly; | ||
363 | enum wlr_edges edge_x = WLR_EDGE_NONE; | ||
364 | enum wlr_edges edge_y = WLR_EDGE_NONE; | ||
365 | struct sway_container *con = seat->op_container; | ||
366 | |||
367 | if (seat->op_resize_edge & WLR_EDGE_TOP) { | ||
368 | amount_y = (seat->op_ref_height - moved_y) - con->height; | ||
369 | edge_y = WLR_EDGE_TOP; | ||
370 | } else if (seat->op_resize_edge & WLR_EDGE_BOTTOM) { | ||
371 | amount_y = (seat->op_ref_height + moved_y) - con->height; | ||
372 | edge_y = WLR_EDGE_BOTTOM; | ||
373 | } | ||
374 | if (seat->op_resize_edge & WLR_EDGE_LEFT) { | ||
375 | amount_x = (seat->op_ref_width - moved_x) - con->width; | ||
376 | edge_x = WLR_EDGE_LEFT; | ||
377 | } else if (seat->op_resize_edge & WLR_EDGE_RIGHT) { | ||
378 | amount_x = (seat->op_ref_width + moved_x) - con->width; | ||
379 | edge_x = WLR_EDGE_RIGHT; | ||
380 | } | ||
381 | |||
382 | if (amount_x != 0) { | ||
383 | container_resize_tiled(seat->op_container, edge_x, amount_x); | ||
384 | } | ||
385 | if (amount_y != 0) { | ||
386 | container_resize_tiled(seat->op_container, edge_y, amount_y); | ||
387 | } | ||
388 | } | ||
389 | |||
304 | void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | 390 | void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, |
305 | bool allow_refocusing) { | 391 | bool allow_refocusing) { |
306 | if (time_msec == 0) { | 392 | if (time_msec == 0) { |
@@ -310,10 +396,18 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
310 | struct sway_seat *seat = cursor->seat; | 396 | struct sway_seat *seat = cursor->seat; |
311 | 397 | ||
312 | if (seat->operation != OP_NONE) { | 398 | if (seat->operation != OP_NONE) { |
313 | if (seat->operation == OP_MOVE) { | 399 | switch (seat->operation) { |
400 | case OP_MOVE: | ||
314 | handle_move_motion(seat, cursor); | 401 | handle_move_motion(seat, cursor); |
315 | } else { | 402 | break; |
316 | handle_resize_motion(seat, cursor); | 403 | case OP_RESIZE_FLOATING: |
404 | handle_resize_floating_motion(seat, cursor); | ||
405 | break; | ||
406 | case OP_RESIZE_TILING: | ||
407 | handle_resize_tiling_motion(seat, cursor); | ||
408 | break; | ||
409 | case OP_NONE: | ||
410 | break; | ||
317 | } | 411 | } |
318 | cursor->previous.x = cursor->cursor->x; | 412 | cursor->previous.x = cursor->cursor->x; |
319 | cursor->previous.y = cursor->cursor->y; | 413 | cursor->previous.y = cursor->cursor->y; |
@@ -375,12 +469,20 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
375 | if (client != cursor->image_client) { | 469 | if (client != cursor->image_client) { |
376 | cursor_set_image(cursor, "left_ptr", client); | 470 | cursor_set_image(cursor, "left_ptr", client); |
377 | } | 471 | } |
378 | } else if (c && container_is_floating(c)) { | 472 | } else if (c) { |
379 | // Try a floating container's resize edge | 473 | // Try a container's resize edge |
380 | enum wlr_edges edge = find_resize_edge(c, cursor); | 474 | enum wlr_edges edge = find_resize_edge(c, cursor); |
381 | const char *image = edge == WLR_EDGE_NONE ? | 475 | if (edge == WLR_EDGE_NONE) { |
382 | "left_ptr" : wlr_xcursor_get_resize_name(edge); | 476 | cursor_set_image(cursor, "left_ptr", NULL); |
383 | cursor_set_image(cursor, image, NULL); | 477 | } else if (container_is_floating(c)) { |
478 | cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); | ||
479 | } else { | ||
480 | if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) { | ||
481 | cursor_set_image(cursor, "col-resize", NULL); | ||
482 | } else { | ||
483 | cursor_set_image(cursor, "row-resize", NULL); | ||
484 | } | ||
485 | } | ||
384 | } else { | 486 | } else { |
385 | cursor_set_image(cursor, "left_ptr", NULL); | 487 | cursor_set_image(cursor, "left_ptr", NULL); |
386 | } | 488 | } |
@@ -423,57 +525,6 @@ static void handle_cursor_motion_absolute( | |||
423 | transaction_commit_dirty(); | 525 | transaction_commit_dirty(); |
424 | } | 526 | } |
425 | 527 | ||
426 | static void dispatch_cursor_button_floating(struct sway_cursor *cursor, | ||
427 | uint32_t time_msec, uint32_t button, enum wlr_button_state state, | ||
428 | struct wlr_surface *surface, double sx, double sy, | ||
429 | struct sway_container *cont) { | ||
430 | struct sway_seat *seat = cursor->seat; | ||
431 | |||
432 | seat_set_focus(seat, cont); | ||
433 | |||
434 | // Deny moving or resizing a fullscreen container | ||
435 | if (container_is_fullscreen_or_child(cont)) { | ||
436 | seat_pointer_notify_button(seat, time_msec, button, state); | ||
437 | return; | ||
438 | } | ||
439 | struct sway_container *floater = cont; | ||
440 | while (floater->parent->layout != L_FLOATING) { | ||
441 | floater = floater->parent; | ||
442 | } | ||
443 | |||
444 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); | ||
445 | bool mod_pressed = keyboard && | ||
446 | (wlr_keyboard_get_modifiers(keyboard) & config->floating_mod); | ||
447 | enum wlr_edges edge = find_resize_edge(floater, cursor); | ||
448 | bool over_title = edge == WLR_EDGE_NONE && !surface; | ||
449 | |||
450 | // Check for beginning move | ||
451 | uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; | ||
452 | if (button == btn_move && state == WLR_BUTTON_PRESSED && | ||
453 | (mod_pressed || over_title)) { | ||
454 | seat_begin_move(seat, floater, button); | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | // Check for beginning resize | ||
459 | bool resizing_via_border = button == BTN_LEFT && edge != WLR_EDGE_NONE; | ||
460 | uint32_t btn_resize = config->floating_mod_inverse ? BTN_LEFT : BTN_RIGHT; | ||
461 | bool resizing_via_mod = button == btn_resize && mod_pressed; | ||
462 | if ((resizing_via_border || resizing_via_mod) && | ||
463 | state == WLR_BUTTON_PRESSED) { | ||
464 | if (edge == WLR_EDGE_NONE) { | ||
465 | edge |= cursor->cursor->x > floater->x + floater->width / 2 ? | ||
466 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; | ||
467 | edge |= cursor->cursor->y > floater->y + floater->height / 2 ? | ||
468 | WLR_EDGE_BOTTOM : WLR_EDGE_TOP; | ||
469 | } | ||
470 | seat_begin_resize(seat, floater, button, edge); | ||
471 | return; | ||
472 | } | ||
473 | |||
474 | seat_pointer_notify_button(seat, time_msec, button, state); | ||
475 | } | ||
476 | |||
477 | /** | 528 | /** |
478 | * Remove a button (and duplicates) to the sorted list of currently pressed buttons | 529 | * Remove a button (and duplicates) to the sorted list of currently pressed buttons |
479 | */ | 530 | */ |
@@ -553,26 +604,36 @@ static struct sway_binding* get_active_mouse_binding(const struct sway_cursor *c | |||
553 | 604 | ||
554 | void dispatch_cursor_button(struct sway_cursor *cursor, | 605 | void dispatch_cursor_button(struct sway_cursor *cursor, |
555 | uint32_t time_msec, uint32_t button, enum wlr_button_state state) { | 606 | uint32_t time_msec, uint32_t button, enum wlr_button_state state) { |
607 | if (time_msec == 0) { | ||
608 | time_msec = get_current_time_msec(); | ||
609 | } | ||
610 | struct sway_seat *seat = cursor->seat; | ||
611 | |||
612 | // Handle ending seat operation | ||
556 | if (cursor->seat->operation != OP_NONE && | 613 | if (cursor->seat->operation != OP_NONE && |
557 | button == cursor->seat->op_button && state == WLR_BUTTON_RELEASED) { | 614 | button == cursor->seat->op_button && state == WLR_BUTTON_RELEASED) { |
558 | seat_end_mouse_operation(cursor->seat); | 615 | seat_end_mouse_operation(seat); |
559 | seat_pointer_notify_button(cursor->seat, time_msec, button, state); | 616 | seat_pointer_notify_button(seat, time_msec, button, state); |
560 | return; | 617 | return; |
561 | } | 618 | } |
562 | if (time_msec == 0) { | ||
563 | time_msec = get_current_time_msec(); | ||
564 | } | ||
565 | 619 | ||
620 | // Determine what's under the cursor | ||
566 | struct wlr_surface *surface = NULL; | 621 | struct wlr_surface *surface = NULL; |
567 | double sx, sy; | 622 | double sx, sy; |
568 | struct sway_container *cont = container_at_coords(cursor->seat, | 623 | struct sway_container *cont = container_at_coords(seat, |
569 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | 624 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); |
625 | bool is_floating = cont && container_is_floating(cont); | ||
626 | bool is_floating_or_child = cont && container_is_floating_or_child(cont); | ||
627 | bool is_fullscreen_or_child = cont && container_is_fullscreen_or_child(cont); | ||
628 | enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE; | ||
629 | enum wlr_edges resize_edge = edge ? | ||
630 | find_resize_edge(cont, cursor) : WLR_EDGE_NONE; | ||
631 | bool on_border = edge != WLR_EDGE_NONE; | ||
632 | bool on_contents = cont && !on_border && surface; | ||
633 | bool on_titlebar = cont && !on_border && !surface; | ||
570 | 634 | ||
571 | // Handle mouse bindings | 635 | // Handle mouse bindings |
572 | bool on_border = cont && (find_resize_edge(cont, cursor) != WLR_EDGE_NONE); | 636 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); |
573 | bool on_contents = !on_border && surface; | ||
574 | bool on_titlebar = !on_border && !surface; | ||
575 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat); | ||
576 | uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; | 637 | uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; |
577 | 638 | ||
578 | struct sway_binding *binding = NULL; | 639 | struct sway_binding *binding = NULL; |
@@ -588,45 +649,108 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
588 | state_erase_button(cursor, button); | 649 | state_erase_button(cursor, button); |
589 | } | 650 | } |
590 | if (binding) { | 651 | if (binding) { |
591 | seat_execute_command(cursor->seat, binding); | 652 | seat_execute_command(seat, binding); |
592 | // TODO: do we want to pass on the event? | 653 | return; |
593 | } | 654 | } |
594 | 655 | ||
656 | // Handle clicking a layer surface | ||
595 | if (surface && wlr_surface_is_layer_surface(surface)) { | 657 | if (surface && wlr_surface_is_layer_surface(surface)) { |
596 | struct wlr_layer_surface *layer = | 658 | struct wlr_layer_surface *layer = |
597 | wlr_layer_surface_from_wlr_surface(surface); | 659 | wlr_layer_surface_from_wlr_surface(surface); |
598 | if (layer->current.keyboard_interactive) { | 660 | if (layer->current.keyboard_interactive) { |
599 | seat_set_focus_layer(cursor->seat, layer); | 661 | seat_set_focus_layer(seat, layer); |
662 | } | ||
663 | seat_pointer_notify_button(seat, time_msec, button, state); | ||
664 | return; | ||
665 | } | ||
666 | |||
667 | // Handle tiling resize via border | ||
668 | if (resize_edge && button == BTN_LEFT && state == WLR_BUTTON_PRESSED && | ||
669 | !is_floating) { | ||
670 | seat_set_focus(seat, cont); | ||
671 | seat_begin_resize_tiling(seat, cont, button, edge); | ||
672 | return; | ||
673 | } | ||
674 | |||
675 | // Handle tiling resize via mod | ||
676 | bool mod_pressed = keyboard && | ||
677 | (wlr_keyboard_get_modifiers(keyboard) & config->floating_mod); | ||
678 | if (!is_floating_or_child && mod_pressed && state == WLR_BUTTON_PRESSED) { | ||
679 | uint32_t btn_resize = config->floating_mod_inverse ? | ||
680 | BTN_LEFT : BTN_RIGHT; | ||
681 | if (button == btn_resize) { | ||
682 | edge = 0; | ||
683 | edge |= cursor->cursor->x > cont->x + cont->width / 2 ? | ||
684 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; | ||
685 | edge |= cursor->cursor->y > cont->y + cont->height / 2 ? | ||
686 | WLR_EDGE_BOTTOM : WLR_EDGE_TOP; | ||
687 | |||
688 | const char *image = NULL; | ||
689 | if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) { | ||
690 | image = "nw-resize"; | ||
691 | } else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) { | ||
692 | image = "ne-resize"; | ||
693 | } else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) { | ||
694 | image = "se-resize"; | ||
695 | } else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) { | ||
696 | image = "sw-resize"; | ||
697 | } | ||
698 | cursor_set_image(seat->cursor, image, NULL); | ||
699 | seat_set_focus(seat, cont); | ||
700 | seat_begin_resize_tiling(seat, cont, button, edge); | ||
701 | return; | ||
600 | } | 702 | } |
601 | seat_pointer_notify_button(cursor->seat, time_msec, button, state); | 703 | } |
602 | } else if (cont && container_is_floating_or_child(cont)) { | 704 | |
603 | dispatch_cursor_button_floating(cursor, time_msec, button, state, | 705 | // Handle beginning floating move |
604 | surface, sx, sy, cont); | 706 | if (is_floating_or_child && !is_fullscreen_or_child && |
605 | } else if (surface && cont && cont->type != C_VIEW) { | 707 | state == WLR_BUTTON_PRESSED) { |
606 | // Avoid moving keyboard focus from a surface that accepts it to one | 708 | uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; |
607 | // that does not unless the change would move us to a new workspace. | 709 | if (button == btn_move && state == WLR_BUTTON_PRESSED && |
608 | // | 710 | (mod_pressed || on_titlebar)) { |
609 | // This prevents, for example, losing focus when clicking on swaybar. | 711 | while (cont->parent->layout != L_FLOATING) { |
610 | struct sway_container *new_ws = cont; | 712 | cont = cont->parent; |
611 | if (new_ws && new_ws->type != C_WORKSPACE) { | 713 | } |
612 | new_ws = container_parent(new_ws, C_WORKSPACE); | 714 | seat_begin_move(seat, cont, button); |
715 | return; | ||
613 | } | 716 | } |
614 | struct sway_container *old_ws = seat_get_focus(cursor->seat); | 717 | } |
615 | if (old_ws && old_ws->type != C_WORKSPACE) { | 718 | |
616 | old_ws = container_parent(old_ws, C_WORKSPACE); | 719 | // Handle beginning floating resize |
720 | if (is_floating_or_child && !is_fullscreen_or_child && | ||
721 | state == WLR_BUTTON_PRESSED) { | ||
722 | // Via border | ||
723 | if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) { | ||
724 | seat_begin_resize_floating(seat, cont, button, resize_edge); | ||
725 | return; | ||
617 | } | 726 | } |
618 | if (new_ws != old_ws) { | 727 | |
619 | seat_set_focus(cursor->seat, cont); | 728 | // Via mod+click |
729 | struct sway_container *floater = cont; | ||
730 | while (floater->parent->layout != L_FLOATING) { | ||
731 | floater = floater->parent; | ||
732 | } | ||
733 | uint32_t btn_resize = config->floating_mod_inverse ? | ||
734 | BTN_LEFT : BTN_RIGHT; | ||
735 | if (button == btn_resize) { | ||
736 | edge = 0; | ||
737 | edge |= cursor->cursor->x > floater->x + floater->width / 2 ? | ||
738 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; | ||
739 | edge |= cursor->cursor->y > floater->y + floater->height / 2 ? | ||
740 | WLR_EDGE_BOTTOM : WLR_EDGE_TOP; | ||
741 | seat_begin_resize_floating(seat, floater, button, edge); | ||
742 | return; | ||
620 | } | 743 | } |
621 | seat_pointer_notify_button(cursor->seat, time_msec, button, state); | ||
622 | } else if (cont) { | ||
623 | seat_set_focus(cursor->seat, cont); | ||
624 | seat_pointer_notify_button(cursor->seat, time_msec, button, state); | ||
625 | } else { | ||
626 | seat_pointer_notify_button(cursor->seat, time_msec, button, state); | ||
627 | } | 744 | } |
628 | 745 | ||
629 | transaction_commit_dirty(); | 746 | // Handle clicking a container surface |
747 | if (cont) { | ||
748 | seat_set_focus(seat, cont); | ||
749 | seat_pointer_notify_button(seat, time_msec, button, state); | ||
750 | return; | ||
751 | } | ||
752 | |||
753 | seat_pointer_notify_button(seat, time_msec, button, state); | ||
630 | } | 754 | } |
631 | 755 | ||
632 | static void handle_cursor_button(struct wl_listener *listener, void *data) { | 756 | static void handle_cursor_button(struct wl_listener *listener, void *data) { |
@@ -635,6 +759,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
635 | struct wlr_event_pointer_button *event = data; | 759 | struct wlr_event_pointer_button *event = data; |
636 | dispatch_cursor_button(cursor, | 760 | dispatch_cursor_button(cursor, |
637 | event->time_msec, event->button, event->state); | 761 | event->time_msec, event->button, event->state); |
762 | transaction_commit_dirty(); | ||
638 | } | 763 | } |
639 | 764 | ||
640 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { | 765 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { |
@@ -782,6 +907,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
782 | dispatch_cursor_button(cursor, event->time_msec, | 907 | dispatch_cursor_button(cursor, event->time_msec, |
783 | BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ? | 908 | BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ? |
784 | WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED); | 909 | WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED); |
910 | transaction_commit_dirty(); | ||
785 | } | 911 | } |
786 | 912 | ||
787 | static void handle_tool_button(struct wl_listener *listener, void *data) { | 913 | static void handle_tool_button(struct wl_listener *listener, void *data) { |
@@ -806,6 +932,7 @@ static void handle_tool_button(struct wl_listener *listener, void *data) { | |||
806 | cursor->tool_buttons--; | 932 | cursor->tool_buttons--; |
807 | break; | 933 | break; |
808 | } | 934 | } |
935 | transaction_commit_dirty(); | ||
809 | } | 936 | } |
810 | 937 | ||
811 | static void handle_request_set_cursor(struct wl_listener *listener, | 938 | static void handle_request_set_cursor(struct wl_listener *listener, |