diff options
Diffstat (limited to 'sway/input')
-rw-r--r-- | sway/input/cursor.c | 295 | ||||
-rw-r--r-- | sway/input/input-manager.c | 56 | ||||
-rw-r--r-- | sway/input/keyboard.c | 13 | ||||
-rw-r--r-- | sway/input/seat.c | 159 |
4 files changed, 444 insertions, 79 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 944e35aa..65d04cac 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -5,14 +5,19 @@ #elif __FreeBSD__ #include <dev/evdev/input-event-codes.h> #endif +#include <limits.h> #include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_idle.h> #include "list.h" #include "log.h" +#include "sway/desktop.h" +#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" +#include "sway/input/keyboard.h" #include "sway/layers.h" #include "sway/output.h" +#include "sway/tree/arrange.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" #include "wlr-layer-shell-unstable-v1-protocol.h" @@ -126,7 +131,7 @@ static struct sway_container *container_at_coords( return ws; } - c = seat_get_focus_inactive(seat, output->swayc); + c = seat_get_active_child(seat, output->swayc); if (c) { return c; } @@ -138,6 +143,171 @@ static struct sway_container *container_at_coords( return output->swayc; } +static enum wlr_edges find_resize_edge(struct sway_container *cont, + struct sway_cursor *cursor) { + if (cont->type != C_VIEW) { + return WLR_EDGE_NONE; + } + struct sway_view *view = cont->sway_view; + if (view->border == B_NONE || !view->border_thickness || view->using_csd) { + return WLR_EDGE_NONE; + } + + enum wlr_edges edge = 0; + if (cursor->cursor->x < cont->x + view->border_thickness) { + edge |= WLR_EDGE_LEFT; + } + if (cursor->cursor->y < cont->y + view->border_thickness) { + edge |= WLR_EDGE_TOP; + } + if (cursor->cursor->x >= cont->x + cont->width - view->border_thickness) { + edge |= WLR_EDGE_RIGHT; + } + if (cursor->cursor->y >= cont->y + cont->height - view->border_thickness) { + edge |= WLR_EDGE_BOTTOM; + } + return edge; +} + +static void handle_move_motion(struct sway_seat *seat, + struct sway_cursor *cursor) { + struct sway_container *con = seat->op_container; + desktop_damage_whole_container(con); + container_floating_translate(con, + cursor->cursor->x - cursor->previous.x, + cursor->cursor->y - cursor->previous.y); + desktop_damage_whole_container(con); +} + +static void calculate_floating_constraints(struct sway_container *con, + int *min_width, int *max_width, int *min_height, int *max_height) { + if (config->floating_minimum_width == -1) { // no minimum + *min_width = 0; + } else if (config->floating_minimum_width == 0) { // automatic + *min_width = 75; + } else { + *min_width = config->floating_minimum_width; + } + + if (config->floating_minimum_height == -1) { // no minimum + *min_height = 0; + } else if (config->floating_minimum_height == 0) { // automatic + *min_height = 50; + } else { + *min_height = config->floating_minimum_height; + } + + if (config->floating_maximum_width == -1) { // no maximum + *max_width = INT_MAX; + } else if (config->floating_maximum_width == 0) { // automatic + struct sway_container *ws = container_parent(con, C_WORKSPACE); + *max_width = ws->width; + } else { + *max_width = config->floating_maximum_width; + } + + if (config->floating_maximum_height == -1) { // no maximum + *max_height = INT_MAX; + } else if (config->floating_maximum_height == 0) { // automatic + struct sway_container *ws = container_parent(con, C_WORKSPACE); + *max_height = ws->height; + } else { + *max_height = config->floating_maximum_height; + } +} + +static void handle_resize_motion(struct sway_seat *seat, + struct sway_cursor *cursor) { + struct sway_container *con = seat->op_container; + enum wlr_edges edge = seat->op_resize_edge; + + // The amount the mouse has moved since the start of the resize operation + // Positive is down/right + double mouse_move_x = cursor->cursor->x - seat->op_ref_lx; + double mouse_move_y = cursor->cursor->y - seat->op_ref_ly; + + if (edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM) { + mouse_move_x = 0; + } + if (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT) { + mouse_move_y = 0; + } + + double grow_width = edge & WLR_EDGE_LEFT ? -mouse_move_x : mouse_move_x; + double grow_height = edge & WLR_EDGE_TOP ? -mouse_move_y : mouse_move_y; + + if (seat->op_resize_preserve_ratio) { + double x_multiplier = grow_width / seat->op_ref_width; + double y_multiplier = grow_height / seat->op_ref_height; + double max_multiplier = fmax(x_multiplier, y_multiplier); + grow_width = seat->op_ref_width * max_multiplier; + grow_height = seat->op_ref_height * max_multiplier; + } + + // Determine new width/height, and accommodate for floating min/max values + double width = seat->op_ref_width + grow_width; + double height = seat->op_ref_height + grow_height; + int min_width, max_width, min_height, max_height; + calculate_floating_constraints(con, &min_width, &max_width, + &min_height, &max_height); + width = fmax(min_width, fmin(width, max_width)); + height = fmax(min_height, fmin(height, max_height)); + + // Apply the view's min/max size + if (con->type == C_VIEW) { + double view_min_width, view_max_width, view_min_height, view_max_height; + view_get_constraints(con->sway_view, &view_min_width, &view_max_width, + &view_min_height, &view_max_height); + width = fmax(view_min_width, fmin(width, view_max_width)); + height = fmax(view_min_height, fmin(height, view_max_height)); + } + + // Recalculate these, in case we hit a min/max limit + grow_width = width - seat->op_ref_width; + grow_height = height - seat->op_ref_height; + + // Determine grow x/y values - these are relative to the container's x/y at + // the start of the resize operation. + double grow_x = 0, grow_y = 0; + if (edge & WLR_EDGE_LEFT) { + grow_x = -grow_width; + } else if (edge & WLR_EDGE_RIGHT) { + grow_x = 0; + } else { + grow_x = -grow_width / 2; + } + if (edge & WLR_EDGE_TOP) { + grow_y = -grow_height; + } else if (edge & WLR_EDGE_BOTTOM) { + grow_y = 0; + } else { + grow_y = -grow_height / 2; + } + + // Determine the amounts we need to bump everything relative to the current + // size. + int relative_grow_width = width - con->width; + int relative_grow_height = height - con->height; + int relative_grow_x = (seat->op_ref_con_lx + grow_x) - con->x; + int relative_grow_y = (seat->op_ref_con_ly + grow_y) - con->y; + + // Actually resize stuff + con->x += relative_grow_x; + con->y += relative_grow_y; + con->width += relative_grow_width; + con->height += relative_grow_height; + + if (con->type == C_VIEW) { + struct sway_view *view = con->sway_view; + view->x += relative_grow_x; + view->y += relative_grow_y; + view->width += relative_grow_width; + view->height += relative_grow_height; + } + + arrange_windows(con); +} + void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, bool allow_refocusing) { if (time_msec == 0) { @@ -145,6 +315,18 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, } struct sway_seat *seat = cursor->seat; + + if (seat->operation != OP_NONE) { + if (seat->operation == OP_MOVE) { + handle_move_motion(seat, cursor); + } else { + handle_resize_motion(seat, cursor); + } + cursor->previous.x = cursor->cursor->x; + cursor->previous.y = cursor->cursor->y; + return; + } + struct wlr_seat *wlr_seat = seat->wlr_seat; struct wlr_surface *surface = NULL; double sx, sy; @@ -193,15 +375,21 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, } } - // reset cursor if switching between clients - struct wl_client *client = NULL; - if (surface != NULL) { - client = wl_resource_get_client(surface->resource); - } - if (client != cursor->image_client) { - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, - "left_ptr", cursor->cursor); - cursor->image_client = client; + // 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 (c && container_is_floating(c)) { + // Try a floating container's resize edge + enum wlr_edges edge = find_resize_edge(c, cursor); + const char *image = edge == WLR_EDGE_NONE ? + "left_ptr" : wlr_xcursor_get_resize_name(edge); + cursor_set_image(cursor, image, NULL); + } else { + cursor_set_image(cursor, "left_ptr", NULL); } // send pointer enter/leave @@ -228,6 +416,7 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { wlr_cursor_move(cursor->cursor, event->device, event->delta_x, event->delta_y); cursor_send_pointer_motion(cursor, event->time_msec, true); + transaction_commit_dirty(); } static void handle_cursor_motion_absolute( @@ -238,10 +427,56 @@ static void handle_cursor_motion_absolute( struct wlr_event_pointer_motion_absolute *event = data; wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); cursor_send_pointer_motion(cursor, event->time_msec, true); + transaction_commit_dirty(); +} + +static void dispatch_cursor_button_floating(struct sway_cursor *cursor, + uint32_t time_msec, uint32_t button, enum wlr_button_state state, + struct wlr_surface *surface, double sx, double sy, + struct sway_container *cont) { + struct sway_seat *seat = cursor->seat; + + // Deny moving or resizing a fullscreen view + if (cont->type == C_VIEW && cont->sway_view->is_fullscreen) { + seat_pointer_notify_button(seat, time_msec, button, state); + return; + } + + struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); + bool mod_pressed = keyboard && + (wlr_keyboard_get_modifiers(keyboard) & config->floating_mod); + enum wlr_edges edge = find_resize_edge(cont, cursor); + bool over_title = edge == WLR_EDGE_NONE && !surface; + + // Check for beginning move + if (button == BTN_LEFT && state == WLR_BUTTON_PRESSED && + (mod_pressed || over_title)) { + seat_begin_move(seat, cont, BTN_LEFT); + return; + } + + // Check for beginning resize + bool resizing_via_border = button == BTN_LEFT && edge != WLR_EDGE_NONE; + bool resizing_via_mod = button == BTN_RIGHT && mod_pressed; + if ((resizing_via_border || resizing_via_mod) && + state == WLR_BUTTON_PRESSED) { + seat_begin_resize(seat, cont, button, edge); + return; + } + + // Send event to surface + seat_set_focus(seat, cont); + seat_pointer_notify_button(seat, time_msec, button, state); } void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, uint32_t button, enum wlr_button_state state) { + if (cursor->seat->operation != OP_NONE && + button == cursor->seat->op_button && state == WLR_BUTTON_RELEASED) { + seat_end_mouse_operation(cursor->seat); + seat_pointer_notify_button(cursor->seat, time_msec, button, state); + return; + } if (time_msec == 0) { time_msec = get_current_time_msec(); } @@ -255,14 +490,16 @@ void dispatch_cursor_button(struct sway_cursor *cursor, wlr_layer_surface_from_wlr_surface(surface); if (layer->current.keyboard_interactive) { seat_set_focus_layer(cursor->seat, layer); - return; } - } - // Avoid moving keyboard focus from a surface that accepts it to one - // that does not unless the change would move us to a new workspace. - // - // This prevents, for example, losing focus when clicking on swaybar. - if (surface && cont && cont->type != C_VIEW) { + seat_pointer_notify_button(cursor->seat, time_msec, button, state); + } else if (cont && container_is_floating(cont)) { + dispatch_cursor_button_floating(cursor, time_msec, button, state, + surface, sx, sy, cont); + } else if (surface && cont && cont->type != C_VIEW) { + // Avoid moving keyboard focus from a surface that accepts it to one + // that does not unless the change would move us to a new workspace. + // + // This prevents, for example, losing focus when clicking on swaybar. struct sway_container *new_ws = cont; if (new_ws && new_ws->type != C_WORKSPACE) { new_ws = container_parent(new_ws, C_WORKSPACE); @@ -274,12 +511,15 @@ void dispatch_cursor_button(struct sway_cursor *cursor, if (new_ws != old_ws) { seat_set_focus(cursor->seat, cont); } + seat_pointer_notify_button(cursor->seat, time_msec, button, state); } else if (cont) { seat_set_focus(cursor->seat, cont); + seat_pointer_notify_button(cursor->seat, time_msec, button, state); + } else { + seat_pointer_notify_button(cursor->seat, time_msec, button, state); } - wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, - time_msec, button, state); + transaction_commit_dirty(); } static void handle_cursor_button(struct wl_listener *listener, void *data) { @@ -425,6 +665,7 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { wlr_cursor_warp_absolute(cursor->cursor, event->device, x, y); cursor_send_pointer_motion(cursor, event->time_msec, true); + transaction_commit_dirty(); } static void handle_tool_tip(struct wl_listener *listener, void *data) { @@ -464,6 +705,9 @@ 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 (cursor->seat->operation != OP_NONE) { + return; + } struct wlr_seat_pointer_request_set_cursor_event *event = data; struct wl_client *focused_client = NULL; @@ -476,15 +720,26 @@ static void handle_request_set_cursor(struct wl_listener *listener, // TODO: check cursor mode if (focused_client == NULL || event->seat_client->client != focused_client) { - wlr_log(L_DEBUG, "denying request to set cursor from unfocused client"); + wlr_log(WLR_DEBUG, "denying request to set cursor from unfocused client"); return; } wlr_cursor_set_surface(cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y); + cursor->image = NULL; cursor->image_client = focused_client; } +void cursor_set_image(struct sway_cursor *cursor, const char *image, + struct wl_client *client) { + if (!cursor->image || strcmp(cursor->image, image) != 0) { + wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, + cursor->cursor); + cursor->image = image; + } + cursor->image_client = client; +} + void sway_cursor_destroy(struct sway_cursor *cursor) { if (!cursor) { return; diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 29b47a7b..0b7cb766 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -61,7 +61,7 @@ static char *get_device_identifier(struct wlr_input_device *device) { int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; char *identifier = malloc(len); if (!identifier) { - wlr_log(L_ERROR, "Unable to allocate unique input device name"); + wlr_log(WLR_ERROR, "Unable to allocate unique input device name"); return NULL; } @@ -104,77 +104,89 @@ static void input_manager_libinput_config_pointer( } libinput_device = wlr_libinput_get_device_handle(wlr_device); - wlr_log(L_DEBUG, "input_manager_libinput_config_pointer(%s)", + wlr_log(WLR_DEBUG, "input_manager_libinput_config_pointer(%s)", ic->identifier); if (ic->accel_profile != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", ic->identifier, ic->accel_profile); libinput_device_config_accel_set_profile(libinput_device, ic->accel_profile); } if (ic->click_method != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", ic->identifier, ic->click_method); libinput_device_config_click_set_method(libinput_device, ic->click_method); } if (ic->drag_lock != INT_MIN) { - wlr_log(L_DEBUG, + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", ic->identifier, ic->click_method); libinput_device_config_tap_set_drag_lock_enabled(libinput_device, ic->drag_lock); } if (ic->dwt != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", ic->identifier, ic->dwt); libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); } if (ic->left_handed != INT_MIN) { - wlr_log(L_DEBUG, + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)", ic->identifier, ic->left_handed); libinput_device_config_left_handed_set(libinput_device, ic->left_handed); } if (ic->middle_emulation != INT_MIN) { - wlr_log(L_DEBUG, + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", ic->identifier, ic->middle_emulation); libinput_device_config_middle_emulation_set_enabled(libinput_device, ic->middle_emulation); } if (ic->natural_scroll != INT_MIN) { - wlr_log(L_DEBUG, + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", ic->identifier, ic->natural_scroll); libinput_device_config_scroll_set_natural_scroll_enabled( libinput_device, ic->natural_scroll); } if (ic->pointer_accel != FLT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", ic->identifier, ic->pointer_accel); libinput_device_config_accel_set_speed(libinput_device, ic->pointer_accel); } + if (ic->scroll_button != INT_MIN) { + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) scroll_set_button(%d)", + ic->identifier, ic->scroll_button); + libinput_device_config_scroll_set_button(libinput_device, + ic->scroll_button); + } if (ic->scroll_method != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", ic->identifier, ic->scroll_method); libinput_device_config_scroll_set_method(libinput_device, ic->scroll_method); } if (ic->send_events != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", ic->identifier, ic->send_events); libinput_device_config_send_events_set_mode(libinput_device, ic->send_events); } if (ic->tap != INT_MIN) { - wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", ic->identifier, ic->tap); libinput_device_config_tap_set_enabled(libinput_device, ic->tap); } + if (ic->tap_button_map != INT_MIN) { + wlr_log(WLR_DEBUG, "libinput_config_pointer(%s) tap_set_button_map(%d)", + ic->identifier, ic->tap); + libinput_device_config_tap_set_button_map(libinput_device, + ic->tap_button_map); + } } static void handle_device_destroy(struct wl_listener *listener, void *data) { @@ -187,7 +199,7 @@ static void handle_device_destroy(struct wl_listener *listener, void *data) { return; } - wlr_log(L_DEBUG, "removing device: '%s'", + wlr_log(WLR_DEBUG, "removing device: '%s'", input_device->identifier); struct sway_seat *seat = NULL; @@ -217,16 +229,19 @@ static void handle_new_input(struct wl_listener *listener, void *data) { input_device->identifier = get_device_identifier(device); wl_list_insert(&input->devices, &input_device->link); - wlr_log(L_DEBUG, "adding device: '%s'", + wlr_log(WLR_DEBUG, "adding device: '%s'", input_device->identifier); if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) { input_manager_libinput_config_pointer(input_device); } + wl_signal_add(&device->events.destroy, &input_device->device_destroy); + input_device->device_destroy.notify = handle_device_destroy; + struct sway_seat *seat = NULL; if (!input_has_seat_configuration(input)) { - wlr_log(L_DEBUG, "no seat configuration, using default seat"); + wlr_log(WLR_DEBUG, "no seat configuration, using default seat"); seat = input_manager_get_seat(input, default_seat); seat_add_device(seat, input_device); return; @@ -256,13 +271,10 @@ static void handle_new_input(struct wl_listener *listener, void *data) { } if (!added) { - wlr_log(L_DEBUG, + wlr_log(WLR_DEBUG, "device '%s' is not configured on any seats", input_device->identifier); } - - wl_signal_add(&device->events.destroy, &input_device->device_destroy); - input_device->device_destroy.notify = handle_device_destroy; } static void handle_inhibit_activate(struct wl_listener *listener, void *data) { @@ -282,7 +294,7 @@ static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) seat_set_exclusive_client(seat, NULL); struct sway_container *previous = seat_get_focus(seat); if (previous) { - wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, + wlr_log(WLR_DEBUG, "Returning focus to %p %s '%s'", previous, container_type_to_str(previous->type), previous->name); // Hack to get seat to re-focus the return value of get_focus seat_set_focus(seat, previous->parent); @@ -359,7 +371,7 @@ void input_manager_apply_input_config(struct sway_input_manager *input, void input_manager_apply_seat_config(struct sway_input_manager *input, struct seat_config *seat_config) { - wlr_log(L_DEBUG, "applying new seat config for seat %s", + wlr_log(WLR_DEBUG, "applying new seat config for seat %s", seat_config->name); struct sway_seat *seat = input_manager_get_seat(input, seat_config->name); if (!seat) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index ec149d06..ede38519 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -3,6 +3,7 @@ #include <wlr/backend/multi.h> #include <wlr/backend/session.h> #include <wlr/types/wlr_idle.h> +#include "sway/desktop/transaction.h" #include "sway/input/seat.h" #include "sway/input/keyboard.h" #include "sway/input/input-manager.h" @@ -108,7 +109,7 @@ static void get_active_binding(const struct sway_shortcut_state *state, } if (*current_binding && *current_binding != binding) { - wlr_log(L_DEBUG, "encountered duplicate bindings %d and %d", + wlr_log(WLR_DEBUG, "encountered duplicate bindings %d and %d", (*current_binding)->order, binding->order); } else { *current_binding = binding; @@ -122,12 +123,13 @@ static void get_active_binding(const struct sway_shortcut_state *state, */ static void keyboard_execute_command(struct sway_keyboard *keyboard, struct sway_binding *binding) { - wlr_log(L_DEBUG, "running command for binding: %s", + wlr_log(WLR_DEBUG, "running command for binding: %s", binding->command); config->handler_context.seat = keyboard->seat_device->sway_seat; struct cmd_results *results = execute_command(binding->command, NULL); + transaction_commit_dirty(); if (results->status != CMD_SUCCESS) { - wlr_log(L_DEBUG, "could not run command for binding: %s (%s)", + wlr_log(WLR_DEBUG, "could not run command for binding: %s (%s)", binding->command, results->error); } free_cmd_results(results); @@ -386,7 +388,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { - wlr_log(L_DEBUG, "cannot configure keyboard: keymap does not exist"); + wlr_log(WLR_DEBUG, "cannot configure keyboard: keymap does not exist"); xkb_context_unref(context); return; } @@ -420,6 +422,9 @@ void sway_keyboard_destroy(struct sway_keyboard *keyboard) { if (!keyboard) { return; } + if (keyboard->keymap) { + xkb_keymap_unref(keyboard->keymap); + } wl_list_remove(&keyboard->keyboard_key.link); wl_list_remove(&keyboard->keyboard_modifiers.link); free(keyboard); diff --git a/sway/input/seat.c b/sway/input/seat.c index 2c2087da..fc9e54b6 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1,6 +1,11 @@ #define _XOPEN_SOURCE 700 #define _POSIX_C_SOURCE 199309L #include <assert.h> +#ifdef __linux__ +#include <linux/input-event-codes.h> +#elif __FreeBSD__ +#include <dev/evdev/input-event-codes.h> +#endif #include <strings.h> #include <time.h> #include <wlr/types/wlr_cursor.h> @@ -75,7 +80,7 @@ static void seat_send_activate(struct sway_container *con, struct sway_seat *seat) { if (con->type == C_VIEW) { if (!seat_is_input_allowed(seat, con->sway_view->surface)) { - wlr_log(L_DEBUG, "Refusing to set focus, input is inhibited"); + wlr_log(WLR_DEBUG, "Refusing to set focus, input is inhibited"); return; } view_set_activated(con->sway_view, true); @@ -219,7 +224,7 @@ static struct sway_seat_container *seat_container_from_container( seat_con = calloc(1, sizeof(struct sway_seat_container)); if (seat_con == NULL) { - wlr_log(L_ERROR, "could not allocate seat container"); + wlr_log(WLR_ERROR, "could not allocate seat container"); return NULL; } @@ -301,7 +306,7 @@ static void handle_new_drag_icon(struct wl_listener *listener, void *data) { struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon)); if (icon == NULL) { - wlr_log(L_ERROR, "Allocation failed"); + wlr_log(WLR_ERROR, "Allocation failed"); return; } icon->seat = seat; @@ -348,6 +353,7 @@ struct sway_seat *seat_create(struct sway_input_manager *input, free(seat); return NULL; } + seat->wlr_seat->data = seat; seat->cursor = sway_cursor_create(seat); if (!seat->cursor) { @@ -391,7 +397,7 @@ static void seat_apply_input_config(struct sway_seat *seat, struct input_config *ic = input_device_get_config( sway_device->input_device); if (ic != NULL) { - wlr_log(L_DEBUG, "Applying input config to %s", + wlr_log(WLR_DEBUG, "Applying input config to %s", sway_device->input_device->identifier); mapped_to_output = ic->mapped_to_output; @@ -401,7 +407,7 @@ static void seat_apply_input_config(struct sway_seat *seat, mapped_to_output = sway_device->input_device->wlr_device->output_name; } if (mapped_to_output != NULL) { - wlr_log(L_DEBUG, "Mapping input device %s to output %s", + wlr_log(WLR_DEBUG, "Mapping input device %s to output %s", sway_device->input_device->identifier, mapped_to_output); struct sway_container *output = NULL; for (int i = 0; i < root_container.children->length; ++i) { @@ -415,7 +421,7 @@ static void seat_apply_input_config(struct sway_seat *seat, wlr_cursor_map_input_to_output(seat->cursor->cursor, sway_device->input_device->wlr_device, output->sway_output->wlr_output); - wlr_log(L_DEBUG, "Mapped to output %s", output->name); + wlr_log(WLR_DEBUG, "Mapped to output %s", output->name); } } } @@ -495,7 +501,7 @@ void seat_configure_device(struct sway_seat *seat, seat_configure_tablet_tool(seat, seat_device); break; case WLR_INPUT_DEVICE_TABLET_PAD: - wlr_log(L_DEBUG, "TODO: configure tablet pad"); + wlr_log(WLR_DEBUG, "TODO: configure tablet pad"); break; } } @@ -510,11 +516,11 @@ void seat_add_device(struct sway_seat *seat, struct sway_seat_device *seat_device = calloc(1, sizeof(struct sway_seat_device)); if (!seat_device) { - wlr_log(L_DEBUG, "could not allocate seat device"); + wlr_log(WLR_DEBUG, "could not allocate seat device"); return; } - wlr_log(L_DEBUG, "adding device %s to seat %s", + wlr_log(WLR_DEBUG, "adding device %s to seat %s", input_device->identifier, seat->wlr_seat->name); seat_device->sway_seat = seat; @@ -533,7 +539,7 @@ void seat_remove_device(struct sway_seat *seat, return; } - wlr_log(L_DEBUG, "removing device %s from seat %s", + wlr_log(WLR_DEBUG, "removing device %s from seat %s", input_device->identifier, seat->wlr_seat->name); seat_device_destroy(seat_device); @@ -594,6 +600,12 @@ static void seat_send_unfocus(struct sway_container *container, } } +static int handle_urgent_timeout(void *data) { + struct sway_view *view = data; + view_set_urgent(view, false); + return 0; +} + void seat_set_focus_warp(struct sway_seat *seat, struct sway_container *container, bool warp) { if (seat->focused_layer) { @@ -616,6 +628,7 @@ void seat_set_focus_warp(struct sway_seat *seat, if (last_workspace && last_workspace == new_workspace && last_workspace->sway_workspace->fullscreen + && container && container->type == C_VIEW && !container->sway_view->is_fullscreen) { return; } @@ -649,6 +662,7 @@ void seat_set_focus_warp(struct sway_seat *seat, while (parent) { wl_list_remove(&parent->link); wl_list_insert(&seat->focus_stack, &parent->link); + container_set_dirty(parent->container); parent = seat_container_from_container(seat, @@ -661,9 +675,39 @@ void seat_set_focus_warp(struct sway_seat *seat, if (last_focus) { seat_send_unfocus(last_focus, seat); } - seat_send_focus(container, seat); - container_damage_whole(container); + + container_set_dirty(container); + container_set_dirty(container->parent); // for focused_inactive_child + if (last_focus) { + container_set_dirty(last_focus); + } + } + + // If urgent, either unset the urgency or start a timer to unset it + if (container && container->type == C_VIEW && + view_is_urgent(container->sway_view) && + !container->sway_view->urgent_timer) { + struct sway_view *view = container->sway_view; + if (last_workspace && last_workspace != new_workspace && + config->urgent_timeout > 0) { + view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop, + handle_urgent_timeout, view); + wl_event_source_timer_update(view->urgent_timer, + config->urgent_timeout); + } else { + view_set_urgent(view, false); + } + } + + // If we've focused a floating container, bring it to the front. + // We do this by putting it at the end of the floating list. + // This must happen for both the pending and current children lists. + if (container && container_is_floating(container)) { + list_move_to_end(container->parent->children, container); + if (container_has_ancestor(container, container->current.parent)) { + list_move_to_end(container->parent->current.children, container); + } } // clean up unfocused empty workspace on new output @@ -707,11 +751,7 @@ void seat_set_focus_warp(struct sway_seat *seat, } } - if (last_focus) { - container_damage_whole(last_focus); - } - - if (last_workspace && last_workspace != new_workspace) { + if (last_focus != NULL) { cursor_send_pointer_motion(seat->cursor, 0, true); } @@ -726,11 +766,11 @@ void seat_set_focus(struct sway_seat *seat, } void seat_set_focus_surface(struct sway_seat *seat, - struct wlr_surface *surface) { + struct wlr_surface *surface, bool unfocus) { if (seat->focused_layer != NULL) { return; } - if (seat->has_focus) { + if (seat->has_focus && unfocus) { struct sway_container *focus = seat_get_focus(seat); seat_send_unfocus(focus, seat); seat->has_focus = false; @@ -752,7 +792,7 @@ void seat_set_focus_layer(struct sway_seat *seat, struct sway_container *previous = seat_get_focus_inactive(seat, &root_container); if (previous) { - wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, + wlr_log(WLR_DEBUG, "Returning focus to %p %s '%s'", previous, container_type_to_str(previous->type), previous->name); // Hack to get seat to re-focus the return value of get_focus seat_set_focus(seat, previous->parent); @@ -762,7 +802,7 @@ void seat_set_focus_layer(struct sway_seat *seat, } else if (!layer || seat->focused_layer == layer) { return; } - seat_set_focus_surface(seat, layer->surface); + seat_set_focus_surface(seat, layer->surface, true); if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { seat->focused_layer = layer; } @@ -830,18 +870,6 @@ struct sway_container *seat_get_active_child(struct sway_seat *seat, return NULL; } -struct sway_container *seat_get_active_current_child(struct sway_seat *seat, - struct sway_container *container) { - struct sway_container *child = seat_get_active_child(seat, container); - if (child) { - return child; - } - if (container->current.children->length == 1) { - return container->current.children->items[0]; - } - return NULL; -} - struct sway_container *seat_get_focus(struct sway_seat *seat) { if (!seat->has_focus) { return NULL; @@ -873,3 +901,68 @@ struct seat_config *seat_get_config(struct sway_seat *seat) { return NULL; } + +void seat_begin_move(struct sway_seat *seat, struct sway_container *con, + uint32_t button) { + if (!seat->cursor) { + wlr_log(WLR_DEBUG, "Ignoring move request due to no cursor device"); + return; + } + seat->operation = OP_MOVE; + seat->op_container = con; + seat->op_button = button; + cursor_set_image(seat->cursor, "grab", NULL); +} + +void seat_begin_resize(struct sway_seat *seat, struct sway_container *con, + uint32_t button, enum wlr_edges edge) { + if (!seat->cursor) { + wlr_log(WLR_DEBUG, "Ignoring resize request due to no cursor device"); + return; + } + struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); + seat->operation = OP_RESIZE; + seat->op_container = con; + seat->op_resize_preserve_ratio = keyboard && + (wlr_keyboard_get_modifiers(keyboard) & WLR_MODIFIER_SHIFT); + seat->op_resize_edge = edge == WLR_EDGE_NONE ? + RESIZE_EDGE_BOTTOM | RESIZE_EDGE_RIGHT : edge; + seat->op_button = button; + seat->op_ref_lx = seat->cursor->cursor->x; + seat->op_ref_ly = seat->cursor->cursor->y; + seat->op_ref_con_lx = con->x; + seat->op_ref_con_ly = con->y; + seat->op_ref_width = con->width; + seat->op_ref_height = con->height; + + const char *image = edge == WLR_EDGE_NONE ? + "se-resize" : wlr_xcursor_get_resize_name(edge); + cursor_set_image(seat->cursor, image, NULL); +} + +void seat_end_mouse_operation(struct sway_seat *seat) { + switch (seat->operation) { + case OP_MOVE: + { + // We "move" the container to its own location so it discovers its + // output again. + struct sway_container *con = seat->op_container; + container_floating_move_to(con, con->x, con->y); + } + case OP_RESIZE: + // Don't need to do anything here. + break; + case OP_NONE: + break; + } + seat->operation = OP_NONE; + seat->op_container = NULL; + cursor_set_image(seat->cursor, "left_ptr", NULL); +} + +void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, + uint32_t button, enum wlr_button_state state) { + seat->last_button = button; + seat->last_button_serial = wlr_seat_pointer_notify_button(seat->wlr_seat, + time_msec, button, state); +} |