diff options
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r-- | sway/input/cursor.c | 680 |
1 files changed, 45 insertions, 635 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 011b4929..61084447 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -158,132 +158,9 @@ struct sway_node *node_at_coords( return &ws->node; } -/** - * Determine if the edge of the given container is on the edge of the - * workspace/output. - */ -static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) { - enum sway_container_layout layout = L_NONE; - switch (edge) { - case WLR_EDGE_TOP: - case WLR_EDGE_BOTTOM: - layout = L_VERT; - break; - case WLR_EDGE_LEFT: - case WLR_EDGE_RIGHT: - layout = L_HORIZ; - break; - case WLR_EDGE_NONE: - sway_assert(false, "Never reached"); - return false; - } - - // Iterate the parents until we find one with the layout we want, - // then check if the child has siblings between it and the edge. - while (cont) { - if (container_parent_layout(cont) == layout) { - list_t *siblings = container_get_siblings(cont); - int index = list_find(siblings, cont); - if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) { - return false; - } - if (index < siblings->length - 1 && - (edge == WLR_EDGE_RIGHT || edge == WLR_EDGE_BOTTOM)) { - return false; - } - } - cont = cont->parent; - } - return true; -} - -static enum wlr_edges find_edge(struct sway_container *cont, - struct sway_cursor *cursor) { - if (!cont->view) { - return WLR_EDGE_NONE; - } - if (cont->border == B_NONE || !cont->border_thickness || - cont->border == B_CSD) { - return WLR_EDGE_NONE; - } - - enum wlr_edges edge = 0; - if (cursor->cursor->x < cont->x + cont->border_thickness) { - edge |= WLR_EDGE_LEFT; - } - if (cursor->cursor->y < cont->y + cont->border_thickness) { - edge |= WLR_EDGE_TOP; - } - if (cursor->cursor->x >= cont->x + cont->width - cont->border_thickness) { - edge |= WLR_EDGE_RIGHT; - } - if (cursor->cursor->y >= cont->y + cont->height - cont->border_thickness) { - edge |= WLR_EDGE_BOTTOM; - } - - return edge; -} - -/** - * If the cursor is over a _resizable_ edge, return the edge. - * Edges that can't be resized are edges of the workspace. - */ -static enum wlr_edges find_resize_edge(struct sway_container *cont, - struct sway_cursor *cursor) { - enum wlr_edges edge = find_edge(cont, cursor); - if (edge && !container_is_floating(cont) && edge_is_external(cont, edge)) { - return WLR_EDGE_NONE; - } - return edge; -} - -static void cursor_do_rebase(struct sway_cursor *cursor, uint32_t time_msec, - struct sway_node *node, struct wlr_surface *surface, - double sx, double sy) { - // Handle cursor image - if (surface) { - // Reset cursor if switching between clients - struct wl_client *client = wl_resource_get_client(surface->resource); - if (client != cursor->image_client) { - cursor_set_image(cursor, "left_ptr", client); - } - } else if (node && node->type == N_CONTAINER) { - // Try a node's resize edge - enum wlr_edges edge = find_resize_edge(node->sway_container, cursor); - if (edge == WLR_EDGE_NONE) { - cursor_set_image(cursor, "left_ptr", NULL); - } else if (container_is_floating(node->sway_container)) { - cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); - } else { - if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) { - cursor_set_image(cursor, "col-resize", NULL); - } else { - cursor_set_image(cursor, "row-resize", NULL); - } - } - } else { - cursor_set_image(cursor, "left_ptr", NULL); - } - - // Send pointer enter/leave - struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; - if (surface) { - if (seat_is_input_allowed(cursor->seat, surface)) { - wlr_seat_pointer_notify_enter(wlr_seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(wlr_seat, time_msec, sx, sy); - } - } else { - wlr_seat_pointer_clear_focus(wlr_seat); - } -} - void cursor_rebase(struct sway_cursor *cursor) { uint32_t time_msec = get_current_time_msec(); - struct wlr_surface *surface = NULL; - double sx = 0.0, sy = 0.0; - cursor->previous.node = node_at_coords(cursor->seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); - cursor_do_rebase(cursor, time_msec, cursor->previous.node, surface, sx, sy); + seatop_rebase(cursor->seat, time_msec); } void cursor_rebase_all(void) { @@ -293,9 +170,7 @@ void cursor_rebase_all(void) { struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { - if (!seat_doing_seatop(seat)) { - cursor_rebase(seat->cursor); - } + cursor_rebase(seat->cursor); } } @@ -345,90 +220,17 @@ void cursor_unhide(struct sway_cursor *cursor) { cursor_rebase(cursor); } -void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, - struct sway_node *node, struct wlr_surface *surface, - double sx, double sy) { - if (time_msec == 0) { - time_msec = get_current_time_msec(); - } - - struct sway_seat *seat = cursor->seat; - - if (seat_doing_seatop(seat)) { - seatop_motion(seat, time_msec); - cursor->previous.x = cursor->cursor->x; - cursor->previous.y = cursor->cursor->y; - return; - } - - struct sway_node *prev_node = cursor->previous.node; - - // Update the stored previous position - cursor->previous.x = cursor->cursor->x; - cursor->previous.y = cursor->cursor->y; - cursor->previous.node = node; - - if (node && (config->focus_follows_mouse == FOLLOWS_YES || - config->focus_follows_mouse == FOLLOWS_ALWAYS)) { - struct sway_node *focus = seat_get_focus(seat); - if (focus && node->type == N_WORKSPACE) { - // Only follow the mouse if it would move to a new output - // Otherwise we'll focus the workspace, which is probably wrong - struct sway_output *focused_output = node_get_output(focus); - struct sway_output *output = node_get_output(node); - if (output != focused_output) { - seat_set_focus(seat, seat_get_focus_inactive(seat, node)); - } - } else if (node->type == N_CONTAINER && node->sway_container->view) { - // Focus node if the following are true: - // - cursor is over a new view, i.e. entered a new window; and - // - the new view is visible, i.e. not hidden in a stack or tab; and - // - the seat does not have a keyboard grab - if ((!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) && - node != prev_node && - view_is_visible(node->sway_container->view)) || - config->focus_follows_mouse == FOLLOWS_ALWAYS) { - seat_set_focus(seat, node); - } else { - struct sway_node *next_focus = - seat_get_focus_inactive(seat, &root->node); - if (next_focus && next_focus->type == N_CONTAINER && - next_focus->sway_container->view && - view_is_visible(next_focus->sway_container->view)) { - seat_set_focus(seat, next_focus); - } - } - } - } - - cursor_do_rebase(cursor, time_msec, node, surface, sx, sy); - - struct sway_drag_icon *drag_icon; - wl_list_for_each(drag_icon, &root->drag_icons, link) { - if (drag_icon->seat == seat) { - drag_icon_update_position(drag_icon); - } - } -} - -static void handle_cursor_motion(struct wl_listener *listener, void *data) { - struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); - struct wlr_event_pointer_motion *event = data; +static void cursor_motion(struct sway_cursor *cursor, uint32_t time_msec, + struct wlr_input_device *device, double dx, double dy, + double dx_unaccel, double dy_unaccel) { cursor_handle_activity(cursor); - double dx = event->delta_x; - double dy = event->delta_y; - - double dx_unaccel = event->unaccel_dx; - double dy_unaccel = event->unaccel_dy; - wlr_relative_pointer_manager_v1_send_relative_motion( server.relative_pointer_manager, - cursor->seat->wlr_seat, (uint64_t)event->time_msec * 1000, + cursor->seat->wlr_seat, (uint64_t)time_msec * 1000, dx, dy, dx_unaccel, dy_unaccel); struct wlr_surface *surface = NULL; - struct sway_node *node = NULL; double sx, sy; if (cursor->active_constraint) { node_at_coords(cursor->seat, @@ -448,50 +250,18 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { dy = sy_confined - sy; } - wlr_cursor_move(cursor->cursor, event->device, dx, dy); - - // Recalculate pointer location after layout checks - node = node_at_coords(cursor->seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + wlr_cursor_move(cursor->cursor, device, dx, dy); - cursor_send_pointer_motion(cursor, event->time_msec, node, surface, - sx, sy); - transaction_commit_dirty(); + seatop_motion(cursor->seat, time_msec, dx, dy); } -static void cursor_motion_absolute(struct sway_cursor *cursor, - uint32_t time_msec, struct wlr_input_device *dev, - double x, double y) { - cursor_handle_activity(cursor); - - double lx, ly; - wlr_cursor_absolute_to_layout_coords(cursor->cursor, dev, - x, y, &lx, &ly); - - double dx = lx - cursor->cursor->x; - double dy = ly - cursor->cursor->y; - wlr_relative_pointer_manager_v1_send_relative_motion( - server.relative_pointer_manager, - cursor->seat->wlr_seat, (uint64_t)time_msec * 1000, - dx, dy, dx, dy); - - struct wlr_surface *surface = NULL; - double sx = 0.0, sy = 0.0; - struct sway_node *node = node_at_coords(cursor->seat, - lx, ly, &surface, &sx, &sy); - - if (cursor->active_constraint) { - if (cursor->active_constraint->surface != surface) { - return; - } - if (!pixman_region32_contains_point(&cursor->confine, - floor(sx), floor(sy), NULL)) { - return; - } - } +static void handle_cursor_motion_relative( + struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); + struct wlr_event_pointer_motion *e = data; - wlr_cursor_warp_closest(cursor->cursor, dev, lx, ly); - cursor_send_pointer_motion(cursor, time_msec, node, surface, sx, sy); + cursor_motion(cursor, e->time_msec, e->device, e->delta_x, e->delta_y, + e->unaccel_dx, e->unaccel_dy); transaction_commit_dirty(); } @@ -501,98 +271,15 @@ static void handle_cursor_motion_absolute( wl_container_of(listener, cursor, motion_absolute); struct wlr_event_pointer_motion_absolute *event = data; - cursor_motion_absolute(cursor, event->time_msec, event->device, - event->x, event->y); -} - -/** - * Remove a button (and duplicates) to the sorted list of currently pressed buttons - */ -static void state_erase_button(struct sway_cursor *cursor, uint32_t button) { - size_t j = 0; - for (size_t i = 0; i < cursor->pressed_button_count; ++i) { - if (i > j) { - cursor->pressed_buttons[j] = cursor->pressed_buttons[i]; - } - if (cursor->pressed_buttons[i] != button) { - ++j; - } - } - while (cursor->pressed_button_count > j) { - --cursor->pressed_button_count; - cursor->pressed_buttons[cursor->pressed_button_count] = 0; - } -} - -/** - * Add a button to the sorted list of currently pressed buttons, if there - * is space. - */ -static void state_add_button(struct sway_cursor *cursor, uint32_t button) { - if (cursor->pressed_button_count >= SWAY_CURSOR_PRESSED_BUTTONS_CAP) { - return; - } - size_t i = 0; - while (i < cursor->pressed_button_count && cursor->pressed_buttons[i] < button) { - ++i; - } - size_t j = cursor->pressed_button_count; - while (j > i) { - cursor->pressed_buttons[j] = cursor->pressed_buttons[j - 1]; - --j; - } - cursor->pressed_buttons[i] = button; - cursor->pressed_button_count++; -} - -/** - * Return the mouse binding which matches modifier, click location, release, - * and pressed button state, otherwise return null. - */ -static struct sway_binding* get_active_mouse_binding( - const struct sway_cursor *cursor, list_t *bindings, uint32_t modifiers, - bool release, bool on_titlebar, bool on_border, bool on_content, - bool on_workspace, const char *identifier) { - uint32_t click_region = - ((on_titlebar || on_workspace) ? BINDING_TITLEBAR : 0) | - ((on_border || on_workspace) ? BINDING_BORDER : 0) | - ((on_content || on_workspace) ? BINDING_CONTENTS : 0); - - struct sway_binding *current = NULL; - for (int i = 0; i < bindings->length; ++i) { - struct sway_binding *binding = bindings->items[i]; - if (modifiers ^ binding->modifiers || - cursor->pressed_button_count != (size_t)binding->keys->length || - release != (binding->flags & BINDING_RELEASE) || - !(click_region & binding->flags) || - (on_workspace && - (click_region & binding->flags) != click_region) || - (strcmp(binding->input, identifier) != 0 && - strcmp(binding->input, "*") != 0)) { - continue; - } + double lx, ly; + wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, + event->x, event->y, &lx, &ly); - bool match = true; - for (size_t j = 0; j < cursor->pressed_button_count; j++) { - uint32_t key = *(uint32_t *)binding->keys->items[j]; - if (key != cursor->pressed_buttons[j]) { - match = false; - break; - } - } - if (!match) { - continue; - } + double dx = lx - cursor->cursor->x; + double dy = ly - cursor->cursor->y; - if (!current || strcmp(current->input, "*") == 0) { - current = binding; - if (strcmp(current->input, identifier) == 0) { - // If a binding is found for the exact input, quit searching - break; - } - } - } - return current; + cursor_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); + transaction_commit_dirty(); } void dispatch_cursor_button(struct sway_cursor *cursor, @@ -601,318 +288,33 @@ void dispatch_cursor_button(struct sway_cursor *cursor, if (time_msec == 0) { time_msec = get_current_time_msec(); } - struct sway_seat *seat = cursor->seat; - // Handle existing seat operation - if (seat_doing_seatop(seat)) { - if (state == WLR_BUTTON_PRESSED) { - state_add_button(cursor, button); - } else { - state_erase_button(cursor, button); - } - seatop_button(seat, time_msec, device, button, state); - if (button == seat->seatop_button && state == WLR_BUTTON_RELEASED) { - seatop_finish(seat, time_msec); - } - return; - } - - // Determine what's under the cursor - struct wlr_surface *surface = NULL; - double sx, sy; - struct sway_node *node = node_at_coords(seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); - struct sway_container *cont = node && node->type == N_CONTAINER ? - node->sway_container : NULL; - bool is_floating = cont && container_is_floating(cont); - bool is_floating_or_child = cont && container_is_floating_or_child(cont); - bool is_fullscreen_or_child = cont && container_is_fullscreen_or_child(cont); - enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE; - enum wlr_edges resize_edge = edge ? - find_resize_edge(cont, cursor) : WLR_EDGE_NONE; - bool on_border = edge != WLR_EDGE_NONE; - bool on_contents = cont && !on_border && surface; - bool on_workspace = node && node->type == N_WORKSPACE; - bool on_titlebar = cont && !on_border && !surface; - - // Handle mouse bindings - struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); - uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; - - char *device_identifier = device ? input_device_get_identifier(device) - : strdup("*"); - struct sway_binding *binding = NULL; - if (state == WLR_BUTTON_PRESSED) { - state_add_button(cursor, button); - binding = get_active_mouse_binding(cursor, - config->current_mode->mouse_bindings, modifiers, false, - on_titlebar, on_border, on_contents, on_workspace, - device_identifier); - } else { - binding = get_active_mouse_binding(cursor, - config->current_mode->mouse_bindings, modifiers, true, - on_titlebar, on_border, on_contents, on_workspace, - device_identifier); - state_erase_button(cursor, button); - } - free(device_identifier); - if (binding) { - seat_execute_command(seat, binding); - return; - } - - // Handle clicking an empty workspace - if (node && node->type == N_WORKSPACE) { - seat_set_focus(seat, node); - return; - } - - // Handle clicking a layer surface - if (surface && wlr_surface_is_layer_surface(surface)) { - struct wlr_layer_surface_v1 *layer = - wlr_layer_surface_v1_from_wlr_surface(surface); - if (layer->current.keyboard_interactive) { - seat_set_focus_layer(seat, layer); - } - seat_pointer_notify_button(seat, time_msec, button, state); - return; - } - - // Handle tiling resize via border - if (cont && resize_edge && button == BTN_LEFT && - state == WLR_BUTTON_PRESSED && !is_floating) { - seat_set_focus_container(seat, cont); - seatop_begin_resize_tiling(seat, cont, button, edge); - return; - } - - // Handle tiling resize via mod - bool mod_pressed = keyboard && - (wlr_keyboard_get_modifiers(keyboard) & config->floating_mod); - if (cont && !is_floating_or_child && mod_pressed && - state == WLR_BUTTON_PRESSED) { - uint32_t btn_resize = config->floating_mod_inverse ? - BTN_LEFT : BTN_RIGHT; - if (button == btn_resize) { - edge = 0; - edge |= cursor->cursor->x > cont->x + cont->width / 2 ? - WLR_EDGE_RIGHT : WLR_EDGE_LEFT; - edge |= cursor->cursor->y > cont->y + cont->height / 2 ? - WLR_EDGE_BOTTOM : WLR_EDGE_TOP; - - const char *image = NULL; - if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) { - image = "nw-resize"; - } else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) { - image = "ne-resize"; - } else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) { - image = "se-resize"; - } else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) { - image = "sw-resize"; - } - cursor_set_image(seat->cursor, image, NULL); - seat_set_focus_container(seat, cont); - seatop_begin_resize_tiling(seat, cont, button, edge); - return; - } - } - - // Handle beginning floating move - if (cont && is_floating_or_child && !is_fullscreen_or_child && - state == WLR_BUTTON_PRESSED) { - uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; - if (button == btn_move && state == WLR_BUTTON_PRESSED && - (mod_pressed || on_titlebar)) { - while (cont->parent) { - cont = cont->parent; - } - seat_set_focus_container(seat, cont); - seatop_begin_move_floating(seat, cont, button); - return; - } - } - - // Handle beginning floating resize - if (cont && is_floating_or_child && !is_fullscreen_or_child && - state == WLR_BUTTON_PRESSED) { - // Via border - if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) { - seatop_begin_resize_floating(seat, cont, button, resize_edge); - return; - } - - // Via mod+click - uint32_t btn_resize = config->floating_mod_inverse ? - BTN_LEFT : BTN_RIGHT; - if (mod_pressed && button == btn_resize) { - struct sway_container *floater = cont; - while (floater->parent) { - floater = floater->parent; - } - edge = 0; - edge |= cursor->cursor->x > floater->x + floater->width / 2 ? - WLR_EDGE_RIGHT : WLR_EDGE_LEFT; - edge |= cursor->cursor->y > floater->y + floater->height / 2 ? - WLR_EDGE_BOTTOM : WLR_EDGE_TOP; - seatop_begin_resize_floating(seat, floater, button, edge); - return; - } - } - - // Handle moving a tiling container - if (config->tiling_drag && (mod_pressed || on_titlebar) && - state == WLR_BUTTON_PRESSED && !is_floating_or_child && - cont && cont->fullscreen_mode == FULLSCREEN_NONE) { - struct sway_container *focus = seat_get_focused_container(seat); - bool focused = focus == cont || container_has_ancestor(focus, cont); - if (on_titlebar && !focused) { - node = seat_get_focus_inactive(seat, &cont->node); - seat_set_focus(seat, node); - } - - // If moving a container by it's title bar, use a threshold for the drag - if (!mod_pressed && config->tiling_drag_threshold > 0) { - seatop_begin_move_tiling_threshold(seat, cont, button); - } else { - seatop_begin_move_tiling(seat, cont, button); - } - return; - } - - // Handle mousedown on a container surface - if (surface && cont && state == WLR_BUTTON_PRESSED) { - seat_set_focus_container(seat, cont); - seatop_begin_down(seat, cont, time_msec, button, sx, sy); - seat_pointer_notify_button(seat, time_msec, button, WLR_BUTTON_PRESSED); - return; - } - - // Handle clicking a container surface or decorations - if (cont) { - node = seat_get_focus_inactive(seat, &cont->node); - seat_set_focus(seat, node); - seat_pointer_notify_button(seat, time_msec, button, state); - return; - } - - seat_pointer_notify_button(seat, time_msec, button, state); + seatop_button(cursor->seat, time_msec, device, button, state); } static void handle_cursor_button(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, button); struct wlr_event_pointer_button *event = data; cursor_handle_activity(cursor); + + if (event->state == WLR_BUTTON_PRESSED) { + cursor->pressed_button_count++; + } else { + if (cursor->pressed_button_count > 0) { + cursor->pressed_button_count--; + } else { + sway_log(SWAY_ERROR, "Pressed button count was wrong"); + } + } + dispatch_cursor_button(cursor, event->device, event->time_msec, event->button, event->state); transaction_commit_dirty(); } -static uint32_t wl_axis_to_button(struct wlr_event_pointer_axis *event) { - switch (event->orientation) { - case WLR_AXIS_ORIENTATION_VERTICAL: - return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN; - case WLR_AXIS_ORIENTATION_HORIZONTAL: - return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT; - default: - sway_log(SWAY_DEBUG, "Unknown axis orientation"); - return 0; - } -} - void dispatch_cursor_axis(struct sway_cursor *cursor, struct wlr_event_pointer_axis *event) { - struct sway_seat *seat = cursor->seat; - struct sway_input_device *input_device = - event->device ? event->device->data : NULL; - struct input_config *ic = - input_device ? input_device_get_config(input_device) : NULL; - - // Determine what's under the cursor - struct wlr_surface *surface = NULL; - double sx, sy; - struct sway_node *node = node_at_coords(seat, - cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); - struct sway_container *cont = node && node->type == N_CONTAINER ? - node->sway_container : NULL; - enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE; - bool on_border = edge != WLR_EDGE_NONE; - bool on_titlebar = cont && !on_border && !surface; - bool on_titlebar_border = cont && on_border && - cursor->cursor->y < cont->content_y; - bool on_contents = cont && !on_border && surface; - bool on_workspace = node && node->type == N_WORKSPACE; - float scroll_factor = - (ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor; - - bool handled = false; - - // Gather information needed for mouse bindings - struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); - uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; - struct wlr_input_device *device = - input_device ? input_device->wlr_device : NULL; - char *dev_id = device ? input_device_get_identifier(device) : strdup("*"); - uint32_t button = wl_axis_to_button(event); - - // Handle mouse bindings - x11 mouse buttons 4-7 - press event - struct sway_binding *binding = NULL; - state_add_button(cursor, button); - binding = get_active_mouse_binding(cursor, - config->current_mode->mouse_bindings, modifiers, false, - on_titlebar, on_border, on_contents, on_workspace, dev_id); - if (binding) { - seat_execute_command(seat, binding); - handled = true; - } - - // Scrolling on a tabbed or stacked title bar (handled as press event) - if (!handled && (on_titlebar || on_titlebar_border)) { - enum sway_container_layout layout = container_parent_layout(cont); - if (layout == L_TABBED || layout == L_STACKED) { - struct sway_node *tabcontainer = node_get_parent(node); - struct sway_node *active = - seat_get_active_tiling_child(seat, tabcontainer); - list_t *siblings = container_get_siblings(cont); - int desired = list_find(siblings, active->sway_container) + - round(scroll_factor * event->delta_discrete); - if (desired < 0) { - desired = 0; - } else if (desired >= siblings->length) { - desired = siblings->length - 1; - } - struct sway_node *old_focus = seat_get_focus(seat); - struct sway_container *new_sibling_con = siblings->items[desired]; - struct sway_node *new_sibling = &new_sibling_con->node; - struct sway_node *new_focus = - seat_get_focus_inactive(seat, new_sibling); - if (node_has_ancestor(old_focus, tabcontainer)) { - seat_set_focus(seat, new_focus); - } else { - // Scrolling when focus is not in the tabbed container at all - seat_set_raw_focus(seat, new_sibling); - seat_set_raw_focus(seat, new_focus); - seat_set_raw_focus(seat, old_focus); - } - handled = true; - } - } - - // Handle mouse bindings - x11 mouse buttons 4-7 - release event - binding = get_active_mouse_binding(cursor, - config->current_mode->mouse_bindings, modifiers, true, - on_titlebar, on_border, on_contents, on_workspace, dev_id); - state_erase_button(cursor, button); - if (binding) { - seat_execute_command(seat, binding); - handled = true; - } - free(dev_id); - - if (!handled) { - wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, - event->orientation, scroll_factor * event->delta, - round(scroll_factor * event->delta_discrete), event->source); - } + seatop_axis(cursor->seat, event); } static void handle_cursor_axis(struct wl_listener *listener, void *data) { @@ -1054,8 +456,16 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { apply_mapping_from_region(event->device, ic->mapped_from_region, &x, &y); } - cursor_motion_absolute(cursor, event->time_msec, event->device, x, y); + double lx, ly; + wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, + x, y, &lx, &ly); + + double dx = lx - cursor->cursor->x; + double dy = ly - cursor->cursor->y; + + cursor_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); + transaction_commit_dirty(); } static void handle_tool_tip(struct wl_listener *listener, void *data) { @@ -1142,7 +552,7 @@ static void handle_request_set_cursor(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, request_set_cursor); - if (seat_doing_seatop(cursor->seat)) { + if (!seatop_allows_set_cursor(cursor->seat)) { return; } struct wlr_seat_pointer_request_set_cursor_event *event = data; @@ -1257,7 +667,7 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { // input events wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); - cursor->motion.notify = handle_cursor_motion; + cursor->motion.notify = handle_cursor_motion_relative; wl_signal_add(&wlr_cursor->events.motion_absolute, &cursor->motion_absolute); |