diff options
Diffstat (limited to 'sway/input')
-rw-r--r-- | sway/input/cursor.c | 587 | ||||
-rw-r--r-- | sway/input/input-manager.c | 149 | ||||
-rw-r--r-- | sway/input/keyboard.c | 190 | ||||
-rw-r--r-- | sway/input/libinput.c | 105 | ||||
-rw-r--r-- | sway/input/seat.c | 449 | ||||
-rw-r--r-- | sway/input/seatop_default.c | 543 | ||||
-rw-r--r-- | sway/input/seatop_down.c | 181 | ||||
-rw-r--r-- | sway/input/seatop_move_floating.c | 6 | ||||
-rw-r--r-- | sway/input/seatop_move_tiling.c | 75 | ||||
-rw-r--r-- | sway/input/seatop_resize_floating.c | 21 | ||||
-rw-r--r-- | sway/input/seatop_resize_tiling.c | 3 | ||||
-rw-r--r-- | sway/input/switch.c | 34 | ||||
-rw-r--r-- | sway/input/tablet.c | 50 | ||||
-rw-r--r-- | sway/input/text_input.c | 229 |
14 files changed, 1785 insertions, 837 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 2fe5b202..0b4a36d9 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <assert.h> | 1 | #include <assert.h> |
3 | #include <math.h> | 2 | #include <math.h> |
4 | #include <libevdev/libevdev.h> | 3 | #include <libevdev/libevdev.h> |
@@ -7,8 +6,9 @@ | |||
7 | #include <time.h> | 6 | #include <time.h> |
8 | #include <strings.h> | 7 | #include <strings.h> |
9 | #include <wlr/types/wlr_cursor.h> | 8 | #include <wlr/types/wlr_cursor.h> |
10 | #include <wlr/types/wlr_idle.h> | 9 | #include <wlr/types/wlr_cursor_shape_v1.h> |
11 | #include <wlr/types/wlr_pointer.h> | 10 | #include <wlr/types/wlr_pointer.h> |
11 | #include <wlr/types/wlr_relative_pointer_v1.h> | ||
12 | #include <wlr/types/wlr_touch.h> | 12 | #include <wlr/types/wlr_touch.h> |
13 | #include <wlr/types/wlr_tablet_v2.h> | 13 | #include <wlr/types/wlr_tablet_v2.h> |
14 | #include <wlr/types/wlr_tablet_pad.h> | 14 | #include <wlr/types/wlr_tablet_pad.h> |
@@ -19,12 +19,12 @@ | |||
19 | #include "log.h" | 19 | #include "log.h" |
20 | #include "util.h" | 20 | #include "util.h" |
21 | #include "sway/commands.h" | 21 | #include "sway/commands.h" |
22 | #include "sway/desktop.h" | ||
23 | #include "sway/input/cursor.h" | 22 | #include "sway/input/cursor.h" |
24 | #include "sway/input/keyboard.h" | 23 | #include "sway/input/keyboard.h" |
25 | #include "sway/input/tablet.h" | 24 | #include "sway/input/tablet.h" |
26 | #include "sway/layers.h" | 25 | #include "sway/layers.h" |
27 | #include "sway/output.h" | 26 | #include "sway/output.h" |
27 | #include "sway/scene_descriptor.h" | ||
28 | #include "sway/tree/container.h" | 28 | #include "sway/tree/container.h" |
29 | #include "sway/tree/root.h" | 29 | #include "sway/tree/root.h" |
30 | #include "sway/tree/view.h" | 30 | #include "sway/tree/view.h" |
@@ -37,45 +37,6 @@ static uint32_t get_current_time_msec(void) { | |||
37 | return now.tv_sec * 1000 + now.tv_nsec / 1000000; | 37 | return now.tv_sec * 1000 + now.tv_nsec / 1000000; |
38 | } | 38 | } |
39 | 39 | ||
40 | static struct wlr_surface *layer_surface_at(struct sway_output *output, | ||
41 | struct wl_list *layer, double ox, double oy, double *sx, double *sy) { | ||
42 | struct sway_layer_surface *sway_layer; | ||
43 | wl_list_for_each_reverse(sway_layer, layer, link) { | ||
44 | double _sx = ox - sway_layer->geo.x; | ||
45 | double _sy = oy - sway_layer->geo.y; | ||
46 | struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( | ||
47 | sway_layer->layer_surface, _sx, _sy, sx, sy); | ||
48 | if (sub) { | ||
49 | return sub; | ||
50 | } | ||
51 | } | ||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | static bool surface_is_xdg_popup(struct wlr_surface *surface) { | ||
56 | if (wlr_surface_is_xdg_surface(surface)) { | ||
57 | struct wlr_xdg_surface *xdg_surface = | ||
58 | wlr_xdg_surface_from_wlr_surface(surface); | ||
59 | return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP; | ||
60 | } | ||
61 | return false; | ||
62 | } | ||
63 | |||
64 | static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, | ||
65 | struct wl_list *layer, double ox, double oy, double *sx, double *sy) { | ||
66 | struct sway_layer_surface *sway_layer; | ||
67 | wl_list_for_each_reverse(sway_layer, layer, link) { | ||
68 | double _sx = ox - sway_layer->geo.x; | ||
69 | double _sy = oy - sway_layer->geo.y; | ||
70 | struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( | ||
71 | sway_layer->layer_surface, _sx, _sy, sx, sy); | ||
72 | if (sub && surface_is_xdg_popup(sub)) { | ||
73 | return sub; | ||
74 | } | ||
75 | } | ||
76 | return NULL; | ||
77 | } | ||
78 | |||
79 | /** | 40 | /** |
80 | * Returns the node at the cursor's position. If there is a surface at that | 41 | * Returns the node at the cursor's position. If there is a surface at that |
81 | * location, it is stored in **surface (it may not be a view). | 42 | * location, it is stored in **surface (it may not be a view). |
@@ -83,116 +44,101 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output, | |||
83 | struct sway_node *node_at_coords( | 44 | struct sway_node *node_at_coords( |
84 | struct sway_seat *seat, double lx, double ly, | 45 | struct sway_seat *seat, double lx, double ly, |
85 | struct wlr_surface **surface, double *sx, double *sy) { | 46 | struct wlr_surface **surface, double *sx, double *sy) { |
86 | // check for unmanaged views first | 47 | struct wlr_scene_node *scene_node = NULL; |
87 | #if HAVE_XWAYLAND | 48 | |
88 | struct wl_list *unmanaged = &root->xwayland_unmanaged; | 49 | struct wlr_scene_node *node; |
89 | struct sway_xwayland_unmanaged *unmanaged_surface; | 50 | wl_list_for_each_reverse(node, &root->layer_tree->children, link) { |
90 | wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { | 51 | struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node); |
91 | struct wlr_xwayland_surface *xsurface = | 52 | |
92 | unmanaged_surface->wlr_xwayland_surface; | 53 | bool non_interactive = scene_descriptor_try_get(&layer->node, |
93 | 54 | SWAY_SCENE_DESC_NON_INTERACTIVE); | |
94 | double _sx = lx - unmanaged_surface->lx; | 55 | if (non_interactive) { |
95 | double _sy = ly - unmanaged_surface->ly; | 56 | continue; |
96 | if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { | 57 | } |
97 | *surface = xsurface->surface; | 58 | |
98 | *sx = _sx; | 59 | scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy); |
99 | *sy = _sy; | 60 | if (scene_node) { |
100 | return NULL; | 61 | break; |
101 | } | 62 | } |
102 | } | 63 | } |
64 | |||
65 | if (scene_node) { | ||
66 | // determine what wlr_surface we clicked on | ||
67 | if (scene_node->type == WLR_SCENE_NODE_BUFFER) { | ||
68 | struct wlr_scene_buffer *scene_buffer = | ||
69 | wlr_scene_buffer_from_node(scene_node); | ||
70 | struct wlr_scene_surface *scene_surface = | ||
71 | wlr_scene_surface_try_from_buffer(scene_buffer); | ||
72 | |||
73 | if (scene_surface) { | ||
74 | *surface = scene_surface->surface; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // determine what container we clicked on | ||
79 | struct wlr_scene_node *current = scene_node; | ||
80 | while (true) { | ||
81 | struct sway_container *con = scene_descriptor_try_get(current, | ||
82 | SWAY_SCENE_DESC_CONTAINER); | ||
83 | |||
84 | if (!con) { | ||
85 | struct sway_view *view = scene_descriptor_try_get(current, | ||
86 | SWAY_SCENE_DESC_VIEW); | ||
87 | if (view) { | ||
88 | con = view->container; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | if (!con) { | ||
93 | struct sway_popup_desc *popup = | ||
94 | scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP); | ||
95 | if (popup && popup->view) { | ||
96 | con = popup->view->container; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | if (con && (!con->view || con->view->surface)) { | ||
101 | return &con->node; | ||
102 | } | ||
103 | |||
104 | if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) { | ||
105 | // We don't want to feed through the current workspace on | ||
106 | // layer shells | ||
107 | return NULL; | ||
108 | } | ||
109 | |||
110 | #if WLR_HAS_XWAYLAND | ||
111 | if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) { | ||
112 | return NULL; | ||
113 | } | ||
103 | #endif | 114 | #endif |
104 | // find the output the cursor is on | 115 | |
116 | if (!current->parent) { | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | current = ¤t->parent->node; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | // if we aren't on a container, determine what workspace we are on | ||
105 | struct wlr_output *wlr_output = wlr_output_layout_output_at( | 125 | struct wlr_output *wlr_output = wlr_output_layout_output_at( |
106 | root->output_layout, lx, ly); | 126 | root->output_layout, lx, ly); |
107 | if (wlr_output == NULL) { | 127 | if (wlr_output == NULL) { |
108 | return NULL; | 128 | return NULL; |
109 | } | 129 | } |
130 | |||
110 | struct sway_output *output = wlr_output->data; | 131 | struct sway_output *output = wlr_output->data; |
111 | if (!output || !output->enabled) { | 132 | if (!output || !output->enabled) { |
112 | // output is being destroyed or is being enabled | 133 | // output is being destroyed or is being enabled |
113 | return NULL; | 134 | return NULL; |
114 | } | 135 | } |
115 | double ox = lx, oy = ly; | ||
116 | wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); | ||
117 | 136 | ||
118 | if (root->fullscreen_global) { | ||
119 | // Try fullscreen container | ||
120 | struct sway_container *con = tiling_container_at( | ||
121 | &root->fullscreen_global->node, lx, ly, surface, sx, sy); | ||
122 | if (con) { | ||
123 | return &con->node; | ||
124 | } | ||
125 | return NULL; | ||
126 | } | ||
127 | |||
128 | // find the focused workspace on the output for this seat | ||
129 | struct sway_workspace *ws = output_get_active_workspace(output); | 137 | struct sway_workspace *ws = output_get_active_workspace(output); |
130 | if (!ws) { | 138 | if (!ws) { |
131 | return NULL; | 139 | return NULL; |
132 | } | 140 | } |
133 | 141 | ||
134 | if ((*surface = layer_surface_at(output, | ||
135 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], | ||
136 | ox, oy, sx, sy))) { | ||
137 | return NULL; | ||
138 | } | ||
139 | if (ws->fullscreen) { | ||
140 | // Try transient containers | ||
141 | for (int i = 0; i < ws->floating->length; ++i) { | ||
142 | struct sway_container *floater = ws->floating->items[i]; | ||
143 | if (container_is_transient_for(floater, ws->fullscreen)) { | ||
144 | struct sway_container *con = tiling_container_at( | ||
145 | &floater->node, lx, ly, surface, sx, sy); | ||
146 | if (con) { | ||
147 | return &con->node; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | // Try fullscreen container | ||
152 | struct sway_container *con = | ||
153 | tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy); | ||
154 | if (con) { | ||
155 | return &con->node; | ||
156 | } | ||
157 | return NULL; | ||
158 | } | ||
159 | if ((*surface = layer_surface_popup_at(output, | ||
160 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | ||
161 | ox, oy, sx, sy))) { | ||
162 | return NULL; | ||
163 | } | ||
164 | if ((*surface = layer_surface_popup_at(output, | ||
165 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | ||
166 | ox, oy, sx, sy))) { | ||
167 | return NULL; | ||
168 | } | ||
169 | if ((*surface = layer_surface_popup_at(output, | ||
170 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | ||
171 | ox, oy, sx, sy))) { | ||
172 | return NULL; | ||
173 | } | ||
174 | if ((*surface = layer_surface_at(output, | ||
175 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], | ||
176 | ox, oy, sx, sy))) { | ||
177 | return NULL; | ||
178 | } | ||
179 | |||
180 | struct sway_container *c; | ||
181 | if ((c = container_at(ws, lx, ly, surface, sx, sy))) { | ||
182 | return &c->node; | ||
183 | } | ||
184 | |||
185 | if ((*surface = layer_surface_at(output, | ||
186 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], | ||
187 | ox, oy, sx, sy))) { | ||
188 | return NULL; | ||
189 | } | ||
190 | if ((*surface = layer_surface_at(output, | ||
191 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], | ||
192 | ox, oy, sx, sy))) { | ||
193 | return NULL; | ||
194 | } | ||
195 | |||
196 | return &ws->node; | 142 | return &ws->node; |
197 | } | 143 | } |
198 | 144 | ||
@@ -218,7 +164,7 @@ void cursor_update_image(struct sway_cursor *cursor, | |||
218 | // Try a node's resize edge | 164 | // Try a node's resize edge |
219 | enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor); | 165 | enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor); |
220 | if (edge == WLR_EDGE_NONE) { | 166 | if (edge == WLR_EDGE_NONE) { |
221 | cursor_set_image(cursor, "left_ptr", NULL); | 167 | cursor_set_image(cursor, "default", NULL); |
222 | } else if (container_is_floating(node->sway_container)) { | 168 | } else if (container_is_floating(node->sway_container)) { |
223 | cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); | 169 | cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); |
224 | } else { | 170 | } else { |
@@ -229,12 +175,12 @@ void cursor_update_image(struct sway_cursor *cursor, | |||
229 | } | 175 | } |
230 | } | 176 | } |
231 | } else { | 177 | } else { |
232 | cursor_set_image(cursor, "left_ptr", NULL); | 178 | cursor_set_image(cursor, "default", NULL); |
233 | } | 179 | } |
234 | } | 180 | } |
235 | 181 | ||
236 | static void cursor_hide(struct sway_cursor *cursor) { | 182 | static void cursor_hide(struct sway_cursor *cursor) { |
237 | wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); | 183 | wlr_cursor_unset_image(cursor->cursor); |
238 | cursor->hidden = true; | 184 | cursor->hidden = true; |
239 | wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); | 185 | wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); |
240 | } | 186 | } |
@@ -297,7 +243,7 @@ static enum sway_input_idle_source idle_source_from_device( | |||
297 | return IDLE_SOURCE_POINTER; | 243 | return IDLE_SOURCE_POINTER; |
298 | case WLR_INPUT_DEVICE_TOUCH: | 244 | case WLR_INPUT_DEVICE_TOUCH: |
299 | return IDLE_SOURCE_TOUCH; | 245 | return IDLE_SOURCE_TOUCH; |
300 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 246 | case WLR_INPUT_DEVICE_TABLET: |
301 | return IDLE_SOURCE_TABLET_TOOL; | 247 | return IDLE_SOURCE_TABLET_TOOL; |
302 | case WLR_INPUT_DEVICE_TABLET_PAD: | 248 | case WLR_INPUT_DEVICE_TABLET_PAD: |
303 | return IDLE_SOURCE_TABLET_PAD; | 249 | return IDLE_SOURCE_TABLET_PAD; |
@@ -346,7 +292,7 @@ void cursor_unhide(struct sway_cursor *cursor) { | |||
346 | wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor)); | 292 | wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor)); |
347 | } | 293 | } |
348 | 294 | ||
349 | static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | 295 | void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, |
350 | struct wlr_input_device *device, double dx, double dy, | 296 | struct wlr_input_device *device, double dx, double dy, |
351 | double dx_unaccel, double dy_unaccel) { | 297 | double dx_unaccel, double dy_unaccel) { |
352 | wlr_relative_pointer_manager_v1_send_relative_motion( | 298 | wlr_relative_pointer_manager_v1_send_relative_motion( |
@@ -383,33 +329,34 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
383 | static void handle_pointer_motion_relative( | 329 | static void handle_pointer_motion_relative( |
384 | struct wl_listener *listener, void *data) { | 330 | struct wl_listener *listener, void *data) { |
385 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); | 331 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); |
386 | struct wlr_event_pointer_motion *e = data; | 332 | struct wlr_pointer_motion_event *e = data; |
387 | cursor_handle_activity_from_device(cursor, e->device); | 333 | cursor_handle_activity_from_device(cursor, &e->pointer->base); |
388 | 334 | ||
389 | pointer_motion(cursor, e->time_msec, e->device, e->delta_x, e->delta_y, | 335 | pointer_motion(cursor, e->time_msec, &e->pointer->base, e->delta_x, |
390 | e->unaccel_dx, e->unaccel_dy); | 336 | e->delta_y, e->unaccel_dx, e->unaccel_dy); |
391 | } | 337 | } |
392 | 338 | ||
393 | static void handle_pointer_motion_absolute( | 339 | static void handle_pointer_motion_absolute( |
394 | struct wl_listener *listener, void *data) { | 340 | struct wl_listener *listener, void *data) { |
395 | struct sway_cursor *cursor = | 341 | struct sway_cursor *cursor = |
396 | wl_container_of(listener, cursor, motion_absolute); | 342 | wl_container_of(listener, cursor, motion_absolute); |
397 | struct wlr_event_pointer_motion_absolute *event = data; | 343 | struct wlr_pointer_motion_absolute_event *event = data; |
398 | cursor_handle_activity_from_device(cursor, event->device); | 344 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
399 | 345 | ||
400 | double lx, ly; | 346 | double lx, ly; |
401 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, | 347 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->pointer->base, |
402 | event->x, event->y, &lx, &ly); | 348 | event->x, event->y, &lx, &ly); |
403 | 349 | ||
404 | double dx = lx - cursor->cursor->x; | 350 | double dx = lx - cursor->cursor->x; |
405 | double dy = ly - cursor->cursor->y; | 351 | double dy = ly - cursor->cursor->y; |
406 | 352 | ||
407 | pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); | 353 | pointer_motion(cursor, event->time_msec, &event->pointer->base, dx, dy, |
354 | dx, dy); | ||
408 | } | 355 | } |
409 | 356 | ||
410 | void dispatch_cursor_button(struct sway_cursor *cursor, | 357 | void dispatch_cursor_button(struct sway_cursor *cursor, |
411 | struct wlr_input_device *device, uint32_t time_msec, uint32_t button, | 358 | struct wlr_input_device *device, uint32_t time_msec, uint32_t button, |
412 | enum wlr_button_state state) { | 359 | enum wl_pointer_button_state state) { |
413 | if (time_msec == 0) { | 360 | if (time_msec == 0) { |
414 | time_msec = get_current_time_msec(); | 361 | time_msec = get_current_time_msec(); |
415 | } | 362 | } |
@@ -419,9 +366,9 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
419 | 366 | ||
420 | static void handle_pointer_button(struct wl_listener *listener, void *data) { | 367 | static void handle_pointer_button(struct wl_listener *listener, void *data) { |
421 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); | 368 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); |
422 | struct wlr_event_pointer_button *event = data; | 369 | struct wlr_pointer_button_event *event = data; |
423 | 370 | ||
424 | if (event->state == WLR_BUTTON_PRESSED) { | 371 | if (event->state == WL_POINTER_BUTTON_STATE_PRESSED) { |
425 | cursor->pressed_button_count++; | 372 | cursor->pressed_button_count++; |
426 | } else { | 373 | } else { |
427 | if (cursor->pressed_button_count > 0) { | 374 | if (cursor->pressed_button_count > 0) { |
@@ -431,20 +378,20 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) { | |||
431 | } | 378 | } |
432 | } | 379 | } |
433 | 380 | ||
434 | cursor_handle_activity_from_device(cursor, event->device); | 381 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
435 | dispatch_cursor_button(cursor, event->device, | 382 | dispatch_cursor_button(cursor, &event->pointer->base, |
436 | event->time_msec, event->button, event->state); | 383 | event->time_msec, event->button, event->state); |
437 | } | 384 | } |
438 | 385 | ||
439 | void dispatch_cursor_axis(struct sway_cursor *cursor, | 386 | void dispatch_cursor_axis(struct sway_cursor *cursor, |
440 | struct wlr_event_pointer_axis *event) { | 387 | struct wlr_pointer_axis_event *event) { |
441 | seatop_pointer_axis(cursor->seat, event); | 388 | seatop_pointer_axis(cursor->seat, event); |
442 | } | 389 | } |
443 | 390 | ||
444 | static void handle_pointer_axis(struct wl_listener *listener, void *data) { | 391 | static void handle_pointer_axis(struct wl_listener *listener, void *data) { |
445 | struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); | 392 | struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); |
446 | struct wlr_event_pointer_axis *event = data; | 393 | struct wlr_pointer_axis_event *event = data; |
447 | cursor_handle_activity_from_device(cursor, event->device); | 394 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
448 | dispatch_cursor_axis(cursor, event); | 395 | dispatch_cursor_axis(cursor, event); |
449 | } | 396 | } |
450 | 397 | ||
@@ -455,93 +402,76 @@ static void handle_pointer_frame(struct wl_listener *listener, void *data) { | |||
455 | 402 | ||
456 | static void handle_touch_down(struct wl_listener *listener, void *data) { | 403 | static void handle_touch_down(struct wl_listener *listener, void *data) { |
457 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); | 404 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); |
458 | struct wlr_event_touch_down *event = data; | 405 | struct wlr_touch_down_event *event = data; |
459 | cursor_handle_activity_from_device(cursor, event->device); | 406 | cursor_handle_activity_from_device(cursor, &event->touch->base); |
460 | cursor_hide(cursor); | 407 | cursor_hide(cursor); |
461 | 408 | ||
462 | struct sway_seat *seat = cursor->seat; | 409 | struct sway_seat *seat = cursor->seat; |
463 | struct wlr_seat *wlr_seat = seat->wlr_seat; | ||
464 | struct wlr_surface *surface = NULL; | ||
465 | 410 | ||
466 | double lx, ly; | 411 | double lx, ly; |
467 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, | 412 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, |
468 | event->x, event->y, &lx, &ly); | 413 | event->x, event->y, &lx, &ly); |
469 | double sx, sy; | ||
470 | struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy); | ||
471 | 414 | ||
472 | seat->touch_id = event->touch_id; | 415 | seat->touch_id = event->touch_id; |
473 | seat->touch_x = lx; | 416 | seat->touch_x = lx; |
474 | seat->touch_y = ly; | 417 | seat->touch_y = ly; |
475 | 418 | ||
476 | if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { | 419 | seatop_touch_down(seat, event, lx, ly); |
477 | if (seat_is_input_allowed(seat, surface)) { | 420 | } |
478 | wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec, | ||
479 | event->touch_id, sx, sy); | ||
480 | 421 | ||
481 | if (focused_node) { | 422 | static void handle_touch_up(struct wl_listener *listener, void *data) { |
482 | seat_set_focus(seat, focused_node); | 423 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); |
483 | } | 424 | struct wlr_touch_up_event *event = data; |
425 | cursor_handle_activity_from_device(cursor, &event->touch->base); | ||
426 | |||
427 | struct sway_seat *seat = cursor->seat; | ||
428 | |||
429 | if (cursor->simulating_pointer_from_touch) { | ||
430 | if (cursor->pointer_touch_id == cursor->seat->touch_id) { | ||
431 | cursor->pointer_touch_up = true; | ||
432 | dispatch_cursor_button(cursor, &event->touch->base, | ||
433 | event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); | ||
484 | } | 434 | } |
485 | } else if (!cursor->simulating_pointer_from_touch && | 435 | } else { |
486 | (!surface || seat_is_input_allowed(seat, surface))) { | 436 | seatop_touch_up(seat, event); |
487 | // Fallback to cursor simulation. | ||
488 | // The pointer_touch_id state is needed, so drags are not aborted when over | ||
489 | // a surface supporting touch and multi touch events don't interfere. | ||
490 | cursor->simulating_pointer_from_touch = true; | ||
491 | cursor->pointer_touch_id = seat->touch_id; | ||
492 | double dx, dy; | ||
493 | dx = lx - cursor->cursor->x; | ||
494 | dy = ly - cursor->cursor->y; | ||
495 | pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); | ||
496 | dispatch_cursor_button(cursor, event->device, event->time_msec, | ||
497 | BTN_LEFT, WLR_BUTTON_PRESSED); | ||
498 | } | 437 | } |
499 | } | 438 | } |
500 | 439 | ||
501 | static void handle_touch_up(struct wl_listener *listener, void *data) { | 440 | static void handle_touch_cancel(struct wl_listener *listener, void *data) { |
502 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); | 441 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_cancel); |
503 | struct wlr_event_touch_up *event = data; | 442 | struct wlr_touch_cancel_event *event = data; |
504 | cursor_handle_activity_from_device(cursor, event->device); | 443 | cursor_handle_activity_from_device(cursor, &event->touch->base); |
505 | 444 | ||
506 | struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; | 445 | struct sway_seat *seat = cursor->seat; |
507 | 446 | ||
508 | if (cursor->simulating_pointer_from_touch) { | 447 | if (cursor->simulating_pointer_from_touch) { |
509 | if (cursor->pointer_touch_id == cursor->seat->touch_id) { | 448 | if (cursor->pointer_touch_id == cursor->seat->touch_id) { |
510 | cursor->pointer_touch_up = true; | 449 | cursor->pointer_touch_up = true; |
511 | dispatch_cursor_button(cursor, event->device, event->time_msec, | 450 | dispatch_cursor_button(cursor, &event->touch->base, |
512 | BTN_LEFT, WLR_BUTTON_RELEASED); | 451 | event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); |
513 | } | 452 | } |
514 | } else { | 453 | } else { |
515 | wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); | 454 | seatop_touch_cancel(seat, event); |
516 | } | 455 | } |
517 | } | 456 | } |
518 | 457 | ||
519 | static void handle_touch_motion(struct wl_listener *listener, void *data) { | 458 | static void handle_touch_motion(struct wl_listener *listener, void *data) { |
520 | struct sway_cursor *cursor = | 459 | struct sway_cursor *cursor = |
521 | wl_container_of(listener, cursor, touch_motion); | 460 | wl_container_of(listener, cursor, touch_motion); |
522 | struct wlr_event_touch_motion *event = data; | 461 | struct wlr_touch_motion_event *event = data; |
523 | cursor_handle_activity_from_device(cursor, event->device); | 462 | cursor_handle_activity_from_device(cursor, &event->touch->base); |
524 | 463 | ||
525 | struct sway_seat *seat = cursor->seat; | 464 | struct sway_seat *seat = cursor->seat; |
526 | struct wlr_seat *wlr_seat = seat->wlr_seat; | ||
527 | struct wlr_surface *surface = NULL; | ||
528 | 465 | ||
529 | double lx, ly; | 466 | double lx, ly; |
530 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, | 467 | wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base, |
531 | event->x, event->y, &lx, &ly); | 468 | event->x, event->y, &lx, &ly); |
532 | double sx, sy; | ||
533 | node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy); | ||
534 | 469 | ||
535 | if (seat->touch_id == event->touch_id) { | 470 | if (seat->touch_id == event->touch_id) { |
536 | seat->touch_x = lx; | 471 | seat->touch_x = lx; |
537 | seat->touch_y = ly; | 472 | seat->touch_y = ly; |
538 | 473 | ||
539 | struct sway_drag_icon *drag_icon; | 474 | drag_icons_update_position(seat); |
540 | wl_list_for_each(drag_icon, &root->drag_icons, link) { | ||
541 | if (drag_icon->seat == seat) { | ||
542 | drag_icon_update_position(drag_icon); | ||
543 | } | ||
544 | } | ||
545 | } | 475 | } |
546 | 476 | ||
547 | if (cursor->simulating_pointer_from_touch) { | 477 | if (cursor->simulating_pointer_from_touch) { |
@@ -549,11 +479,11 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { | |||
549 | double dx, dy; | 479 | double dx, dy; |
550 | dx = lx - cursor->cursor->x; | 480 | dx = lx - cursor->cursor->x; |
551 | dy = ly - cursor->cursor->y; | 481 | dy = ly - cursor->cursor->y; |
552 | pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); | 482 | pointer_motion(cursor, event->time_msec, &event->touch->base, |
483 | dx, dy, dx, dy); | ||
553 | } | 484 | } |
554 | } else if (surface) { | 485 | } else { |
555 | wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, | 486 | seatop_touch_motion(seat, event, lx, ly); |
556 | event->touch_id, sx, sy); | ||
557 | } | 487 | } |
558 | } | 488 | } |
559 | 489 | ||
@@ -588,14 +518,15 @@ static void apply_mapping_from_region(struct wlr_input_device *device, | |||
588 | double x1 = region->x1, x2 = region->x2; | 518 | double x1 = region->x1, x2 = region->x2; |
589 | double y1 = region->y1, y2 = region->y2; | 519 | double y1 = region->y1, y2 = region->y2; |
590 | 520 | ||
591 | if (region->mm) { | 521 | if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET) { |
592 | if (device->width_mm == 0 || device->height_mm == 0) { | 522 | struct wlr_tablet *tablet = wlr_tablet_from_input_device(device); |
523 | if (tablet->width_mm == 0 || tablet->height_mm == 0) { | ||
593 | return; | 524 | return; |
594 | } | 525 | } |
595 | x1 /= device->width_mm; | 526 | x1 /= tablet->width_mm; |
596 | x2 /= device->width_mm; | 527 | x2 /= tablet->width_mm; |
597 | y1 /= device->height_mm; | 528 | y1 /= tablet->height_mm; |
598 | y2 /= device->height_mm; | 529 | y2 /= tablet->height_mm; |
599 | } | 530 | } |
600 | 531 | ||
601 | *x = apply_mapping_from_coord(x1, x2, *x); | 532 | *x = apply_mapping_from_coord(x1, x2, *x); |
@@ -657,8 +588,8 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor, | |||
657 | 588 | ||
658 | static void handle_tool_axis(struct wl_listener *listener, void *data) { | 589 | static void handle_tool_axis(struct wl_listener *listener, void *data) { |
659 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); | 590 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); |
660 | struct wlr_event_tablet_tool_axis *event = data; | 591 | struct wlr_tablet_tool_axis_event *event = data; |
661 | cursor_handle_activity_from_device(cursor, event->device); | 592 | cursor_handle_activity_from_device(cursor, &event->tablet->base); |
662 | 593 | ||
663 | struct sway_tablet_tool *sway_tool = event->tool->data; | 594 | struct sway_tablet_tool *sway_tool = event->tool->data; |
664 | if (!sway_tool) { | 595 | if (!sway_tool) { |
@@ -713,8 +644,8 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { | |||
713 | 644 | ||
714 | static void handle_tool_tip(struct wl_listener *listener, void *data) { | 645 | static void handle_tool_tip(struct wl_listener *listener, void *data) { |
715 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); | 646 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); |
716 | struct wlr_event_tablet_tool_tip *event = data; | 647 | struct wlr_tablet_tool_tip_event *event = data; |
717 | cursor_handle_activity_from_device(cursor, event->device); | 648 | cursor_handle_activity_from_device(cursor, &event->tablet->base); |
718 | 649 | ||
719 | struct sway_tablet_tool *sway_tool = event->tool->data; | 650 | struct sway_tablet_tool *sway_tool = event->tool->data; |
720 | struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; | 651 | struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; |
@@ -729,8 +660,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
729 | if (cursor->simulating_pointer_from_tool_tip && | 660 | if (cursor->simulating_pointer_from_tool_tip && |
730 | event->state == WLR_TABLET_TOOL_TIP_UP) { | 661 | event->state == WLR_TABLET_TOOL_TIP_UP) { |
731 | cursor->simulating_pointer_from_tool_tip = false; | 662 | cursor->simulating_pointer_from_tool_tip = false; |
732 | dispatch_cursor_button(cursor, event->device, event->time_msec, | 663 | dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec, |
733 | BTN_LEFT, WLR_BUTTON_RELEASED); | 664 | BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); |
734 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 665 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
735 | } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { | 666 | } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { |
736 | // If we started holding the tool tip down on a surface that accepts | 667 | // If we started holding the tool tip down on a surface that accepts |
@@ -741,8 +672,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
741 | WLR_TABLET_TOOL_TIP_UP); | 672 | WLR_TABLET_TOOL_TIP_UP); |
742 | } else { | 673 | } else { |
743 | cursor->simulating_pointer_from_tool_tip = true; | 674 | cursor->simulating_pointer_from_tool_tip = true; |
744 | dispatch_cursor_button(cursor, event->device, event->time_msec, | 675 | dispatch_cursor_button(cursor, &event->tablet->base, |
745 | BTN_LEFT, WLR_BUTTON_PRESSED); | 676 | event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); |
746 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 677 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
747 | } | 678 | } |
748 | } else { | 679 | } else { |
@@ -764,12 +695,13 @@ static struct sway_tablet *get_tablet_for_device(struct sway_cursor *cursor, | |||
764 | static void handle_tool_proximity(struct wl_listener *listener, void *data) { | 695 | static void handle_tool_proximity(struct wl_listener *listener, void *data) { |
765 | struct sway_cursor *cursor = | 696 | struct sway_cursor *cursor = |
766 | wl_container_of(listener, cursor, tool_proximity); | 697 | wl_container_of(listener, cursor, tool_proximity); |
767 | struct wlr_event_tablet_tool_proximity *event = data; | 698 | struct wlr_tablet_tool_proximity_event *event = data; |
768 | cursor_handle_activity_from_device(cursor, event->device); | 699 | cursor_handle_activity_from_device(cursor, &event->tablet->base); |
769 | 700 | ||
770 | struct wlr_tablet_tool *tool = event->tool; | 701 | struct wlr_tablet_tool *tool = event->tool; |
771 | if (!tool->data) { | 702 | if (!tool->data) { |
772 | struct sway_tablet *tablet = get_tablet_for_device(cursor, event->device); | 703 | struct sway_tablet *tablet = get_tablet_for_device(cursor, |
704 | &event->tablet->base); | ||
773 | if (!tablet) { | 705 | if (!tablet) { |
774 | sway_log(SWAY_ERROR, "no tablet for tablet tool"); | 706 | sway_log(SWAY_ERROR, "no tablet for tablet tool"); |
775 | return; | 707 | return; |
@@ -794,8 +726,8 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) { | |||
794 | 726 | ||
795 | static void handle_tool_button(struct wl_listener *listener, void *data) { | 727 | static void handle_tool_button(struct wl_listener *listener, void *data) { |
796 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); | 728 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); |
797 | struct wlr_event_tablet_tool_button *event = data; | 729 | struct wlr_tablet_tool_button_event *event = data; |
798 | cursor_handle_activity_from_device(cursor, event->device); | 730 | cursor_handle_activity_from_device(cursor, &event->tablet->base); |
799 | 731 | ||
800 | struct sway_tablet_tool *sway_tool = event->tool->data; | 732 | struct sway_tablet_tool *sway_tool = event->tool->data; |
801 | if (!sway_tool) { | 733 | if (!sway_tool) { |
@@ -810,31 +742,71 @@ static void handle_tool_button(struct wl_listener *listener, void *data) { | |||
810 | node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, | 742 | node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, |
811 | &surface, &sx, &sy); | 743 | &surface, &sx, &sy); |
812 | 744 | ||
813 | if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { | 745 | // TODO: floating resize should support graphics tablet events |
746 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat); | ||
747 | uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; | ||
748 | bool mod_pressed = modifiers & config->floating_mod; | ||
749 | |||
750 | bool surface_supports_tablet_events = | ||
751 | surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface); | ||
752 | |||
753 | // Simulate pointer when: | ||
754 | // 1. The modifier key is pressed, OR | ||
755 | // 2. The surface under the cursor does not support tablet events. | ||
756 | bool should_simulate_pointer = mod_pressed || !surface_supports_tablet_events; | ||
757 | |||
758 | // Similar to tool tip, we need to selectively simulate mouse events, but we | ||
759 | // want to make sure that it is always consistent. Because all tool buttons | ||
760 | // currently map to BTN_RIGHT, we need to keep count of how many tool | ||
761 | // buttons are currently pressed down so we can send consistent events. | ||
762 | // | ||
763 | // The logic follows: | ||
764 | // - If we are already simulating the pointer, we should continue to do so | ||
765 | // until at least no tool button is held down. | ||
766 | // - If we should simulate the pointer and no tool button is currently held | ||
767 | // down, begin simulating the pointer. | ||
768 | // - If neither of the above are true, send the tablet events. | ||
769 | if ((cursor->tool_buttons > 0 && cursor->simulating_pointer_from_tool_button) | ||
770 | || (cursor->tool_buttons == 0 && should_simulate_pointer)) { | ||
771 | cursor->simulating_pointer_from_tool_button = true; | ||
772 | |||
814 | // TODO: the user may want to configure which tool buttons are mapped to | 773 | // TODO: the user may want to configure which tool buttons are mapped to |
815 | // which simulated pointer buttons | 774 | // which simulated pointer buttons |
816 | switch (event->state) { | 775 | switch (event->state) { |
817 | case WLR_BUTTON_PRESSED: | 776 | case WLR_BUTTON_PRESSED: |
818 | if (cursor->tool_buttons == 0) { | 777 | if (cursor->tool_buttons == 0) { |
819 | dispatch_cursor_button(cursor, event->device, | 778 | dispatch_cursor_button(cursor, &event->tablet->base, |
820 | event->time_msec, BTN_RIGHT, event->state); | 779 | event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_PRESSED); |
821 | } | 780 | } |
822 | cursor->tool_buttons++; | ||
823 | break; | 781 | break; |
824 | case WLR_BUTTON_RELEASED: | 782 | case WLR_BUTTON_RELEASED: |
825 | if (cursor->tool_buttons == 1) { | 783 | if (cursor->tool_buttons <= 1) { |
826 | dispatch_cursor_button(cursor, event->device, | 784 | dispatch_cursor_button(cursor, &event->tablet->base, |
827 | event->time_msec, BTN_RIGHT, event->state); | 785 | event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_RELEASED); |
828 | } | 786 | } |
829 | cursor->tool_buttons--; | ||
830 | break; | 787 | break; |
831 | } | 788 | } |
832 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); | 789 | wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); |
833 | return; | 790 | } else { |
791 | cursor->simulating_pointer_from_tool_button = false; | ||
792 | |||
793 | wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool, | ||
794 | event->button, (enum zwp_tablet_pad_v2_button_state)event->state); | ||
834 | } | 795 | } |
835 | 796 | ||
836 | wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool, | 797 | // Update tool button count. |
837 | event->button, (enum zwp_tablet_pad_v2_button_state)event->state); | 798 | switch (event->state) { |
799 | case WLR_BUTTON_PRESSED: | ||
800 | cursor->tool_buttons++; | ||
801 | break; | ||
802 | case WLR_BUTTON_RELEASED: | ||
803 | if (cursor->tool_buttons == 0) { | ||
804 | sway_log(SWAY_ERROR, "inconsistent tablet tool button events"); | ||
805 | } else { | ||
806 | cursor->tool_buttons--; | ||
807 | } | ||
808 | break; | ||
809 | } | ||
838 | } | 810 | } |
839 | 811 | ||
840 | static void check_constraint_region(struct sway_cursor *cursor) { | 812 | static void check_constraint_region(struct sway_cursor *cursor) { |
@@ -920,59 +892,68 @@ static void handle_request_pointer_set_cursor(struct wl_listener *listener, | |||
920 | event->hotspot_y, focused_client); | 892 | event->hotspot_y, focused_client); |
921 | } | 893 | } |
922 | 894 | ||
895 | static void handle_pointer_hold_begin(struct wl_listener *listener, void *data) { | ||
896 | struct sway_cursor *cursor = wl_container_of( | ||
897 | listener, cursor, hold_begin); | ||
898 | struct wlr_pointer_hold_begin_event *event = data; | ||
899 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | ||
900 | seatop_hold_begin(cursor->seat, event); | ||
901 | } | ||
902 | |||
903 | static void handle_pointer_hold_end(struct wl_listener *listener, void *data) { | ||
904 | struct sway_cursor *cursor = wl_container_of( | ||
905 | listener, cursor, hold_end); | ||
906 | struct wlr_pointer_hold_end_event *event = data; | ||
907 | cursor_handle_activity_from_device(cursor, &event->pointer->base); | ||
908 | seatop_hold_end(cursor->seat, event); | ||
909 | } | ||
910 | |||
923 | static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) { | 911 | static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) { |
924 | struct sway_cursor *cursor = wl_container_of( | 912 | struct sway_cursor *cursor = wl_container_of( |
925 | listener, cursor, pinch_begin); | 913 | listener, cursor, pinch_begin); |
926 | struct wlr_event_pointer_pinch_begin *event = data; | 914 | struct wlr_pointer_pinch_begin_event *event = data; |
927 | wlr_pointer_gestures_v1_send_pinch_begin( | 915 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
928 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 916 | seatop_pinch_begin(cursor->seat, event); |
929 | event->time_msec, event->fingers); | ||
930 | } | 917 | } |
931 | 918 | ||
932 | static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) { | 919 | static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) { |
933 | struct sway_cursor *cursor = wl_container_of( | 920 | struct sway_cursor *cursor = wl_container_of( |
934 | listener, cursor, pinch_update); | 921 | listener, cursor, pinch_update); |
935 | struct wlr_event_pointer_pinch_update *event = data; | 922 | struct wlr_pointer_pinch_update_event *event = data; |
936 | wlr_pointer_gestures_v1_send_pinch_update( | 923 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
937 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 924 | seatop_pinch_update(cursor->seat, event); |
938 | event->time_msec, event->dx, event->dy, | ||
939 | event->scale, event->rotation); | ||
940 | } | 925 | } |
941 | 926 | ||
942 | static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { | 927 | static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { |
943 | struct sway_cursor *cursor = wl_container_of( | 928 | struct sway_cursor *cursor = wl_container_of( |
944 | listener, cursor, pinch_end); | 929 | listener, cursor, pinch_end); |
945 | struct wlr_event_pointer_pinch_end *event = data; | 930 | struct wlr_pointer_pinch_end_event *event = data; |
946 | wlr_pointer_gestures_v1_send_pinch_end( | 931 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
947 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 932 | seatop_pinch_end(cursor->seat, event); |
948 | event->time_msec, event->cancelled); | ||
949 | } | 933 | } |
950 | 934 | ||
951 | static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) { | 935 | static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) { |
952 | struct sway_cursor *cursor = wl_container_of( | 936 | struct sway_cursor *cursor = wl_container_of( |
953 | listener, cursor, swipe_begin); | 937 | listener, cursor, swipe_begin); |
954 | struct wlr_event_pointer_swipe_begin *event = data; | 938 | struct wlr_pointer_swipe_begin_event *event = data; |
955 | wlr_pointer_gestures_v1_send_swipe_begin( | 939 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
956 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 940 | seatop_swipe_begin(cursor->seat, event); |
957 | event->time_msec, event->fingers); | ||
958 | } | 941 | } |
959 | 942 | ||
960 | static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) { | 943 | static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) { |
961 | struct sway_cursor *cursor = wl_container_of( | 944 | struct sway_cursor *cursor = wl_container_of( |
962 | listener, cursor, swipe_update); | 945 | listener, cursor, swipe_update); |
963 | struct wlr_event_pointer_swipe_update *event = data; | 946 | struct wlr_pointer_swipe_update_event *event = data; |
964 | wlr_pointer_gestures_v1_send_swipe_update( | 947 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
965 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 948 | seatop_swipe_update(cursor->seat, event); |
966 | event->time_msec, event->dx, event->dy); | ||
967 | } | 949 | } |
968 | 950 | ||
969 | static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { | 951 | static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { |
970 | struct sway_cursor *cursor = wl_container_of( | 952 | struct sway_cursor *cursor = wl_container_of( |
971 | listener, cursor, swipe_end); | 953 | listener, cursor, swipe_end); |
972 | struct wlr_event_pointer_swipe_end *event = data; | 954 | struct wlr_pointer_swipe_end_event *event = data; |
973 | wlr_pointer_gestures_v1_send_swipe_end( | 955 | cursor_handle_activity_from_device(cursor, &event->pointer->base); |
974 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 956 | seatop_swipe_end(cursor->seat, event); |
975 | event->time_msec, event->cancelled); | ||
976 | } | 957 | } |
977 | 958 | ||
978 | static void handle_image_surface_destroy(struct wl_listener *listener, | 959 | static void handle_image_surface_destroy(struct wl_listener *listener, |
@@ -1011,10 +992,9 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image, | |||
1011 | } | 992 | } |
1012 | 993 | ||
1013 | if (!image) { | 994 | if (!image) { |
1014 | wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); | 995 | wlr_cursor_unset_image(cursor->cursor); |
1015 | } else if (!current_image || strcmp(current_image, image) != 0) { | 996 | } else if (!current_image || strcmp(current_image, image) != 0) { |
1016 | wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, | 997 | wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image); |
1017 | cursor->cursor); | ||
1018 | } | 998 | } |
1019 | } | 999 | } |
1020 | 1000 | ||
@@ -1046,6 +1026,8 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { | |||
1046 | wl_event_source_remove(cursor->hide_source); | 1026 | wl_event_source_remove(cursor->hide_source); |
1047 | 1027 | ||
1048 | wl_list_remove(&cursor->image_surface_destroy.link); | 1028 | wl_list_remove(&cursor->image_surface_destroy.link); |
1029 | wl_list_remove(&cursor->hold_begin.link); | ||
1030 | wl_list_remove(&cursor->hold_end.link); | ||
1049 | wl_list_remove(&cursor->pinch_begin.link); | 1031 | wl_list_remove(&cursor->pinch_begin.link); |
1050 | wl_list_remove(&cursor->pinch_update.link); | 1032 | wl_list_remove(&cursor->pinch_update.link); |
1051 | wl_list_remove(&cursor->pinch_end.link); | 1033 | wl_list_remove(&cursor->pinch_end.link); |
@@ -1059,6 +1041,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { | |||
1059 | wl_list_remove(&cursor->frame.link); | 1041 | wl_list_remove(&cursor->frame.link); |
1060 | wl_list_remove(&cursor->touch_down.link); | 1042 | wl_list_remove(&cursor->touch_down.link); |
1061 | wl_list_remove(&cursor->touch_up.link); | 1043 | wl_list_remove(&cursor->touch_up.link); |
1044 | wl_list_remove(&cursor->touch_cancel.link); | ||
1062 | wl_list_remove(&cursor->touch_motion.link); | 1045 | wl_list_remove(&cursor->touch_motion.link); |
1063 | wl_list_remove(&cursor->touch_frame.link); | 1046 | wl_list_remove(&cursor->touch_frame.link); |
1064 | wl_list_remove(&cursor->tool_axis.link); | 1047 | wl_list_remove(&cursor->tool_axis.link); |
@@ -1095,19 +1078,24 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
1095 | wl_list_init(&cursor->image_surface_destroy.link); | 1078 | wl_list_init(&cursor->image_surface_destroy.link); |
1096 | cursor->image_surface_destroy.notify = handle_image_surface_destroy; | 1079 | cursor->image_surface_destroy.notify = handle_image_surface_destroy; |
1097 | 1080 | ||
1098 | cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display); | 1081 | wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin); |
1099 | cursor->pinch_begin.notify = handle_pointer_pinch_begin; | 1082 | cursor->hold_begin.notify = handle_pointer_hold_begin; |
1083 | wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end); | ||
1084 | cursor->hold_end.notify = handle_pointer_hold_end; | ||
1085 | |||
1100 | wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); | 1086 | wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); |
1101 | cursor->pinch_update.notify = handle_pointer_pinch_update; | 1087 | cursor->pinch_begin.notify = handle_pointer_pinch_begin; |
1102 | wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update); | 1088 | wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update); |
1103 | cursor->pinch_end.notify = handle_pointer_pinch_end; | 1089 | cursor->pinch_update.notify = handle_pointer_pinch_update; |
1104 | wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end); | 1090 | wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end); |
1105 | cursor->swipe_begin.notify = handle_pointer_swipe_begin; | 1091 | cursor->pinch_end.notify = handle_pointer_pinch_end; |
1092 | |||
1106 | wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin); | 1093 | wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin); |
1107 | cursor->swipe_update.notify = handle_pointer_swipe_update; | 1094 | cursor->swipe_begin.notify = handle_pointer_swipe_begin; |
1108 | wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); | 1095 | wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); |
1109 | cursor->swipe_end.notify = handle_pointer_swipe_end; | 1096 | cursor->swipe_update.notify = handle_pointer_swipe_update; |
1110 | wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end); | 1097 | wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end); |
1098 | cursor->swipe_end.notify = handle_pointer_swipe_end; | ||
1111 | 1099 | ||
1112 | // input events | 1100 | // input events |
1113 | wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); | 1101 | wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); |
@@ -1132,6 +1120,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
1132 | wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); | 1120 | wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); |
1133 | cursor->touch_up.notify = handle_touch_up; | 1121 | cursor->touch_up.notify = handle_touch_up; |
1134 | 1122 | ||
1123 | wl_signal_add(&wlr_cursor->events.touch_cancel, &cursor->touch_cancel); | ||
1124 | cursor->touch_cancel.notify = handle_touch_cancel; | ||
1125 | |||
1135 | wl_signal_add(&wlr_cursor->events.touch_motion, | 1126 | wl_signal_add(&wlr_cursor->events.touch_motion, |
1136 | &cursor->touch_motion); | 1127 | &cursor->touch_motion); |
1137 | cursor->touch_motion.notify = handle_touch_motion; | 1128 | cursor->touch_motion.notify = handle_touch_motion; |
@@ -1224,11 +1215,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) { | |||
1224 | // Get event code from name | 1215 | // Get event code from name |
1225 | int code = libevdev_event_code_from_name(EV_KEY, name); | 1216 | int code = libevdev_event_code_from_name(EV_KEY, name); |
1226 | if (code == -1) { | 1217 | if (code == -1) { |
1227 | size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1; | 1218 | *error = format_str("Unknown event %s", name); |
1228 | *error = malloc(len); | ||
1229 | if (*error) { | ||
1230 | snprintf(*error, len, "Unknown event %s", name); | ||
1231 | } | ||
1232 | return 0; | 1219 | return 0; |
1233 | } | 1220 | } |
1234 | return code; | 1221 | return code; |
@@ -1250,13 +1237,8 @@ uint32_t get_mouse_bindcode(const char *name, char **error) { | |||
1250 | } | 1237 | } |
1251 | const char *event = libevdev_event_code_get_name(EV_KEY, code); | 1238 | const char *event = libevdev_event_code_get_name(EV_KEY, code); |
1252 | if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { | 1239 | if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { |
1253 | size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button", | 1240 | *error = format_str("Event code %d (%s) is not a button", |
1254 | code, event ? event : "(null)") + 1; | 1241 | code, event ? event : "(null)"); |
1255 | *error = malloc(len); | ||
1256 | if (*error) { | ||
1257 | snprintf(*error, len, "Event code %d (%s) is not a button", | ||
1258 | code, event ? event : "(null)"); | ||
1259 | } | ||
1260 | return 0; | 1242 | return 0; |
1261 | } | 1243 | } |
1262 | return code; | 1244 | return code; |
@@ -1289,12 +1271,15 @@ const char *get_mouse_button_name(uint32_t button) { | |||
1289 | static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { | 1271 | static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { |
1290 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; | 1272 | struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; |
1291 | 1273 | ||
1292 | if (constraint->current.committed & | 1274 | if (constraint->current.cursor_hint.enabled) { |
1293 | WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { | ||
1294 | double sx = constraint->current.cursor_hint.x; | 1275 | double sx = constraint->current.cursor_hint.x; |
1295 | double sy = constraint->current.cursor_hint.y; | 1276 | double sy = constraint->current.cursor_hint.y; |
1296 | 1277 | ||
1297 | struct sway_view *view = view_from_wlr_surface(constraint->surface); | 1278 | struct sway_view *view = view_from_wlr_surface(constraint->surface); |
1279 | if (!view) { | ||
1280 | return; | ||
1281 | } | ||
1282 | |||
1298 | struct sway_container *con = view->container; | 1283 | struct sway_container *con = view->container; |
1299 | 1284 | ||
1300 | double lx = sx + con->pending.content_x - view->geometry.x; | 1285 | double lx = sx + con->pending.content_x - view->geometry.x; |
@@ -1345,12 +1330,9 @@ void handle_pointer_constraint(struct wl_listener *listener, void *data) { | |||
1345 | sway_constraint->destroy.notify = handle_constraint_destroy; | 1330 | sway_constraint->destroy.notify = handle_constraint_destroy; |
1346 | wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); | 1331 | wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); |
1347 | 1332 | ||
1348 | struct sway_node *focus = seat_get_focus(seat); | 1333 | struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface; |
1349 | if (focus && focus->type == N_CONTAINER && focus->sway_container->view) { | 1334 | if (surface && surface == constraint->surface) { |
1350 | struct wlr_surface *surface = focus->sway_container->view->surface; | 1335 | sway_cursor_constrain(seat->cursor, constraint); |
1351 | if (surface == constraint->surface) { | ||
1352 | sway_cursor_constrain(seat->cursor, constraint); | ||
1353 | } | ||
1354 | } | 1336 | } |
1355 | } | 1337 | } |
1356 | 1338 | ||
@@ -1408,3 +1390,26 @@ void sway_cursor_constrain(struct sway_cursor *cursor, | |||
1408 | wl_signal_add(&constraint->surface->events.commit, | 1390 | wl_signal_add(&constraint->surface->events.commit, |
1409 | &cursor->constraint_commit); | 1391 | &cursor->constraint_commit); |
1410 | } | 1392 | } |
1393 | |||
1394 | void handle_request_set_cursor_shape(struct wl_listener *listener, void *data) { | ||
1395 | const struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; | ||
1396 | struct sway_seat *seat = event->seat_client->seat->data; | ||
1397 | |||
1398 | if (!seatop_allows_set_cursor(seat)) { | ||
1399 | return; | ||
1400 | } | ||
1401 | |||
1402 | struct wl_client *focused_client = NULL; | ||
1403 | struct wlr_surface *focused_surface = seat->wlr_seat->pointer_state.focused_surface; | ||
1404 | if (focused_surface != NULL) { | ||
1405 | focused_client = wl_resource_get_client(focused_surface->resource); | ||
1406 | } | ||
1407 | |||
1408 | // TODO: check cursor mode | ||
1409 | if (focused_client == NULL || event->seat_client->client != focused_client) { | ||
1410 | sway_log(SWAY_DEBUG, "denying request to set cursor from unfocused client"); | ||
1411 | return; | ||
1412 | } | ||
1413 | |||
1414 | cursor_set_image(seat->cursor, wlr_cursor_shape_v1_name(event->shape), focused_client); | ||
1415 | } | ||
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index f04a8ce0..248ca34e 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -1,12 +1,12 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <ctype.h> | 1 | #include <ctype.h> |
3 | #include <stdio.h> | 2 | #include <stdio.h> |
4 | #include <string.h> | 3 | #include <string.h> |
5 | #include <math.h> | 4 | #include <math.h> |
5 | #include <assert.h> | ||
6 | #include <wlr/config.h> | ||
6 | #include <wlr/backend/libinput.h> | 7 | #include <wlr/backend/libinput.h> |
7 | #include <wlr/types/wlr_cursor.h> | 8 | #include <wlr/types/wlr_cursor.h> |
8 | #include <wlr/types/wlr_keyboard_group.h> | 9 | #include <wlr/types/wlr_keyboard_group.h> |
9 | #include <wlr/types/wlr_input_inhibitor.h> | ||
10 | #include <wlr/types/wlr_virtual_keyboard_v1.h> | 10 | #include <wlr/types/wlr_virtual_keyboard_v1.h> |
11 | #include <wlr/types/wlr_virtual_pointer_v1.h> | 11 | #include <wlr/types/wlr_virtual_pointer_v1.h> |
12 | #include "sway/config.h" | 12 | #include "sway/config.h" |
@@ -22,6 +22,10 @@ | |||
22 | #include "list.h" | 22 | #include "list.h" |
23 | #include "log.h" | 23 | #include "log.h" |
24 | 24 | ||
25 | #if WLR_HAS_LIBINPUT_BACKEND | ||
26 | #include <wlr/backend/libinput.h> | ||
27 | #endif | ||
28 | |||
25 | #define DEFAULT_SEAT "seat0" | 29 | #define DEFAULT_SEAT "seat0" |
26 | 30 | ||
27 | struct input_config *current_input_config = NULL; | 31 | struct input_config *current_input_config = NULL; |
@@ -63,8 +67,15 @@ struct sway_seat *input_manager_sway_seat_from_wlr_seat(struct wlr_seat *wlr_sea | |||
63 | } | 67 | } |
64 | 68 | ||
65 | char *input_device_get_identifier(struct wlr_input_device *device) { | 69 | char *input_device_get_identifier(struct wlr_input_device *device) { |
66 | int vendor = device->vendor; | 70 | int vendor = 0, product = 0; |
67 | int product = device->product; | 71 | #if WLR_HAS_LIBINPUT_BACKEND |
72 | if (wlr_input_device_is_libinput(device)) { | ||
73 | struct libinput_device *libinput_dev = wlr_libinput_get_device_handle(device); | ||
74 | vendor = libinput_device_get_id_vendor(libinput_dev); | ||
75 | product = libinput_device_get_id_product(libinput_dev); | ||
76 | } | ||
77 | #endif | ||
78 | |||
68 | char *name = strdup(device->name ? device->name : ""); | 79 | char *name = strdup(device->name ? device->name : ""); |
69 | strip_whitespace(name); | 80 | strip_whitespace(name); |
70 | 81 | ||
@@ -76,20 +87,13 @@ char *input_device_get_identifier(struct wlr_input_device *device) { | |||
76 | } | 87 | } |
77 | } | 88 | } |
78 | 89 | ||
79 | const char *fmt = "%d:%d:%s"; | 90 | char *identifier = format_str("%d:%d:%s", vendor, product, name); |
80 | int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; | ||
81 | char *identifier = malloc(len); | ||
82 | if (!identifier) { | ||
83 | sway_log(SWAY_ERROR, "Unable to allocate unique input device name"); | ||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | snprintf(identifier, len, fmt, vendor, product, name); | ||
88 | free(name); | 91 | free(name); |
89 | return identifier; | 92 | return identifier; |
90 | } | 93 | } |
91 | 94 | ||
92 | static bool device_is_touchpad(struct sway_input_device *device) { | 95 | static bool device_is_touchpad(struct sway_input_device *device) { |
96 | #if WLR_HAS_LIBINPUT_BACKEND | ||
93 | if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER || | 97 | if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER || |
94 | !wlr_input_device_is_libinput(device->wlr_device)) { | 98 | !wlr_input_device_is_libinput(device->wlr_device)) { |
95 | return false; | 99 | return false; |
@@ -99,6 +103,9 @@ static bool device_is_touchpad(struct sway_input_device *device) { | |||
99 | wlr_libinput_get_device_handle(device->wlr_device); | 103 | wlr_libinput_get_device_handle(device->wlr_device); |
100 | 104 | ||
101 | return libinput_device_config_tap_get_finger_count(libinput_device) > 0; | 105 | return libinput_device_config_tap_get_finger_count(libinput_device) > 0; |
106 | #else | ||
107 | return false; | ||
108 | #endif | ||
102 | } | 109 | } |
103 | 110 | ||
104 | const char *input_device_get_type(struct sway_input_device *device) { | 111 | const char *input_device_get_type(struct sway_input_device *device) { |
@@ -113,7 +120,7 @@ const char *input_device_get_type(struct sway_input_device *device) { | |||
113 | return "keyboard"; | 120 | return "keyboard"; |
114 | case WLR_INPUT_DEVICE_TOUCH: | 121 | case WLR_INPUT_DEVICE_TOUCH: |
115 | return "touch"; | 122 | return "touch"; |
116 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 123 | case WLR_INPUT_DEVICE_TABLET: |
117 | return "tablet_tool"; | 124 | return "tablet_tool"; |
118 | case WLR_INPUT_DEVICE_TABLET_PAD: | 125 | case WLR_INPUT_DEVICE_TABLET_PAD: |
119 | return "tablet_pad"; | 126 | return "tablet_pad"; |
@@ -236,7 +243,11 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
236 | 243 | ||
237 | apply_input_type_config(input_device); | 244 | apply_input_type_config(input_device); |
238 | 245 | ||
239 | sway_input_configure_libinput_device(input_device); | 246 | #if WLR_HAS_LIBINPUT_BACKEND |
247 | bool config_changed = sway_input_configure_libinput_device(input_device); | ||
248 | #else | ||
249 | bool config_changed = false; | ||
250 | #endif | ||
240 | 251 | ||
241 | wl_signal_add(&device->events.destroy, &input_device->device_destroy); | 252 | wl_signal_add(&device->events.destroy, &input_device->device_destroy); |
242 | input_device->device_destroy.notify = handle_device_destroy; | 253 | input_device->device_destroy.notify = handle_device_destroy; |
@@ -274,29 +285,9 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
274 | } | 285 | } |
275 | 286 | ||
276 | ipc_event_input("added", input_device); | 287 | ipc_event_input("added", input_device); |
277 | } | ||
278 | 288 | ||
279 | static void handle_inhibit_activate(struct wl_listener *listener, void *data) { | 289 | if (config_changed) { |
280 | struct sway_input_manager *input_manager = wl_container_of( | 290 | ipc_event_input("libinput_config", input_device); |
281 | listener, input_manager, inhibit_activate); | ||
282 | struct sway_seat *seat; | ||
283 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
284 | seat_set_exclusive_client(seat, input_manager->inhibit->active_client); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) { | ||
289 | struct sway_input_manager *input_manager = wl_container_of( | ||
290 | listener, input_manager, inhibit_deactivate); | ||
291 | struct sway_seat *seat; | ||
292 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
293 | seat_set_exclusive_client(seat, NULL); | ||
294 | struct sway_node *previous = seat_get_focus(seat); | ||
295 | if (previous) { | ||
296 | // Hack to get seat to re-focus the return value of get_focus | ||
297 | seat_set_focus(seat, NULL); | ||
298 | seat_set_focus(seat, previous); | ||
299 | } | ||
300 | } | 291 | } |
301 | } | 292 | } |
302 | 293 | ||
@@ -377,7 +368,7 @@ void handle_virtual_keyboard(struct wl_listener *listener, void *data) { | |||
377 | struct sway_input_manager *input_manager = | 368 | struct sway_input_manager *input_manager = |
378 | wl_container_of(listener, input_manager, virtual_keyboard_new); | 369 | wl_container_of(listener, input_manager, virtual_keyboard_new); |
379 | struct wlr_virtual_keyboard_v1 *keyboard = data; | 370 | struct wlr_virtual_keyboard_v1 *keyboard = data; |
380 | struct wlr_input_device *device = &keyboard->input_device; | 371 | struct wlr_input_device *device = &keyboard->keyboard.base; |
381 | 372 | ||
382 | // TODO: Amend protocol to allow NULL seat | 373 | // TODO: Amend protocol to allow NULL seat |
383 | struct sway_seat *seat = keyboard->seat ? | 374 | struct sway_seat *seat = keyboard->seat ? |
@@ -410,7 +401,7 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) { | |||
410 | wl_container_of(listener, input_manager, virtual_pointer_new); | 401 | wl_container_of(listener, input_manager, virtual_pointer_new); |
411 | struct wlr_virtual_pointer_v1_new_pointer_event *event = data; | 402 | struct wlr_virtual_pointer_v1_new_pointer_event *event = data; |
412 | struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; | 403 | struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; |
413 | struct wlr_input_device *device = &pointer->input_device; | 404 | struct wlr_input_device *device = &pointer->pointer.base; |
414 | 405 | ||
415 | struct sway_seat *seat = event->suggested_seat ? | 406 | struct sway_seat *seat = event->suggested_seat ? |
416 | input_manager_sway_seat_from_wlr_seat(event->suggested_seat) : | 407 | input_manager_sway_seat_from_wlr_seat(event->suggested_seat) : |
@@ -442,6 +433,20 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) { | |||
442 | } | 433 | } |
443 | } | 434 | } |
444 | 435 | ||
436 | static void handle_transient_seat_manager_create_seat( | ||
437 | struct wl_listener *listener, void *data) { | ||
438 | struct wlr_transient_seat_v1 *transient_seat = data; | ||
439 | static uint64_t i; | ||
440 | char name[256]; | ||
441 | snprintf(name, sizeof(name), "transient-%"PRIx64, i++); | ||
442 | struct sway_seat *seat = seat_create(name); | ||
443 | if (seat && seat->wlr_seat) { | ||
444 | wlr_transient_seat_v1_ready(transient_seat, seat->wlr_seat); | ||
445 | } else { | ||
446 | wlr_transient_seat_v1_deny(transient_seat); | ||
447 | } | ||
448 | } | ||
449 | |||
445 | struct sway_input_manager *input_manager_create(struct sway_server *server) { | 450 | struct sway_input_manager *input_manager_create(struct sway_server *server) { |
446 | struct sway_input_manager *input = | 451 | struct sway_input_manager *input = |
447 | calloc(1, sizeof(struct sway_input_manager)); | 452 | calloc(1, sizeof(struct sway_input_manager)); |
@@ -468,14 +473,6 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) { | |||
468 | &input->virtual_pointer_new); | 473 | &input->virtual_pointer_new); |
469 | input->virtual_pointer_new.notify = handle_virtual_pointer; | 474 | input->virtual_pointer_new.notify = handle_virtual_pointer; |
470 | 475 | ||
471 | input->inhibit = wlr_input_inhibit_manager_create(server->wl_display); | ||
472 | input->inhibit_activate.notify = handle_inhibit_activate; | ||
473 | wl_signal_add(&input->inhibit->events.activate, | ||
474 | &input->inhibit_activate); | ||
475 | input->inhibit_deactivate.notify = handle_inhibit_deactivate; | ||
476 | wl_signal_add(&input->inhibit->events.deactivate, | ||
477 | &input->inhibit_deactivate); | ||
478 | |||
479 | input->keyboard_shortcuts_inhibit = | 476 | input->keyboard_shortcuts_inhibit = |
480 | wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display); | 477 | wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display); |
481 | input->keyboard_shortcuts_inhibit_new_inhibitor.notify = | 478 | input->keyboard_shortcuts_inhibit_new_inhibitor.notify = |
@@ -483,6 +480,17 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) { | |||
483 | wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor, | 480 | wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor, |
484 | &input->keyboard_shortcuts_inhibit_new_inhibitor); | 481 | &input->keyboard_shortcuts_inhibit_new_inhibitor); |
485 | 482 | ||
483 | input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display); | ||
484 | |||
485 | input->transient_seat_manager = | ||
486 | wlr_transient_seat_manager_v1_create(server->wl_display); | ||
487 | assert(input->transient_seat_manager); | ||
488 | |||
489 | input->transient_seat_create.notify = | ||
490 | handle_transient_seat_manager_create_seat; | ||
491 | wl_signal_add(&input->transient_seat_manager->events.create_seat, | ||
492 | &input->transient_seat_create); | ||
493 | |||
486 | return input; | 494 | return input; |
487 | } | 495 | } |
488 | 496 | ||
@@ -520,21 +528,50 @@ static void retranslate_keysyms(struct input_config *input_config) { | |||
520 | return; | 528 | return; |
521 | } | 529 | } |
522 | } | 530 | } |
531 | |||
532 | for (int i = 0; i < config->input_type_configs->length; ++i) { | ||
533 | struct input_config *ic = config->input_type_configs->items[i]; | ||
534 | if (ic->xkb_layout || ic->xkb_file) { | ||
535 | // this is the first config with xkb_layout or xkb_file | ||
536 | if (ic->identifier == input_config->identifier) { | ||
537 | translate_keysyms(ic); | ||
538 | } | ||
539 | |||
540 | return; | ||
541 | } | ||
542 | } | ||
523 | } | 543 | } |
524 | 544 | ||
525 | static void input_manager_configure_input( | 545 | static void input_manager_configure_input( |
526 | struct sway_input_device *input_device) { | 546 | struct sway_input_device *input_device) { |
527 | sway_input_configure_libinput_device(input_device); | 547 | #if WLR_HAS_LIBINPUT_BACKEND |
548 | bool config_changed = sway_input_configure_libinput_device(input_device); | ||
549 | #else | ||
550 | bool config_changed = false; | ||
551 | #endif | ||
528 | struct sway_seat *seat = NULL; | 552 | struct sway_seat *seat = NULL; |
529 | wl_list_for_each(seat, &server.input->seats, link) { | 553 | wl_list_for_each(seat, &server.input->seats, link) { |
530 | seat_configure_device(seat, input_device); | 554 | seat_configure_device(seat, input_device); |
531 | } | 555 | } |
556 | if (config_changed) { | ||
557 | ipc_event_input("libinput_config", input_device); | ||
558 | } | ||
532 | } | 559 | } |
533 | 560 | ||
534 | void input_manager_configure_all_inputs(void) { | 561 | void input_manager_configure_all_input_mappings(void) { |
535 | struct sway_input_device *input_device = NULL; | 562 | struct sway_input_device *input_device; |
536 | wl_list_for_each(input_device, &server.input->devices, link) { | 563 | wl_list_for_each(input_device, &server.input->devices, link) { |
537 | input_manager_configure_input(input_device); | 564 | struct sway_seat *seat; |
565 | wl_list_for_each(seat, &server.input->seats, link) { | ||
566 | seat_configure_device_mapping(seat, input_device); | ||
567 | } | ||
568 | |||
569 | #if WLR_HAS_LIBINPUT_BACKEND | ||
570 | // Input devices mapped to unavailable outputs get their libinput | ||
571 | // send_events setting switched to false. We need to re-enable this | ||
572 | // when the output appears. | ||
573 | sway_input_configure_libinput_device_send_events(input_device); | ||
574 | #endif | ||
538 | } | 575 | } |
539 | } | 576 | } |
540 | 577 | ||
@@ -556,7 +593,9 @@ void input_manager_apply_input_config(struct input_config *input_config) { | |||
556 | } | 593 | } |
557 | 594 | ||
558 | void input_manager_reset_input(struct sway_input_device *input_device) { | 595 | void input_manager_reset_input(struct sway_input_device *input_device) { |
596 | #if WLR_HAS_LIBINPUT_BACKEND | ||
559 | sway_input_reset_libinput_device(input_device); | 597 | sway_input_reset_libinput_device(input_device); |
598 | #endif | ||
560 | struct sway_seat *seat = NULL; | 599 | struct sway_seat *seat = NULL; |
561 | wl_list_for_each(seat, &server.input->seats, link) { | 600 | wl_list_for_each(seat, &server.input->seats, link) { |
562 | seat_reset_device(seat, input_device); | 601 | seat_reset_device(seat, input_device); |
@@ -564,6 +603,13 @@ void input_manager_reset_input(struct sway_input_device *input_device) { | |||
564 | } | 603 | } |
565 | 604 | ||
566 | void input_manager_reset_all_inputs(void) { | 605 | void input_manager_reset_all_inputs(void) { |
606 | // Set the active keyboard to NULL to avoid spamming configuration updates | ||
607 | // for all keyboard devices. | ||
608 | struct sway_seat *seat; | ||
609 | wl_list_for_each(seat, &server.input->seats, link) { | ||
610 | wlr_seat_set_keyboard(seat->wlr_seat, NULL); | ||
611 | } | ||
612 | |||
567 | struct sway_input_device *input_device = NULL; | 613 | struct sway_input_device *input_device = NULL; |
568 | wl_list_for_each(input_device, &server.input->devices, link) { | 614 | wl_list_for_each(input_device, &server.input->devices, link) { |
569 | input_manager_reset_input(input_device); | 615 | input_manager_reset_input(input_device); |
@@ -572,7 +618,6 @@ void input_manager_reset_all_inputs(void) { | |||
572 | // If there is at least one keyboard using the default keymap, repeat delay, | 618 | // If there is at least one keyboard using the default keymap, repeat delay, |
573 | // and repeat rate, then it is possible that there is a keyboard group that | 619 | // and repeat rate, then it is possible that there is a keyboard group that |
574 | // need their keyboard disarmed. | 620 | // need their keyboard disarmed. |
575 | struct sway_seat *seat; | ||
576 | wl_list_for_each(seat, &server.input->seats, link) { | 621 | wl_list_for_each(seat, &server.input->seats, link) { |
577 | struct sway_keyboard_group *group; | 622 | struct sway_keyboard_group *group; |
578 | wl_list_for_each(group, &seat->keyboard_groups, link) { | 623 | wl_list_for_each(group, &seat->keyboard_groups, link) { |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index f258ac7d..f74d0658 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -1,10 +1,9 @@ | |||
1 | #include <assert.h> | 1 | #include <assert.h> |
2 | #include <limits.h> | 2 | #include <limits.h> |
3 | #include <strings.h> | 3 | #include <strings.h> |
4 | #include <wlr/config.h> | ||
4 | #include <wlr/backend/multi.h> | 5 | #include <wlr/backend/multi.h> |
5 | #include <wlr/backend/session.h> | ||
6 | #include <wlr/interfaces/wlr_keyboard.h> | 6 | #include <wlr/interfaces/wlr_keyboard.h> |
7 | #include <wlr/types/wlr_idle.h> | ||
8 | #include <wlr/types/wlr_keyboard.h> | 7 | #include <wlr/types/wlr_keyboard.h> |
9 | #include <wlr/types/wlr_keyboard_group.h> | 8 | #include <wlr/types/wlr_keyboard_group.h> |
10 | #include <xkbcommon/xkbcommon-names.h> | 9 | #include <xkbcommon/xkbcommon-names.h> |
@@ -16,6 +15,10 @@ | |||
16 | #include "sway/ipc-server.h" | 15 | #include "sway/ipc-server.h" |
17 | #include "log.h" | 16 | #include "log.h" |
18 | 17 | ||
18 | #if WLR_HAS_SESSION | ||
19 | #include <wlr/backend/session.h> | ||
20 | #endif | ||
21 | |||
19 | static struct modifier_key { | 22 | static struct modifier_key { |
20 | char *name; | 23 | char *name; |
21 | uint32_t mod; | 24 | uint32_t mod; |
@@ -29,6 +32,7 @@ static struct modifier_key { | |||
29 | { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 }, | 32 | { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 }, |
30 | { "Mod3", WLR_MODIFIER_MOD3 }, | 33 | { "Mod3", WLR_MODIFIER_MOD3 }, |
31 | { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO }, | 34 | { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO }, |
35 | { "Super", WLR_MODIFIER_LOGO }, | ||
32 | { "Mod5", WLR_MODIFIER_MOD5 }, | 36 | { "Mod5", WLR_MODIFIER_MOD5 }, |
33 | }; | 37 | }; |
34 | 38 | ||
@@ -264,14 +268,12 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, | |||
264 | xkb_keysym_t keysym = pressed_keysyms[i]; | 268 | xkb_keysym_t keysym = pressed_keysyms[i]; |
265 | if (keysym >= XKB_KEY_XF86Switch_VT_1 && | 269 | if (keysym >= XKB_KEY_XF86Switch_VT_1 && |
266 | keysym <= XKB_KEY_XF86Switch_VT_12) { | 270 | keysym <= XKB_KEY_XF86Switch_VT_12) { |
267 | if (wlr_backend_is_multi(server.backend)) { | 271 | #if WLR_HAS_SESSION |
268 | struct wlr_session *session = | 272 | if (server.session) { |
269 | wlr_backend_get_session(server.backend); | 273 | unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1; |
270 | if (session) { | 274 | wlr_session_change_vt(server.session, vt); |
271 | unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1; | ||
272 | wlr_session_change_vt(session, vt); | ||
273 | } | ||
274 | } | 275 | } |
276 | #endif | ||
275 | return true; | 277 | return true; |
276 | } | 278 | } |
277 | } | 279 | } |
@@ -291,14 +293,12 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard, | |||
291 | static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, | 293 | static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, |
292 | xkb_keycode_t keycode, const xkb_keysym_t **keysyms, | 294 | xkb_keycode_t keycode, const xkb_keysym_t **keysyms, |
293 | uint32_t *modifiers) { | 295 | uint32_t *modifiers) { |
294 | struct wlr_input_device *device = | 296 | *modifiers = wlr_keyboard_get_modifiers(keyboard->wlr); |
295 | keyboard->seat_device->input_device->wlr_device; | ||
296 | *modifiers = wlr_keyboard_get_modifiers(device->keyboard); | ||
297 | xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2( | 297 | xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2( |
298 | device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); | 298 | keyboard->wlr->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); |
299 | *modifiers = *modifiers & ~consumed; | 299 | *modifiers = *modifiers & ~consumed; |
300 | 300 | ||
301 | return xkb_state_key_get_syms(device->keyboard->xkb_state, | 301 | return xkb_state_key_get_syms(keyboard->wlr->xkb_state, |
302 | keycode, keysyms); | 302 | keycode, keysyms); |
303 | } | 303 | } |
304 | 304 | ||
@@ -314,13 +314,11 @@ static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, | |||
314 | static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, | 314 | static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, |
315 | xkb_keycode_t keycode, const xkb_keysym_t **keysyms, | 315 | xkb_keycode_t keycode, const xkb_keysym_t **keysyms, |
316 | uint32_t *modifiers) { | 316 | uint32_t *modifiers) { |
317 | struct wlr_input_device *device = | 317 | *modifiers = wlr_keyboard_get_modifiers(keyboard->wlr); |
318 | keyboard->seat_device->input_device->wlr_device; | ||
319 | *modifiers = wlr_keyboard_get_modifiers(device->keyboard); | ||
320 | 318 | ||
321 | xkb_layout_index_t layout_index = xkb_state_key_get_layout( | 319 | xkb_layout_index_t layout_index = xkb_state_key_get_layout( |
322 | device->keyboard->xkb_state, keycode); | 320 | keyboard->wlr->xkb_state, keycode); |
323 | return xkb_keymap_key_get_syms_by_level(device->keyboard->keymap, | 321 | return xkb_keymap_key_get_syms_by_level(keyboard->wlr->keymap, |
324 | keycode, layout_index, 0, keysyms); | 322 | keycode, layout_index, 0, keysyms); |
325 | } | 323 | } |
326 | 324 | ||
@@ -360,8 +358,7 @@ static void update_keyboard_state(struct sway_keyboard *keyboard, | |||
360 | keyinfo->keycode, &keyinfo->translated_keysyms, | 358 | keyinfo->keycode, &keyinfo->translated_keysyms, |
361 | &keyinfo->translated_modifiers); | 359 | &keyinfo->translated_modifiers); |
362 | 360 | ||
363 | keyinfo->code_modifiers = wlr_keyboard_get_modifiers( | 361 | keyinfo->code_modifiers = wlr_keyboard_get_modifiers(keyboard->wlr); |
364 | keyboard->seat_device->input_device->wlr_device->keyboard); | ||
365 | 362 | ||
366 | // Update shortcut model keyinfo | 363 | // Update shortcut model keyinfo |
367 | update_shortcut_state(&keyboard->state_keycodes, raw_keycode, keystate, | 364 | update_shortcut_state(&keyboard->state_keycodes, raw_keycode, keystate, |
@@ -401,15 +398,15 @@ static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab( | |||
401 | } | 398 | } |
402 | 399 | ||
403 | static void handle_key_event(struct sway_keyboard *keyboard, | 400 | static void handle_key_event(struct sway_keyboard *keyboard, |
404 | struct wlr_event_keyboard_key *event) { | 401 | struct wlr_keyboard_key_event *event) { |
405 | struct sway_seat *seat = keyboard->seat_device->sway_seat; | 402 | struct sway_seat *seat = keyboard->seat_device->sway_seat; |
406 | struct wlr_seat *wlr_seat = seat->wlr_seat; | 403 | struct wlr_seat *wlr_seat = seat->wlr_seat; |
407 | struct wlr_input_device *wlr_device = | 404 | struct wlr_input_device *wlr_device = |
408 | keyboard->seat_device->input_device->wlr_device; | 405 | keyboard->seat_device->input_device->wlr_device; |
409 | char *device_identifier = input_device_get_identifier(wlr_device); | 406 | char *device_identifier = input_device_get_identifier(wlr_device); |
410 | bool exact_identifier = wlr_device->keyboard->group != NULL; | 407 | bool exact_identifier = keyboard->wlr->group != NULL; |
411 | seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD); | 408 | seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD); |
412 | bool input_inhibited = seat->exclusive_client != NULL; | 409 | bool locked = server.session_lock.lock; |
413 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = | 410 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = |
414 | keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); | 411 | keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); |
415 | bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; | 412 | bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; |
@@ -427,17 +424,17 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
427 | struct sway_binding *binding_released = NULL; | 424 | struct sway_binding *binding_released = NULL; |
428 | get_active_binding(&keyboard->state_keycodes, | 425 | get_active_binding(&keyboard->state_keycodes, |
429 | config->current_mode->keycode_bindings, &binding_released, | 426 | config->current_mode->keycode_bindings, &binding_released, |
430 | keyinfo.code_modifiers, true, input_inhibited, | 427 | keyinfo.code_modifiers, true, locked, |
431 | shortcuts_inhibited, device_identifier, | 428 | shortcuts_inhibited, device_identifier, |
432 | exact_identifier, keyboard->effective_layout); | 429 | exact_identifier, keyboard->effective_layout); |
433 | get_active_binding(&keyboard->state_keysyms_raw, | 430 | get_active_binding(&keyboard->state_keysyms_raw, |
434 | config->current_mode->keysym_bindings, &binding_released, | 431 | config->current_mode->keysym_bindings, &binding_released, |
435 | keyinfo.raw_modifiers, true, input_inhibited, | 432 | keyinfo.raw_modifiers, true, locked, |
436 | shortcuts_inhibited, device_identifier, | 433 | shortcuts_inhibited, device_identifier, |
437 | exact_identifier, keyboard->effective_layout); | 434 | exact_identifier, keyboard->effective_layout); |
438 | get_active_binding(&keyboard->state_keysyms_translated, | 435 | get_active_binding(&keyboard->state_keysyms_translated, |
439 | config->current_mode->keysym_bindings, &binding_released, | 436 | config->current_mode->keysym_bindings, &binding_released, |
440 | keyinfo.translated_modifiers, true, input_inhibited, | 437 | keyinfo.translated_modifiers, true, locked, |
441 | shortcuts_inhibited, device_identifier, | 438 | shortcuts_inhibited, device_identifier, |
442 | exact_identifier, keyboard->effective_layout); | 439 | exact_identifier, keyboard->effective_layout); |
443 | 440 | ||
@@ -459,17 +456,17 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
459 | if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { | 456 | if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { |
460 | get_active_binding(&keyboard->state_keycodes, | 457 | get_active_binding(&keyboard->state_keycodes, |
461 | config->current_mode->keycode_bindings, &binding, | 458 | config->current_mode->keycode_bindings, &binding, |
462 | keyinfo.code_modifiers, false, input_inhibited, | 459 | keyinfo.code_modifiers, false, locked, |
463 | shortcuts_inhibited, device_identifier, | 460 | shortcuts_inhibited, device_identifier, |
464 | exact_identifier, keyboard->effective_layout); | 461 | exact_identifier, keyboard->effective_layout); |
465 | get_active_binding(&keyboard->state_keysyms_raw, | 462 | get_active_binding(&keyboard->state_keysyms_raw, |
466 | config->current_mode->keysym_bindings, &binding, | 463 | config->current_mode->keysym_bindings, &binding, |
467 | keyinfo.raw_modifiers, false, input_inhibited, | 464 | keyinfo.raw_modifiers, false, locked, |
468 | shortcuts_inhibited, device_identifier, | 465 | shortcuts_inhibited, device_identifier, |
469 | exact_identifier, keyboard->effective_layout); | 466 | exact_identifier, keyboard->effective_layout); |
470 | get_active_binding(&keyboard->state_keysyms_translated, | 467 | get_active_binding(&keyboard->state_keysyms_translated, |
471 | config->current_mode->keysym_bindings, &binding, | 468 | config->current_mode->keysym_bindings, &binding, |
472 | keyinfo.translated_modifiers, false, input_inhibited, | 469 | keyinfo.translated_modifiers, false, locked, |
473 | shortcuts_inhibited, device_identifier, | 470 | shortcuts_inhibited, device_identifier, |
474 | exact_identifier, keyboard->effective_layout); | 471 | exact_identifier, keyboard->effective_layout); |
475 | } | 472 | } |
@@ -477,10 +474,10 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
477 | // Set up (or clear) keyboard repeat for a pressed binding. Since the | 474 | // Set up (or clear) keyboard repeat for a pressed binding. Since the |
478 | // binding may remove the keyboard, the timer needs to be updated first | 475 | // binding may remove the keyboard, the timer needs to be updated first |
479 | if (binding && !(binding->flags & BINDING_NOREPEAT) && | 476 | if (binding && !(binding->flags & BINDING_NOREPEAT) && |
480 | wlr_device->keyboard->repeat_info.delay > 0) { | 477 | keyboard->wlr->repeat_info.delay > 0) { |
481 | keyboard->repeat_binding = binding; | 478 | keyboard->repeat_binding = binding; |
482 | if (wl_event_source_timer_update(keyboard->key_repeat_source, | 479 | if (wl_event_source_timer_update(keyboard->key_repeat_source, |
483 | wlr_device->keyboard->repeat_info.delay) < 0) { | 480 | keyboard->wlr->repeat_info.delay) < 0) { |
484 | sway_log(SWAY_DEBUG, "failed to set key repeat timer"); | 481 | sway_log(SWAY_DEBUG, "failed to set key repeat timer"); |
485 | } | 482 | } |
486 | } else if (keyboard->repeat_binding) { | 483 | } else if (keyboard->repeat_binding) { |
@@ -492,7 +489,7 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
492 | handled = true; | 489 | handled = true; |
493 | } | 490 | } |
494 | 491 | ||
495 | if (!handled && wlr_device->keyboard->group) { | 492 | if (!handled && keyboard->wlr->group) { |
496 | // Only handle device specific bindings for keyboards in a group | 493 | // Only handle device specific bindings for keyboards in a group |
497 | free(device_identifier); | 494 | free(device_identifier); |
498 | return; | 495 | return; |
@@ -517,7 +514,7 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
517 | &keyboard->state_pressed_sent, event->keycode, | 514 | &keyboard->state_pressed_sent, event->keycode, |
518 | event->state, keyinfo.keycode, 0); | 515 | event->state, keyinfo.keycode, 0); |
519 | if (pressed_sent) { | 516 | if (pressed_sent) { |
520 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | 517 | wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); |
521 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, | 518 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, |
522 | event->keycode, event->state); | 519 | event->keycode, event->state); |
523 | handled = true; | 520 | handled = true; |
@@ -528,8 +525,7 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
528 | struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); | 525 | struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); |
529 | 526 | ||
530 | if (kb_grab) { | 527 | if (kb_grab) { |
531 | wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, | 528 | wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, keyboard->wlr); |
532 | wlr_device->keyboard); | ||
533 | wlr_input_method_keyboard_grab_v2_send_key(kb_grab, | 529 | wlr_input_method_keyboard_grab_v2_send_key(kb_grab, |
534 | event->time_msec, event->keycode, event->state); | 530 | event->time_msec, event->keycode, event->state); |
535 | handled = true; | 531 | handled = true; |
@@ -542,7 +538,7 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
542 | update_shortcut_state( | 538 | update_shortcut_state( |
543 | &keyboard->state_pressed_sent, event->keycode, event->state, | 539 | &keyboard->state_pressed_sent, event->keycode, event->state, |
544 | keyinfo.keycode, 0); | 540 | keyinfo.keycode, 0); |
545 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | 541 | wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); |
546 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, | 542 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, |
547 | event->keycode, event->state); | 543 | event->keycode, event->state); |
548 | } | 544 | } |
@@ -618,14 +614,12 @@ static void handle_keyboard_group_leave(struct wl_listener *listener, | |||
618 | } | 614 | } |
619 | 615 | ||
620 | static int handle_keyboard_repeat(void *data) { | 616 | static int handle_keyboard_repeat(void *data) { |
621 | struct sway_keyboard *keyboard = (struct sway_keyboard *)data; | 617 | struct sway_keyboard *keyboard = data; |
622 | struct wlr_keyboard *wlr_device = | ||
623 | keyboard->seat_device->input_device->wlr_device->keyboard; | ||
624 | if (keyboard->repeat_binding) { | 618 | if (keyboard->repeat_binding) { |
625 | if (wlr_device->repeat_info.rate > 0) { | 619 | if (keyboard->wlr->repeat_info.rate > 0) { |
626 | // We queue the next event first, as the command might cancel it | 620 | // We queue the next event first, as the command might cancel it |
627 | if (wl_event_source_timer_update(keyboard->key_repeat_source, | 621 | if (wl_event_source_timer_update(keyboard->key_repeat_source, |
628 | 1000 / wlr_device->repeat_info.rate) < 0) { | 622 | 1000 / keyboard->wlr->repeat_info.rate) < 0) { |
629 | sway_log(SWAY_DEBUG, "failed to update key repeat timer"); | 623 | sway_log(SWAY_DEBUG, "failed to update key repeat timer"); |
630 | } | 624 | } |
631 | } | 625 | } |
@@ -658,31 +652,28 @@ static void determine_bar_visibility(uint32_t modifiers) { | |||
658 | } | 652 | } |
659 | 653 | ||
660 | static void handle_modifier_event(struct sway_keyboard *keyboard) { | 654 | static void handle_modifier_event(struct sway_keyboard *keyboard) { |
661 | struct wlr_input_device *wlr_device = | 655 | if (!keyboard->wlr->group) { |
662 | keyboard->seat_device->input_device->wlr_device; | ||
663 | if (!wlr_device->keyboard->group) { | ||
664 | struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); | 656 | struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); |
665 | 657 | ||
666 | if (kb_grab) { | 658 | if (kb_grab) { |
667 | wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, | 659 | wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, keyboard->wlr); |
668 | wlr_device->keyboard); | ||
669 | wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab, | 660 | wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab, |
670 | &wlr_device->keyboard->modifiers); | 661 | &keyboard->wlr->modifiers); |
671 | } else { | 662 | } else { |
672 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | 663 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; |
673 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | 664 | wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); |
674 | wlr_seat_keyboard_notify_modifiers(wlr_seat, | 665 | wlr_seat_keyboard_notify_modifiers(wlr_seat, |
675 | &wlr_device->keyboard->modifiers); | 666 | &keyboard->wlr->modifiers); |
676 | } | 667 | } |
677 | 668 | ||
678 | uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); | 669 | uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->wlr); |
679 | determine_bar_visibility(modifiers); | 670 | determine_bar_visibility(modifiers); |
680 | } | 671 | } |
681 | 672 | ||
682 | if (wlr_device->keyboard->modifiers.group != keyboard->effective_layout) { | 673 | if (keyboard->wlr->modifiers.group != keyboard->effective_layout) { |
683 | keyboard->effective_layout = wlr_device->keyboard->modifiers.group; | 674 | keyboard->effective_layout = keyboard->wlr->modifiers.group; |
684 | 675 | ||
685 | if (!wlr_keyboard_group_from_wlr_keyboard(wlr_device->keyboard)) { | 676 | if (!wlr_keyboard_group_from_wlr_keyboard(keyboard->wlr)) { |
686 | ipc_event_input("xkb_layout", keyboard->seat_device->input_device); | 677 | ipc_event_input("xkb_layout", keyboard->seat_device->input_device); |
687 | } | 678 | } |
688 | } | 679 | } |
@@ -711,6 +702,7 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | |||
711 | } | 702 | } |
712 | 703 | ||
713 | keyboard->seat_device = device; | 704 | keyboard->seat_device = device; |
705 | keyboard->wlr = wlr_keyboard_from_input_device(device->input_device->wlr_device); | ||
714 | device->keyboard = keyboard; | 706 | device->keyboard = keyboard; |
715 | 707 | ||
716 | wl_list_init(&keyboard->keyboard_key.link); | 708 | wl_list_init(&keyboard->keyboard_key.link); |
@@ -724,23 +716,11 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | |||
724 | 716 | ||
725 | static void handle_xkb_context_log(struct xkb_context *context, | 717 | static void handle_xkb_context_log(struct xkb_context *context, |
726 | enum xkb_log_level level, const char *format, va_list args) { | 718 | enum xkb_log_level level, const char *format, va_list args) { |
727 | va_list args_copy; | 719 | char *error = vformat_str(format, args); |
728 | va_copy(args_copy, args); | ||
729 | size_t length = vsnprintf(NULL, 0, format, args_copy) + 1; | ||
730 | va_end(args_copy); | ||
731 | |||
732 | char *error = malloc(length); | ||
733 | if (!error) { | ||
734 | sway_log(SWAY_ERROR, "Failed to allocate libxkbcommon log message"); | ||
735 | return; | ||
736 | } | ||
737 | |||
738 | va_copy(args_copy, args); | ||
739 | vsnprintf(error, length, format, args_copy); | ||
740 | va_end(args_copy); | ||
741 | 720 | ||
742 | if (error[length - 2] == '\n') { | 721 | size_t len = strlen(error); |
743 | error[length - 2] = '\0'; | 722 | if (error[len - 1] == '\n') { |
723 | error[len - 1] = '\0'; | ||
744 | } | 724 | } |
745 | 725 | ||
746 | sway_log_importance_t importance = SWAY_DEBUG; | 726 | sway_log_importance_t importance = SWAY_DEBUG; |
@@ -761,7 +741,7 @@ static void handle_xkb_context_log(struct xkb_context *context, | |||
761 | 741 | ||
762 | struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, | 742 | struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, |
763 | char **error) { | 743 | char **error) { |
764 | struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | 744 | struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_SECURE_GETENV); |
765 | if (!sway_assert(context, "cannot create XKB context")) { | 745 | if (!sway_assert(context, "cannot create XKB context")) { |
766 | return NULL; | 746 | return NULL; |
767 | } | 747 | } |
@@ -775,13 +755,8 @@ struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, | |||
775 | if (!keymap_file) { | 755 | if (!keymap_file) { |
776 | sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file); | 756 | sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file); |
777 | if (error) { | 757 | if (error) { |
778 | size_t len = snprintf(NULL, 0, "cannot read xkb file %s: %s", | 758 | *error = format_str("cannot read xkb file %s: %s", |
779 | ic->xkb_file, strerror(errno)) + 1; | 759 | ic->xkb_file, strerror(errno)); |
780 | *error = malloc(len); | ||
781 | if (*error) { | ||
782 | snprintf(*error, len, "cannot read xkb_file %s: %s", | ||
783 | ic->xkb_file, strerror(errno)); | ||
784 | } | ||
785 | } | 760 | } |
786 | goto cleanup; | 761 | goto cleanup; |
787 | } | 762 | } |
@@ -819,13 +794,12 @@ static void destroy_empty_wlr_keyboard_group(void *data) { | |||
819 | 794 | ||
820 | static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { | 795 | static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { |
821 | struct sway_input_device *device = keyboard->seat_device->input_device; | 796 | struct sway_input_device *device = keyboard->seat_device->input_device; |
822 | struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; | 797 | struct wlr_keyboard_group *wlr_group = keyboard->wlr->group; |
823 | struct wlr_keyboard_group *wlr_group = wlr_keyboard->group; | ||
824 | 798 | ||
825 | sway_log(SWAY_DEBUG, "Removing keyboard %s from group %p", | 799 | sway_log(SWAY_DEBUG, "Removing keyboard %s from group %p", |
826 | device->identifier, wlr_group); | 800 | device->identifier, wlr_group); |
827 | 801 | ||
828 | wlr_keyboard_group_remove_keyboard(wlr_keyboard->group, wlr_keyboard); | 802 | wlr_keyboard_group_remove_keyboard(keyboard->wlr->group, keyboard->wlr); |
829 | 803 | ||
830 | if (wl_list_empty(&wlr_group->devices)) { | 804 | if (wl_list_empty(&wlr_group->devices)) { |
831 | sway_log(SWAY_DEBUG, "Destroying empty keyboard group %p", | 805 | sway_log(SWAY_DEBUG, "Destroying empty keyboard group %p", |
@@ -850,9 +824,7 @@ static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { | |||
850 | } | 824 | } |
851 | 825 | ||
852 | static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { | 826 | static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { |
853 | struct sway_input_device *device = keyboard->seat_device->input_device; | 827 | if (!keyboard->wlr->group) { |
854 | struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; | ||
855 | if (!wlr_keyboard->group) { | ||
856 | return; | 828 | return; |
857 | } | 829 | } |
858 | 830 | ||
@@ -868,7 +840,7 @@ static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { | |||
868 | break; | 840 | break; |
869 | case KEYBOARD_GROUP_DEFAULT: /* fallthrough */ | 841 | case KEYBOARD_GROUP_DEFAULT: /* fallthrough */ |
870 | case KEYBOARD_GROUP_SMART:; | 842 | case KEYBOARD_GROUP_SMART:; |
871 | struct wlr_keyboard_group *group = wlr_keyboard->group; | 843 | struct wlr_keyboard_group *group = keyboard->wlr->group; |
872 | if (!wlr_keyboard_keymaps_match(keyboard->keymap, group->keyboard.keymap) || | 844 | if (!wlr_keyboard_keymaps_match(keyboard->keymap, group->keyboard.keymap) || |
873 | !repeat_info_match(keyboard, &group->keyboard)) { | 845 | !repeat_info_match(keyboard, &group->keyboard)) { |
874 | sway_keyboard_group_remove(keyboard); | 846 | sway_keyboard_group_remove(keyboard); |
@@ -879,7 +851,6 @@ static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { | |||
879 | 851 | ||
880 | static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | 852 | static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { |
881 | struct sway_input_device *device = keyboard->seat_device->input_device; | 853 | struct sway_input_device *device = keyboard->seat_device->input_device; |
882 | struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; | ||
883 | struct sway_seat *seat = keyboard->seat_device->sway_seat; | 854 | struct sway_seat *seat = keyboard->seat_device->sway_seat; |
884 | struct seat_config *sc = seat_get_config(seat); | 855 | struct seat_config *sc = seat_get_config(seat); |
885 | 856 | ||
@@ -911,7 +882,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | |||
911 | repeat_info_match(keyboard, &wlr_group->keyboard)) { | 882 | repeat_info_match(keyboard, &wlr_group->keyboard)) { |
912 | sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", | 883 | sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", |
913 | device->identifier, wlr_group); | 884 | device->identifier, wlr_group); |
914 | wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard); | 885 | wlr_keyboard_group_add_keyboard(wlr_group, keyboard->wlr); |
915 | return; | 886 | return; |
916 | } | 887 | } |
917 | break; | 888 | break; |
@@ -950,7 +921,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | |||
950 | goto cleanup; | 921 | goto cleanup; |
951 | } | 922 | } |
952 | sway_group->seat_device->input_device->wlr_device = | 923 | sway_group->seat_device->input_device->wlr_device = |
953 | sway_group->wlr_group->input_device; | 924 | &sway_group->wlr_group->keyboard.base; |
954 | 925 | ||
955 | if (!sway_keyboard_create(seat, sway_group->seat_device)) { | 926 | if (!sway_keyboard_create(seat, sway_group->seat_device)) { |
956 | sway_log(SWAY_ERROR, "Failed to allocate sway_keyboard for group"); | 927 | sway_log(SWAY_ERROR, "Failed to allocate sway_keyboard for group"); |
@@ -959,7 +930,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { | |||
959 | 930 | ||
960 | sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", | 931 | sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", |
961 | device->identifier, sway_group->wlr_group); | 932 | device->identifier, sway_group->wlr_group); |
962 | wlr_keyboard_group_add_keyboard(sway_group->wlr_group, wlr_keyboard); | 933 | wlr_keyboard_group_add_keyboard(sway_group->wlr_group, keyboard->wlr); |
963 | 934 | ||
964 | wl_list_insert(&seat->keyboard_groups, &sway_group->link); | 935 | wl_list_insert(&seat->keyboard_groups, &sway_group->link); |
965 | 936 | ||
@@ -991,10 +962,8 @@ cleanup: | |||
991 | void sway_keyboard_configure(struct sway_keyboard *keyboard) { | 962 | void sway_keyboard_configure(struct sway_keyboard *keyboard) { |
992 | struct input_config *input_config = | 963 | struct input_config *input_config = |
993 | input_device_get_config(keyboard->seat_device->input_device); | 964 | input_device_get_config(keyboard->seat_device->input_device); |
994 | struct wlr_input_device *wlr_device = | ||
995 | keyboard->seat_device->input_device->wlr_device; | ||
996 | 965 | ||
997 | if (!sway_assert(!wlr_keyboard_group_from_wlr_keyboard(wlr_device->keyboard), | 966 | if (!sway_assert(!wlr_keyboard_group_from_wlr_keyboard(keyboard->wlr), |
998 | "sway_keyboard_configure should not be called with a " | 967 | "sway_keyboard_configure should not be called with a " |
999 | "keyboard group's keyboard")) { | 968 | "keyboard group's keyboard")) { |
1000 | return; | 969 | return; |
@@ -1036,11 +1005,11 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { | |||
1036 | 1005 | ||
1037 | sway_keyboard_group_remove_invalid(keyboard); | 1006 | sway_keyboard_group_remove_invalid(keyboard); |
1038 | 1007 | ||
1039 | wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); | 1008 | wlr_keyboard_set_keymap(keyboard->wlr, keyboard->keymap); |
1040 | wlr_keyboard_set_repeat_info(wlr_device->keyboard, | 1009 | wlr_keyboard_set_repeat_info(keyboard->wlr, |
1041 | keyboard->repeat_rate, keyboard->repeat_delay); | 1010 | keyboard->repeat_rate, keyboard->repeat_delay); |
1042 | 1011 | ||
1043 | if (!wlr_device->keyboard->group) { | 1012 | if (!keyboard->wlr->group) { |
1044 | sway_keyboard_group_add(keyboard); | 1013 | sway_keyboard_group_add(keyboard); |
1045 | } | 1014 | } |
1046 | 1015 | ||
@@ -1060,40 +1029,42 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { | |||
1060 | } | 1029 | } |
1061 | } | 1030 | } |
1062 | if (locked_mods) { | 1031 | if (locked_mods) { |
1063 | wlr_keyboard_notify_modifiers(wlr_device->keyboard, 0, 0, | 1032 | wlr_keyboard_notify_modifiers(keyboard->wlr, 0, 0, |
1064 | locked_mods, 0); | 1033 | locked_mods, 0); |
1065 | uint32_t leds = 0; | 1034 | uint32_t leds = 0; |
1066 | for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { | 1035 | for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { |
1067 | if (xkb_state_led_index_is_active( | 1036 | if (xkb_state_led_index_is_active(keyboard->wlr->xkb_state, |
1068 | wlr_device->keyboard->xkb_state, | 1037 | keyboard->wlr->led_indexes[i])) { |
1069 | wlr_device->keyboard->led_indexes[i])) { | ||
1070 | leds |= (1 << i); | 1038 | leds |= (1 << i); |
1071 | } | 1039 | } |
1072 | } | 1040 | } |
1073 | if (wlr_device->keyboard->group) { | 1041 | if (keyboard->wlr->group) { |
1074 | wlr_keyboard_led_update( | 1042 | wlr_keyboard_led_update(&keyboard->wlr->group->keyboard, leds); |
1075 | &wlr_device->keyboard->group->keyboard, leds); | ||
1076 | } else { | 1043 | } else { |
1077 | wlr_keyboard_led_update(wlr_device->keyboard, leds); | 1044 | wlr_keyboard_led_update(keyboard->wlr, leds); |
1078 | } | 1045 | } |
1079 | } | 1046 | } |
1080 | } else { | 1047 | } else { |
1081 | xkb_keymap_unref(keymap); | 1048 | xkb_keymap_unref(keymap); |
1082 | sway_keyboard_group_remove_invalid(keyboard); | 1049 | sway_keyboard_group_remove_invalid(keyboard); |
1083 | if (!wlr_device->keyboard->group) { | 1050 | if (!keyboard->wlr->group) { |
1084 | sway_keyboard_group_add(keyboard); | 1051 | sway_keyboard_group_add(keyboard); |
1085 | } | 1052 | } |
1086 | } | 1053 | } |
1087 | 1054 | ||
1055 | // If the seat has no active keyboard, set this one | ||
1088 | struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; | 1056 | struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; |
1089 | wlr_seat_set_keyboard(seat, wlr_device); | 1057 | struct wlr_keyboard *current_keyboard = seat->keyboard_state.keyboard; |
1058 | if (current_keyboard == NULL) { | ||
1059 | wlr_seat_set_keyboard(seat, keyboard->wlr); | ||
1060 | } | ||
1090 | 1061 | ||
1091 | wl_list_remove(&keyboard->keyboard_key.link); | 1062 | wl_list_remove(&keyboard->keyboard_key.link); |
1092 | wl_signal_add(&wlr_device->keyboard->events.key, &keyboard->keyboard_key); | 1063 | wl_signal_add(&keyboard->wlr->events.key, &keyboard->keyboard_key); |
1093 | keyboard->keyboard_key.notify = handle_keyboard_key; | 1064 | keyboard->keyboard_key.notify = handle_keyboard_key; |
1094 | 1065 | ||
1095 | wl_list_remove(&keyboard->keyboard_modifiers.link); | 1066 | wl_list_remove(&keyboard->keyboard_modifiers.link); |
1096 | wl_signal_add(&wlr_device->keyboard->events.modifiers, | 1067 | wl_signal_add(&keyboard->wlr->events.modifiers, |
1097 | &keyboard->keyboard_modifiers); | 1068 | &keyboard->keyboard_modifiers); |
1098 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; | 1069 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; |
1099 | 1070 | ||
@@ -1110,12 +1081,11 @@ void sway_keyboard_destroy(struct sway_keyboard *keyboard) { | |||
1110 | if (!keyboard) { | 1081 | if (!keyboard) { |
1111 | return; | 1082 | return; |
1112 | } | 1083 | } |
1113 | if (keyboard->seat_device->input_device->wlr_device->keyboard->group) { | 1084 | if (keyboard->wlr->group) { |
1114 | sway_keyboard_group_remove(keyboard); | 1085 | sway_keyboard_group_remove(keyboard); |
1115 | } | 1086 | } |
1116 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | 1087 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; |
1117 | struct sway_input_device *device = keyboard->seat_device->input_device; | 1088 | if (wlr_seat_get_keyboard(wlr_seat) == keyboard->wlr) { |
1118 | if (wlr_seat_get_keyboard(wlr_seat) == device->wlr_device->keyboard) { | ||
1119 | wlr_seat_set_keyboard(wlr_seat, NULL); | 1089 | wlr_seat_set_keyboard(wlr_seat, NULL); |
1120 | } | 1090 | } |
1121 | if (keyboard->keymap) { | 1091 | if (keyboard->keymap) { |
diff --git a/sway/input/libinput.c b/sway/input/libinput.c index 060a584a..0266c7a9 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c | |||
@@ -79,6 +79,16 @@ static bool set_accel_speed(struct libinput_device *device, double speed) { | |||
79 | return true; | 79 | return true; |
80 | } | 80 | } |
81 | 81 | ||
82 | static bool set_rotation_angle(struct libinput_device *device, double angle) { | ||
83 | if (!libinput_device_config_rotation_is_available(device) || | ||
84 | libinput_device_config_rotation_get_angle(device) == angle) { | ||
85 | return false; | ||
86 | } | ||
87 | sway_log(SWAY_DEBUG, "rotation_set_angle(%f)", angle); | ||
88 | log_status(libinput_device_config_rotation_set_angle(device, angle)); | ||
89 | return true; | ||
90 | } | ||
91 | |||
82 | static bool set_accel_profile(struct libinput_device *device, | 92 | static bool set_accel_profile(struct libinput_device *device, |
83 | enum libinput_config_accel_profile profile) { | 93 | enum libinput_config_accel_profile profile) { |
84 | if (!libinput_device_config_accel_is_available(device) || | 94 | if (!libinput_device_config_accel_is_available(device) || |
@@ -156,6 +166,18 @@ static bool set_scroll_button(struct libinput_device *dev, uint32_t button) { | |||
156 | return true; | 166 | return true; |
157 | } | 167 | } |
158 | 168 | ||
169 | static bool set_scroll_button_lock(struct libinput_device *dev, | ||
170 | enum libinput_config_scroll_button_lock_state lock) { | ||
171 | uint32_t scroll = libinput_device_config_scroll_get_methods(dev); | ||
172 | if ((scroll & ~LIBINPUT_CONFIG_SCROLL_NO_SCROLL) == 0 || | ||
173 | libinput_device_config_scroll_get_button_lock(dev) == lock) { | ||
174 | return false; | ||
175 | } | ||
176 | sway_log(SWAY_DEBUG, "scroll_set_button_lock(%" PRIu32 ")", lock); | ||
177 | log_status(libinput_device_config_scroll_set_button_lock(dev, lock)); | ||
178 | return true; | ||
179 | } | ||
180 | |||
159 | static bool set_dwt(struct libinput_device *device, bool dwt) { | 181 | static bool set_dwt(struct libinput_device *device, bool dwt) { |
160 | if (!libinput_device_config_dwt_is_available(device) || | 182 | if (!libinput_device_config_dwt_is_available(device) || |
161 | libinput_device_config_dwt_get_enabled(device) == dwt) { | 183 | libinput_device_config_dwt_get_enabled(device) == dwt) { |
@@ -166,6 +188,16 @@ static bool set_dwt(struct libinput_device *device, bool dwt) { | |||
166 | return true; | 188 | return true; |
167 | } | 189 | } |
168 | 190 | ||
191 | static bool set_dwtp(struct libinput_device *device, bool dwtp) { | ||
192 | if (!libinput_device_config_dwtp_is_available(device) || | ||
193 | libinput_device_config_dwtp_get_enabled(device) == dwtp) { | ||
194 | return false; | ||
195 | } | ||
196 | sway_log(SWAY_DEBUG, "dwtp_set_enabled(%d)", dwtp); | ||
197 | log_status(libinput_device_config_dwtp_set_enabled(device, dwtp)); | ||
198 | return true; | ||
199 | } | ||
200 | |||
169 | static bool set_calibration_matrix(struct libinput_device *dev, float mat[6]) { | 201 | static bool set_calibration_matrix(struct libinput_device *dev, float mat[6]) { |
170 | if (!libinput_device_config_calibration_has_matrix(dev)) { | 202 | if (!libinput_device_config_calibration_has_matrix(dev)) { |
171 | return false; | 203 | return false; |
@@ -187,35 +219,38 @@ static bool set_calibration_matrix(struct libinput_device *dev, float mat[6]) { | |||
187 | return changed; | 219 | return changed; |
188 | } | 220 | } |
189 | 221 | ||
190 | void sway_input_configure_libinput_device(struct sway_input_device *input_device) { | 222 | static bool configure_send_events(struct libinput_device *device, |
191 | struct input_config *ic = input_device_get_config(input_device); | 223 | struct input_config *ic) { |
192 | if (!ic || !wlr_input_device_is_libinput(input_device->wlr_device)) { | ||
193 | return; | ||
194 | } | ||
195 | |||
196 | struct libinput_device *device = | ||
197 | wlr_libinput_get_device_handle(input_device->wlr_device); | ||
198 | sway_log(SWAY_DEBUG, "sway_input_configure_libinput_device('%s' on '%s')", | ||
199 | ic->identifier, input_device->identifier); | ||
200 | |||
201 | bool changed = false; | ||
202 | if (ic->mapped_to_output && | 224 | if (ic->mapped_to_output && |
225 | strcmp("*", ic->mapped_to_output) != 0 && | ||
203 | !output_by_name_or_id(ic->mapped_to_output)) { | 226 | !output_by_name_or_id(ic->mapped_to_output)) { |
204 | sway_log(SWAY_DEBUG, | 227 | sway_log(SWAY_DEBUG, |
205 | "%s '%s' is mapped to offline output '%s'; disabling input", | 228 | "%s '%s' is mapped to offline output '%s'; disabling input", |
206 | ic->input_type, ic->identifier, ic->mapped_to_output); | 229 | ic->input_type, ic->identifier, ic->mapped_to_output); |
207 | changed |= set_send_events(device, | 230 | return set_send_events(device, LIBINPUT_CONFIG_SEND_EVENTS_DISABLED); |
208 | LIBINPUT_CONFIG_SEND_EVENTS_DISABLED); | ||
209 | } else if (ic->send_events != INT_MIN) { | 231 | } else if (ic->send_events != INT_MIN) { |
210 | changed |= set_send_events(device, ic->send_events); | 232 | return set_send_events(device, ic->send_events); |
211 | } else { | 233 | } else { |
212 | // Have to reset to the default mode here, otherwise if ic->send_events | 234 | // Have to reset to the default mode here, otherwise if ic->send_events |
213 | // is unset and a mapped output just came online after being disabled, | 235 | // is unset and a mapped output just came online after being disabled, |
214 | // we'd remain stuck sending no events. | 236 | // we'd remain stuck sending no events. |
215 | changed |= set_send_events(device, | 237 | return set_send_events(device, |
216 | libinput_device_config_send_events_get_default_mode(device)); | 238 | libinput_device_config_send_events_get_default_mode(device)); |
217 | } | 239 | } |
240 | } | ||
241 | |||
242 | bool sway_input_configure_libinput_device(struct sway_input_device *input_device) { | ||
243 | struct input_config *ic = input_device_get_config(input_device); | ||
244 | if (!ic || !wlr_input_device_is_libinput(input_device->wlr_device)) { | ||
245 | return false; | ||
246 | } | ||
247 | |||
248 | struct libinput_device *device = | ||
249 | wlr_libinput_get_device_handle(input_device->wlr_device); | ||
250 | sway_log(SWAY_DEBUG, "sway_input_configure_libinput_device('%s' on '%s')", | ||
251 | ic->identifier, input_device->identifier); | ||
218 | 252 | ||
253 | bool changed = configure_send_events(device, ic); | ||
219 | if (ic->tap != INT_MIN) { | 254 | if (ic->tap != INT_MIN) { |
220 | changed |= set_tap(device, ic->tap); | 255 | changed |= set_tap(device, ic->tap); |
221 | } | 256 | } |
@@ -231,6 +266,9 @@ void sway_input_configure_libinput_device(struct sway_input_device *input_device | |||
231 | if (ic->pointer_accel != FLT_MIN) { | 266 | if (ic->pointer_accel != FLT_MIN) { |
232 | changed |= set_accel_speed(device, ic->pointer_accel); | 267 | changed |= set_accel_speed(device, ic->pointer_accel); |
233 | } | 268 | } |
269 | if (ic->rotation_angle != FLT_MIN) { | ||
270 | changed |= set_rotation_angle(device, ic->rotation_angle); | ||
271 | } | ||
234 | if (ic->accel_profile != INT_MIN) { | 272 | if (ic->accel_profile != INT_MIN) { |
235 | changed |= set_accel_profile(device, ic->accel_profile); | 273 | changed |= set_accel_profile(device, ic->accel_profile); |
236 | } | 274 | } |
@@ -252,13 +290,33 @@ void sway_input_configure_libinput_device(struct sway_input_device *input_device | |||
252 | if (ic->scroll_button != INT_MIN) { | 290 | if (ic->scroll_button != INT_MIN) { |
253 | changed |= set_scroll_button(device, ic->scroll_button); | 291 | changed |= set_scroll_button(device, ic->scroll_button); |
254 | } | 292 | } |
293 | if (ic->scroll_button_lock != INT_MIN) { | ||
294 | changed |= set_scroll_button_lock(device, ic->scroll_button_lock); | ||
295 | } | ||
255 | if (ic->dwt != INT_MIN) { | 296 | if (ic->dwt != INT_MIN) { |
256 | changed |= set_dwt(device, ic->dwt); | 297 | changed |= set_dwt(device, ic->dwt); |
257 | } | 298 | } |
299 | if (ic->dwtp != INT_MIN) { | ||
300 | changed |= set_dwtp(device, ic->dwtp); | ||
301 | } | ||
258 | if (ic->calibration_matrix.configured) { | 302 | if (ic->calibration_matrix.configured) { |
259 | changed |= set_calibration_matrix(device, ic->calibration_matrix.matrix); | 303 | changed |= set_calibration_matrix(device, ic->calibration_matrix.matrix); |
260 | } | 304 | } |
261 | 305 | ||
306 | return changed; | ||
307 | } | ||
308 | |||
309 | void sway_input_configure_libinput_device_send_events( | ||
310 | struct sway_input_device *input_device) { | ||
311 | struct input_config *ic = input_device_get_config(input_device); | ||
312 | if (!ic || !wlr_input_device_is_libinput(input_device->wlr_device)) { | ||
313 | return; | ||
314 | } | ||
315 | |||
316 | struct libinput_device *device = | ||
317 | wlr_libinput_get_device_handle(input_device->wlr_device); | ||
318 | bool changed = configure_send_events(device, ic); | ||
319 | |||
262 | if (changed) { | 320 | if (changed) { |
263 | ipc_event_input("libinput_config", input_device); | 321 | ipc_event_input("libinput_config", input_device); |
264 | } | 322 | } |
@@ -287,6 +345,8 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) { | |||
287 | libinput_device_config_tap_get_default_drag_lock_enabled(device)); | 345 | libinput_device_config_tap_get_default_drag_lock_enabled(device)); |
288 | changed |= set_accel_speed(device, | 346 | changed |= set_accel_speed(device, |
289 | libinput_device_config_accel_get_default_speed(device)); | 347 | libinput_device_config_accel_get_default_speed(device)); |
348 | changed |= set_rotation_angle(device, | ||
349 | libinput_device_config_rotation_get_default_angle(device)); | ||
290 | changed |= set_accel_profile(device, | 350 | changed |= set_accel_profile(device, |
291 | libinput_device_config_accel_get_default_profile(device)); | 351 | libinput_device_config_accel_get_default_profile(device)); |
292 | changed |= set_natural_scroll(device, | 352 | changed |= set_natural_scroll(device, |
@@ -304,6 +364,8 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) { | |||
304 | libinput_device_config_scroll_get_default_button(device)); | 364 | libinput_device_config_scroll_get_default_button(device)); |
305 | changed |= set_dwt(device, | 365 | changed |= set_dwt(device, |
306 | libinput_device_config_dwt_get_default_enabled(device)); | 366 | libinput_device_config_dwt_get_default_enabled(device)); |
367 | changed |= set_dwtp(device, | ||
368 | libinput_device_config_dwtp_get_default_enabled(device)); | ||
307 | 369 | ||
308 | float matrix[6]; | 370 | float matrix[6]; |
309 | libinput_device_config_calibration_get_default_matrix(device, matrix); | 371 | libinput_device_config_calibration_get_default_matrix(device, matrix); |
@@ -332,6 +394,13 @@ bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) { | |||
332 | return false; | 394 | return false; |
333 | } | 395 | } |
334 | 396 | ||
335 | const char prefix[] = "platform-"; | 397 | const char prefix_platform[] = "platform-"; |
336 | return strncmp(id_path, prefix, strlen(prefix)) == 0; | 398 | if (strncmp(id_path, prefix_platform, strlen(prefix_platform)) != 0) { |
399 | return false; | ||
400 | } | ||
401 | |||
402 | const char prefix_pci[] = "pci-"; | ||
403 | const char infix_platform[] = "-platform-"; | ||
404 | return (strncmp(id_path, prefix_pci, strlen(prefix_pci)) == 0) && | ||
405 | strstr(id_path, infix_platform); | ||
337 | } | 406 | } |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 2d714acd..da4bb12a 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -1,22 +1,23 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <assert.h> | 1 | #include <assert.h> |
3 | #include <linux/input-event-codes.h> | 2 | #include <linux/input-event-codes.h> |
4 | #include <string.h> | 3 | #include <string.h> |
5 | #include <strings.h> | 4 | #include <strings.h> |
6 | #include <time.h> | 5 | #include <time.h> |
6 | #include <wlr/config.h> | ||
7 | #include <wlr/types/wlr_cursor.h> | 7 | #include <wlr/types/wlr_cursor.h> |
8 | #include <wlr/types/wlr_data_device.h> | 8 | #include <wlr/types/wlr_data_device.h> |
9 | #include <wlr/types/wlr_idle.h> | 9 | #include <wlr/types/wlr_idle_notify_v1.h> |
10 | #include <wlr/types/wlr_keyboard_group.h> | 10 | #include <wlr/types/wlr_keyboard_group.h> |
11 | #include <wlr/types/wlr_output_layout.h> | 11 | #include <wlr/types/wlr_output_layout.h> |
12 | #include <wlr/types/wlr_primary_selection.h> | 12 | #include <wlr/types/wlr_primary_selection.h> |
13 | #include <wlr/types/wlr_tablet_v2.h> | 13 | #include <wlr/types/wlr_tablet_v2.h> |
14 | #include <wlr/types/wlr_touch.h> | ||
14 | #include <wlr/types/wlr_xcursor_manager.h> | 15 | #include <wlr/types/wlr_xcursor_manager.h> |
15 | #include "config.h" | 16 | #include "config.h" |
16 | #include "list.h" | 17 | #include "list.h" |
17 | #include "log.h" | 18 | #include "log.h" |
18 | #include "sway/config.h" | 19 | #include "sway/config.h" |
19 | #include "sway/desktop.h" | 20 | #include "sway/scene_descriptor.h" |
20 | #include "sway/input/cursor.h" | 21 | #include "sway/input/cursor.h" |
21 | #include "sway/input/input-manager.h" | 22 | #include "sway/input/input-manager.h" |
22 | #include "sway/input/keyboard.h" | 23 | #include "sway/input/keyboard.h" |
@@ -42,6 +43,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { | |||
42 | sway_keyboard_destroy(seat_device->keyboard); | 43 | sway_keyboard_destroy(seat_device->keyboard); |
43 | sway_tablet_destroy(seat_device->tablet); | 44 | sway_tablet_destroy(seat_device->tablet); |
44 | sway_tablet_pad_destroy(seat_device->tablet_pad); | 45 | sway_tablet_pad_destroy(seat_device->tablet_pad); |
46 | sway_switch_destroy(seat_device->switch_device); | ||
45 | wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, | 47 | wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, |
46 | seat_device->input_device->wlr_device); | 48 | seat_device->input_device->wlr_device); |
47 | wl_list_remove(&seat_device->link); | 49 | wl_list_remove(&seat_device->link); |
@@ -51,10 +53,26 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) { | |||
51 | static void seat_node_destroy(struct sway_seat_node *seat_node) { | 53 | static void seat_node_destroy(struct sway_seat_node *seat_node) { |
52 | wl_list_remove(&seat_node->destroy.link); | 54 | wl_list_remove(&seat_node->destroy.link); |
53 | wl_list_remove(&seat_node->link); | 55 | wl_list_remove(&seat_node->link); |
56 | |||
57 | /* | ||
58 | * This is the only time we remove items from the focus stack without | ||
59 | * immediately re-adding them. If we just removed the last thing, | ||
60 | * mark that nothing has focus anymore. | ||
61 | */ | ||
62 | if (wl_list_empty(&seat_node->seat->focus_stack)) { | ||
63 | seat_node->seat->has_focus = false; | ||
64 | } | ||
65 | |||
54 | free(seat_node); | 66 | free(seat_node); |
55 | } | 67 | } |
56 | 68 | ||
57 | void seat_destroy(struct sway_seat *seat) { | 69 | void seat_destroy(struct sway_seat *seat) { |
70 | wlr_seat_destroy(seat->wlr_seat); | ||
71 | } | ||
72 | |||
73 | static void handle_seat_destroy(struct wl_listener *listener, void *data) { | ||
74 | struct sway_seat *seat = wl_container_of(listener, seat, destroy); | ||
75 | |||
58 | if (seat == config->handler_context.seat) { | 76 | if (seat == config->handler_context.seat) { |
59 | config->handler_context.seat = input_manager_get_default_seat(); | 77 | config->handler_context.seat = input_manager_get_default_seat(); |
60 | } | 78 | } |
@@ -75,10 +93,11 @@ void seat_destroy(struct sway_seat *seat) { | |||
75 | wl_list_remove(&seat->request_set_selection.link); | 93 | wl_list_remove(&seat->request_set_selection.link); |
76 | wl_list_remove(&seat->request_set_primary_selection.link); | 94 | wl_list_remove(&seat->request_set_primary_selection.link); |
77 | wl_list_remove(&seat->link); | 95 | wl_list_remove(&seat->link); |
78 | wlr_seat_destroy(seat->wlr_seat); | 96 | wl_list_remove(&seat->destroy.link); |
79 | for (int i = 0; i < seat->deferred_bindings->length; i++) { | 97 | for (int i = 0; i < seat->deferred_bindings->length; i++) { |
80 | free_sway_binding(seat->deferred_bindings->items[i]); | 98 | free_sway_binding(seat->deferred_bindings->items[i]); |
81 | } | 99 | } |
100 | wlr_scene_node_destroy(&seat->scene_tree->node); | ||
82 | list_free(seat->deferred_bindings); | 101 | list_free(seat->deferred_bindings); |
83 | free(seat->prev_workspace_name); | 102 | free(seat->prev_workspace_name); |
84 | free(seat); | 103 | free(seat); |
@@ -86,21 +105,10 @@ void seat_destroy(struct sway_seat *seat) { | |||
86 | 105 | ||
87 | void seat_idle_notify_activity(struct sway_seat *seat, | 106 | void seat_idle_notify_activity(struct sway_seat *seat, |
88 | enum sway_input_idle_source source) { | 107 | enum sway_input_idle_source source) { |
89 | uint32_t mask = seat->idle_inhibit_sources; | 108 | if ((source & seat->idle_inhibit_sources) == 0) { |
90 | struct wlr_idle_timeout *timeout; | 109 | return; |
91 | int ntimers = 0, nidle = 0; | ||
92 | wl_list_for_each(timeout, &server.idle->idle_timers, link) { | ||
93 | ++ntimers; | ||
94 | if (timeout->idle_state) { | ||
95 | ++nidle; | ||
96 | } | ||
97 | } | ||
98 | if (nidle == ntimers) { | ||
99 | mask = seat->idle_wake_sources; | ||
100 | } | ||
101 | if ((source & mask) > 0) { | ||
102 | wlr_idle_notify_activity(server.idle, seat->wlr_seat); | ||
103 | } | 110 | } |
111 | wlr_idle_notifier_v1_notify_activity(server.idle_notifier_v1, seat->wlr_seat); | ||
104 | } | 112 | } |
105 | 113 | ||
106 | /** | 114 | /** |
@@ -130,7 +138,7 @@ static struct sway_keyboard *sway_keyboard_for_wlr_keyboard( | |||
130 | if (input_device->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { | 138 | if (input_device->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { |
131 | continue; | 139 | continue; |
132 | } | 140 | } |
133 | if (input_device->wlr_device->keyboard == wlr_keyboard) { | 141 | if (input_device->wlr_device == &wlr_keyboard->base) { |
134 | return seat_device->keyboard; | 142 | return seat_device->keyboard; |
135 | } | 143 | } |
136 | } | 144 | } |
@@ -138,7 +146,7 @@ static struct sway_keyboard *sway_keyboard_for_wlr_keyboard( | |||
138 | wl_list_for_each(group, &seat->keyboard_groups, link) { | 146 | wl_list_for_each(group, &seat->keyboard_groups, link) { |
139 | struct sway_input_device *input_device = | 147 | struct sway_input_device *input_device = |
140 | group->seat_device->input_device; | 148 | group->seat_device->input_device; |
141 | if (input_device->wlr_device->keyboard == wlr_keyboard) { | 149 | if (input_device->wlr_device == &wlr_keyboard->base) { |
142 | return group->seat_device->keyboard; | 150 | return group->seat_device->keyboard; |
143 | } | 151 | } |
144 | } | 152 | } |
@@ -162,11 +170,11 @@ static void seat_keyboard_notify_enter(struct sway_seat *seat, | |||
162 | state->pressed_keycodes, state->npressed, &keyboard->modifiers); | 170 | state->pressed_keycodes, state->npressed, &keyboard->modifiers); |
163 | } | 171 | } |
164 | 172 | ||
165 | static void seat_tablet_pads_notify_enter(struct sway_seat *seat, | 173 | static void seat_tablet_pads_set_focus(struct sway_seat *seat, |
166 | struct wlr_surface *surface) { | 174 | struct wlr_surface *surface) { |
167 | struct sway_seat_device *seat_device; | 175 | struct sway_seat_device *seat_device; |
168 | wl_list_for_each(seat_device, &seat->devices, link) { | 176 | wl_list_for_each(seat_device, &seat->devices, link) { |
169 | sway_tablet_pad_notify_enter(seat_device->tablet_pad, surface); | 177 | sway_tablet_pad_set_focus(seat_device->tablet_pad, surface); |
170 | } | 178 | } |
171 | } | 179 | } |
172 | 180 | ||
@@ -182,7 +190,7 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) { | |||
182 | node->sway_container->view : NULL; | 190 | node->sway_container->view : NULL; |
183 | 191 | ||
184 | if (view && seat_is_input_allowed(seat, view->surface)) { | 192 | if (view && seat_is_input_allowed(seat, view->surface)) { |
185 | #if HAVE_XWAYLAND | 193 | #if WLR_HAS_XWAYLAND |
186 | if (view->type == SWAY_VIEW_XWAYLAND) { | 194 | if (view->type == SWAY_VIEW_XWAYLAND) { |
187 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; | 195 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; |
188 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 196 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
@@ -190,7 +198,7 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) { | |||
190 | #endif | 198 | #endif |
191 | 199 | ||
192 | seat_keyboard_notify_enter(seat, view->surface); | 200 | seat_keyboard_notify_enter(seat, view->surface); |
193 | seat_tablet_pads_notify_enter(seat, view->surface); | 201 | seat_tablet_pads_set_focus(seat, view->surface); |
194 | sway_input_method_relay_set_focus(&seat->im_relay, view->surface); | 202 | sway_input_method_relay_set_focus(&seat->im_relay, view->surface); |
195 | 203 | ||
196 | struct wlr_pointer_constraint_v1 *constraint = | 204 | struct wlr_pointer_constraint_v1 *constraint = |
@@ -210,14 +218,13 @@ void seat_for_each_node(struct sway_seat *seat, | |||
210 | 218 | ||
211 | struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, | 219 | struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, |
212 | struct sway_node *ancestor) { | 220 | struct sway_node *ancestor) { |
213 | if (ancestor->type == N_CONTAINER && ancestor->sway_container->view) { | 221 | if (node_is_view(ancestor)) { |
214 | return ancestor->sway_container; | 222 | return ancestor->sway_container; |
215 | } | 223 | } |
216 | struct sway_seat_node *current; | 224 | struct sway_seat_node *current; |
217 | wl_list_for_each(current, &seat->focus_stack, link) { | 225 | wl_list_for_each(current, &seat->focus_stack, link) { |
218 | struct sway_node *node = current->node; | 226 | struct sway_node *node = current->node; |
219 | if (node->type == N_CONTAINER && node->sway_container->view && | 227 | if (node_is_view(node) && node_has_ancestor(node, ancestor)) { |
220 | node_has_ancestor(node, ancestor)) { | ||
221 | return node->sway_container; | 228 | return node->sway_container; |
222 | } | 229 | } |
223 | } | 230 | } |
@@ -236,7 +243,7 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) { | |||
236 | seat_node_destroy(seat_node); | 243 | seat_node_destroy(seat_node); |
237 | // If an unmanaged or layer surface is focused when an output gets | 244 | // If an unmanaged or layer surface is focused when an output gets |
238 | // disabled and an empty workspace on the output was focused by the | 245 | // disabled and an empty workspace on the output was focused by the |
239 | // seat, the seat needs to refocus it's focus inactive to update the | 246 | // seat, the seat needs to refocus its focus inactive to update the |
240 | // value of seat->workspace. | 247 | // value of seat->workspace. |
241 | if (seat->workspace == node->sway_workspace) { | 248 | if (seat->workspace == node->sway_workspace) { |
242 | struct sway_node *node = seat_get_focus_inactive(seat, &root->node); | 249 | struct sway_node *node = seat_get_focus_inactive(seat, &root->node); |
@@ -352,25 +359,15 @@ static void handle_new_node(struct wl_listener *listener, void *data) { | |||
352 | seat_node_from_node(seat, node); | 359 | seat_node_from_node(seat, node); |
353 | } | 360 | } |
354 | 361 | ||
355 | static void drag_icon_damage_whole(struct sway_drag_icon *icon) { | 362 | static void drag_icon_update_position(struct sway_seat *seat, struct wlr_scene_node *node) { |
356 | if (!icon->wlr_drag_icon->mapped) { | 363 | struct wlr_drag_icon *wlr_icon = scene_descriptor_try_get(node, SWAY_SCENE_DESC_DRAG_ICON); |
357 | return; | ||
358 | } | ||
359 | desktop_damage_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, true); | ||
360 | } | ||
361 | |||
362 | void drag_icon_update_position(struct sway_drag_icon *icon) { | ||
363 | drag_icon_damage_whole(icon); | ||
364 | |||
365 | struct wlr_drag_icon *wlr_icon = icon->wlr_drag_icon; | ||
366 | struct sway_seat *seat = icon->seat; | ||
367 | struct wlr_cursor *cursor = seat->cursor->cursor; | 364 | struct wlr_cursor *cursor = seat->cursor->cursor; |
365 | |||
368 | switch (wlr_icon->drag->grab_type) { | 366 | switch (wlr_icon->drag->grab_type) { |
369 | case WLR_DRAG_GRAB_KEYBOARD: | 367 | case WLR_DRAG_GRAB_KEYBOARD: |
370 | return; | 368 | return; |
371 | case WLR_DRAG_GRAB_KEYBOARD_POINTER: | 369 | case WLR_DRAG_GRAB_KEYBOARD_POINTER: |
372 | icon->x = cursor->x; | 370 | wlr_scene_node_set_position(node, cursor->x, cursor->y); |
373 | icon->y = cursor->y; | ||
374 | break; | 371 | break; |
375 | case WLR_DRAG_GRAB_KEYBOARD_TOUCH:; | 372 | case WLR_DRAG_GRAB_KEYBOARD_TOUCH:; |
376 | struct wlr_touch_point *point = | 373 | struct wlr_touch_point *point = |
@@ -378,39 +375,15 @@ void drag_icon_update_position(struct sway_drag_icon *icon) { | |||
378 | if (point == NULL) { | 375 | if (point == NULL) { |
379 | return; | 376 | return; |
380 | } | 377 | } |
381 | icon->x = seat->touch_x; | 378 | wlr_scene_node_set_position(node, seat->touch_x, seat->touch_y); |
382 | icon->y = seat->touch_y; | ||
383 | } | 379 | } |
384 | |||
385 | drag_icon_damage_whole(icon); | ||
386 | } | 380 | } |
387 | 381 | ||
388 | static void drag_icon_handle_surface_commit(struct wl_listener *listener, | 382 | void drag_icons_update_position(struct sway_seat *seat) { |
389 | void *data) { | 383 | struct wlr_scene_node *node; |
390 | struct sway_drag_icon *icon = | 384 | wl_list_for_each(node, &seat->drag_icons->children, link) { |
391 | wl_container_of(listener, icon, surface_commit); | 385 | drag_icon_update_position(seat, node); |
392 | drag_icon_update_position(icon); | 386 | } |
393 | } | ||
394 | |||
395 | static void drag_icon_handle_map(struct wl_listener *listener, void *data) { | ||
396 | struct sway_drag_icon *icon = wl_container_of(listener, icon, map); | ||
397 | drag_icon_damage_whole(icon); | ||
398 | } | ||
399 | |||
400 | static void drag_icon_handle_unmap(struct wl_listener *listener, void *data) { | ||
401 | struct sway_drag_icon *icon = wl_container_of(listener, icon, unmap); | ||
402 | drag_icon_damage_whole(icon); | ||
403 | } | ||
404 | |||
405 | static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) { | ||
406 | struct sway_drag_icon *icon = wl_container_of(listener, icon, destroy); | ||
407 | icon->wlr_drag_icon->data = NULL; | ||
408 | wl_list_remove(&icon->link); | ||
409 | wl_list_remove(&icon->surface_commit.link); | ||
410 | wl_list_remove(&icon->unmap.link); | ||
411 | wl_list_remove(&icon->map.link); | ||
412 | wl_list_remove(&icon->destroy.link); | ||
413 | free(icon); | ||
414 | } | 387 | } |
415 | 388 | ||
416 | static void drag_handle_destroy(struct wl_listener *listener, void *data) { | 389 | static void drag_handle_destroy(struct wl_listener *listener, void *data) { |
@@ -482,27 +455,20 @@ static void handle_start_drag(struct wl_listener *listener, void *data) { | |||
482 | 455 | ||
483 | struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon; | 456 | struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon; |
484 | if (wlr_drag_icon != NULL) { | 457 | if (wlr_drag_icon != NULL) { |
485 | struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon)); | 458 | struct wlr_scene_tree *tree = wlr_scene_drag_icon_create(seat->drag_icons, wlr_drag_icon); |
486 | if (icon == NULL) { | 459 | if (!tree) { |
487 | sway_log(SWAY_ERROR, "Allocation failed"); | 460 | sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene tree"); |
488 | return; | 461 | return; |
489 | } | 462 | } |
490 | icon->seat = seat; | ||
491 | icon->wlr_drag_icon = wlr_drag_icon; | ||
492 | wlr_drag_icon->data = icon; | ||
493 | 463 | ||
494 | icon->surface_commit.notify = drag_icon_handle_surface_commit; | 464 | if (!scene_descriptor_assign(&tree->node, SWAY_SCENE_DESC_DRAG_ICON, |
495 | wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit); | 465 | wlr_drag_icon)) { |
496 | icon->unmap.notify = drag_icon_handle_unmap; | 466 | sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene descriptor"); |
497 | wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap); | 467 | wlr_scene_node_destroy(&tree->node); |
498 | icon->map.notify = drag_icon_handle_map; | 468 | return; |
499 | wl_signal_add(&wlr_drag_icon->events.map, &icon->map); | 469 | } |
500 | icon->destroy.notify = drag_icon_handle_destroy; | ||
501 | wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy); | ||
502 | |||
503 | wl_list_insert(&root->drag_icons, &icon->link); | ||
504 | 470 | ||
505 | drag_icon_update_position(icon); | 471 | drag_icon_update_position(seat, &tree->node); |
506 | } | 472 | } |
507 | seatop_begin_default(seat); | 473 | seatop_begin_default(seat); |
508 | } | 474 | } |
@@ -549,8 +515,18 @@ struct sway_seat *seat_create(const char *seat_name) { | |||
549 | return NULL; | 515 | return NULL; |
550 | } | 516 | } |
551 | 517 | ||
518 | bool failed = false; | ||
519 | seat->scene_tree = alloc_scene_tree(root->layers.seat, &failed); | ||
520 | seat->drag_icons = alloc_scene_tree(seat->scene_tree, &failed); | ||
521 | if (failed) { | ||
522 | wlr_scene_node_destroy(&seat->scene_tree->node); | ||
523 | free(seat); | ||
524 | return NULL; | ||
525 | } | ||
526 | |||
552 | seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name); | 527 | seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name); |
553 | if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { | 528 | if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { |
529 | wlr_scene_node_destroy(&seat->scene_tree->node); | ||
554 | free(seat); | 530 | free(seat); |
555 | return NULL; | 531 | return NULL; |
556 | } | 532 | } |
@@ -558,11 +534,15 @@ struct sway_seat *seat_create(const char *seat_name) { | |||
558 | 534 | ||
559 | seat->cursor = sway_cursor_create(seat); | 535 | seat->cursor = sway_cursor_create(seat); |
560 | if (!seat->cursor) { | 536 | if (!seat->cursor) { |
537 | wlr_scene_node_destroy(&seat->scene_tree->node); | ||
561 | wlr_seat_destroy(seat->wlr_seat); | 538 | wlr_seat_destroy(seat->wlr_seat); |
562 | free(seat); | 539 | free(seat); |
563 | return NULL; | 540 | return NULL; |
564 | } | 541 | } |
565 | 542 | ||
543 | seat->destroy.notify = handle_seat_destroy; | ||
544 | wl_signal_add(&seat->wlr_seat->events.destroy, &seat->destroy); | ||
545 | |||
566 | seat->idle_inhibit_sources = seat->idle_wake_sources = | 546 | seat->idle_inhibit_sources = seat->idle_wake_sources = |
567 | IDLE_SOURCE_KEYBOARD | | 547 | IDLE_SOURCE_KEYBOARD | |
568 | IDLE_SOURCE_POINTER | | 548 | IDLE_SOURCE_POINTER | |
@@ -636,7 +616,7 @@ static void seat_update_capabilities(struct sway_seat *seat) { | |||
636 | case WLR_INPUT_DEVICE_TOUCH: | 616 | case WLR_INPUT_DEVICE_TOUCH: |
637 | caps |= WL_SEAT_CAPABILITY_TOUCH; | 617 | caps |= WL_SEAT_CAPABILITY_TOUCH; |
638 | break; | 618 | break; |
639 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 619 | case WLR_INPUT_DEVICE_TABLET: |
640 | caps |= WL_SEAT_CAPABILITY_POINTER; | 620 | caps |= WL_SEAT_CAPABILITY_POINTER; |
641 | break; | 621 | break; |
642 | case WLR_INPUT_DEVICE_SWITCH: | 622 | case WLR_INPUT_DEVICE_SWITCH: |
@@ -654,7 +634,7 @@ static void seat_update_capabilities(struct sway_seat *seat) { | |||
654 | } else { | 634 | } else { |
655 | wlr_seat_set_capabilities(seat->wlr_seat, caps); | 635 | wlr_seat_set_capabilities(seat->wlr_seat, caps); |
656 | if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) { | 636 | if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) { |
657 | cursor_set_image(seat->cursor, "left_ptr", NULL); | 637 | cursor_set_image(seat->cursor, "default", NULL); |
658 | } | 638 | } |
659 | } | 639 | } |
660 | } | 640 | } |
@@ -694,19 +674,28 @@ static const char *get_builtin_output_name(void) { | |||
694 | static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { | 674 | static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { |
695 | switch (seat_device->input_device->wlr_device->type) { | 675 | switch (seat_device->input_device->wlr_device->type) { |
696 | case WLR_INPUT_DEVICE_TOUCH: | 676 | case WLR_INPUT_DEVICE_TOUCH: |
697 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 677 | case WLR_INPUT_DEVICE_TABLET: |
698 | return true; | 678 | return true; |
699 | default: | 679 | default: |
700 | return false; | 680 | return false; |
701 | } | 681 | } |
702 | } | 682 | } |
703 | 683 | ||
704 | static void seat_apply_input_config(struct sway_seat *seat, | 684 | static void seat_apply_input_mapping(struct sway_seat *seat, |
705 | struct sway_seat_device *sway_device) { | 685 | struct sway_seat_device *sway_device) { |
706 | struct input_config *ic = | 686 | struct input_config *ic = |
707 | input_device_get_config(sway_device->input_device); | 687 | input_device_get_config(sway_device->input_device); |
708 | 688 | ||
709 | sway_log(SWAY_DEBUG, "Applying input config to %s", | 689 | switch (sway_device->input_device->wlr_device->type) { |
690 | case WLR_INPUT_DEVICE_POINTER: | ||
691 | case WLR_INPUT_DEVICE_TOUCH: | ||
692 | case WLR_INPUT_DEVICE_TABLET: | ||
693 | break; | ||
694 | default: | ||
695 | return; // these devices don't support mappings | ||
696 | } | ||
697 | |||
698 | sway_log(SWAY_DEBUG, "Applying input mapping to %s", | ||
710 | sway_device->input_device->identifier); | 699 | sway_device->input_device->identifier); |
711 | 700 | ||
712 | const char *mapped_to_output = ic == NULL ? NULL : ic->mapped_to_output; | 701 | const char *mapped_to_output = ic == NULL ? NULL : ic->mapped_to_output; |
@@ -715,14 +704,26 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
715 | ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to; | 704 | ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to; |
716 | 705 | ||
717 | switch (mapped_to) { | 706 | switch (mapped_to) { |
718 | case MAPPED_TO_DEFAULT: | 707 | case MAPPED_TO_DEFAULT:; |
719 | /* | 708 | /* |
720 | * If the wlroots backend provides an output name, use that. | 709 | * If the wlroots backend provides an output name, use that. |
721 | * | 710 | * |
722 | * Otherwise, try to map built-in touch and tablet tool devices to the | 711 | * Otherwise, try to map built-in touch and pointer devices to the |
723 | * built-in output. | 712 | * built-in output. |
724 | */ | 713 | */ |
725 | mapped_to_output = sway_device->input_device->wlr_device->output_name; | 714 | struct wlr_input_device *dev = sway_device->input_device->wlr_device; |
715 | switch (dev->type) { | ||
716 | case WLR_INPUT_DEVICE_POINTER: | ||
717 | mapped_to_output = wlr_pointer_from_input_device(dev)->output_name; | ||
718 | break; | ||
719 | case WLR_INPUT_DEVICE_TOUCH: | ||
720 | mapped_to_output = wlr_touch_from_input_device(dev)->output_name; | ||
721 | break; | ||
722 | default: | ||
723 | mapped_to_output = NULL; | ||
724 | break; | ||
725 | } | ||
726 | #if WLR_HAS_LIBINPUT_BACKEND | ||
726 | if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) && | 727 | if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) && |
727 | sway_libinput_device_is_builtin(sway_device->input_device)) { | 728 | sway_libinput_device_is_builtin(sway_device->input_device)) { |
728 | mapped_to_output = get_builtin_output_name(); | 729 | mapped_to_output = get_builtin_output_name(); |
@@ -731,6 +732,10 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
731 | mapped_to_output, sway_device->input_device->identifier); | 732 | mapped_to_output, sway_device->input_device->identifier); |
732 | } | 733 | } |
733 | } | 734 | } |
735 | #else | ||
736 | (void)is_touch_or_tablet_tool; | ||
737 | (void)get_builtin_output_name; | ||
738 | #endif | ||
734 | if (mapped_to_output == NULL) { | 739 | if (mapped_to_output == NULL) { |
735 | return; | 740 | return; |
736 | } | 741 | } |
@@ -774,12 +779,9 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
774 | 779 | ||
775 | static void seat_configure_pointer(struct sway_seat *seat, | 780 | static void seat_configure_pointer(struct sway_seat *seat, |
776 | struct sway_seat_device *sway_device) { | 781 | struct sway_seat_device *sway_device) { |
777 | if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { | 782 | seat_configure_xcursor(seat); |
778 | seat_configure_xcursor(seat); | ||
779 | } | ||
780 | wlr_cursor_attach_input_device(seat->cursor->cursor, | 783 | wlr_cursor_attach_input_device(seat->cursor->cursor, |
781 | sway_device->input_device->wlr_device); | 784 | sway_device->input_device->wlr_device); |
782 | seat_apply_input_config(seat, sway_device); | ||
783 | wl_event_source_timer_update( | 785 | wl_event_source_timer_update( |
784 | seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); | 786 | seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); |
785 | } | 787 | } |
@@ -790,13 +792,22 @@ static void seat_configure_keyboard(struct sway_seat *seat, | |||
790 | sway_keyboard_create(seat, seat_device); | 792 | sway_keyboard_create(seat, seat_device); |
791 | } | 793 | } |
792 | sway_keyboard_configure(seat_device->keyboard); | 794 | sway_keyboard_configure(seat_device->keyboard); |
793 | wlr_seat_set_keyboard(seat->wlr_seat, | 795 | |
794 | seat_device->input_device->wlr_device); | 796 | // We only need to update the current keyboard, as the rest will be updated |
795 | struct sway_node *focus = seat_get_focus(seat); | 797 | // as they are activated. |
796 | if (focus && node_is_view(focus)) { | 798 | struct wlr_keyboard *wlr_keyboard = |
797 | // force notify reenter to pick up the new configuration | 799 | wlr_keyboard_from_input_device(seat_device->input_device->wlr_device); |
800 | struct wlr_keyboard *current_keyboard = seat->wlr_seat->keyboard_state.keyboard; | ||
801 | if (wlr_keyboard != current_keyboard) { | ||
802 | return; | ||
803 | } | ||
804 | |||
805 | // force notify reenter to pick up the new configuration. This reuses | ||
806 | // the current focused surface to avoid breaking input grabs. | ||
807 | struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface; | ||
808 | if (surface) { | ||
798 | wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); | 809 | wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); |
799 | seat_keyboard_notify_enter(seat, focus->sway_container->view->surface); | 810 | seat_keyboard_notify_enter(seat, surface); |
800 | } | 811 | } |
801 | } | 812 | } |
802 | 813 | ||
@@ -805,7 +816,6 @@ static void seat_configure_switch(struct sway_seat *seat, | |||
805 | if (!seat_device->switch_device) { | 816 | if (!seat_device->switch_device) { |
806 | sway_switch_create(seat, seat_device); | 817 | sway_switch_create(seat, seat_device); |
807 | } | 818 | } |
808 | seat_apply_input_config(seat, seat_device); | ||
809 | sway_switch_configure(seat_device->switch_device); | 819 | sway_switch_configure(seat_device->switch_device); |
810 | } | 820 | } |
811 | 821 | ||
@@ -813,7 +823,6 @@ static void seat_configure_touch(struct sway_seat *seat, | |||
813 | struct sway_seat_device *sway_device) { | 823 | struct sway_seat_device *sway_device) { |
814 | wlr_cursor_attach_input_device(seat->cursor->cursor, | 824 | wlr_cursor_attach_input_device(seat->cursor->cursor, |
815 | sway_device->input_device->wlr_device); | 825 | sway_device->input_device->wlr_device); |
816 | seat_apply_input_config(seat, sway_device); | ||
817 | } | 826 | } |
818 | 827 | ||
819 | static void seat_configure_tablet_tool(struct sway_seat *seat, | 828 | static void seat_configure_tablet_tool(struct sway_seat *seat, |
@@ -824,7 +833,6 @@ static void seat_configure_tablet_tool(struct sway_seat *seat, | |||
824 | sway_configure_tablet(sway_device->tablet); | 833 | sway_configure_tablet(sway_device->tablet); |
825 | wlr_cursor_attach_input_device(seat->cursor->cursor, | 834 | wlr_cursor_attach_input_device(seat->cursor->cursor, |
826 | sway_device->input_device->wlr_device); | 835 | sway_device->input_device->wlr_device); |
827 | seat_apply_input_config(seat, sway_device); | ||
828 | } | 836 | } |
829 | 837 | ||
830 | static void seat_configure_tablet_pad(struct sway_seat *seat, | 838 | static void seat_configure_tablet_pad(struct sway_seat *seat, |
@@ -874,13 +882,25 @@ void seat_configure_device(struct sway_seat *seat, | |||
874 | case WLR_INPUT_DEVICE_TOUCH: | 882 | case WLR_INPUT_DEVICE_TOUCH: |
875 | seat_configure_touch(seat, seat_device); | 883 | seat_configure_touch(seat, seat_device); |
876 | break; | 884 | break; |
877 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 885 | case WLR_INPUT_DEVICE_TABLET: |
878 | seat_configure_tablet_tool(seat, seat_device); | 886 | seat_configure_tablet_tool(seat, seat_device); |
879 | break; | 887 | break; |
880 | case WLR_INPUT_DEVICE_TABLET_PAD: | 888 | case WLR_INPUT_DEVICE_TABLET_PAD: |
881 | seat_configure_tablet_pad(seat, seat_device); | 889 | seat_configure_tablet_pad(seat, seat_device); |
882 | break; | 890 | break; |
883 | } | 891 | } |
892 | |||
893 | seat_apply_input_mapping(seat, seat_device); | ||
894 | } | ||
895 | |||
896 | void seat_configure_device_mapping(struct sway_seat *seat, | ||
897 | struct sway_input_device *input_device) { | ||
898 | struct sway_seat_device *seat_device = seat_get_device(seat, input_device); | ||
899 | if (!seat_device) { | ||
900 | return; | ||
901 | } | ||
902 | |||
903 | seat_apply_input_mapping(seat, seat_device); | ||
884 | } | 904 | } |
885 | 905 | ||
886 | void seat_reset_device(struct sway_seat *seat, | 906 | void seat_reset_device(struct sway_seat *seat, |
@@ -901,7 +921,7 @@ void seat_reset_device(struct sway_seat *seat, | |||
901 | case WLR_INPUT_DEVICE_TOUCH: | 921 | case WLR_INPUT_DEVICE_TOUCH: |
902 | seat_reset_input_config(seat, seat_device); | 922 | seat_reset_input_config(seat, seat_device); |
903 | break; | 923 | break; |
904 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 924 | case WLR_INPUT_DEVICE_TABLET: |
905 | seat_reset_input_config(seat, seat_device); | 925 | seat_reset_input_config(seat, seat_device); |
906 | break; | 926 | break; |
907 | case WLR_INPUT_DEVICE_TABLET_PAD: | 927 | case WLR_INPUT_DEVICE_TABLET_PAD: |
@@ -982,7 +1002,7 @@ void seat_configure_xcursor(struct sway_seat *seat) { | |||
982 | setenv("XCURSOR_THEME", cursor_theme, 1); | 1002 | setenv("XCURSOR_THEME", cursor_theme, 1); |
983 | } | 1003 | } |
984 | 1004 | ||
985 | #if HAVE_XWAYLAND | 1005 | #if WLR_HAS_XWAYLAND |
986 | if (server.xwayland.wlr_xwayland && (!server.xwayland.xcursor_manager || | 1006 | if (server.xwayland.wlr_xwayland && (!server.xwayland.xcursor_manager || |
987 | !xcursor_manager_is_named(server.xwayland.xcursor_manager, | 1007 | !xcursor_manager_is_named(server.xwayland.xcursor_manager, |
988 | cursor_theme) || | 1008 | cursor_theme) || |
@@ -997,7 +1017,7 @@ void seat_configure_xcursor(struct sway_seat *seat) { | |||
997 | 1017 | ||
998 | wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); | 1018 | wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); |
999 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( | 1019 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( |
1000 | server.xwayland.xcursor_manager, "left_ptr", 1); | 1020 | server.xwayland.xcursor_manager, "default", 1); |
1001 | if (xcursor != NULL) { | 1021 | if (xcursor != NULL) { |
1002 | struct wlr_xcursor_image *image = xcursor->images[0]; | 1022 | struct wlr_xcursor_image *image = xcursor->images[0]; |
1003 | wlr_xwayland_set_cursor( | 1023 | wlr_xwayland_set_cursor( |
@@ -1023,32 +1043,35 @@ void seat_configure_xcursor(struct sway_seat *seat) { | |||
1023 | sway_log(SWAY_ERROR, | 1043 | sway_log(SWAY_ERROR, |
1024 | "Cannot create XCursor manager for theme '%s'", cursor_theme); | 1044 | "Cannot create XCursor manager for theme '%s'", cursor_theme); |
1025 | } | 1045 | } |
1026 | } | ||
1027 | 1046 | ||
1028 | for (int i = 0; i < root->outputs->length; ++i) { | 1047 | |
1029 | struct sway_output *sway_output = root->outputs->items[i]; | 1048 | for (int i = 0; i < root->outputs->length; ++i) { |
1030 | struct wlr_output *output = sway_output->wlr_output; | 1049 | struct sway_output *sway_output = root->outputs->items[i]; |
1031 | bool result = | 1050 | struct wlr_output *output = sway_output->wlr_output; |
1032 | wlr_xcursor_manager_load(seat->cursor->xcursor_manager, | 1051 | bool result = |
1033 | output->scale); | 1052 | wlr_xcursor_manager_load(seat->cursor->xcursor_manager, |
1034 | if (!result) { | 1053 | output->scale); |
1035 | sway_log(SWAY_ERROR, | 1054 | if (!result) { |
1036 | "Cannot load xcursor theme for output '%s' with scale %f", | 1055 | sway_log(SWAY_ERROR, |
1037 | output->name, output->scale); | 1056 | "Cannot load xcursor theme for output '%s' with scale %f", |
1057 | output->name, output->scale); | ||
1058 | } | ||
1038 | } | 1059 | } |
1039 | } | ||
1040 | 1060 | ||
1041 | // Reset the cursor so that we apply it to outputs that just appeared | 1061 | // Reset the cursor so that we apply it to outputs that just appeared |
1042 | cursor_set_image(seat->cursor, NULL, NULL); | 1062 | cursor_set_image(seat->cursor, NULL, NULL); |
1043 | cursor_set_image(seat->cursor, "left_ptr", NULL); | 1063 | cursor_set_image(seat->cursor, "default", NULL); |
1044 | wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, | 1064 | wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, |
1045 | seat->cursor->cursor->y); | 1065 | seat->cursor->cursor->y); |
1066 | } | ||
1046 | } | 1067 | } |
1047 | 1068 | ||
1048 | bool seat_is_input_allowed(struct sway_seat *seat, | 1069 | bool seat_is_input_allowed(struct sway_seat *seat, |
1049 | struct wlr_surface *surface) { | 1070 | struct wlr_surface *surface) { |
1050 | struct wl_client *client = wl_resource_get_client(surface->resource); | 1071 | if (server.session_lock.lock) { |
1051 | return !seat->exclusive_client || seat->exclusive_client == client; | 1072 | return sway_session_lock_has_surface(server.session_lock.lock, surface); |
1073 | } | ||
1074 | return true; | ||
1052 | } | 1075 | } |
1053 | 1076 | ||
1054 | static void send_unfocus(struct sway_container *con, void *data) { | 1077 | static void send_unfocus(struct sway_container *con, void *data) { |
@@ -1107,15 +1130,7 @@ void seat_set_raw_focus(struct sway_seat *seat, struct sway_node *node) { | |||
1107 | } | 1130 | } |
1108 | } | 1131 | } |
1109 | 1132 | ||
1110 | void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { | 1133 | static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *node) { |
1111 | if (seat->focused_layer) { | ||
1112 | struct wlr_layer_surface_v1 *layer = seat->focused_layer; | ||
1113 | seat_set_focus_layer(seat, NULL); | ||
1114 | seat_set_focus(seat, node); | ||
1115 | seat_set_focus_layer(seat, layer); | ||
1116 | return; | ||
1117 | } | ||
1118 | |||
1119 | struct sway_node *last_focus = seat_get_focus(seat); | 1134 | struct sway_node *last_focus = seat_get_focus(seat); |
1120 | if (last_focus == node) { | 1135 | if (last_focus == node) { |
1121 | return; | 1136 | return; |
@@ -1248,6 +1263,24 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { | |||
1248 | } | 1263 | } |
1249 | } | 1264 | } |
1250 | 1265 | ||
1266 | void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { | ||
1267 | // Prevents the layer from losing focus if it has keyboard exclusivity | ||
1268 | if (seat->has_exclusive_layer) { | ||
1269 | struct wlr_layer_surface_v1 *layer = seat->focused_layer; | ||
1270 | seat_set_focus_layer(seat, NULL); | ||
1271 | seat_set_workspace_focus(seat, node); | ||
1272 | seat_set_focus_layer(seat, layer); | ||
1273 | } else if (seat->focused_layer) { | ||
1274 | seat_set_focus_layer(seat, NULL); | ||
1275 | seat_set_workspace_focus(seat, node); | ||
1276 | } else { | ||
1277 | seat_set_workspace_focus(seat, node); | ||
1278 | } | ||
1279 | if (server.session_lock.lock) { | ||
1280 | seat_set_focus_surface(seat, server.session_lock.lock->focused, false); | ||
1281 | } | ||
1282 | } | ||
1283 | |||
1251 | void seat_set_focus_container(struct sway_seat *seat, | 1284 | void seat_set_focus_container(struct sway_seat *seat, |
1252 | struct sway_container *con) { | 1285 | struct sway_container *con) { |
1253 | seat_set_focus(seat, con ? &con->node : NULL); | 1286 | seat_set_focus(seat, con ? &con->node : NULL); |
@@ -1273,7 +1306,7 @@ void seat_set_focus_surface(struct sway_seat *seat, | |||
1273 | } | 1306 | } |
1274 | 1307 | ||
1275 | sway_input_method_relay_set_focus(&seat->im_relay, surface); | 1308 | sway_input_method_relay_set_focus(&seat->im_relay, surface); |
1276 | seat_tablet_pads_notify_enter(seat, surface); | 1309 | seat_tablet_pads_set_focus(seat, surface); |
1277 | } | 1310 | } |
1278 | 1311 | ||
1279 | void seat_set_focus_layer(struct sway_seat *seat, | 1312 | void seat_set_focus_layer(struct sway_seat *seat, |
@@ -1287,28 +1320,23 @@ void seat_set_focus_layer(struct sway_seat *seat, | |||
1287 | seat_set_focus(seat, previous); | 1320 | seat_set_focus(seat, previous); |
1288 | } | 1321 | } |
1289 | return; | 1322 | return; |
1290 | } else if (!layer || seat->focused_layer == layer) { | 1323 | } else if (!layer) { |
1291 | return; | 1324 | return; |
1292 | } | 1325 | } |
1293 | assert(layer->mapped); | 1326 | assert(layer->surface->mapped); |
1294 | seat_set_focus_surface(seat, layer->surface, true); | 1327 | if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && |
1295 | if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { | 1328 | layer->current.keyboard_interactive |
1296 | seat->focused_layer = layer; | 1329 | == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { |
1330 | seat->has_exclusive_layer = true; | ||
1297 | } | 1331 | } |
1298 | } | 1332 | if (seat->focused_layer == layer) { |
1299 | |||
1300 | void seat_set_exclusive_client(struct sway_seat *seat, | ||
1301 | struct wl_client *client) { | ||
1302 | if (!client) { | ||
1303 | seat->exclusive_client = client; | ||
1304 | // Triggers a refocus of the topmost surface layer if necessary | ||
1305 | // TODO: Make layer surface focus per-output based on cursor position | ||
1306 | for (int i = 0; i < root->outputs->length; ++i) { | ||
1307 | struct sway_output *output = root->outputs->items[i]; | ||
1308 | arrange_layers(output); | ||
1309 | } | ||
1310 | return; | 1333 | return; |
1311 | } | 1334 | } |
1335 | seat_set_focus_surface(seat, layer->surface, true); | ||
1336 | seat->focused_layer = layer; | ||
1337 | } | ||
1338 | |||
1339 | void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client) { | ||
1312 | if (seat->focused_layer) { | 1340 | if (seat->focused_layer) { |
1313 | if (wl_resource_get_client(seat->focused_layer->resource) != client) { | 1341 | if (wl_resource_get_client(seat->focused_layer->resource) != client) { |
1314 | seat_set_focus_layer(seat, NULL); | 1342 | seat_set_focus_layer(seat, NULL); |
@@ -1335,7 +1363,6 @@ void seat_set_exclusive_client(struct sway_seat *seat, | |||
1335 | now.tv_nsec / 1000, point->touch_id); | 1363 | now.tv_nsec / 1000, point->touch_id); |
1336 | } | 1364 | } |
1337 | } | 1365 | } |
1338 | seat->exclusive_client = client; | ||
1339 | } | 1366 | } |
1340 | 1367 | ||
1341 | struct sway_node *seat_get_focus_inactive(struct sway_seat *seat, | 1368 | struct sway_node *seat_get_focus_inactive(struct sway_seat *seat, |
@@ -1416,9 +1443,8 @@ struct sway_node *seat_get_focus(struct sway_seat *seat) { | |||
1416 | if (!seat->has_focus) { | 1443 | if (!seat->has_focus) { |
1417 | return NULL; | 1444 | return NULL; |
1418 | } | 1445 | } |
1419 | if (wl_list_empty(&seat->focus_stack)) { | 1446 | sway_assert(!wl_list_empty(&seat->focus_stack), |
1420 | return NULL; | 1447 | "focus_stack is empty, but has_focus is true"); |
1421 | } | ||
1422 | struct sway_seat_node *current = | 1448 | struct sway_seat_node *current = |
1423 | wl_container_of(seat->focus_stack.next, current, link); | 1449 | wl_container_of(seat->focus_stack.next, current, link); |
1424 | return current->node; | 1450 | return current->node; |
@@ -1503,7 +1529,7 @@ struct seat_config *seat_get_config_by_name(const char *name) { | |||
1503 | } | 1529 | } |
1504 | 1530 | ||
1505 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, | 1531 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, |
1506 | uint32_t button, enum wlr_button_state state) { | 1532 | uint32_t button, enum wl_pointer_button_state state) { |
1507 | seat->last_button_serial = wlr_seat_pointer_notify_button(seat->wlr_seat, | 1533 | seat->last_button_serial = wlr_seat_pointer_notify_button(seat->wlr_seat, |
1508 | time_msec, button, state); | 1534 | time_msec, button, state); |
1509 | } | 1535 | } |
@@ -1540,7 +1566,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con) { | |||
1540 | 1566 | ||
1541 | void seatop_button(struct sway_seat *seat, uint32_t time_msec, | 1567 | void seatop_button(struct sway_seat *seat, uint32_t time_msec, |
1542 | struct wlr_input_device *device, uint32_t button, | 1568 | struct wlr_input_device *device, uint32_t button, |
1543 | enum wlr_button_state state) { | 1569 | enum wl_pointer_button_state state) { |
1544 | if (seat->seatop_impl->button) { | 1570 | if (seat->seatop_impl->button) { |
1545 | seat->seatop_impl->button(seat, time_msec, device, button, state); | 1571 | seat->seatop_impl->button(seat, time_msec, device, button, state); |
1546 | } | 1572 | } |
@@ -1553,12 +1579,38 @@ void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { | |||
1553 | } | 1579 | } |
1554 | 1580 | ||
1555 | void seatop_pointer_axis(struct sway_seat *seat, | 1581 | void seatop_pointer_axis(struct sway_seat *seat, |
1556 | struct wlr_event_pointer_axis *event) { | 1582 | struct wlr_pointer_axis_event *event) { |
1557 | if (seat->seatop_impl->pointer_axis) { | 1583 | if (seat->seatop_impl->pointer_axis) { |
1558 | seat->seatop_impl->pointer_axis(seat, event); | 1584 | seat->seatop_impl->pointer_axis(seat, event); |
1559 | } | 1585 | } |
1560 | } | 1586 | } |
1561 | 1587 | ||
1588 | void seatop_touch_motion(struct sway_seat *seat, struct wlr_touch_motion_event *event, | ||
1589 | double lx, double ly) { | ||
1590 | if (seat->seatop_impl->touch_motion) { | ||
1591 | seat->seatop_impl->touch_motion(seat, event, lx, ly); | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | void seatop_touch_up(struct sway_seat *seat, struct wlr_touch_up_event *event) { | ||
1596 | if (seat->seatop_impl->touch_up) { | ||
1597 | seat->seatop_impl->touch_up(seat, event); | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *event, | ||
1602 | double lx, double ly) { | ||
1603 | if (seat->seatop_impl->touch_down) { | ||
1604 | seat->seatop_impl->touch_down(seat, event, lx, ly); | ||
1605 | } | ||
1606 | } | ||
1607 | |||
1608 | void seatop_touch_cancel(struct sway_seat *seat, struct wlr_touch_cancel_event *event) { | ||
1609 | if (seat->seatop_impl->touch_cancel) { | ||
1610 | seat->seatop_impl->touch_cancel(seat, event); | ||
1611 | } | ||
1612 | } | ||
1613 | |||
1562 | void seatop_tablet_tool_tip(struct sway_seat *seat, | 1614 | void seatop_tablet_tool_tip(struct sway_seat *seat, |
1563 | struct sway_tablet_tool *tool, uint32_t time_msec, | 1615 | struct sway_tablet_tool *tool, uint32_t time_msec, |
1564 | enum wlr_tablet_tool_tip_state state) { | 1616 | enum wlr_tablet_tool_tip_state state) { |
@@ -1576,6 +1628,62 @@ void seatop_tablet_tool_motion(struct sway_seat *seat, | |||
1576 | } | 1628 | } |
1577 | } | 1629 | } |
1578 | 1630 | ||
1631 | void seatop_hold_begin(struct sway_seat *seat, | ||
1632 | struct wlr_pointer_hold_begin_event *event) { | ||
1633 | if (seat->seatop_impl->hold_begin) { | ||
1634 | seat->seatop_impl->hold_begin(seat, event); | ||
1635 | } | ||
1636 | } | ||
1637 | |||
1638 | void seatop_hold_end(struct sway_seat *seat, | ||
1639 | struct wlr_pointer_hold_end_event *event) { | ||
1640 | if (seat->seatop_impl->hold_end) { | ||
1641 | seat->seatop_impl->hold_end(seat, event); | ||
1642 | } | ||
1643 | } | ||
1644 | |||
1645 | void seatop_pinch_begin(struct sway_seat *seat, | ||
1646 | struct wlr_pointer_pinch_begin_event *event) { | ||
1647 | if (seat->seatop_impl->pinch_begin) { | ||
1648 | seat->seatop_impl->pinch_begin(seat, event); | ||
1649 | } | ||
1650 | } | ||
1651 | |||
1652 | void seatop_pinch_update(struct sway_seat *seat, | ||
1653 | struct wlr_pointer_pinch_update_event *event) { | ||
1654 | if (seat->seatop_impl->pinch_update) { | ||
1655 | seat->seatop_impl->pinch_update(seat, event); | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | void seatop_pinch_end(struct sway_seat *seat, | ||
1660 | struct wlr_pointer_pinch_end_event *event) { | ||
1661 | if (seat->seatop_impl->pinch_end) { | ||
1662 | seat->seatop_impl->pinch_end(seat, event); | ||
1663 | } | ||
1664 | } | ||
1665 | |||
1666 | void seatop_swipe_begin(struct sway_seat *seat, | ||
1667 | struct wlr_pointer_swipe_begin_event *event) { | ||
1668 | if (seat->seatop_impl->swipe_begin) { | ||
1669 | seat->seatop_impl->swipe_begin(seat, event); | ||
1670 | } | ||
1671 | } | ||
1672 | |||
1673 | void seatop_swipe_update(struct sway_seat *seat, | ||
1674 | struct wlr_pointer_swipe_update_event *event) { | ||
1675 | if (seat->seatop_impl->swipe_update) { | ||
1676 | seat->seatop_impl->swipe_update(seat, event); | ||
1677 | } | ||
1678 | } | ||
1679 | |||
1680 | void seatop_swipe_end(struct sway_seat *seat, | ||
1681 | struct wlr_pointer_swipe_end_event *event) { | ||
1682 | if (seat->seatop_impl->swipe_end) { | ||
1683 | seat->seatop_impl->swipe_end(seat, event); | ||
1684 | } | ||
1685 | } | ||
1686 | |||
1579 | void seatop_rebase(struct sway_seat *seat, uint32_t time_msec) { | 1687 | void seatop_rebase(struct sway_seat *seat, uint32_t time_msec) { |
1580 | if (seat->seatop_impl->rebase) { | 1688 | if (seat->seatop_impl->rebase) { |
1581 | seat->seatop_impl->rebase(seat, time_msec); | 1689 | seat->seatop_impl->rebase(seat, time_msec); |
@@ -1591,13 +1699,6 @@ void seatop_end(struct sway_seat *seat) { | |||
1591 | seat->seatop_impl = NULL; | 1699 | seat->seatop_impl = NULL; |
1592 | } | 1700 | } |
1593 | 1701 | ||
1594 | void seatop_render(struct sway_seat *seat, struct sway_output *output, | ||
1595 | pixman_region32_t *damage) { | ||
1596 | if (seat->seatop_impl->render) { | ||
1597 | seat->seatop_impl->render(seat, output, damage); | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | bool seatop_allows_set_cursor(struct sway_seat *seat) { | 1702 | bool seatop_allows_set_cursor(struct sway_seat *seat) { |
1602 | return seat->seatop_impl->allow_set_cursor; | 1703 | return seat->seatop_impl->allow_set_cursor; |
1603 | } | 1704 | } |
diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index f9eb8c8a..e01fa933 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c | |||
@@ -1,18 +1,21 @@ | |||
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 "sway/desktop/transaction.h" | 8 | #include "sway/desktop/transaction.h" |
8 | #include "sway/input/cursor.h" | 9 | #include "sway/input/cursor.h" |
9 | #include "sway/input/seat.h" | 10 | #include "sway/input/seat.h" |
10 | #include "sway/input/tablet.h" | 11 | #include "sway/input/tablet.h" |
12 | #include "sway/layers.h" | ||
11 | #include "sway/output.h" | 13 | #include "sway/output.h" |
14 | #include "sway/scene_descriptor.h" | ||
12 | #include "sway/tree/view.h" | 15 | #include "sway/tree/view.h" |
13 | #include "sway/tree/workspace.h" | 16 | #include "sway/tree/workspace.h" |
14 | #include "log.h" | 17 | #include "log.h" |
15 | #if HAVE_XWAYLAND | 18 | #if WLR_HAS_XWAYLAND |
16 | #include "sway/xwayland.h" | 19 | #include "sway/xwayland.h" |
17 | #endif | 20 | #endif |
18 | 21 | ||
@@ -20,6 +23,7 @@ struct seatop_default_event { | |||
20 | struct sway_node *previous_node; | 23 | struct sway_node *previous_node; |
21 | uint32_t pressed_buttons[SWAY_CURSOR_PRESSED_BUTTONS_CAP]; | 24 | uint32_t pressed_buttons[SWAY_CURSOR_PRESSED_BUTTONS_CAP]; |
22 | size_t pressed_button_count; | 25 | size_t pressed_button_count; |
26 | struct gesture_tracker gestures; | ||
23 | }; | 27 | }; |
24 | 28 | ||
25 | /*-----------------------------------------\ | 29 | /*-----------------------------------------\ |
@@ -51,6 +55,9 @@ static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) { | |||
51 | while (cont) { | 55 | while (cont) { |
52 | if (container_parent_layout(cont) == layout) { | 56 | if (container_parent_layout(cont) == layout) { |
53 | list_t *siblings = container_get_siblings(cont); | 57 | list_t *siblings = container_get_siblings(cont); |
58 | if (!siblings) { | ||
59 | return false; | ||
60 | } | ||
54 | int index = list_find(siblings, cont); | 61 | int index = list_find(siblings, cont); |
55 | if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) { | 62 | if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) { |
56 | return false; | 63 | return false; |
@@ -226,14 +233,15 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, | |||
226 | struct sway_container *cont = node && node->type == N_CONTAINER ? | 233 | struct sway_container *cont = node && node->type == N_CONTAINER ? |
227 | node->sway_container : NULL; | 234 | node->sway_container : NULL; |
228 | 235 | ||
229 | if (wlr_surface_is_layer_surface(surface)) { | 236 | struct wlr_layer_surface_v1 *layer; |
237 | #if WLR_HAS_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) { | ||
230 | // Handle tapping a layer surface | 242 | // Handle tapping a layer surface |
231 | struct wlr_layer_surface_v1 *layer = | 243 | seat_set_focus_layer(seat, layer); |
232 | wlr_layer_surface_v1_from_wlr_surface(surface); | 244 | transaction_commit_dirty(); |
233 | if (layer->current.keyboard_interactive) { | ||
234 | seat_set_focus_layer(seat, layer); | ||
235 | transaction_commit_dirty(); | ||
236 | } | ||
237 | } else if (cont) { | 245 | } else if (cont) { |
238 | bool is_floating_or_child = container_is_floating_or_child(cont); | 246 | bool is_floating_or_child = container_is_floating_or_child(cont); |
239 | bool is_fullscreen_or_child = container_is_fullscreen_or_child(cont); | 247 | bool is_fullscreen_or_child = container_is_fullscreen_or_child(cont); |
@@ -258,20 +266,17 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, | |||
258 | 266 | ||
259 | // Handle tapping on a container surface | 267 | // Handle tapping on a container surface |
260 | seat_set_focus_container(seat, cont); | 268 | seat_set_focus_container(seat, cont); |
261 | seatop_begin_down(seat, node->sway_container, time_msec, sx, sy); | 269 | seatop_begin_down(seat, node->sway_container, sx, sy); |
262 | } | 270 | } |
263 | #if HAVE_XWAYLAND | 271 | #if WLR_HAS_XWAYLAND |
264 | // Handle tapping on an xwayland unmanaged view | 272 | // Handle tapping on an xwayland unmanaged view |
265 | else if (wlr_surface_is_xwayland_surface(surface)) { | 273 | else if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) && |
266 | struct wlr_xwayland_surface *xsurface = | 274 | xsurface->override_redirect && |
267 | wlr_xwayland_surface_from_wlr_surface(surface); | 275 | wlr_xwayland_or_surface_wants_focus(xsurface)) { |
268 | if (xsurface->override_redirect && | 276 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; |
269 | wlr_xwayland_or_surface_wants_focus(xsurface)) { | 277 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
270 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; | 278 | seat_set_focus_surface(seat, xsurface->surface, false); |
271 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 279 | transaction_commit_dirty(); |
272 | seat_set_focus_surface(seat, xsurface->surface, false); | ||
273 | transaction_commit_dirty(); | ||
274 | } | ||
275 | } | 280 | } |
276 | #endif | 281 | #endif |
277 | 282 | ||
@@ -285,7 +290,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, | |||
285 | 290 | ||
286 | static bool trigger_pointer_button_binding(struct sway_seat *seat, | 291 | static bool trigger_pointer_button_binding(struct sway_seat *seat, |
287 | struct wlr_input_device *device, uint32_t button, | 292 | struct wlr_input_device *device, uint32_t button, |
288 | enum wlr_button_state state, uint32_t modifiers, | 293 | enum wl_pointer_button_state state, uint32_t modifiers, |
289 | 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) { |
290 | // 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 |
291 | // pointer input for one. Emulated input should not trigger bindings. The | 296 | // pointer input for one. Emulated input should not trigger bindings. The |
@@ -299,7 +304,7 @@ static bool trigger_pointer_button_binding(struct sway_seat *seat, | |||
299 | char *device_identifier = device ? input_device_get_identifier(device) | 304 | char *device_identifier = device ? input_device_get_identifier(device) |
300 | : strdup("*"); | 305 | : strdup("*"); |
301 | struct sway_binding *binding = NULL; | 306 | struct sway_binding *binding = NULL; |
302 | if (state == WLR_BUTTON_PRESSED) { | 307 | if (state == WL_POINTER_BUTTON_STATE_PRESSED) { |
303 | state_add_button(e, button); | 308 | state_add_button(e, button); |
304 | binding = get_active_mouse_binding(e, | 309 | binding = get_active_mouse_binding(e, |
305 | config->current_mode->mouse_bindings, modifiers, false, | 310 | config->current_mode->mouse_bindings, modifiers, false, |
@@ -324,7 +329,7 @@ static bool trigger_pointer_button_binding(struct sway_seat *seat, | |||
324 | 329 | ||
325 | 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, |
326 | struct wlr_input_device *device, uint32_t button, | 331 | struct wlr_input_device *device, uint32_t button, |
327 | enum wlr_button_state state) { | 332 | enum wl_pointer_button_state state) { |
328 | struct sway_cursor *cursor = seat->cursor; | 333 | struct sway_cursor *cursor = seat->cursor; |
329 | 334 | ||
330 | // Determine what's under the cursor | 335 | // Determine what's under the cursor |
@@ -357,7 +362,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
357 | 362 | ||
358 | // Handle clicking an empty workspace | 363 | // Handle clicking an empty workspace |
359 | if (node && node->type == N_WORKSPACE) { | 364 | if (node && node->type == N_WORKSPACE) { |
360 | if (state == WLR_BUTTON_PRESSED) { | 365 | if (state == WL_POINTER_BUTTON_STATE_PRESSED) { |
361 | seat_set_focus(seat, node); | 366 | seat_set_focus(seat, node); |
362 | transaction_commit_dirty(); | 367 | transaction_commit_dirty(); |
363 | } | 368 | } |
@@ -365,21 +370,23 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
365 | return; | 370 | return; |
366 | } | 371 | } |
367 | 372 | ||
368 | // Handle clicking a layer surface | 373 | // Handle clicking a layer surface and its popups/subsurfaces |
369 | if (surface && wlr_surface_is_layer_surface(surface)) { | 374 | struct wlr_layer_surface_v1 *layer = NULL; |
370 | struct wlr_layer_surface_v1 *layer = | 375 | if ((layer = toplevel_layer_surface_from_surface(surface))) { |
371 | wlr_layer_surface_v1_from_wlr_surface(surface); | ||
372 | if (layer->current.keyboard_interactive) { | 376 | if (layer->current.keyboard_interactive) { |
373 | seat_set_focus_layer(seat, layer); | 377 | seat_set_focus_layer(seat, layer); |
374 | transaction_commit_dirty(); | 378 | transaction_commit_dirty(); |
375 | } | 379 | } |
380 | if (state == WL_POINTER_BUTTON_STATE_PRESSED) { | ||
381 | seatop_begin_down_on_surface(seat, surface, sx, sy); | ||
382 | } | ||
376 | seat_pointer_notify_button(seat, time_msec, button, state); | 383 | seat_pointer_notify_button(seat, time_msec, button, state); |
377 | return; | 384 | return; |
378 | } | 385 | } |
379 | 386 | ||
380 | // Handle tiling resize via border | 387 | // Handle tiling resize via border |
381 | if (cont && resize_edge && button == BTN_LEFT && | 388 | if (cont && resize_edge && button == BTN_LEFT && |
382 | state == WLR_BUTTON_PRESSED && !is_floating) { | 389 | state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating) { |
383 | // 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 |
384 | // 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 |
385 | // 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. |
@@ -397,7 +404,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
397 | // Handle tiling resize via mod | 404 | // Handle tiling resize via mod |
398 | bool mod_pressed = modifiers & config->floating_mod; | 405 | bool mod_pressed = modifiers & config->floating_mod; |
399 | if (cont && !is_floating_or_child && mod_pressed && | 406 | if (cont && !is_floating_or_child && mod_pressed && |
400 | state == WLR_BUTTON_PRESSED) { | 407 | state == WL_POINTER_BUTTON_STATE_PRESSED) { |
401 | uint32_t btn_resize = config->floating_mod_inverse ? | 408 | uint32_t btn_resize = config->floating_mod_inverse ? |
402 | BTN_LEFT : BTN_RIGHT; | 409 | BTN_LEFT : BTN_RIGHT; |
403 | if (button == btn_resize) { | 410 | if (button == btn_resize) { |
@@ -424,13 +431,31 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
424 | } | 431 | } |
425 | } | 432 | } |
426 | 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 | |||
427 | // Handle beginning floating move | 454 | // Handle beginning floating move |
428 | if (cont && is_floating_or_child && !is_fullscreen_or_child && | 455 | if (cont && is_floating_or_child && !is_fullscreen_or_child && |
429 | state == WLR_BUTTON_PRESSED) { | 456 | state == WL_POINTER_BUTTON_STATE_PRESSED) { |
430 | 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; |
431 | if (button == btn_move && (mod_pressed || on_titlebar)) { | 458 | if (button == btn_move && (mod_pressed || on_titlebar)) { |
432 | seat_set_focus_container(seat, | ||
433 | seat_get_focus_inactive_view(seat, &cont->node)); | ||
434 | seatop_begin_move_floating(seat, container_toplevel_ancestor(cont)); | 459 | seatop_begin_move_floating(seat, container_toplevel_ancestor(cont)); |
435 | return; | 460 | return; |
436 | } | 461 | } |
@@ -438,9 +463,10 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
438 | 463 | ||
439 | // Handle beginning floating resize | 464 | // Handle beginning floating resize |
440 | if (cont && is_floating_or_child && !is_fullscreen_or_child && | 465 | if (cont && is_floating_or_child && !is_fullscreen_or_child && |
441 | state == WLR_BUTTON_PRESSED) { | 466 | state == WL_POINTER_BUTTON_STATE_PRESSED) { |
442 | // Via border | 467 | // Via border |
443 | 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); | ||
444 | seatop_begin_resize_floating(seat, cont, resize_edge); | 470 | seatop_begin_resize_floating(seat, cont, resize_edge); |
445 | return; | 471 | return; |
446 | } | 472 | } |
@@ -455,6 +481,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
455 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; | 481 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; |
456 | edge |= cursor->cursor->y > floater->pending.y + floater->pending.height / 2 ? | 482 | edge |= cursor->cursor->y > floater->pending.y + floater->pending.height / 2 ? |
457 | WLR_EDGE_BOTTOM : WLR_EDGE_TOP; | 483 | WLR_EDGE_BOTTOM : WLR_EDGE_TOP; |
484 | seat_set_focus_container(seat, floater); | ||
458 | seatop_begin_resize_floating(seat, floater, edge); | 485 | seatop_begin_resize_floating(seat, floater, edge); |
459 | return; | 486 | return; |
460 | } | 487 | } |
@@ -462,55 +489,43 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
462 | 489 | ||
463 | // Handle moving a tiling container | 490 | // Handle moving a tiling container |
464 | if (config->tiling_drag && (mod_pressed || on_titlebar) && | 491 | if (config->tiling_drag && (mod_pressed || on_titlebar) && |
465 | state == WLR_BUTTON_PRESSED && !is_floating_or_child && | 492 | state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child && |
466 | cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { | 493 | cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { |
467 | struct sway_container *focus = seat_get_focused_container(seat); | 494 | // If moving a container by its title bar, use a threshold for the drag |
468 | bool focused = focus == cont || container_has_ancestor(focus, cont); | ||
469 | if (on_titlebar && !focused) { | ||
470 | node = seat_get_focus_inactive(seat, &cont->node); | ||
471 | seat_set_focus(seat, node); | ||
472 | } | ||
473 | |||
474 | // If moving a container by it's title bar, use a threshold for the drag | ||
475 | if (!mod_pressed && config->tiling_drag_threshold > 0) { | 495 | if (!mod_pressed && config->tiling_drag_threshold > 0) { |
476 | seatop_begin_move_tiling_threshold(seat, cont); | 496 | seatop_begin_move_tiling_threshold(seat, cont); |
477 | } else { | 497 | } else { |
478 | seatop_begin_move_tiling(seat, cont); | 498 | seatop_begin_move_tiling(seat, cont); |
479 | } | 499 | } |
500 | |||
480 | return; | 501 | return; |
481 | } | 502 | } |
482 | 503 | ||
483 | // Handle mousedown on a container surface | 504 | // Handle mousedown on a container surface |
484 | if (surface && cont && state == WLR_BUTTON_PRESSED) { | 505 | if (surface && cont && state == WL_POINTER_BUTTON_STATE_PRESSED) { |
485 | seat_set_focus_container(seat, cont); | 506 | seatop_begin_down(seat, cont, sx, sy); |
486 | seatop_begin_down(seat, cont, time_msec, sx, sy); | 507 | seat_pointer_notify_button(seat, time_msec, button, WL_POINTER_BUTTON_STATE_PRESSED); |
487 | seat_pointer_notify_button(seat, time_msec, button, WLR_BUTTON_PRESSED); | ||
488 | return; | 508 | return; |
489 | } | 509 | } |
490 | 510 | ||
491 | // Handle clicking a container surface or decorations | 511 | // Handle clicking a container surface or decorations |
492 | if (cont && state == WLR_BUTTON_PRESSED) { | 512 | if (cont && state == WL_POINTER_BUTTON_STATE_PRESSED) { |
493 | node = seat_get_focus_inactive(seat, &cont->node); | ||
494 | seat_set_focus(seat, node); | ||
495 | transaction_commit_dirty(); | ||
496 | seat_pointer_notify_button(seat, time_msec, button, state); | 513 | seat_pointer_notify_button(seat, time_msec, button, state); |
497 | return; | 514 | return; |
498 | } | 515 | } |
499 | 516 | ||
500 | #if HAVE_XWAYLAND | 517 | #if WLR_HAS_XWAYLAND |
501 | // Handle clicking on xwayland unmanaged view | 518 | // Handle clicking on xwayland unmanaged view |
502 | if (surface && wlr_surface_is_xwayland_surface(surface)) { | 519 | struct wlr_xwayland_surface *xsurface; |
503 | struct wlr_xwayland_surface *xsurface = | 520 | if (surface && |
504 | wlr_xwayland_surface_from_wlr_surface(surface); | 521 | (xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) && |
505 | if (xsurface->override_redirect && | 522 | xsurface->override_redirect && |
506 | wlr_xwayland_or_surface_wants_focus(xsurface)) { | 523 | wlr_xwayland_or_surface_wants_focus(xsurface)) { |
507 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; | 524 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; |
508 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 525 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
509 | seat_set_focus_surface(seat, xsurface->surface, false); | 526 | seat_set_focus_surface(seat, xsurface->surface, false); |
510 | transaction_commit_dirty(); | 527 | transaction_commit_dirty(); |
511 | seat_pointer_notify_button(seat, time_msec, button, state); | 528 | seat_pointer_notify_button(seat, time_msec, button, state); |
512 | return; | ||
513 | } | ||
514 | } | 529 | } |
515 | #endif | 530 | #endif |
516 | 531 | ||
@@ -533,6 +548,21 @@ static void check_focus_follows_mouse(struct sway_seat *seat, | |||
533 | if (wlr_output == NULL) { | 548 | if (wlr_output == NULL) { |
534 | return; | 549 | return; |
535 | } | 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 | |||
536 | struct sway_output *hovered_output = wlr_output->data; | 566 | struct sway_output *hovered_output = wlr_output->data; |
537 | if (focus && hovered_output != node_get_output(focus)) { | 567 | if (focus && hovered_output != node_get_output(focus)) { |
538 | struct sway_workspace *ws = output_get_active_workspace(hovered_output); | 568 | struct sway_workspace *ws = output_get_active_workspace(hovered_output); |
@@ -593,12 +623,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { | |||
593 | wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); | 623 | wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); |
594 | } | 624 | } |
595 | 625 | ||
596 | struct sway_drag_icon *drag_icon; | 626 | drag_icons_update_position(seat); |
597 | wl_list_for_each(drag_icon, &root->drag_icons, link) { | ||
598 | if (drag_icon->seat == seat) { | ||
599 | drag_icon_update_position(drag_icon); | ||
600 | } | ||
601 | } | ||
602 | 627 | ||
603 | e->previous_node = node; | 628 | e->previous_node = node; |
604 | } | 629 | } |
@@ -628,25 +653,50 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, | |||
628 | 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); |
629 | } | 654 | } |
630 | 655 | ||
631 | struct sway_drag_icon *drag_icon; | 656 | drag_icons_update_position(seat); |
632 | wl_list_for_each(drag_icon, &root->drag_icons, link) { | ||
633 | if (drag_icon->seat == seat) { | ||
634 | drag_icon_update_position(drag_icon); | ||
635 | } | ||
636 | } | ||
637 | 657 | ||
638 | e->previous_node = node; | 658 | e->previous_node = node; |
639 | } | 659 | } |
640 | 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 | |||
641 | /*----------------------------------------\ | 691 | /*----------------------------------------\ |
642 | * Functions used by handle_pointer_axis / | 692 | * Functions used by handle_pointer_axis / |
643 | *--------------------------------------*/ | 693 | *--------------------------------------*/ |
644 | 694 | ||
645 | static uint32_t wl_axis_to_button(struct wlr_event_pointer_axis *event) { | 695 | static uint32_t wl_axis_to_button(struct wlr_pointer_axis_event *event) { |
646 | switch (event->orientation) { | 696 | switch (event->orientation) { |
647 | case WLR_AXIS_ORIENTATION_VERTICAL: | 697 | case WL_POINTER_AXIS_VERTICAL_SCROLL: |
648 | return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN; | 698 | return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN; |
649 | case WLR_AXIS_ORIENTATION_HORIZONTAL: | 699 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: |
650 | return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT; | 700 | return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT; |
651 | default: | 701 | default: |
652 | sway_log(SWAY_DEBUG, "Unknown axis orientation"); | 702 | sway_log(SWAY_DEBUG, "Unknown axis orientation"); |
@@ -655,9 +705,9 @@ static uint32_t wl_axis_to_button(struct wlr_event_pointer_axis *event) { | |||
655 | } | 705 | } |
656 | 706 | ||
657 | static void handle_pointer_axis(struct sway_seat *seat, | 707 | static void handle_pointer_axis(struct sway_seat *seat, |
658 | struct wlr_event_pointer_axis *event) { | 708 | struct wlr_pointer_axis_event *event) { |
659 | struct sway_input_device *input_device = | 709 | struct sway_input_device *input_device = |
660 | event->device ? event->device->data : NULL; | 710 | event->pointer ? event->pointer->base.data : NULL; |
661 | struct input_config *ic = | 711 | struct input_config *ic = |
662 | input_device ? input_device_get_config(input_device) : NULL; | 712 | input_device ? input_device_get_config(input_device) : NULL; |
663 | struct sway_cursor *cursor = seat->cursor; | 713 | struct sway_cursor *cursor = seat->cursor; |
@@ -703,6 +753,7 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
703 | 753 | ||
704 | // 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) |
705 | if (!handled && (on_titlebar || on_titlebar_border)) { | 755 | if (!handled && (on_titlebar || on_titlebar_border)) { |
756 | struct sway_node *new_focus; | ||
706 | enum sway_container_layout layout = container_parent_layout(cont); | 757 | enum sway_container_layout layout = container_parent_layout(cont); |
707 | if (layout == L_TABBED || layout == L_STACKED) { | 758 | if (layout == L_TABBED || layout == L_STACKED) { |
708 | struct sway_node *tabcontainer = node_get_parent(node); | 759 | struct sway_node *tabcontainer = node_get_parent(node); |
@@ -710,7 +761,7 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
710 | seat_get_active_tiling_child(seat, tabcontainer); | 761 | seat_get_active_tiling_child(seat, tabcontainer); |
711 | list_t *siblings = container_get_siblings(cont); | 762 | list_t *siblings = container_get_siblings(cont); |
712 | int desired = list_find(siblings, active->sway_container) + | 763 | int desired = list_find(siblings, active->sway_container) + |
713 | round(scroll_factor * event->delta_discrete); | 764 | roundf(scroll_factor * event->delta_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); |
714 | if (desired < 0) { | 765 | if (desired < 0) { |
715 | desired = 0; | 766 | desired = 0; |
716 | } else if (desired >= siblings->length) { | 767 | } else if (desired >= siblings->length) { |
@@ -719,14 +770,16 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
719 | 770 | ||
720 | struct sway_container *new_sibling_con = siblings->items[desired]; | 771 | struct sway_container *new_sibling_con = siblings->items[desired]; |
721 | struct sway_node *new_sibling = &new_sibling_con->node; | 772 | struct sway_node *new_sibling = &new_sibling_con->node; |
722 | struct sway_node *new_focus = | ||
723 | seat_get_focus_inactive(seat, new_sibling); | ||
724 | // Use the focused child of the tabbed/stacked container, not the | 773 | // Use the focused child of the tabbed/stacked container, not the |
725 | // container the user scrolled on. | 774 | // container the user scrolled on. |
726 | seat_set_focus(seat, new_focus); | 775 | new_focus = seat_get_focus_inactive(seat, new_sibling); |
727 | transaction_commit_dirty(); | 776 | } else { |
728 | handled = true; | 777 | new_focus = seat_get_focus_inactive(seat, &cont->node); |
729 | } | 778 | } |
779 | |||
780 | seat_set_focus(seat, new_focus); | ||
781 | transaction_commit_dirty(); | ||
782 | handled = true; | ||
730 | } | 783 | } |
731 | 784 | ||
732 | // Handle mouse bindings - x11 mouse buttons 4-7 - release event | 785 | // Handle mouse bindings - x11 mouse buttons 4-7 - release event |
@@ -742,8 +795,307 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
742 | 795 | ||
743 | if (!handled) { | 796 | if (!handled) { |
744 | 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, |
745 | event->orientation, scroll_factor * event->delta, | 798 | event->orientation, scroll_factor * event->delta, |
746 | round(scroll_factor * event->delta_discrete), event->source); | 799 | roundf(scroll_factor * event->delta_discrete), event->source, |
800 | event->relative_direction); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | /*------------------------------------\ | ||
805 | * Functions used by gesture support / | ||
806 | *----------------------------------*/ | ||
807 | |||
808 | /** | ||
809 | * Check gesture binding for a specific gesture type and finger count. | ||
810 | * Returns true if binding is present, false otherwise | ||
811 | */ | ||
812 | static bool gesture_binding_check(list_t *bindings, enum gesture_type type, | ||
813 | uint8_t fingers, struct sway_input_device *device) { | ||
814 | char *input = | ||
815 | device ? input_device_get_identifier(device->wlr_device) : strdup("*"); | ||
816 | |||
817 | for (int i = 0; i < bindings->length; ++i) { | ||
818 | struct sway_gesture_binding *binding = bindings->items[i]; | ||
819 | |||
820 | // Check type and finger count | ||
821 | if (!gesture_check(&binding->gesture, type, fingers)) { | ||
822 | continue; | ||
823 | } | ||
824 | |||
825 | // Check that input matches | ||
826 | if (strcmp(binding->input, "*") != 0 && | ||
827 | strcmp(binding->input, input) != 0) { | ||
828 | continue; | ||
829 | } | ||
830 | |||
831 | free(input); | ||
832 | |||
833 | return true; | ||
834 | } | ||
835 | |||
836 | free(input); | ||
837 | |||
838 | return false; | ||
839 | } | ||
840 | |||
841 | /** | ||
842 | * Return the gesture binding which matches gesture type, finger count | ||
843 | * and direction, otherwise return null. | ||
844 | */ | ||
845 | static struct sway_gesture_binding* gesture_binding_match( | ||
846 | list_t *bindings, struct gesture *gesture, const char *input) { | ||
847 | struct sway_gesture_binding *current = NULL; | ||
848 | |||
849 | // Find best matching binding | ||
850 | for (int i = 0; i < bindings->length; ++i) { | ||
851 | struct sway_gesture_binding *binding = bindings->items[i]; | ||
852 | bool exact = binding->flags & BINDING_EXACT; | ||
853 | |||
854 | // Check gesture matching | ||
855 | if (!gesture_match(&binding->gesture, gesture, exact)) { | ||
856 | continue; | ||
857 | } | ||
858 | |||
859 | // Check input matching | ||
860 | if (strcmp(binding->input, "*") != 0 && | ||
861 | strcmp(binding->input, input) != 0) { | ||
862 | continue; | ||
863 | } | ||
864 | |||
865 | // If we already have a match ... | ||
866 | if (current) { | ||
867 | // ... check if input matching is equivalent | ||
868 | if (strcmp(current->input, binding->input) == 0) { | ||
869 | |||
870 | // ... - do not override an exact binding | ||
871 | if (!exact && current->flags & BINDING_EXACT) { | ||
872 | continue; | ||
873 | } | ||
874 | |||
875 | // ... - and ensure direction matching is better or equal | ||
876 | if (gesture_compare(¤t->gesture, &binding->gesture) > 0) { | ||
877 | continue; | ||
878 | } | ||
879 | } else if (strcmp(binding->input, "*") == 0) { | ||
880 | // ... do not accept worse input match | ||
881 | continue; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | // Accept newer or better match | ||
886 | current = binding; | ||
887 | |||
888 | // If exact binding and input is found, quit search | ||
889 | if (strcmp(current->input, input) == 0 && | ||
890 | gesture_compare(¤t->gesture, gesture) == 0) { | ||
891 | break; | ||
892 | } | ||
893 | } // for all gesture bindings | ||
894 | |||
895 | return current; | ||
896 | } | ||
897 | |||
898 | // Wrapper around gesture_tracker_end to use tracker with sway bindings | ||
899 | static struct sway_gesture_binding* gesture_tracker_end_and_match( | ||
900 | struct gesture_tracker *tracker, struct sway_input_device* device) { | ||
901 | // Determine name of input that received gesture | ||
902 | char *input = device | ||
903 | ? input_device_get_identifier(device->wlr_device) | ||
904 | : strdup("*"); | ||
905 | |||
906 | // Match tracking result to binding | ||
907 | struct gesture *gesture = gesture_tracker_end(tracker); | ||
908 | struct sway_gesture_binding *binding = gesture_binding_match( | ||
909 | config->current_mode->gesture_bindings, gesture, input); | ||
910 | free(gesture); | ||
911 | free(input); | ||
912 | |||
913 | return binding; | ||
914 | } | ||
915 | |||
916 | // Small wrapper around seat_execute_command to work on gesture bindings | ||
917 | static void gesture_binding_execute(struct sway_seat *seat, | ||
918 | struct sway_gesture_binding *binding) { | ||
919 | struct sway_binding *dummy_binding = | ||
920 | calloc(1, sizeof(struct sway_binding)); | ||
921 | dummy_binding->type = BINDING_GESTURE; | ||
922 | dummy_binding->command = binding->command; | ||
923 | |||
924 | char *description = gesture_to_string(&binding->gesture); | ||
925 | sway_log(SWAY_DEBUG, "executing gesture binding: %s", description); | ||
926 | free(description); | ||
927 | |||
928 | seat_execute_command(seat, dummy_binding); | ||
929 | |||
930 | free(dummy_binding); | ||
931 | } | ||
932 | |||
933 | static void handle_hold_begin(struct sway_seat *seat, | ||
934 | struct wlr_pointer_hold_begin_event *event) { | ||
935 | // Start tracking gesture if there is a matching binding ... | ||
936 | struct sway_input_device *device = | ||
937 | event->pointer ? event->pointer->base.data : NULL; | ||
938 | list_t *bindings = config->current_mode->gesture_bindings; | ||
939 | if (gesture_binding_check(bindings, GESTURE_TYPE_HOLD, event->fingers, device)) { | ||
940 | struct seatop_default_event *seatop = seat->seatop_data; | ||
941 | gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_HOLD, event->fingers); | ||
942 | } else { | ||
943 | // ... otherwise forward to client | ||
944 | struct sway_cursor *cursor = seat->cursor; | ||
945 | wlr_pointer_gestures_v1_send_hold_begin( | ||
946 | server.input->pointer_gestures, cursor->seat->wlr_seat, | ||
947 | event->time_msec, event->fingers); | ||
948 | } | ||
949 | } | ||
950 | |||
951 | static void handle_hold_end(struct sway_seat *seat, | ||
952 | struct wlr_pointer_hold_end_event *event) { | ||
953 | // Ensure that gesture is being tracked and was not cancelled | ||
954 | struct seatop_default_event *seatop = seat->seatop_data; | ||
955 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_HOLD)) { | ||
956 | struct sway_cursor *cursor = seat->cursor; | ||
957 | wlr_pointer_gestures_v1_send_hold_end( | ||
958 | server.input->pointer_gestures, cursor->seat->wlr_seat, | ||
959 | event->time_msec, event->cancelled); | ||
960 | return; | ||
961 | } | ||
962 | if (event->cancelled) { | ||
963 | gesture_tracker_cancel(&seatop->gestures); | ||
964 | return; | ||
965 | } | ||
966 | |||
967 | // End gesture tracking and execute matched binding | ||
968 | struct sway_input_device *device = | ||
969 | event->pointer ? event->pointer->base.data : NULL; | ||
970 | struct sway_gesture_binding *binding = gesture_tracker_end_and_match( | ||
971 | &seatop->gestures, device); | ||
972 | |||
973 | if (binding) { | ||
974 | gesture_binding_execute(seat, binding); | ||
975 | } | ||
976 | } | ||
977 | |||
978 | static void handle_pinch_begin(struct sway_seat *seat, | ||
979 | struct wlr_pointer_pinch_begin_event *event) { | ||
980 | // Start tracking gesture if there is a matching binding ... | ||
981 | struct sway_input_device *device = | ||
982 | event->pointer ? event->pointer->base.data : NULL; | ||
983 | list_t *bindings = config->current_mode->gesture_bindings; | ||
984 | if (gesture_binding_check(bindings, GESTURE_TYPE_PINCH, event->fingers, device)) { | ||
985 | struct seatop_default_event *seatop = seat->seatop_data; | ||
986 | gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_PINCH, event->fingers); | ||
987 | } else { | ||
988 | // ... otherwise forward to client | ||
989 | struct sway_cursor *cursor = seat->cursor; | ||
990 | wlr_pointer_gestures_v1_send_pinch_begin( | ||
991 | server.input->pointer_gestures, cursor->seat->wlr_seat, | ||
992 | event->time_msec, event->fingers); | ||
993 | } | ||
994 | } | ||
995 | |||
996 | static void handle_pinch_update(struct sway_seat *seat, | ||
997 | struct wlr_pointer_pinch_update_event *event) { | ||
998 | // Update any ongoing tracking ... | ||
999 | struct seatop_default_event *seatop = seat->seatop_data; | ||
1000 | if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) { | ||
1001 | gesture_tracker_update(&seatop->gestures, event->dx, event->dy, | ||
1002 | event->scale, event->rotation); | ||
1003 | } else { | ||
1004 | // ... otherwise forward to client | ||
1005 | struct sway_cursor *cursor = seat->cursor; | ||
1006 | wlr_pointer_gestures_v1_send_pinch_update( | ||
1007 | server.input->pointer_gestures, | ||
1008 | cursor->seat->wlr_seat, | ||
1009 | event->time_msec, event->dx, event->dy, | ||
1010 | event->scale, event->rotation); | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | static void handle_pinch_end(struct sway_seat *seat, | ||
1015 | struct wlr_pointer_pinch_end_event *event) { | ||
1016 | // Ensure that gesture is being tracked and was not cancelled | ||
1017 | struct seatop_default_event *seatop = seat->seatop_data; | ||
1018 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) { | ||
1019 | struct sway_cursor *cursor = seat->cursor; | ||
1020 | wlr_pointer_gestures_v1_send_pinch_end( | ||
1021 | server.input->pointer_gestures, cursor->seat->wlr_seat, | ||
1022 | event->time_msec, event->cancelled); | ||
1023 | return; | ||
1024 | } | ||
1025 | if (event->cancelled) { | ||
1026 | gesture_tracker_cancel(&seatop->gestures); | ||
1027 | return; | ||
1028 | } | ||
1029 | |||
1030 | // End gesture tracking and execute matched binding | ||
1031 | struct sway_input_device *device = | ||
1032 | event->pointer ? event->pointer->base.data : NULL; | ||
1033 | struct sway_gesture_binding *binding = gesture_tracker_end_and_match( | ||
1034 | &seatop->gestures, device); | ||
1035 | |||
1036 | if (binding) { | ||
1037 | gesture_binding_execute(seat, binding); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | static void handle_swipe_begin(struct sway_seat *seat, | ||
1042 | struct wlr_pointer_swipe_begin_event *event) { | ||
1043 | // Start tracking gesture if there is a matching binding ... | ||
1044 | struct sway_input_device *device = | ||
1045 | event->pointer ? event->pointer->base.data : NULL; | ||
1046 | list_t *bindings = config->current_mode->gesture_bindings; | ||
1047 | if (gesture_binding_check(bindings, GESTURE_TYPE_SWIPE, event->fingers, device)) { | ||
1048 | struct seatop_default_event *seatop = seat->seatop_data; | ||
1049 | gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_SWIPE, event->fingers); | ||
1050 | } else { | ||
1051 | // ... otherwise forward to client | ||
1052 | struct sway_cursor *cursor = seat->cursor; | ||
1053 | wlr_pointer_gestures_v1_send_swipe_begin( | ||
1054 | server.input->pointer_gestures, cursor->seat->wlr_seat, | ||
1055 | event->time_msec, event->fingers); | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | static void handle_swipe_update(struct sway_seat *seat, | ||
1060 | struct wlr_pointer_swipe_update_event *event) { | ||
1061 | |||
1062 | // Update any ongoing tracking ... | ||
1063 | struct seatop_default_event *seatop = seat->seatop_data; | ||
1064 | if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) { | ||
1065 | gesture_tracker_update(&seatop->gestures, | ||
1066 | event->dx, event->dy, NAN, NAN); | ||
1067 | } else { | ||
1068 | // ... otherwise forward to client | ||
1069 | struct sway_cursor *cursor = seat->cursor; | ||
1070 | wlr_pointer_gestures_v1_send_swipe_update( | ||
1071 | server.input->pointer_gestures, cursor->seat->wlr_seat, | ||
1072 | event->time_msec, event->dx, event->dy); | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | static void handle_swipe_end(struct sway_seat *seat, | ||
1077 | struct wlr_pointer_swipe_end_event *event) { | ||
1078 | // Ensure gesture is being tracked and was not cancelled | ||
1079 | struct seatop_default_event *seatop = seat->seatop_data; | ||
1080 | if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) { | ||
1081 | struct sway_cursor *cursor = seat->cursor; | ||
1082 | wlr_pointer_gestures_v1_send_swipe_end(server.input->pointer_gestures, | ||
1083 | cursor->seat->wlr_seat, event->time_msec, event->cancelled); | ||
1084 | return; | ||
1085 | } | ||
1086 | if (event->cancelled) { | ||
1087 | gesture_tracker_cancel(&seatop->gestures); | ||
1088 | return; | ||
1089 | } | ||
1090 | |||
1091 | // End gesture tracking and execute matched binding | ||
1092 | struct sway_input_device *device = | ||
1093 | event->pointer ? event->pointer->base.data : NULL; | ||
1094 | struct sway_gesture_binding *binding = gesture_tracker_end_and_match( | ||
1095 | &seatop->gestures, device); | ||
1096 | |||
1097 | if (binding) { | ||
1098 | gesture_binding_execute(seat, binding); | ||
747 | } | 1099 | } |
748 | } | 1100 | } |
749 | 1101 | ||
@@ -776,6 +1128,15 @@ static const struct sway_seatop_impl seatop_impl = { | |||
776 | .pointer_axis = handle_pointer_axis, | 1128 | .pointer_axis = handle_pointer_axis, |
777 | .tablet_tool_tip = handle_tablet_tool_tip, | 1129 | .tablet_tool_tip = handle_tablet_tool_tip, |
778 | .tablet_tool_motion = handle_tablet_tool_motion, | 1130 | .tablet_tool_motion = handle_tablet_tool_motion, |
1131 | .hold_begin = handle_hold_begin, | ||
1132 | .hold_end = handle_hold_end, | ||
1133 | .pinch_begin = handle_pinch_begin, | ||
1134 | .pinch_update = handle_pinch_update, | ||
1135 | .pinch_end = handle_pinch_end, | ||
1136 | .swipe_begin = handle_swipe_begin, | ||
1137 | .swipe_update = handle_swipe_update, | ||
1138 | .swipe_end = handle_swipe_end, | ||
1139 | .touch_down = handle_touch_down, | ||
779 | .rebase = handle_rebase, | 1140 | .rebase = handle_rebase, |
780 | .allow_set_cursor = true, | 1141 | .allow_set_cursor = true, |
781 | }; | 1142 | }; |
@@ -786,8 +1147,8 @@ void seatop_begin_default(struct sway_seat *seat) { | |||
786 | struct seatop_default_event *e = | 1147 | struct seatop_default_event *e = |
787 | calloc(1, sizeof(struct seatop_default_event)); | 1148 | calloc(1, sizeof(struct seatop_default_event)); |
788 | sway_assert(e, "Unable to allocate seatop_default_event"); | 1149 | sway_assert(e, "Unable to allocate seatop_default_event"); |
1150 | |||
789 | seat->seatop_impl = &seatop_impl; | 1151 | seat->seatop_impl = &seatop_impl; |
790 | seat->seatop_data = e; | 1152 | seat->seatop_data = e; |
791 | |||
792 | seatop_rebase(seat, 0); | 1153 | seatop_rebase(seat, 0); |
793 | } | 1154 | } |
diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index 844cf5ab..340e334b 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c | |||
@@ -1,23 +1,138 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <float.h> | 1 | #include <float.h> |
3 | #include <wlr/types/wlr_cursor.h> | 2 | #include <wlr/types/wlr_cursor.h> |
4 | #include <wlr/types/wlr_tablet_v2.h> | 3 | #include <wlr/types/wlr_tablet_v2.h> |
4 | #include <wlr/types/wlr_touch.h> | ||
5 | #include "sway/input/cursor.h" | 5 | #include "sway/input/cursor.h" |
6 | #include "sway/input/seat.h" | 6 | #include "sway/input/seat.h" |
7 | #include "sway/tree/view.h" | 7 | #include "sway/tree/view.h" |
8 | #include "sway/desktop/transaction.h" | 8 | #include "sway/desktop/transaction.h" |
9 | #include "log.h" | 9 | #include "log.h" |
10 | 10 | ||
11 | struct seatop_touch_point_event { | ||
12 | double ref_lx, ref_ly; // touch's x/y at start of op | ||
13 | double ref_con_lx, ref_con_ly; // container's x/y at start of op | ||
14 | int32_t touch_id; | ||
15 | struct wl_list link; | ||
16 | }; | ||
17 | |||
11 | struct seatop_down_event { | 18 | struct seatop_down_event { |
12 | struct sway_container *con; | 19 | struct sway_container *con; |
20 | struct sway_seat *seat; | ||
21 | struct wl_listener surface_destroy; | ||
22 | struct wlr_surface *surface; | ||
13 | double ref_lx, ref_ly; // cursor's x/y at start of op | 23 | double ref_lx, ref_ly; // cursor's x/y at start of op |
14 | double ref_con_lx, ref_con_ly; // container's x/y at start of op | 24 | double ref_con_lx, ref_con_ly; // container's x/y at start of op |
25 | struct wl_list point_events; // seatop_touch_point_event::link | ||
15 | }; | 26 | }; |
16 | 27 | ||
28 | static void handle_touch_motion(struct sway_seat *seat, | ||
29 | struct wlr_touch_motion_event *event, double lx, double ly) { | ||
30 | struct seatop_down_event *e = seat->seatop_data; | ||
31 | |||
32 | struct seatop_touch_point_event *point_event; | ||
33 | bool found = false; | ||
34 | wl_list_for_each(point_event, &e->point_events, link) { | ||
35 | if (point_event->touch_id == event->touch_id) { | ||
36 | found = true; | ||
37 | break; | ||
38 | } | ||
39 | } | ||
40 | if (!found) { | ||
41 | return; // Probably not a point_event from this seatop_down | ||
42 | } | ||
43 | |||
44 | double moved_x = lx - point_event->ref_lx; | ||
45 | double moved_y = ly - point_event->ref_ly; | ||
46 | double sx = point_event->ref_con_lx + moved_x; | ||
47 | double sy = point_event->ref_con_ly + moved_y; | ||
48 | |||
49 | wlr_seat_touch_notify_motion(seat->wlr_seat, event->time_msec, | ||
50 | event->touch_id, sx, sy); | ||
51 | } | ||
52 | |||
53 | static void handle_touch_up(struct sway_seat *seat, | ||
54 | struct wlr_touch_up_event *event) { | ||
55 | struct seatop_down_event *e = seat->seatop_data; | ||
56 | struct seatop_touch_point_event *point_event, *tmp; | ||
57 | |||
58 | wl_list_for_each_safe(point_event, tmp, &e->point_events, link) { | ||
59 | if (point_event->touch_id == event->touch_id) { | ||
60 | wl_list_remove(&point_event->link); | ||
61 | free(point_event); | ||
62 | break; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id); | ||
67 | |||
68 | if (wl_list_empty(&e->point_events)) { | ||
69 | seatop_begin_default(seat); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static void handle_touch_down(struct sway_seat *seat, | ||
74 | struct wlr_touch_down_event *event, double lx, double ly) { | ||
75 | struct seatop_down_event *e = seat->seatop_data; | ||
76 | double sx, sy; | ||
77 | struct wlr_surface *surface = NULL; | ||
78 | struct sway_node *focused_node = node_at_coords(seat, seat->touch_x, | ||
79 | seat->touch_y, &surface, &sx, &sy); | ||
80 | |||
81 | if (!surface || surface != e->surface) { // Must start from the initial surface | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | struct seatop_touch_point_event *point_event = | ||
86 | calloc(1, sizeof(struct seatop_touch_point_event)); | ||
87 | if (!sway_assert(point_event, "Unable to allocate point_event")) { | ||
88 | return; | ||
89 | } | ||
90 | point_event->touch_id = event->touch_id; | ||
91 | point_event->ref_lx = lx; | ||
92 | point_event->ref_ly = ly; | ||
93 | point_event->ref_con_lx = sx; | ||
94 | point_event->ref_con_ly = sy; | ||
95 | |||
96 | wl_list_insert(&e->point_events, &point_event->link); | ||
97 | |||
98 | wlr_seat_touch_notify_down(seat->wlr_seat, surface, event->time_msec, | ||
99 | event->touch_id, sx, sy); | ||
100 | |||
101 | if (focused_node) { | ||
102 | seat_set_focus(seat, focused_node); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | static void handle_touch_cancel(struct sway_seat *seat, | ||
107 | struct wlr_touch_cancel_event *event) { | ||
108 | struct seatop_down_event *e = seat->seatop_data; | ||
109 | struct seatop_touch_point_event *point_event, *tmp; | ||
110 | |||
111 | wl_list_for_each_safe(point_event, tmp, &e->point_events, link) { | ||
112 | if (point_event->touch_id == event->touch_id) { | ||
113 | wl_list_remove(&point_event->link); | ||
114 | free(point_event); | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | if (e->surface) { | ||
120 | struct wl_client *client = wl_resource_get_client(e->surface->resource); | ||
121 | struct wlr_seat_client *seat_client = wlr_seat_client_for_wl_client(seat->wlr_seat, client); | ||
122 | if (seat_client != NULL) { | ||
123 | wlr_seat_touch_notify_cancel(seat->wlr_seat, seat_client); | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if (wl_list_empty(&e->point_events)) { | ||
128 | seatop_begin_default(seat); | ||
129 | } | ||
130 | } | ||
131 | |||
17 | static void handle_pointer_axis(struct sway_seat *seat, | 132 | static void handle_pointer_axis(struct sway_seat *seat, |
18 | struct wlr_event_pointer_axis *event) { | 133 | struct wlr_pointer_axis_event *event) { |
19 | struct sway_input_device *input_device = | 134 | struct sway_input_device *input_device = |
20 | event->device ? event->device->data : NULL; | 135 | event->pointer ? event->pointer->base.data : NULL; |
21 | struct input_config *ic = | 136 | struct input_config *ic = |
22 | input_device ? input_device_get_config(input_device) : NULL; | 137 | input_device ? input_device_get_config(input_device) : NULL; |
23 | float scroll_factor = | 138 | float scroll_factor = |
@@ -25,12 +140,13 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
25 | 140 | ||
26 | wlr_seat_pointer_notify_axis(seat->wlr_seat, event->time_msec, | 141 | wlr_seat_pointer_notify_axis(seat->wlr_seat, event->time_msec, |
27 | event->orientation, scroll_factor * event->delta, | 142 | event->orientation, scroll_factor * event->delta, |
28 | round(scroll_factor * event->delta_discrete), event->source); | 143 | roundf(scroll_factor * event->delta_discrete), event->source, |
144 | event->relative_direction); | ||
29 | } | 145 | } |
30 | 146 | ||
31 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 147 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
32 | struct wlr_input_device *device, uint32_t button, | 148 | struct wlr_input_device *device, uint32_t button, |
33 | enum wlr_button_state state) { | 149 | enum wl_pointer_button_state state) { |
34 | seat_pointer_notify_button(seat, time_msec, button, state); | 150 | seat_pointer_notify_button(seat, time_msec, button, state); |
35 | 151 | ||
36 | if (seat->cursor->pressed_button_count == 0) { | 152 | if (seat->cursor->pressed_button_count == 0) { |
@@ -40,8 +156,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec, | |||
40 | 156 | ||
41 | static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { | 157 | static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { |
42 | struct seatop_down_event *e = seat->seatop_data; | 158 | struct seatop_down_event *e = seat->seatop_data; |
43 | struct sway_container *con = e->con; | 159 | if (seat_is_input_allowed(seat, e->surface)) { |
44 | if (seat_is_input_allowed(seat, con->view->surface)) { | ||
45 | double moved_x = seat->cursor->cursor->x - e->ref_lx; | 160 | double moved_x = seat->cursor->cursor->x - e->ref_lx; |
46 | double moved_y = seat->cursor->cursor->y - e->ref_ly; | 161 | double moved_y = seat->cursor->cursor->y - e->ref_ly; |
47 | double sx = e->ref_con_lx + moved_x; | 162 | double sx = e->ref_con_lx + moved_x; |
@@ -62,8 +177,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, | |||
62 | static void handle_tablet_tool_motion(struct sway_seat *seat, | 177 | static void handle_tablet_tool_motion(struct sway_seat *seat, |
63 | struct sway_tablet_tool *tool, uint32_t time_msec) { | 178 | struct sway_tablet_tool *tool, uint32_t time_msec) { |
64 | struct seatop_down_event *e = seat->seatop_data; | 179 | struct seatop_down_event *e = seat->seatop_data; |
65 | struct sway_container *con = e->con; | 180 | if (seat_is_input_allowed(seat, e->surface)) { |
66 | if (seat_is_input_allowed(seat, con->view->surface)) { | ||
67 | double moved_x = seat->cursor->cursor->x - e->ref_lx; | 181 | double moved_x = seat->cursor->cursor->x - e->ref_lx; |
68 | double moved_y = seat->cursor->cursor->y - e->ref_ly; | 182 | double moved_y = seat->cursor->cursor->y - e->ref_ly; |
69 | double sx = e->ref_con_lx + moved_x; | 183 | double sx = e->ref_con_lx + moved_x; |
@@ -72,6 +186,14 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, | |||
72 | } | 186 | } |
73 | } | 187 | } |
74 | 188 | ||
189 | static void handle_destroy(struct wl_listener *listener, void *data) { | ||
190 | struct seatop_down_event *e = | ||
191 | wl_container_of(listener, e, surface_destroy); | ||
192 | if (e) { | ||
193 | seatop_begin_default(e->seat); | ||
194 | } | ||
195 | } | ||
196 | |||
75 | static void handle_unref(struct sway_seat *seat, struct sway_container *con) { | 197 | static void handle_unref(struct sway_seat *seat, struct sway_container *con) { |
76 | struct seatop_down_event *e = seat->seatop_data; | 198 | struct seatop_down_event *e = seat->seatop_data; |
77 | if (e->con == con) { | 199 | if (e->con == con) { |
@@ -79,34 +201,63 @@ static void handle_unref(struct sway_seat *seat, struct sway_container *con) { | |||
79 | } | 201 | } |
80 | } | 202 | } |
81 | 203 | ||
204 | static void handle_end(struct sway_seat *seat) { | ||
205 | struct seatop_down_event *e = seat->seatop_data; | ||
206 | wl_list_remove(&e->surface_destroy.link); | ||
207 | } | ||
208 | |||
82 | static const struct sway_seatop_impl seatop_impl = { | 209 | static const struct sway_seatop_impl seatop_impl = { |
83 | .button = handle_button, | 210 | .button = handle_button, |
84 | .pointer_motion = handle_pointer_motion, | 211 | .pointer_motion = handle_pointer_motion, |
85 | .pointer_axis = handle_pointer_axis, | 212 | .pointer_axis = handle_pointer_axis, |
86 | .tablet_tool_tip = handle_tablet_tool_tip, | 213 | .tablet_tool_tip = handle_tablet_tool_tip, |
87 | .tablet_tool_motion = handle_tablet_tool_motion, | 214 | .tablet_tool_motion = handle_tablet_tool_motion, |
215 | .touch_motion = handle_touch_motion, | ||
216 | .touch_up = handle_touch_up, | ||
217 | .touch_down = handle_touch_down, | ||
218 | .touch_cancel = handle_touch_cancel, | ||
88 | .unref = handle_unref, | 219 | .unref = handle_unref, |
220 | .end = handle_end, | ||
89 | .allow_set_cursor = true, | 221 | .allow_set_cursor = true, |
90 | }; | 222 | }; |
91 | 223 | ||
92 | void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, | 224 | void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, |
93 | uint32_t time_msec, int sx, int sy) { | 225 | double sx, double sy) { |
226 | seatop_begin_down_on_surface(seat, con->view->surface, sx, sy); | ||
227 | struct seatop_down_event *e = seat->seatop_data; | ||
228 | e->con = con; | ||
229 | |||
230 | container_raise_floating(con); | ||
231 | transaction_commit_dirty(); | ||
232 | } | ||
233 | |||
234 | void seatop_begin_touch_down(struct sway_seat *seat, | ||
235 | struct wlr_surface *surface, struct wlr_touch_down_event *event, | ||
236 | double sx, double sy, double lx, double ly) { | ||
237 | seatop_begin_down_on_surface(seat, surface, sx, sy); | ||
238 | handle_touch_down(seat, event, lx, ly); | ||
239 | } | ||
240 | |||
241 | void seatop_begin_down_on_surface(struct sway_seat *seat, | ||
242 | struct wlr_surface *surface, double sx, double sy) { | ||
94 | seatop_end(seat); | 243 | seatop_end(seat); |
95 | 244 | ||
96 | struct seatop_down_event *e = | 245 | struct seatop_down_event *e = |
97 | calloc(1, sizeof(struct seatop_down_event)); | 246 | calloc(1, sizeof(struct seatop_down_event)); |
98 | if (!e) { | 247 | if (!sway_assert(e, "Unable to allocate e")) { |
99 | return; | 248 | return; |
100 | } | 249 | } |
101 | e->con = con; | 250 | e->con = NULL; |
251 | e->seat = seat; | ||
252 | e->surface = surface; | ||
253 | wl_signal_add(&e->surface->events.destroy, &e->surface_destroy); | ||
254 | e->surface_destroy.notify = handle_destroy; | ||
102 | e->ref_lx = seat->cursor->cursor->x; | 255 | e->ref_lx = seat->cursor->cursor->x; |
103 | e->ref_ly = seat->cursor->cursor->y; | 256 | e->ref_ly = seat->cursor->cursor->y; |
104 | e->ref_con_lx = sx; | 257 | e->ref_con_lx = sx; |
105 | e->ref_con_ly = sy; | 258 | e->ref_con_ly = sy; |
259 | wl_list_init(&e->point_events); | ||
106 | 260 | ||
107 | seat->seatop_impl = &seatop_impl; | 261 | seat->seatop_impl = &seatop_impl; |
108 | seat->seatop_data = e; | 262 | seat->seatop_data = e; |
109 | |||
110 | container_raise_floating(con); | ||
111 | transaction_commit_dirty(); | ||
112 | } | 263 | } |
diff --git a/sway/input/seatop_move_floating.c b/sway/input/seatop_move_floating.c index ddcd4c53..83668d88 100644 --- a/sway/input/seatop_move_floating.c +++ b/sway/input/seatop_move_floating.c | |||
@@ -1,6 +1,4 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <wlr/types/wlr_cursor.h> | 1 | #include <wlr/types/wlr_cursor.h> |
3 | #include "sway/desktop.h" | ||
4 | #include "sway/desktop/transaction.h" | 2 | #include "sway/desktop/transaction.h" |
5 | #include "sway/input/cursor.h" | 3 | #include "sway/input/cursor.h" |
6 | #include "sway/input/seat.h" | 4 | #include "sway/input/seat.h" |
@@ -23,7 +21,7 @@ static void finalize_move(struct sway_seat *seat) { | |||
23 | 21 | ||
24 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 22 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
25 | struct wlr_input_device *device, uint32_t button, | 23 | struct wlr_input_device *device, uint32_t button, |
26 | enum wlr_button_state state) { | 24 | enum wl_pointer_button_state state) { |
27 | if (seat->cursor->pressed_button_count == 0) { | 25 | if (seat->cursor->pressed_button_count == 0) { |
28 | finalize_move(seat); | 26 | finalize_move(seat); |
29 | } | 27 | } |
@@ -39,9 +37,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat, | |||
39 | static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { | 37 | static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { |
40 | struct seatop_move_floating_event *e = seat->seatop_data; | 38 | struct seatop_move_floating_event *e = seat->seatop_data; |
41 | struct wlr_cursor *cursor = seat->cursor->cursor; | 39 | struct wlr_cursor *cursor = seat->cursor->cursor; |
42 | desktop_damage_whole_container(e->con); | ||
43 | container_floating_move_to(e->con, cursor->x - e->dx, cursor->y - e->dy); | 40 | container_floating_move_to(e->con, cursor->x - e->dx, cursor->y - e->dy); |
44 | desktop_damage_whole_container(e->con); | ||
45 | transaction_commit_dirty(); | 41 | transaction_commit_dirty(); |
46 | } | 42 | } |
47 | 43 | ||
diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 223c6c08..c525b77a 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c | |||
@@ -1,8 +1,6 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <limits.h> | 1 | #include <limits.h> |
3 | #include <wlr/types/wlr_cursor.h> | 2 | #include <wlr/types/wlr_cursor.h> |
4 | #include <wlr/util/edges.h> | 3 | #include <wlr/util/edges.h> |
5 | #include "sway/desktop.h" | ||
6 | #include "sway/desktop/transaction.h" | 4 | #include "sway/desktop/transaction.h" |
7 | #include "sway/input/cursor.h" | 5 | #include "sway/input/cursor.h" |
8 | #include "sway/input/seat.h" | 6 | #include "sway/input/seat.h" |
@@ -24,29 +22,17 @@ struct seatop_move_tiling_event { | |||
24 | struct sway_container *con; | 22 | struct sway_container *con; |
25 | struct sway_node *target_node; | 23 | struct sway_node *target_node; |
26 | enum wlr_edges target_edge; | 24 | enum wlr_edges target_edge; |
27 | struct wlr_box drop_box; | ||
28 | double ref_lx, ref_ly; // cursor's x/y at start of op | 25 | double ref_lx, ref_ly; // cursor's x/y at start of op |
29 | bool threshold_reached; | 26 | bool threshold_reached; |
30 | bool split_target; | 27 | bool split_target; |
31 | bool insert_after_target; | 28 | bool insert_after_target; |
29 | struct wlr_scene_rect *indicator_rect; | ||
32 | }; | 30 | }; |
33 | 31 | ||
34 | static void handle_render(struct sway_seat *seat, | 32 | static void handle_end(struct sway_seat *seat) { |
35 | struct sway_output *output, pixman_region32_t *damage) { | ||
36 | struct seatop_move_tiling_event *e = seat->seatop_data; | 33 | struct seatop_move_tiling_event *e = seat->seatop_data; |
37 | if (!e->threshold_reached) { | 34 | wlr_scene_node_destroy(&e->indicator_rect->node); |
38 | return; | 35 | e->indicator_rect = NULL; |
39 | } | ||
40 | if (e->target_node && node_get_output(e->target_node) == output) { | ||
41 | float color[4]; | ||
42 | memcpy(&color, config->border_colors.focused.indicator, | ||
43 | sizeof(float) * 4); | ||
44 | premultiply_alpha(color, 0.5); | ||
45 | struct wlr_box box; | ||
46 | memcpy(&box, &e->drop_box, sizeof(struct wlr_box)); | ||
47 | scale_box(&box, output->wlr_output->scale); | ||
48 | render_rect(output, damage, &box, color); | ||
49 | } | ||
50 | } | 36 | } |
51 | 37 | ||
52 | static void handle_motion_prethreshold(struct sway_seat *seat) { | 38 | static void handle_motion_prethreshold(struct sway_seat *seat) { |
@@ -67,6 +53,7 @@ static void handle_motion_prethreshold(struct sway_seat *seat) { | |||
67 | 53 | ||
68 | // If the threshold has been exceeded, start the actual drag | 54 | // If the threshold has been exceeded, start the actual drag |
69 | if ((cx - sx) * (cx - sx) + (cy - sy) * (cy - sy) > threshold) { | 55 | if ((cx - sx) * (cx - sx) + (cy - sy) * (cy - sy) > threshold) { |
56 | wlr_scene_node_set_enabled(&e->indicator_rect->node, true); | ||
70 | e->threshold_reached = true; | 57 | e->threshold_reached = true; |
71 | cursor_set_image(seat->cursor, "grab", NULL); | 58 | cursor_set_image(seat->cursor, "grab", NULL); |
72 | } | 59 | } |
@@ -165,6 +152,11 @@ static bool split_titlebar(struct sway_node *node, struct sway_container *avoid, | |||
165 | return false; | 152 | return false; |
166 | } | 153 | } |
167 | 154 | ||
155 | static void update_indicator(struct seatop_move_tiling_event *e, struct wlr_box *box) { | ||
156 | wlr_scene_node_set_position(&e->indicator_rect->node, box->x, box->y); | ||
157 | wlr_scene_rect_set_size(e->indicator_rect, box->width, box->height); | ||
158 | } | ||
159 | |||
168 | static void handle_motion_postthreshold(struct sway_seat *seat) { | 160 | static void handle_motion_postthreshold(struct sway_seat *seat) { |
169 | struct seatop_move_tiling_event *e = seat->seatop_data; | 161 | struct seatop_move_tiling_event *e = seat->seatop_data; |
170 | e->split_target = false; | 162 | e->split_target = false; |
@@ -173,8 +165,6 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { | |||
173 | struct sway_cursor *cursor = seat->cursor; | 165 | struct sway_cursor *cursor = seat->cursor; |
174 | struct sway_node *node = node_at_coords(seat, | 166 | struct sway_node *node = node_at_coords(seat, |
175 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | 167 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); |
176 | // Damage the old location | ||
177 | desktop_damage_box(&e->drop_box); | ||
178 | 168 | ||
179 | if (!node) { | 169 | if (!node) { |
180 | // Eg. hovered over a layer surface such as swaybar | 170 | // Eg. hovered over a layer surface such as swaybar |
@@ -187,8 +177,10 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { | |||
187 | // Empty workspace | 177 | // Empty workspace |
188 | e->target_node = node; | 178 | e->target_node = node; |
189 | e->target_edge = WLR_EDGE_NONE; | 179 | e->target_edge = WLR_EDGE_NONE; |
190 | workspace_get_box(node->sway_workspace, &e->drop_box); | 180 | |
191 | desktop_damage_box(&e->drop_box); | 181 | struct wlr_box drop_box; |
182 | workspace_get_box(node->sway_workspace, &drop_box); | ||
183 | update_indicator(e, &drop_box); | ||
192 | return; | 184 | return; |
193 | } | 185 | } |
194 | 186 | ||
@@ -201,11 +193,18 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { | |||
201 | return; | 193 | return; |
202 | } | 194 | } |
203 | 195 | ||
196 | struct wlr_box drop_box = { | ||
197 | .x = con->pending.content_x, | ||
198 | .y = con->pending.content_y, | ||
199 | .width = con->pending.content_width, | ||
200 | .height = con->pending.content_height, | ||
201 | }; | ||
202 | |||
204 | // Check if the cursor is over a tilebar only if the destination | 203 | // Check if the cursor is over a tilebar only if the destination |
205 | // container is not a descendant of the source container. | 204 | // container is not a descendant of the source container. |
206 | if (!surface && !container_has_ancestor(con, e->con) && | 205 | if (!surface && !container_has_ancestor(con, e->con) && |
207 | split_titlebar(node, e->con, cursor->cursor, | 206 | split_titlebar(node, e->con, cursor->cursor, |
208 | &e->drop_box, &e->insert_after_target)) { | 207 | &drop_box, &e->insert_after_target)) { |
209 | // Don't allow dropping over the source container's titlebar | 208 | // Don't allow dropping over the source container's titlebar |
210 | // to give users a chance to cancel a drag operation. | 209 | // to give users a chance to cancel a drag operation. |
211 | if (con == e->con) { | 210 | if (con == e->con) { |
@@ -215,6 +214,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { | |||
215 | e->split_target = true; | 214 | e->split_target = true; |
216 | } | 215 | } |
217 | e->target_edge = WLR_EDGE_NONE; | 216 | e->target_edge = WLR_EDGE_NONE; |
217 | update_indicator(e, &drop_box); | ||
218 | return; | 218 | return; |
219 | } | 219 | } |
220 | 220 | ||
@@ -256,8 +256,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { | |||
256 | e->target_node = node_get_parent(e->target_node); | 256 | e->target_node = node_get_parent(e->target_node); |
257 | } | 257 | } |
258 | e->target_edge = edge; | 258 | e->target_edge = edge; |
259 | e->drop_box = box; | 259 | update_indicator(e, &box); |
260 | desktop_damage_box(&e->drop_box); | ||
261 | return; | 260 | return; |
262 | } | 261 | } |
263 | con = con->pending.parent; | 262 | con = con->pending.parent; |
@@ -299,12 +298,8 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { | |||
299 | } | 298 | } |
300 | 299 | ||
301 | e->target_node = node; | 300 | e->target_node = node; |
302 | e->drop_box.x = con->pending.content_x; | 301 | resize_box(&drop_box, e->target_edge, thickness); |
303 | e->drop_box.y = con->pending.content_y; | 302 | update_indicator(e, &drop_box); |
304 | e->drop_box.width = con->pending.content_width; | ||
305 | e->drop_box.height = con->pending.content_height; | ||
306 | resize_box(&e->drop_box, e->target_edge, thickness); | ||
307 | desktop_damage_box(&e->drop_box); | ||
308 | } | 303 | } |
309 | 304 | ||
310 | static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { | 305 | static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { |
@@ -410,7 +405,7 @@ static void finalize_move(struct sway_seat *seat) { | |||
410 | 405 | ||
411 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 406 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
412 | struct wlr_input_device *device, uint32_t button, | 407 | struct wlr_input_device *device, uint32_t button, |
413 | enum wlr_button_state state) { | 408 | enum wl_pointer_button_state state) { |
414 | if (seat->cursor->pressed_button_count == 0) { | 409 | if (seat->cursor->pressed_button_count == 0) { |
415 | finalize_move(seat); | 410 | finalize_move(seat); |
416 | } | 411 | } |
@@ -439,7 +434,7 @@ static const struct sway_seatop_impl seatop_impl = { | |||
439 | .pointer_motion = handle_pointer_motion, | 434 | .pointer_motion = handle_pointer_motion, |
440 | .tablet_tool_tip = handle_tablet_tool_tip, | 435 | .tablet_tool_tip = handle_tablet_tool_tip, |
441 | .unref = handle_unref, | 436 | .unref = handle_unref, |
442 | .render = handle_render, | 437 | .end = handle_end, |
443 | }; | 438 | }; |
444 | 439 | ||
445 | void seatop_begin_move_tiling_threshold(struct sway_seat *seat, | 440 | void seatop_begin_move_tiling_threshold(struct sway_seat *seat, |
@@ -451,6 +446,20 @@ void seatop_begin_move_tiling_threshold(struct sway_seat *seat, | |||
451 | if (!e) { | 446 | if (!e) { |
452 | return; | 447 | return; |
453 | } | 448 | } |
449 | |||
450 | const float *indicator = config->border_colors.focused.indicator; | ||
451 | float color[4] = { | ||
452 | indicator[0] * .5, | ||
453 | indicator[1] * .5, | ||
454 | indicator[2] * .5, | ||
455 | indicator[3] * .5, | ||
456 | }; | ||
457 | e->indicator_rect = wlr_scene_rect_create(seat->scene_tree, 0, 0, color); | ||
458 | if (!e->indicator_rect) { | ||
459 | free(e); | ||
460 | return; | ||
461 | } | ||
462 | |||
454 | e->con = con; | 463 | e->con = con; |
455 | e->ref_lx = seat->cursor->cursor->x; | 464 | e->ref_lx = seat->cursor->cursor->x; |
456 | e->ref_ly = seat->cursor->cursor->y; | 465 | e->ref_ly = seat->cursor->cursor->y; |
diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c index 8400a4b3..bec86e33 100644 --- a/sway/input/seatop_resize_floating.c +++ b/sway/input/seatop_resize_floating.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <limits.h> | 1 | #include <limits.h> |
3 | #include <wlr/types/wlr_cursor.h> | 2 | #include <wlr/types/wlr_cursor.h> |
4 | #include <wlr/types/wlr_xcursor_manager.h> | 3 | #include <wlr/types/wlr_xcursor_manager.h> |
@@ -21,7 +20,7 @@ struct seatop_resize_floating_event { | |||
21 | 20 | ||
22 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 21 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
23 | struct wlr_input_device *device, uint32_t button, | 22 | struct wlr_input_device *device, uint32_t button, |
24 | enum wlr_button_state state) { | 23 | enum wl_pointer_button_state state) { |
25 | struct seatop_resize_floating_event *e = seat->seatop_data; | 24 | struct seatop_resize_floating_event *e = seat->seatop_data; |
26 | struct sway_container *con = e->con; | 25 | struct sway_container *con = e->con; |
27 | 26 | ||
@@ -80,17 +79,25 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { | |||
80 | double height = e->ref_height + grow_height; | 79 | double height = e->ref_height + grow_height; |
81 | int min_width, max_width, min_height, max_height; | 80 | int min_width, max_width, min_height, max_height; |
82 | floating_calculate_constraints(&min_width, &max_width, | 81 | floating_calculate_constraints(&min_width, &max_width, |
83 | &min_height, &max_height); | 82 | &min_height, &max_height); |
84 | width = fmax(min_width + border_width, fmin(width, max_width)); | 83 | width = fmin(width, max_width - border_width); |
85 | height = fmax(min_height + border_height, fmin(height, max_height)); | 84 | width = fmax(width, min_width + border_width); |
85 | width = fmax(width, 1); | ||
86 | height = fmin(height, max_height - border_height); | ||
87 | height = fmax(height, min_height + border_height); | ||
88 | height = fmax(height, 1); | ||
86 | 89 | ||
87 | // Apply the view's min/max size | 90 | // Apply the view's min/max size |
88 | if (con->view) { | 91 | if (con->view) { |
89 | double view_min_width, view_max_width, view_min_height, view_max_height; | 92 | double view_min_width, view_max_width, view_min_height, view_max_height; |
90 | view_get_constraints(con->view, &view_min_width, &view_max_width, | 93 | view_get_constraints(con->view, &view_min_width, &view_max_width, |
91 | &view_min_height, &view_max_height); | 94 | &view_min_height, &view_max_height); |
92 | width = fmax(view_min_width + border_width, fmin(width, view_max_width)); | 95 | width = fmin(width, view_max_width - border_width); |
93 | height = fmax(view_min_height + border_height, fmin(height, view_max_height)); | 96 | width = fmax(width, view_min_width + border_width); |
97 | width = fmax(width, 1); | ||
98 | height = fmin(height, view_max_height - border_height); | ||
99 | height = fmax(height, view_min_height + border_height); | ||
100 | height = fmax(height, 1); | ||
94 | 101 | ||
95 | } | 102 | } |
96 | 103 | ||
diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c index 869d11b5..15fd333b 100644 --- a/sway/input/seatop_resize_tiling.c +++ b/sway/input/seatop_resize_tiling.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <wlr/types/wlr_cursor.h> | 1 | #include <wlr/types/wlr_cursor.h> |
3 | #include <wlr/util/edges.h> | 2 | #include <wlr/util/edges.h> |
4 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
@@ -46,7 +45,7 @@ static struct sway_container *container_get_resize_sibling( | |||
46 | 45 | ||
47 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 46 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
48 | struct wlr_input_device *device, uint32_t button, | 47 | struct wlr_input_device *device, uint32_t button, |
49 | enum wlr_button_state state) { | 48 | enum wl_pointer_button_state state) { |
50 | struct seatop_resize_tiling_event *e = seat->seatop_data; | 49 | struct seatop_resize_tiling_event *e = seat->seatop_data; |
51 | 50 | ||
52 | if (seat->cursor->pressed_button_count == 0) { | 51 | if (seat->cursor->pressed_button_count == 0) { |
diff --git a/sway/input/switch.c b/sway/input/switch.c index 9ea87a1a..831f4dbf 100644 --- a/sway/input/switch.c +++ b/sway/input/switch.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #include "sway/config.h" | 1 | #include "sway/config.h" |
2 | #include "sway/input/switch.h" | 2 | #include "sway/input/switch.h" |
3 | #include <wlr/types/wlr_idle.h> | ||
4 | #include "log.h" | 3 | #include "log.h" |
5 | 4 | ||
6 | struct sway_switch *sway_switch_create(struct sway_seat *seat, | 5 | struct sway_switch *sway_switch_create(struct sway_seat *seat, |
@@ -11,6 +10,7 @@ struct sway_switch *sway_switch_create(struct sway_seat *seat, | |||
11 | return NULL; | 10 | return NULL; |
12 | } | 11 | } |
13 | device->switch_device = switch_device; | 12 | device->switch_device = switch_device; |
13 | switch_device->wlr = wlr_switch_from_input_device(device->input_device->wlr_device); | ||
14 | switch_device->seat_device = device; | 14 | switch_device->seat_device = device; |
15 | switch_device->state = WLR_SWITCH_STATE_OFF; | 15 | switch_device->state = WLR_SWITCH_STATE_OFF; |
16 | wl_list_init(&switch_device->switch_toggle.link); | 16 | wl_list_init(&switch_device->switch_toggle.link); |
@@ -19,9 +19,22 @@ struct sway_switch *sway_switch_create(struct sway_seat *seat, | |||
19 | return switch_device; | 19 | return switch_device; |
20 | } | 20 | } |
21 | 21 | ||
22 | static bool sway_switch_trigger_test(enum sway_switch_trigger trigger, | ||
23 | enum wlr_switch_state state) { | ||
24 | switch (trigger) { | ||
25 | case SWAY_SWITCH_TRIGGER_ON: | ||
26 | return state == WLR_SWITCH_STATE_ON; | ||
27 | case SWAY_SWITCH_TRIGGER_OFF: | ||
28 | return state == WLR_SWITCH_STATE_OFF; | ||
29 | case SWAY_SWITCH_TRIGGER_TOGGLE: | ||
30 | return true; | ||
31 | } | ||
32 | abort(); // unreachable | ||
33 | } | ||
34 | |||
22 | static void execute_binding(struct sway_switch *sway_switch) { | 35 | static void execute_binding(struct sway_switch *sway_switch) { |
23 | struct sway_seat* seat = sway_switch->seat_device->sway_seat; | 36 | struct sway_seat *seat = sway_switch->seat_device->sway_seat; |
24 | bool input_inhibited = seat->exclusive_client != NULL; | 37 | bool locked = server.session_lock.lock; |
25 | 38 | ||
26 | list_t *bindings = config->current_mode->switch_bindings; | 39 | list_t *bindings = config->current_mode->switch_bindings; |
27 | struct sway_switch_binding *matched_binding = NULL; | 40 | struct sway_switch_binding *matched_binding = NULL; |
@@ -30,22 +43,21 @@ static void execute_binding(struct sway_switch *sway_switch) { | |||
30 | if (binding->type != sway_switch->type) { | 43 | if (binding->type != sway_switch->type) { |
31 | continue; | 44 | continue; |
32 | } | 45 | } |
33 | if (binding->state != WLR_SWITCH_STATE_TOGGLE && | 46 | if (!sway_switch_trigger_test(binding->trigger, sway_switch->state)) { |
34 | binding->state != sway_switch->state) { | ||
35 | continue; | 47 | continue; |
36 | } | 48 | } |
37 | if (config->reloading && (binding->state == WLR_SWITCH_STATE_TOGGLE | 49 | if (config->reloading && (binding->trigger == SWAY_SWITCH_TRIGGER_TOGGLE |
38 | || (binding->flags & BINDING_RELOAD) == 0)) { | 50 | || (binding->flags & BINDING_RELOAD) == 0)) { |
39 | continue; | 51 | continue; |
40 | } | 52 | } |
41 | bool binding_locked = binding->flags & BINDING_LOCKED; | 53 | bool binding_locked = binding->flags & BINDING_LOCKED; |
42 | if (!binding_locked && input_inhibited) { | 54 | if (!binding_locked && locked) { |
43 | continue; | 55 | continue; |
44 | } | 56 | } |
45 | 57 | ||
46 | matched_binding = binding; | 58 | matched_binding = binding; |
47 | 59 | ||
48 | if (binding_locked == input_inhibited) { | 60 | if (binding_locked == locked) { |
49 | break; | 61 | break; |
50 | } | 62 | } |
51 | } | 63 | } |
@@ -65,7 +77,7 @@ static void execute_binding(struct sway_switch *sway_switch) { | |||
65 | static void handle_switch_toggle(struct wl_listener *listener, void *data) { | 77 | static void handle_switch_toggle(struct wl_listener *listener, void *data) { |
66 | struct sway_switch *sway_switch = | 78 | struct sway_switch *sway_switch = |
67 | wl_container_of(listener, sway_switch, switch_toggle); | 79 | wl_container_of(listener, sway_switch, switch_toggle); |
68 | struct wlr_event_switch_toggle *event = data; | 80 | struct wlr_switch_toggle_event *event = data; |
69 | struct sway_seat *seat = sway_switch->seat_device->sway_seat; | 81 | struct sway_seat *seat = sway_switch->seat_device->sway_seat; |
70 | seat_idle_notify_activity(seat, IDLE_SOURCE_SWITCH); | 82 | seat_idle_notify_activity(seat, IDLE_SOURCE_SWITCH); |
71 | 83 | ||
@@ -82,10 +94,8 @@ static void handle_switch_toggle(struct wl_listener *listener, void *data) { | |||
82 | } | 94 | } |
83 | 95 | ||
84 | void sway_switch_configure(struct sway_switch *sway_switch) { | 96 | void sway_switch_configure(struct sway_switch *sway_switch) { |
85 | struct wlr_input_device *wlr_device = | ||
86 | sway_switch->seat_device->input_device->wlr_device; | ||
87 | wl_list_remove(&sway_switch->switch_toggle.link); | 97 | wl_list_remove(&sway_switch->switch_toggle.link); |
88 | wl_signal_add(&wlr_device->switch_device->events.toggle, | 98 | wl_signal_add(&sway_switch->wlr->events.toggle, |
89 | &sway_switch->switch_toggle); | 99 | &sway_switch->switch_toggle); |
90 | sway_switch->switch_toggle.notify = handle_switch_toggle; | 100 | sway_switch->switch_toggle.notify = handle_switch_toggle; |
91 | sway_log(SWAY_DEBUG, "Configured switch for device"); | 101 | sway_log(SWAY_DEBUG, "Configured switch for device"); |
diff --git a/sway/input/tablet.c b/sway/input/tablet.c index 26e86e36..2863642a 100644 --- a/sway/input/tablet.c +++ b/sway/input/tablet.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <stdlib.h> | 1 | #include <stdlib.h> |
3 | #include <wlr/backend/libinput.h> | 2 | #include <wlr/config.h> |
4 | #include <wlr/types/wlr_tablet_v2.h> | 3 | #include <wlr/types/wlr_tablet_v2.h> |
5 | #include <wlr/types/wlr_tablet_tool.h> | 4 | #include <wlr/types/wlr_tablet_tool.h> |
6 | #include <wlr/types/wlr_tablet_pad.h> | 5 | #include <wlr/types/wlr_tablet_pad.h> |
@@ -9,6 +8,10 @@ | |||
9 | #include "sway/input/seat.h" | 8 | #include "sway/input/seat.h" |
10 | #include "sway/input/tablet.h" | 9 | #include "sway/input/tablet.h" |
11 | 10 | ||
11 | #if WLR_HAS_LIBINPUT_BACKEND | ||
12 | #include <wlr/backend/libinput.h> | ||
13 | #endif | ||
14 | |||
12 | static void handle_pad_tablet_destroy(struct wl_listener *listener, void *data) { | 15 | static void handle_pad_tablet_destroy(struct wl_listener *listener, void *data) { |
13 | struct sway_tablet_pad *pad = | 16 | struct sway_tablet_pad *pad = |
14 | wl_container_of(listener, pad, tablet_destroy); | 17 | wl_container_of(listener, pad, tablet_destroy); |
@@ -54,15 +57,14 @@ void sway_configure_tablet(struct sway_tablet *tablet) { | |||
54 | tablet->seat_device->input_device->wlr_device; | 57 | tablet->seat_device->input_device->wlr_device; |
55 | struct sway_seat *seat = tablet->seat_device->sway_seat; | 58 | struct sway_seat *seat = tablet->seat_device->sway_seat; |
56 | 59 | ||
57 | if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { | 60 | seat_configure_xcursor(seat); |
58 | seat_configure_xcursor(seat); | ||
59 | } | ||
60 | 61 | ||
61 | if (!tablet->tablet_v2) { | 62 | if (!tablet->tablet_v2) { |
62 | tablet->tablet_v2 = | 63 | tablet->tablet_v2 = |
63 | wlr_tablet_create(server.tablet_v2, seat->wlr_seat, device); | 64 | wlr_tablet_create(server.tablet_v2, seat->wlr_seat, device); |
64 | } | 65 | } |
65 | 66 | ||
67 | #if WLR_HAS_LIBINPUT_BACKEND | ||
66 | /* Search for a sibling tablet pad */ | 68 | /* Search for a sibling tablet pad */ |
67 | if (!wlr_input_device_is_libinput(device)) { | 69 | if (!wlr_input_device_is_libinput(device)) { |
68 | /* We can only do this on libinput devices */ | 70 | /* We can only do this on libinput devices */ |
@@ -87,6 +89,7 @@ void sway_configure_tablet(struct sway_tablet *tablet) { | |||
87 | break; | 89 | break; |
88 | } | 90 | } |
89 | } | 91 | } |
92 | #endif | ||
90 | } | 93 | } |
91 | 94 | ||
92 | void sway_tablet_destroy(struct sway_tablet *tablet) { | 95 | void sway_tablet_destroy(struct sway_tablet *tablet) { |
@@ -196,7 +199,7 @@ static void handle_tablet_pad_attach(struct wl_listener *listener, | |||
196 | 199 | ||
197 | static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) { | 200 | static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) { |
198 | struct sway_tablet_pad *pad = wl_container_of(listener, pad, ring); | 201 | struct sway_tablet_pad *pad = wl_container_of(listener, pad, ring); |
199 | struct wlr_event_tablet_pad_ring *event = data; | 202 | struct wlr_tablet_pad_ring_event *event = data; |
200 | 203 | ||
201 | if (!pad->current_surface) { | 204 | if (!pad->current_surface) { |
202 | return; | 205 | return; |
@@ -210,7 +213,7 @@ static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) { | |||
210 | 213 | ||
211 | static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) { | 214 | static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) { |
212 | struct sway_tablet_pad *pad = wl_container_of(listener, pad, strip); | 215 | struct sway_tablet_pad *pad = wl_container_of(listener, pad, strip); |
213 | struct wlr_event_tablet_pad_strip *event = data; | 216 | struct wlr_tablet_pad_strip_event *event = data; |
214 | 217 | ||
215 | if (!pad->current_surface) { | 218 | if (!pad->current_surface) { |
216 | return; | 219 | return; |
@@ -224,7 +227,7 @@ static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) { | |||
224 | 227 | ||
225 | static void handle_tablet_pad_button(struct wl_listener *listener, void *data) { | 228 | static void handle_tablet_pad_button(struct wl_listener *listener, void *data) { |
226 | struct sway_tablet_pad *pad = wl_container_of(listener, pad, button); | 229 | struct sway_tablet_pad *pad = wl_container_of(listener, pad, button); |
227 | struct wlr_event_tablet_pad_button *event = data; | 230 | struct wlr_tablet_pad_button_event *event = data; |
228 | 231 | ||
229 | if (!pad->current_surface) { | 232 | if (!pad->current_surface) { |
230 | return; | 233 | return; |
@@ -246,6 +249,7 @@ struct sway_tablet_pad *sway_tablet_pad_create(struct sway_seat *seat, | |||
246 | return NULL; | 249 | return NULL; |
247 | } | 250 | } |
248 | 251 | ||
252 | tablet_pad->wlr = wlr_tablet_pad_from_input_device(device->input_device->wlr_device); | ||
249 | tablet_pad->seat_device = device; | 253 | tablet_pad->seat_device = device; |
250 | wl_list_init(&tablet_pad->attach.link); | 254 | wl_list_init(&tablet_pad->attach.link); |
251 | wl_list_init(&tablet_pad->button.link); | 255 | wl_list_init(&tablet_pad->button.link); |
@@ -260,40 +264,41 @@ struct sway_tablet_pad *sway_tablet_pad_create(struct sway_seat *seat, | |||
260 | } | 264 | } |
261 | 265 | ||
262 | void sway_configure_tablet_pad(struct sway_tablet_pad *tablet_pad) { | 266 | void sway_configure_tablet_pad(struct sway_tablet_pad *tablet_pad) { |
263 | struct wlr_input_device *device = | 267 | struct wlr_input_device *wlr_device = |
264 | tablet_pad->seat_device->input_device->wlr_device; | 268 | tablet_pad->seat_device->input_device->wlr_device; |
265 | struct sway_seat *seat = tablet_pad->seat_device->sway_seat; | 269 | struct sway_seat *seat = tablet_pad->seat_device->sway_seat; |
266 | 270 | ||
267 | if (!tablet_pad->tablet_v2_pad) { | 271 | if (!tablet_pad->tablet_v2_pad) { |
268 | tablet_pad->tablet_v2_pad = | 272 | tablet_pad->tablet_v2_pad = |
269 | wlr_tablet_pad_create(server.tablet_v2, seat->wlr_seat, device); | 273 | wlr_tablet_pad_create(server.tablet_v2, seat->wlr_seat, wlr_device); |
270 | } | 274 | } |
271 | 275 | ||
272 | wl_list_remove(&tablet_pad->attach.link); | 276 | wl_list_remove(&tablet_pad->attach.link); |
273 | tablet_pad->attach.notify = handle_tablet_pad_attach; | 277 | tablet_pad->attach.notify = handle_tablet_pad_attach; |
274 | wl_signal_add(&device->tablet_pad->events.attach_tablet, | 278 | wl_signal_add(&tablet_pad->wlr->events.attach_tablet, |
275 | &tablet_pad->attach); | 279 | &tablet_pad->attach); |
276 | 280 | ||
277 | wl_list_remove(&tablet_pad->button.link); | 281 | wl_list_remove(&tablet_pad->button.link); |
278 | tablet_pad->button.notify = handle_tablet_pad_button; | 282 | tablet_pad->button.notify = handle_tablet_pad_button; |
279 | wl_signal_add(&device->tablet_pad->events.button, &tablet_pad->button); | 283 | wl_signal_add(&tablet_pad->wlr->events.button, &tablet_pad->button); |
280 | 284 | ||
281 | wl_list_remove(&tablet_pad->strip.link); | 285 | wl_list_remove(&tablet_pad->strip.link); |
282 | tablet_pad->strip.notify = handle_tablet_pad_strip; | 286 | tablet_pad->strip.notify = handle_tablet_pad_strip; |
283 | wl_signal_add(&device->tablet_pad->events.strip, &tablet_pad->strip); | 287 | wl_signal_add(&tablet_pad->wlr->events.strip, &tablet_pad->strip); |
284 | 288 | ||
285 | wl_list_remove(&tablet_pad->ring.link); | 289 | wl_list_remove(&tablet_pad->ring.link); |
286 | tablet_pad->ring.notify = handle_tablet_pad_ring; | 290 | tablet_pad->ring.notify = handle_tablet_pad_ring; |
287 | wl_signal_add(&device->tablet_pad->events.ring, &tablet_pad->ring); | 291 | wl_signal_add(&tablet_pad->wlr->events.ring, &tablet_pad->ring); |
288 | 292 | ||
293 | #if WLR_HAS_LIBINPUT_BACKEND | ||
289 | /* Search for a sibling tablet */ | 294 | /* Search for a sibling tablet */ |
290 | if (!wlr_input_device_is_libinput(device)) { | 295 | if (!wlr_input_device_is_libinput(wlr_device)) { |
291 | /* We can only do this on libinput devices */ | 296 | /* We can only do this on libinput devices */ |
292 | return; | 297 | return; |
293 | } | 298 | } |
294 | 299 | ||
295 | struct libinput_device_group *group = | 300 | struct libinput_device_group *group = |
296 | libinput_device_get_device_group(wlr_libinput_get_device_handle(device)); | 301 | libinput_device_get_device_group(wlr_libinput_get_device_handle(wlr_device)); |
297 | struct sway_tablet *tool; | 302 | struct sway_tablet *tool; |
298 | wl_list_for_each(tool, &seat->cursor->tablets, link) { | 303 | wl_list_for_each(tool, &seat->cursor->tablets, link) { |
299 | struct wlr_input_device *tablet = | 304 | struct wlr_input_device *tablet = |
@@ -310,6 +315,7 @@ void sway_configure_tablet_pad(struct sway_tablet_pad *tablet_pad) { | |||
310 | break; | 315 | break; |
311 | } | 316 | } |
312 | } | 317 | } |
318 | #endif | ||
313 | } | 319 | } |
314 | 320 | ||
315 | void sway_tablet_pad_destroy(struct sway_tablet_pad *tablet_pad) { | 321 | void sway_tablet_pad_destroy(struct sway_tablet_pad *tablet_pad) { |
@@ -333,14 +339,10 @@ static void handle_pad_tablet_surface_destroy(struct wl_listener *listener, | |||
333 | struct sway_tablet_pad *tablet_pad = | 339 | struct sway_tablet_pad *tablet_pad = |
334 | wl_container_of(listener, tablet_pad, surface_destroy); | 340 | wl_container_of(listener, tablet_pad, surface_destroy); |
335 | 341 | ||
336 | wlr_tablet_v2_tablet_pad_notify_leave(tablet_pad->tablet_v2_pad, | 342 | sway_tablet_pad_set_focus(tablet_pad, NULL); |
337 | tablet_pad->current_surface); | ||
338 | wl_list_remove(&tablet_pad->surface_destroy.link); | ||
339 | wl_list_init(&tablet_pad->surface_destroy.link); | ||
340 | tablet_pad->current_surface = NULL; | ||
341 | } | 343 | } |
342 | 344 | ||
343 | void sway_tablet_pad_notify_enter(struct sway_tablet_pad *tablet_pad, | 345 | void sway_tablet_pad_set_focus(struct sway_tablet_pad *tablet_pad, |
344 | struct wlr_surface *surface) { | 346 | struct wlr_surface *surface) { |
345 | if (!tablet_pad || !tablet_pad->tablet) { | 347 | if (!tablet_pad || !tablet_pad->tablet) { |
346 | return; | 348 | return; |
@@ -359,7 +361,8 @@ void sway_tablet_pad_notify_enter(struct sway_tablet_pad *tablet_pad, | |||
359 | tablet_pad->current_surface = NULL; | 361 | tablet_pad->current_surface = NULL; |
360 | } | 362 | } |
361 | 363 | ||
362 | if (!wlr_surface_accepts_tablet_v2(tablet_pad->tablet->tablet_v2, surface)) { | 364 | if (surface == NULL || |
365 | !wlr_surface_accepts_tablet_v2(tablet_pad->tablet->tablet_v2, surface)) { | ||
363 | return; | 366 | return; |
364 | } | 367 | } |
365 | 368 | ||
@@ -367,7 +370,6 @@ void sway_tablet_pad_notify_enter(struct sway_tablet_pad *tablet_pad, | |||
367 | tablet_pad->tablet->tablet_v2, surface); | 370 | tablet_pad->tablet->tablet_v2, surface); |
368 | 371 | ||
369 | tablet_pad->current_surface = surface; | 372 | tablet_pad->current_surface = surface; |
370 | wl_list_remove(&tablet_pad->surface_destroy.link); | ||
371 | tablet_pad->surface_destroy.notify = handle_pad_tablet_surface_destroy; | 373 | tablet_pad->surface_destroy.notify = handle_pad_tablet_surface_destroy; |
372 | wl_signal_add(&surface->events.destroy, &tablet_pad->surface_destroy); | 374 | wl_signal_add(&surface->events.destroy, &tablet_pad->surface_destroy); |
373 | } | 375 | } |
diff --git a/sway/input/text_input.c b/sway/input/text_input.c index b8c19c17..c38a3bb2 100644 --- a/sway/input/text_input.c +++ b/sway/input/text_input.c | |||
@@ -2,7 +2,14 @@ | |||
2 | #include <stdlib.h> | 2 | #include <stdlib.h> |
3 | #include "log.h" | 3 | #include "log.h" |
4 | #include "sway/input/seat.h" | 4 | #include "sway/input/seat.h" |
5 | #include "sway/scene_descriptor.h" | ||
6 | #include "sway/tree/root.h" | ||
7 | #include "sway/tree/view.h" | ||
8 | #include "sway/output.h" | ||
5 | #include "sway/input/text_input.h" | 9 | #include "sway/input/text_input.h" |
10 | #include "sway/input/text_input_popup.h" | ||
11 | #include "sway/layers.h" | ||
12 | static void input_popup_update(struct sway_input_popup *popup); | ||
6 | 13 | ||
7 | static struct sway_text_input *relay_get_focusable_text_input( | 14 | static struct sway_text_input *relay_get_focusable_text_input( |
8 | struct sway_input_method_relay *relay) { | 15 | struct sway_input_method_relay *relay) { |
@@ -77,8 +84,6 @@ static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) { | |||
77 | struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat); | 84 | struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat); |
78 | wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab, | 85 | wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab, |
79 | active_keyboard); | 86 | active_keyboard); |
80 | wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab, | ||
81 | &active_keyboard->modifiers); | ||
82 | 87 | ||
83 | wl_signal_add(&keyboard_grab->events.destroy, | 88 | wl_signal_add(&keyboard_grab->events.destroy, |
84 | &relay->input_method_keyboard_grab_destroy); | 89 | &relay->input_method_keyboard_grab_destroy); |
@@ -104,6 +109,10 @@ static void handle_im_destroy(struct wl_listener *listener, void *data) { | |||
104 | input_method_destroy); | 109 | input_method_destroy); |
105 | struct wlr_input_method_v2 *context = data; | 110 | struct wlr_input_method_v2 *context = data; |
106 | assert(context == relay->input_method); | 111 | assert(context == relay->input_method); |
112 | wl_list_remove(&relay->input_method_commit.link); | ||
113 | wl_list_remove(&relay->input_method_grab_keyboard.link); | ||
114 | wl_list_remove(&relay->input_method_destroy.link); | ||
115 | wl_list_remove(&relay->input_method_new_popup_surface.link); | ||
107 | relay->input_method = NULL; | 116 | relay->input_method = NULL; |
108 | struct sway_text_input *text_input = relay_get_focused_text_input(relay); | 117 | struct sway_text_input *text_input = relay_get_focused_text_input(relay); |
109 | if (text_input) { | 118 | if (text_input) { |
@@ -135,6 +144,11 @@ static void relay_send_im_state(struct sway_input_method_relay *relay, | |||
135 | input->current.content_type.hint, | 144 | input->current.content_type.hint, |
136 | input->current.content_type.purpose); | 145 | input->current.content_type.purpose); |
137 | } | 146 | } |
147 | struct sway_input_popup *popup; | ||
148 | wl_list_for_each(popup, &relay->input_popups, link) { | ||
149 | // send_text_input_rectangle is called in this function | ||
150 | input_popup_update(popup); | ||
151 | } | ||
138 | wlr_input_method_v2_send_done(input_method); | 152 | wlr_input_method_v2_send_done(input_method); |
139 | // TODO: pass intent, display popup size | 153 | // TODO: pass intent, display popup size |
140 | } | 154 | } |
@@ -257,6 +271,211 @@ static void relay_handle_text_input(struct wl_listener *listener, | |||
257 | sway_text_input_create(relay, wlr_text_input); | 271 | sway_text_input_create(relay, wlr_text_input); |
258 | } | 272 | } |
259 | 273 | ||
274 | static void input_popup_update(struct sway_input_popup *popup) { | ||
275 | struct sway_text_input *text_input = | ||
276 | relay_get_focused_text_input(popup->relay); | ||
277 | |||
278 | if (text_input == NULL || text_input->input->focused_surface == NULL) { | ||
279 | return; | ||
280 | } | ||
281 | |||
282 | if (popup->scene_tree != NULL) { | ||
283 | wlr_scene_node_destroy(&popup->scene_tree->node); | ||
284 | popup->scene_tree = NULL; | ||
285 | } | ||
286 | if (popup->desc.relative != NULL) { | ||
287 | wlr_scene_node_destroy(popup->desc.relative); | ||
288 | popup->desc.relative = NULL; | ||
289 | } | ||
290 | popup->desc.view = NULL; | ||
291 | |||
292 | if (!popup->popup_surface->surface->mapped) { | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | bool cursor_rect = text_input->input->current.features | ||
297 | & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE; | ||
298 | struct wlr_surface *focused_surface = text_input->input->focused_surface; | ||
299 | struct wlr_box cursor_area = text_input->input->current.cursor_rectangle; | ||
300 | |||
301 | struct wlr_box output_box; | ||
302 | struct wlr_box parent = {0}; | ||
303 | struct wlr_layer_surface_v1 *layer_surface = | ||
304 | wlr_layer_surface_v1_try_from_wlr_surface(focused_surface); | ||
305 | struct wlr_scene_tree *relative_parent; | ||
306 | |||
307 | struct wlr_box geo = {0}; | ||
308 | |||
309 | popup->scene_tree = wlr_scene_subsurface_tree_create(root->layers.popup, popup->popup_surface->surface); | ||
310 | if (layer_surface != NULL) { | ||
311 | struct sway_layer_surface *layer = | ||
312 | layer_surface->data; | ||
313 | if (layer == NULL) { | ||
314 | return; | ||
315 | } | ||
316 | |||
317 | relative_parent = layer->scene->tree; | ||
318 | struct wlr_output *output = layer->layer_surface->output; | ||
319 | wlr_output_layout_get_box(root->output_layout, output, &output_box); | ||
320 | int lx, ly; | ||
321 | wlr_scene_node_coords(&layer->tree->node, &lx, &ly); | ||
322 | parent.x = lx; | ||
323 | parent.y = ly; | ||
324 | popup->desc.view = NULL; | ||
325 | } else { | ||
326 | struct sway_view *view = view_from_wlr_surface(focused_surface); | ||
327 | relative_parent = view->scene_tree; | ||
328 | geo = view->geometry; | ||
329 | int lx, ly; | ||
330 | wlr_scene_node_coords(&view->scene_tree->node, &lx, &ly); | ||
331 | struct wlr_output *output = wlr_output_layout_output_at(root->output_layout, | ||
332 | view->container->pending.content_x + view->geometry.x, | ||
333 | view->container->pending.content_y + view->geometry.y); | ||
334 | wlr_output_layout_get_box(root->output_layout, output, &output_box); | ||
335 | parent.x = lx; | ||
336 | parent.y = ly; | ||
337 | |||
338 | parent.width = view->geometry.width; | ||
339 | parent.height = view->geometry.height; | ||
340 | popup->desc.view = view; | ||
341 | } | ||
342 | |||
343 | struct wlr_scene_tree *relative = wlr_scene_tree_create(relative_parent); | ||
344 | |||
345 | popup->desc.relative = &relative->node; | ||
346 | if (!scene_descriptor_assign(&popup->scene_tree->node, | ||
347 | SWAY_SCENE_DESC_POPUP, &popup->desc)) { | ||
348 | wlr_scene_node_destroy(&popup->scene_tree->node); | ||
349 | popup->scene_tree = NULL; | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | if (!cursor_rect) { | ||
354 | cursor_area.x = 0; | ||
355 | cursor_area.y = 0; | ||
356 | cursor_area.width = parent.width; | ||
357 | cursor_area.height = parent.height; | ||
358 | } | ||
359 | |||
360 | int popup_width = popup->popup_surface->surface->current.width; | ||
361 | int popup_height = popup->popup_surface->surface->current.height; | ||
362 | int x1 = parent.x + cursor_area.x; | ||
363 | int x2 = parent.x + cursor_area.x + cursor_area.width; | ||
364 | int y1 = parent.y + cursor_area.y; | ||
365 | int y2 = parent.y + cursor_area.y + cursor_area.height; | ||
366 | int x = x1; | ||
367 | int y = y2; | ||
368 | |||
369 | int available_right = output_box.x + output_box.width - x1; | ||
370 | int available_left = x2 - output_box.x; | ||
371 | if (available_right < popup_width && available_left > available_right) { | ||
372 | x = x2 - popup_width; | ||
373 | } | ||
374 | |||
375 | int available_down = output_box.y + output_box.height - y2; | ||
376 | int available_up = y1 - output_box.y; | ||
377 | if (available_down < popup_height && available_up > available_down) { | ||
378 | y = y1 - popup_height; | ||
379 | } | ||
380 | |||
381 | wlr_scene_node_set_position(&relative->node, x - parent.x - geo.x, y - parent.y - geo.y); | ||
382 | if (cursor_rect) { | ||
383 | struct wlr_box box = { | ||
384 | .x = x1 - x, | ||
385 | .y = y1 - y, | ||
386 | .width = cursor_area.width, | ||
387 | .height = cursor_area.height, | ||
388 | }; | ||
389 | wlr_input_popup_surface_v2_send_text_input_rectangle( | ||
390 | popup->popup_surface, &box); | ||
391 | } | ||
392 | wlr_scene_node_set_position(&popup->scene_tree->node, x - geo.x, y - geo.y); | ||
393 | } | ||
394 | |||
395 | static void input_popup_set_focus(struct sway_input_popup *popup, | ||
396 | struct wlr_surface *surface) { | ||
397 | wl_list_remove(&popup->focused_surface_unmap.link); | ||
398 | |||
399 | if (surface == NULL) { | ||
400 | wl_list_init(&popup->focused_surface_unmap.link); | ||
401 | input_popup_update(popup); | ||
402 | return; | ||
403 | } | ||
404 | struct wlr_layer_surface_v1 *layer_surface = | ||
405 | wlr_layer_surface_v1_try_from_wlr_surface(surface); | ||
406 | if (layer_surface != NULL) { | ||
407 | wl_signal_add( | ||
408 | &layer_surface->surface->events.unmap, &popup->focused_surface_unmap); | ||
409 | input_popup_update(popup); | ||
410 | return; | ||
411 | } | ||
412 | |||
413 | struct sway_view *view = view_from_wlr_surface(surface); | ||
414 | wl_signal_add(&view->events.unmap, &popup->focused_surface_unmap); | ||
415 | } | ||
416 | |||
417 | static void handle_im_popup_destroy(struct wl_listener *listener, void *data) { | ||
418 | struct sway_input_popup *popup = | ||
419 | wl_container_of(listener, popup, popup_destroy); | ||
420 | wl_list_remove(&popup->focused_surface_unmap.link); | ||
421 | wl_list_remove(&popup->popup_surface_commit.link); | ||
422 | wl_list_remove(&popup->popup_destroy.link); | ||
423 | wl_list_remove(&popup->link); | ||
424 | |||
425 | free(popup); | ||
426 | } | ||
427 | |||
428 | static void handle_im_popup_surface_commit(struct wl_listener *listener, | ||
429 | void *data) { | ||
430 | struct sway_input_popup *popup = | ||
431 | wl_container_of(listener, popup, popup_surface_commit); | ||
432 | input_popup_update(popup); | ||
433 | } | ||
434 | |||
435 | static void handle_im_focused_surface_unmap( | ||
436 | struct wl_listener *listener, void *data) { | ||
437 | struct sway_input_popup *popup = | ||
438 | wl_container_of(listener, popup, focused_surface_unmap); | ||
439 | input_popup_update(popup); | ||
440 | } | ||
441 | |||
442 | static void handle_im_new_popup_surface(struct wl_listener *listener, | ||
443 | void *data) { | ||
444 | struct sway_input_method_relay *relay = wl_container_of(listener, relay, | ||
445 | input_method_new_popup_surface); | ||
446 | struct sway_input_popup *popup = calloc(1, sizeof(*popup)); | ||
447 | popup->relay = relay; | ||
448 | popup->popup_surface = data; | ||
449 | popup->popup_surface->data = popup; | ||
450 | |||
451 | wl_signal_add( | ||
452 | &popup->popup_surface->events.destroy, &popup->popup_destroy); | ||
453 | popup->popup_destroy.notify = handle_im_popup_destroy; | ||
454 | wl_signal_add(&popup->popup_surface->surface->events.commit, | ||
455 | &popup->popup_surface_commit); | ||
456 | popup->popup_surface_commit.notify = handle_im_popup_surface_commit; | ||
457 | wl_list_init(&popup->focused_surface_unmap.link); | ||
458 | popup->focused_surface_unmap.notify = handle_im_focused_surface_unmap; | ||
459 | |||
460 | struct sway_text_input *text_input = relay_get_focused_text_input(relay); | ||
461 | if (text_input != NULL) { | ||
462 | input_popup_set_focus(popup, text_input->input->focused_surface); | ||
463 | } else { | ||
464 | input_popup_set_focus(popup, NULL); | ||
465 | } | ||
466 | |||
467 | wl_list_insert(&relay->input_popups, &popup->link); | ||
468 | } | ||
469 | |||
470 | static void text_input_send_enter(struct sway_text_input *text_input, | ||
471 | struct wlr_surface *surface) { | ||
472 | wlr_text_input_v3_send_enter(text_input->input, surface); | ||
473 | struct sway_input_popup *popup; | ||
474 | wl_list_for_each(popup, &text_input->relay->input_popups, link) { | ||
475 | input_popup_set_focus(popup, surface); | ||
476 | } | ||
477 | } | ||
478 | |||
260 | static void relay_handle_input_method(struct wl_listener *listener, | 479 | static void relay_handle_input_method(struct wl_listener *listener, |
261 | void *data) { | 480 | void *data) { |
262 | struct sway_input_method_relay *relay = wl_container_of(listener, relay, | 481 | struct sway_input_method_relay *relay = wl_container_of(listener, relay, |
@@ -282,10 +501,13 @@ static void relay_handle_input_method(struct wl_listener *listener, | |||
282 | wl_signal_add(&relay->input_method->events.destroy, | 501 | wl_signal_add(&relay->input_method->events.destroy, |
283 | &relay->input_method_destroy); | 502 | &relay->input_method_destroy); |
284 | relay->input_method_destroy.notify = handle_im_destroy; | 503 | relay->input_method_destroy.notify = handle_im_destroy; |
504 | wl_signal_add(&relay->input_method->events.new_popup_surface, | ||
505 | &relay->input_method_new_popup_surface); | ||
506 | relay->input_method_new_popup_surface.notify = handle_im_new_popup_surface; | ||
285 | 507 | ||
286 | struct sway_text_input *text_input = relay_get_focusable_text_input(relay); | 508 | struct sway_text_input *text_input = relay_get_focusable_text_input(relay); |
287 | if (text_input) { | 509 | if (text_input) { |
288 | wlr_text_input_v3_send_enter(text_input->input, | 510 | text_input_send_enter(text_input, |
289 | text_input->pending_focused_surface); | 511 | text_input->pending_focused_surface); |
290 | text_input_set_pending_focused_surface(text_input, NULL); | 512 | text_input_set_pending_focused_surface(text_input, NULL); |
291 | } | 513 | } |
@@ -295,6 +517,7 @@ void sway_input_method_relay_init(struct sway_seat *seat, | |||
295 | struct sway_input_method_relay *relay) { | 517 | struct sway_input_method_relay *relay) { |
296 | relay->seat = seat; | 518 | relay->seat = seat; |
297 | wl_list_init(&relay->text_inputs); | 519 | wl_list_init(&relay->text_inputs); |
520 | wl_list_init(&relay->input_popups); | ||
298 | 521 | ||
299 | relay->text_input_new.notify = relay_handle_text_input; | 522 | relay->text_input_new.notify = relay_handle_text_input; |
300 | wl_signal_add(&server.text_input->events.text_input, | 523 | wl_signal_add(&server.text_input->events.text_input, |