aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/pool-buffer.c1
-rw-r--r--common/gesture.c1
-rw-r--r--common/ipc-client.c1
-rw-r--r--common/log.c1
-rw-r--r--common/loop.c1
-rw-r--r--common/stringop.c1
-rw-r--r--common/util.c1
-rw-r--r--include/sway/desktop/launcher.h4
-rw-r--r--include/sway/desktop/transaction.h3
-rw-r--r--include/sway/input/cursor.h2
-rw-r--r--include/sway/input/input-manager.h3
-rw-r--r--include/sway/input/seat.h7
-rw-r--r--include/sway/input/text_input.h3
-rw-r--r--include/sway/input/text_input_popup.h20
-rw-r--r--include/sway/layers.h5
-rw-r--r--include/sway/output.h2
-rw-r--r--include/sway/server.h19
-rw-r--r--include/sway/tree/view.h17
-rw-r--r--meson.build1
-rwxr-xr-xrelease.sh31
-rw-r--r--sway/commands.c3
-rw-r--r--sway/commands/assign.c1
-rw-r--r--sway/commands/bar.c1
-rw-r--r--sway/commands/bar/font.c1
-rw-r--r--sway/commands/bar/hidden_state.c1
-rw-r--r--sway/commands/bar/icon_theme.c1
-rw-r--r--sway/commands/bar/id.c1
-rw-r--r--sway/commands/bar/mode.c1
-rw-r--r--sway/commands/bar/output.c1
-rw-r--r--sway/commands/bar/position.c1
-rw-r--r--sway/commands/bar/separator_symbol.c1
-rw-r--r--sway/commands/bar/tray_output.c1
-rw-r--r--sway/commands/bind.c1
-rw-r--r--sway/commands/exec_always.c1
-rw-r--r--sway/commands/font.c1
-rw-r--r--sway/commands/gesture.c1
-rw-r--r--sway/commands/input/calibration_matrix.c1
-rw-r--r--sway/commands/input/map_from_region.c1
-rw-r--r--sway/commands/input/map_to_output.c1
-rw-r--r--sway/commands/input/map_to_region.c1
-rw-r--r--sway/commands/input/xkb_file.c1
-rw-r--r--sway/commands/input/xkb_layout.c1
-rw-r--r--sway/commands/input/xkb_model.c1
-rw-r--r--sway/commands/input/xkb_numlock.c1
-rw-r--r--sway/commands/input/xkb_options.c1
-rw-r--r--sway/commands/input/xkb_rules.c1
-rw-r--r--sway/commands/input/xkb_switch_layout.c1
-rw-r--r--sway/commands/input/xkb_variant.c1
-rw-r--r--sway/commands/mark.c1
-rw-r--r--sway/commands/mode.c1
-rw-r--r--sway/commands/move.c10
-rw-r--r--sway/commands/output.c5
-rw-r--r--sway/commands/output/background.c1
-rw-r--r--sway/commands/primary_selection.c4
-rw-r--r--sway/commands/reload.c1
-rw-r--r--sway/commands/seat/attach.c1
-rw-r--r--sway/commands/seat/cursor.c15
-rw-r--r--sway/commands/seat/hide_cursor.c1
-rw-r--r--sway/commands/seat/idle.c1
-rw-r--r--sway/commands/seat/xcursor_theme.c1
-rw-r--r--sway/commands/set.c1
-rw-r--r--sway/commands/show_marks.c1
-rw-r--r--sway/commands/swap.c1
-rw-r--r--sway/commands/title_format.c1
-rw-r--r--sway/commands/unmark.c1
-rw-r--r--sway/commands/workspace.c1
-rw-r--r--sway/commands/xwayland.c2
-rw-r--r--sway/config.c101
-rw-r--r--sway/config/bar.c1
-rw-r--r--sway/config/input.c1
-rw-r--r--sway/config/output.c16
-rw-r--r--sway/config/seat.c1
-rw-r--r--sway/criteria.c1
-rw-r--r--sway/desktop/launcher.c16
-rw-r--r--sway/desktop/layer_shell.c22
-rw-r--r--sway/desktop/output.c15
-rw-r--r--sway/desktop/transaction.c21
-rw-r--r--sway/desktop/xdg_shell.c19
-rw-r--r--sway/desktop/xwayland.c1
-rw-r--r--sway/input/cursor.c26
-rw-r--r--sway/input/input-manager.c39
-rw-r--r--sway/input/seat.c26
-rw-r--r--sway/input/seatop_default.c35
-rw-r--r--sway/input/seatop_down.c3
-rw-r--r--sway/input/seatop_move_floating.c3
-rw-r--r--sway/input/seatop_move_tiling.c3
-rw-r--r--sway/input/seatop_resize_floating.c3
-rw-r--r--sway/input/seatop_resize_tiling.c3
-rw-r--r--sway/input/tablet.c1
-rw-r--r--sway/input/text_input.c227
-rw-r--r--sway/ipc-json.c21
-rw-r--r--sway/ipc-server.c1
-rw-r--r--sway/lock.c2
-rw-r--r--sway/main.c1
-rw-r--r--sway/server.c61
-rw-r--r--sway/sway-ipc.7.scd6
-rw-r--r--sway/sway-output.5.scd12
-rw-r--r--sway/sway_text_node.c7
-rw-r--r--sway/swaynag.c1
-rw-r--r--sway/tree/arrange.c1
-rw-r--r--sway/tree/container.c2
-rw-r--r--sway/tree/node.c1
-rw-r--r--sway/tree/output.c1
-rw-r--r--sway/tree/root.c1
-rw-r--r--sway/tree/view.c49
-rw-r--r--sway/tree/workspace.c1
-rw-r--r--sway/xdg_activation_v1.c25
-rw-r--r--swaybar/bar.c1
-rw-r--r--swaybar/config.c1
-rw-r--r--swaybar/i3bar.c1
-rw-r--r--swaybar/ipc.c1
-rw-r--r--swaybar/main.c1
-rw-r--r--swaybar/render.c1
-rw-r--r--swaybar/status_line.c1
-rw-r--r--swaybar/tray/host.c1
-rw-r--r--swaybar/tray/icon.c1
-rw-r--r--swaybar/tray/item.c1
-rw-r--r--swaybar/tray/watcher.c1
-rw-r--r--swaymsg/main.c1
-rw-r--r--swaynag/config.c1
-rw-r--r--swaynag/main.c1
-rw-r--r--swaynag/swaynag.c1
-rw-r--r--swaynag/types.c1
123 files changed, 688 insertions, 309 deletions
diff --git a/client/pool-buffer.c b/client/pool-buffer.c
index 3546b897..c47c40eb 100644
--- a/client/pool-buffer.c
+++ b/client/pool-buffer.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809
2#include <assert.h> 1#include <assert.h>
3#include <cairo.h> 2#include <cairo.h>
4#include <errno.h> 3#include <errno.h>
diff --git a/common/gesture.c b/common/gesture.c
index 58170443..272aa837 100644
--- a/common/gesture.c
+++ b/common/gesture.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "gesture.h" 1#include "gesture.h"
3 2
4#include <math.h> 3#include <math.h>
diff --git a/common/ipc-client.c b/common/ipc-client.c
index d30212d2..a0be2b2d 100644
--- a/common/ipc-client.c
+++ b/common/ipc-client.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdio.h> 1#include <stdio.h>
3#include <stdint.h> 2#include <stdint.h>
4#include <stdlib.h> 3#include <stdlib.h>
diff --git a/common/log.c b/common/log.c
index 483420e7..3eacdb34 100644
--- a/common/log.c
+++ b/common/log.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200112L
2#include <signal.h> 1#include <signal.h>
3#include <stdarg.h> 2#include <stdarg.h>
4#include <stdio.h> 3#include <stdio.h>
diff --git a/common/loop.c b/common/loop.c
index 80fe18ea..b99c6d55 100644
--- a/common/loop.c
+++ b/common/loop.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200112L
2#include <limits.h> 1#include <limits.h>
3#include <string.h> 2#include <string.h>
4#include <stdbool.h> 3#include <stdbool.h>
diff --git a/common/stringop.c b/common/stringop.c
index c503143a..16d04917 100644
--- a/common/stringop.c
+++ b/common/stringop.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <stdarg.h> 2#include <stdarg.h>
4#include <stdbool.h> 3#include <stdbool.h>
diff --git a/common/util.c b/common/util.c
index 5d4c0673..7c492bcb 100644
--- a/common/util.c
+++ b/common/util.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <fcntl.h> 2#include <fcntl.h>
4#include <math.h> 3#include <math.h>
diff --git a/include/sway/desktop/launcher.h b/include/sway/desktop/launcher.h
index b7716e82..412068a9 100644
--- a/include/sway/desktop/launcher.h
+++ b/include/sway/desktop/launcher.h
@@ -3,14 +3,18 @@
3 3
4#include <stdlib.h> 4#include <stdlib.h>
5#include <wayland-server-core.h> 5#include <wayland-server-core.h>
6#include "sway/input/seat.h"
6 7
7struct launcher_ctx { 8struct launcher_ctx {
8 pid_t pid; 9 pid_t pid;
9 char *fallback_name; 10 char *fallback_name;
10 struct wlr_xdg_activation_token_v1 *token; 11 struct wlr_xdg_activation_token_v1 *token;
11 struct wl_listener token_destroy; 12 struct wl_listener token_destroy;
13 struct sway_seat *seat;
14 struct wl_listener seat_destroy;
12 15
13 bool activated; 16 bool activated;
17 bool had_focused_surface;
14 18
15 struct sway_node *node; 19 struct sway_node *node;
16 struct wl_listener node_destroy; 20 struct wl_listener node_destroy;
diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h
index 17d41fa3..dd7edb7a 100644
--- a/include/sway/desktop/transaction.h
+++ b/include/sway/desktop/transaction.h
@@ -2,6 +2,7 @@
2#define _SWAY_TRANSACTION_H 2#define _SWAY_TRANSACTION_H
3#include <stdint.h> 3#include <stdint.h>
4#include <stdbool.h> 4#include <stdbool.h>
5#include <wlr/types/wlr_scene.h>
5 6
6/** 7/**
7 * Transactions enable us to perform atomic layout updates. 8 * Transactions enable us to perform atomic layout updates.
@@ -58,4 +59,6 @@ bool transaction_notify_view_ready_by_serial(struct sway_view *view,
58bool transaction_notify_view_ready_by_geometry(struct sway_view *view, 59bool transaction_notify_view_ready_by_geometry(struct sway_view *view,
59 double x, double y, int width, int height); 60 double x, double y, int width, int height);
60 61
62void arrange_popups(struct wlr_scene_tree *popups);
63
61#endif 64#endif
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h
index 1e21c66f..527d0350 100644
--- a/include/sway/input/cursor.h
+++ b/include/sway/input/cursor.h
@@ -114,7 +114,7 @@ void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
114 114
115void dispatch_cursor_button(struct sway_cursor *cursor, 115void dispatch_cursor_button(struct sway_cursor *cursor,
116 struct wlr_input_device *device, uint32_t time_msec, uint32_t button, 116 struct wlr_input_device *device, uint32_t time_msec, uint32_t button,
117 enum wlr_button_state state); 117 enum wl_pointer_button_state state);
118 118
119void dispatch_cursor_axis(struct sway_cursor *cursor, 119void dispatch_cursor_axis(struct sway_cursor *cursor,
120 struct wlr_pointer_axis_event *event); 120 struct wlr_pointer_axis_event *event);
diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h
index 145edd4b..45c75199 100644
--- a/include/sway/input/input-manager.h
+++ b/include/sway/input/input-manager.h
@@ -4,6 +4,7 @@
4#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h> 4#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
5#include <wlr/types/wlr_virtual_keyboard_v1.h> 5#include <wlr/types/wlr_virtual_keyboard_v1.h>
6#include <wlr/types/wlr_virtual_pointer_v1.h> 6#include <wlr/types/wlr_virtual_pointer_v1.h>
7#include <wlr/types/wlr_transient_seat_v1.h>
7#include "sway/server.h" 8#include "sway/server.h"
8#include "sway/config.h" 9#include "sway/config.h"
9#include "list.h" 10#include "list.h"
@@ -24,6 +25,7 @@ struct sway_input_manager {
24 struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard; 25 struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
25 struct wlr_virtual_pointer_manager_v1 *virtual_pointer; 26 struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
26 struct wlr_pointer_gestures_v1 *pointer_gestures; 27 struct wlr_pointer_gestures_v1 *pointer_gestures;
28 struct wlr_transient_seat_manager_v1 *transient_seat_manager;
27 29
28 struct wl_listener new_input; 30 struct wl_listener new_input;
29 struct wl_listener inhibit_activate; 31 struct wl_listener inhibit_activate;
@@ -31,6 +33,7 @@ struct sway_input_manager {
31 struct wl_listener keyboard_shortcuts_inhibit_new_inhibitor; 33 struct wl_listener keyboard_shortcuts_inhibit_new_inhibitor;
32 struct wl_listener virtual_keyboard_new; 34 struct wl_listener virtual_keyboard_new;
33 struct wl_listener virtual_pointer_new; 35 struct wl_listener virtual_pointer_new;
36 struct wl_listener transient_seat_create;
34}; 37};
35 38
36struct sway_input_manager *input_manager_create(struct sway_server *server); 39struct sway_input_manager *input_manager_create(struct sway_server *server);
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h
index e5aa8478..428f9679 100644
--- a/include/sway/input/seat.h
+++ b/include/sway/input/seat.h
@@ -17,7 +17,7 @@ struct sway_seat;
17struct sway_seatop_impl { 17struct sway_seatop_impl {
18 void (*button)(struct sway_seat *seat, uint32_t time_msec, 18 void (*button)(struct sway_seat *seat, uint32_t time_msec,
19 struct wlr_input_device *device, uint32_t button, 19 struct wlr_input_device *device, uint32_t button,
20 enum wlr_button_state state); 20 enum wl_pointer_button_state state);
21 void (*pointer_motion)(struct sway_seat *seat, uint32_t time_msec); 21 void (*pointer_motion)(struct sway_seat *seat, uint32_t time_msec);
22 void (*pointer_axis)(struct sway_seat *seat, 22 void (*pointer_axis)(struct sway_seat *seat,
23 struct wlr_pointer_axis_event *event); 23 struct wlr_pointer_axis_event *event);
@@ -124,6 +124,7 @@ struct sway_seat {
124 struct wl_listener start_drag; 124 struct wl_listener start_drag;
125 struct wl_listener request_set_selection; 125 struct wl_listener request_set_selection;
126 struct wl_listener request_set_primary_selection; 126 struct wl_listener request_set_primary_selection;
127 struct wl_listener destroy;
127 128
128 struct wl_list devices; // sway_seat_device::link 129 struct wl_list devices; // sway_seat_device::link
129 struct wl_list keyboard_groups; // sway_keyboard_group::link 130 struct wl_list keyboard_groups; // sway_keyboard_group::link
@@ -286,13 +287,13 @@ struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat,
286 struct sway_workspace *workspace); 287 struct sway_workspace *workspace);
287 288
288void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, 289void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec,
289 uint32_t button, enum wlr_button_state state); 290 uint32_t button, enum wl_pointer_button_state state);
290 291
291void seat_consider_warp_to_focus(struct sway_seat *seat); 292void seat_consider_warp_to_focus(struct sway_seat *seat);
292 293
293void seatop_button(struct sway_seat *seat, uint32_t time_msec, 294void seatop_button(struct sway_seat *seat, uint32_t time_msec,
294 struct wlr_input_device *device, uint32_t button, 295 struct wlr_input_device *device, uint32_t button,
295 enum wlr_button_state state); 296 enum wl_pointer_button_state state);
296 297
297void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec); 298void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec);
298 299
diff --git a/include/sway/input/text_input.h b/include/sway/input/text_input.h
index 214e61d1..1993f928 100644
--- a/include/sway/input/text_input.h
+++ b/include/sway/input/text_input.h
@@ -21,18 +21,21 @@ struct sway_input_method_relay {
21 struct sway_seat *seat; 21 struct sway_seat *seat;
22 22
23 struct wl_list text_inputs; // sway_text_input::link 23 struct wl_list text_inputs; // sway_text_input::link
24 struct wl_list input_popups; // sway_input_popup::link
24 struct wlr_input_method_v2 *input_method; // doesn't have to be present 25 struct wlr_input_method_v2 *input_method; // doesn't have to be present
25 26
26 struct wl_listener text_input_new; 27 struct wl_listener text_input_new;
27 28
28 struct wl_listener input_method_new; 29 struct wl_listener input_method_new;
29 struct wl_listener input_method_commit; 30 struct wl_listener input_method_commit;
31 struct wl_listener input_method_new_popup_surface;
30 struct wl_listener input_method_grab_keyboard; 32 struct wl_listener input_method_grab_keyboard;
31 struct wl_listener input_method_destroy; 33 struct wl_listener input_method_destroy;
32 34
33 struct wl_listener input_method_keyboard_grab_destroy; 35 struct wl_listener input_method_keyboard_grab_destroy;
34}; 36};
35 37
38
36struct sway_text_input { 39struct sway_text_input {
37 struct sway_input_method_relay *relay; 40 struct sway_input_method_relay *relay;
38 41
diff --git a/include/sway/input/text_input_popup.h b/include/sway/input/text_input_popup.h
new file mode 100644
index 00000000..e5f6ab8b
--- /dev/null
+++ b/include/sway/input/text_input_popup.h
@@ -0,0 +1,20 @@
1#ifndef _SWAY_INPUT_TEXT_INPUT_POPUP_H
2#define _SWAY_INPUT_TEXT_INPUT_POPUP_H
3
4#include "sway/tree/view.h"
5
6struct sway_input_popup {
7 struct sway_input_method_relay *relay;
8
9 struct wlr_scene_tree *scene_tree;
10 struct sway_popup_desc desc;
11 struct wlr_input_popup_surface_v2 *popup_surface;
12
13 struct wl_list link;
14
15 struct wl_listener popup_destroy;
16 struct wl_listener popup_surface_commit;
17
18 struct wl_listener focused_surface_unmap;
19};
20#endif
diff --git a/include/sway/layers.h b/include/sway/layers.h
index a7afb900..fd6384e0 100644
--- a/include/sway/layers.h
+++ b/include/sway/layers.h
@@ -3,6 +3,7 @@
3#include <stdbool.h> 3#include <stdbool.h>
4#include <wlr/types/wlr_compositor.h> 4#include <wlr/types/wlr_compositor.h>
5#include <wlr/types/wlr_layer_shell_v1.h> 5#include <wlr/types/wlr_layer_shell_v1.h>
6#include "sway/tree/view.h"
6 7
7struct sway_layer_surface { 8struct sway_layer_surface {
8 struct wl_listener map; 9 struct wl_listener map;
@@ -14,10 +15,12 @@ struct sway_layer_surface {
14 15
15 bool mapped; 16 bool mapped;
16 17
18 struct wlr_scene_tree *popups;
19 struct sway_popup_desc desc;
20
17 struct sway_output *output; 21 struct sway_output *output;
18 struct wlr_scene_layer_surface_v1 *scene; 22 struct wlr_scene_layer_surface_v1 *scene;
19 struct wlr_scene_tree *tree; 23 struct wlr_scene_tree *tree;
20 struct wlr_scene_tree *popups;
21 struct wlr_layer_surface_v1 *layer_surface; 24 struct wlr_layer_surface_v1 *layer_surface;
22}; 25};
23 26
diff --git a/include/sway/output.h b/include/sway/output.h
index 30595f54..d546d488 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -50,7 +50,7 @@ struct sway_output {
50 enum wl_output_subpixel detected_subpixel; 50 enum wl_output_subpixel detected_subpixel;
51 enum scale_filter_mode scale_filter; 51 enum scale_filter_mode scale_filter;
52 52
53 bool enabling, enabled; 53 bool enabled;
54 list_t *workspaces; 54 list_t *workspaces;
55 55
56 struct sway_output_state current; 56 struct sway_output_state current;
diff --git a/include/sway/server.h b/include/sway/server.h
index adb62cda..c71851f6 100644
--- a/include/sway/server.h
+++ b/include/sway/server.h
@@ -2,23 +2,6 @@
2#define _SWAY_SERVER_H 2#define _SWAY_SERVER_H
3#include <stdbool.h> 3#include <stdbool.h>
4#include <wayland-server-core.h> 4#include <wayland-server-core.h>
5#include <wlr/backend.h>
6#include <wlr/render/allocator.h>
7#include <wlr/render/wlr_renderer.h>
8#include <wlr/types/wlr_compositor.h>
9#include <wlr/types/wlr_data_device.h>
10#include <wlr/types/wlr_input_method_v2.h>
11#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
12#include <wlr/types/wlr_drm_lease_v1.h>
13#include <wlr/types/wlr_layer_shell_v1.h>
14#include <wlr/types/wlr_output_management_v1.h>
15#include <wlr/types/wlr_output_power_management_v1.h>
16#include <wlr/types/wlr_presentation_time.h>
17#include <wlr/types/wlr_relative_pointer_v1.h>
18#include <wlr/types/wlr_session_lock_v1.h>
19#include <wlr/types/wlr_server_decoration.h>
20#include <wlr/types/wlr_text_input_v3.h>
21#include <wlr/types/wlr_xdg_shell.h>
22#include "config.h" 5#include "config.h"
23#include "list.h" 6#include "list.h"
24#include "sway/desktop/idle_inhibit_v1.h" 7#include "sway/desktop/idle_inhibit_v1.h"
@@ -63,6 +46,7 @@ struct sway_server {
63 46
64 struct wl_listener new_output; 47 struct wl_listener new_output;
65 struct wl_listener output_layout_change; 48 struct wl_listener output_layout_change;
49 struct wl_listener renderer_lost;
66 50
67 struct wlr_idle_notifier_v1 *idle_notifier_v1; 51 struct wlr_idle_notifier_v1 *idle_notifier_v1;
68 struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1; 52 struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
@@ -116,6 +100,7 @@ struct sway_server {
116 struct wl_listener output_power_manager_set_mode; 100 struct wl_listener output_power_manager_set_mode;
117 struct wlr_input_method_manager_v2 *input_method; 101 struct wlr_input_method_manager_v2 *input_method;
118 struct wlr_text_input_manager_v3 *text_input; 102 struct wlr_text_input_manager_v3 *text_input;
103 struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
119 struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; 104 struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
120 struct wlr_content_type_manager_v1 *content_type_manager_v1; 105 struct wlr_content_type_manager_v1 *content_type_manager_v1;
121 struct wlr_data_control_manager_v1 *data_control_manager_v1; 106 struct wlr_data_control_manager_v1 *data_control_manager_v1;
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 3e5a9bfe..7faacdcc 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -84,6 +84,8 @@ struct sway_view {
84 // transaction state. Updated on every commit. 84 // transaction state. Updated on every commit.
85 struct wlr_box geometry; 85 struct wlr_box geometry;
86 86
87 struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel;
88
87 struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel; 89 struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel;
88 struct wl_listener foreign_activate_request; 90 struct wl_listener foreign_activate_request;
89 struct wl_listener foreign_fullscreen_request; 91 struct wl_listener foreign_fullscreen_request;
@@ -174,6 +176,11 @@ struct sway_xwayland_unmanaged {
174}; 176};
175#endif 177#endif
176 178
179struct sway_popup_desc {
180 struct wlr_scene_node *relative;
181 struct sway_view *view;
182};
183
177struct sway_xdg_popup { 184struct sway_xdg_popup {
178 struct sway_view *view; 185 struct sway_view *view;
179 186
@@ -181,8 +188,11 @@ struct sway_xdg_popup {
181 struct wlr_scene_tree *xdg_surface_tree; 188 struct wlr_scene_tree *xdg_surface_tree;
182 struct wlr_xdg_popup *wlr_xdg_popup; 189 struct wlr_xdg_popup *wlr_xdg_popup;
183 190
191 struct sway_popup_desc desc;
192
184 struct wl_listener surface_commit; 193 struct wl_listener surface_commit;
185 struct wl_listener new_popup; 194 struct wl_listener new_popup;
195 struct wl_listener reposition;
186 struct wl_listener destroy; 196 struct wl_listener destroy;
187}; 197};
188 198
@@ -233,6 +243,11 @@ void view_set_activated(struct sway_view *view, bool activated);
233 */ 243 */
234void view_request_activate(struct sway_view *view, struct sway_seat *seat); 244void view_request_activate(struct sway_view *view, struct sway_seat *seat);
235 245
246/*
247 * Called when the view requests urgent state
248 */
249void view_request_urgent(struct sway_view *view);
250
236/** 251/**
237 * If possible, instructs the client to change their decoration mode. 252 * If possible, instructs the client to change their decoration mode.
238 */ 253 */
@@ -284,6 +299,8 @@ struct sway_view *view_from_wlr_xwayland_surface(
284#endif 299#endif
285struct sway_view *view_from_wlr_surface(struct wlr_surface *surface); 300struct sway_view *view_from_wlr_surface(struct wlr_surface *surface);
286 301
302void view_update_app_id(struct sway_view *view);
303
287/** 304/**
288 * Re-read the view's title property and update any relevant title bars. 305 * Re-read the view's title property and update any relevant title bars.
289 * The force argument makes it recreate the title bars even if the title hasn't 306 * The force argument makes it recreate the title bars even if the title hasn't
diff --git a/meson.build b/meson.build
index f8bf4f80..1043e4ba 100644
--- a/meson.build
+++ b/meson.build
@@ -14,6 +14,7 @@ project(
14add_project_arguments( 14add_project_arguments(
15 [ 15 [
16 '-DWLR_USE_UNSTABLE', 16 '-DWLR_USE_UNSTABLE',
17 '-D_POSIX_C_SOURCE=200809L',
17 18
18 '-Wno-unused-parameter', 19 '-Wno-unused-parameter',
19 '-Wno-unused-result', 20 '-Wno-unused-result',
diff --git a/release.sh b/release.sh
new file mode 100755
index 00000000..62baf415
--- /dev/null
+++ b/release.sh
@@ -0,0 +1,31 @@
1#!/bin/sh -eu
2
3prev=$(git describe --tags --abbrev=0)
4next=$(meson rewrite kwargs info project / 2>&1 >/dev/null | jq -r '.kwargs["project#/"].version')
5
6case "$next" in
7*-dev)
8 echo "This is a development version"
9 exit 1
10 ;;
11esac
12
13if [ "$prev" = "$next" ]; then
14 echo "Version not bumped in meson.build"
15 exit 1
16fi
17
18if ! git diff-index --quiet HEAD -- meson.build; then
19 echo "meson.build not committed"
20 exit 1
21fi
22
23shortlog="$(git shortlog --no-merges "$prev..")"
24(echo "sway $next"; echo ""; echo "$shortlog") | git tag "$next" -ase -F -
25
26prefix=sway-$next
27archive=$prefix.tar.gz
28git archive --prefix="$prefix/" -o "$archive" "$next"
29gpg --output "$archive".sig --detach-sig "$archive"
30
31gh release create "sway $next" -t "$next" -n "" -d "$archive" "$archive.sig"
diff --git a/sway/commands.c b/sway/commands.c
index 55eda183..8d003dfa 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809
2#include <ctype.h> 1#include <ctype.h>
3#include <stdarg.h> 2#include <stdarg.h>
4#include <stdlib.h> 3#include <stdlib.h>
@@ -82,7 +81,6 @@ static const struct cmd_handler handlers[] = {
82 { "no_focus", cmd_no_focus }, 81 { "no_focus", cmd_no_focus },
83 { "output", cmd_output }, 82 { "output", cmd_output },
84 { "popup_during_fullscreen", cmd_popup_during_fullscreen }, 83 { "popup_during_fullscreen", cmd_popup_during_fullscreen },
85 { "primary_selection", cmd_primary_selection },
86 { "seat", cmd_seat }, 84 { "seat", cmd_seat },
87 { "set", cmd_set }, 85 { "set", cmd_set },
88 { "show_marks", cmd_show_marks }, 86 { "show_marks", cmd_show_marks },
@@ -105,6 +103,7 @@ static const struct cmd_handler handlers[] = {
105static const struct cmd_handler config_handlers[] = { 103static const struct cmd_handler config_handlers[] = {
106 { "default_orientation", cmd_default_orientation }, 104 { "default_orientation", cmd_default_orientation },
107 { "include", cmd_include }, 105 { "include", cmd_include },
106 { "primary_selection", cmd_primary_selection },
108 { "swaybg_command", cmd_swaybg_command }, 107 { "swaybg_command", cmd_swaybg_command },
109 { "swaynag_command", cmd_swaynag_command }, 108 { "swaynag_command", cmd_swaynag_command },
110 { "workspace_layout", cmd_workspace_layout }, 109 { "workspace_layout", cmd_workspace_layout },
diff --git a/sway/commands/assign.c b/sway/commands/assign.c
index f7d911f7..bf95cf00 100644
--- a/sway/commands/assign.c
+++ b/sway/commands/assign.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdio.h> 1#include <stdio.h>
3#include <string.h> 2#include <string.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar.c b/sway/commands/bar.c
index 22756acb..635e895b 100644
--- a/sway/commands/bar.c
+++ b/sway/commands/bar.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809
2#include <stdio.h> 1#include <stdio.h>
3#include <string.h> 2#include <string.h>
4#include <strings.h> 3#include <strings.h>
diff --git a/sway/commands/bar/font.c b/sway/commands/bar/font.c
index 891c87af..0c074679 100644
--- a/sway/commands/bar/font.c
+++ b/sway/commands/bar/font.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c
index 8b661e3a..7b38831e 100644
--- a/sway/commands/bar/hidden_state.c
+++ b/sway/commands/bar/hidden_state.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/icon_theme.c b/sway/commands/bar/icon_theme.c
index 6ac07843..fee21709 100644
--- a/sway/commands/bar/icon_theme.c
+++ b/sway/commands/bar/icon_theme.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "config.h" 2#include "config.h"
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c
index a9a61743..46cf4ca9 100644
--- a/sway/commands/bar/id.c
+++ b/sway/commands/bar/id.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c
index 7c2f423b..d69e910b 100644
--- a/sway/commands/bar/mode.c
+++ b/sway/commands/bar/mode.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/output.c b/sway/commands/bar/output.c
index cac1d056..51730176 100644
--- a/sway/commands/bar/output.c
+++ b/sway/commands/bar/output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <string.h> 2#include <string.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/position.c b/sway/commands/bar/position.c
index b207de0b..94f530ec 100644
--- a/sway/commands/bar/position.c
+++ b/sway/commands/bar/position.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/separator_symbol.c b/sway/commands/bar/separator_symbol.c
index 6737d4d2..50e9a873 100644
--- a/sway/commands/bar/separator_symbol.c
+++ b/sway/commands/bar/separator_symbol.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/bar/tray_output.c b/sway/commands/bar/tray_output.c
index eb3b486e..679facf7 100644
--- a/sway/commands/bar/tray_output.c
+++ b/sway/commands/bar/tray_output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "config.h" 2#include "config.h"
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 979e178f..268f2855 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <libevdev/libevdev.h> 1#include <libevdev/libevdev.h>
3#include <linux/input-event-codes.h> 2#include <linux/input-event-codes.h>
4#include <string.h> 3#include <string.h>
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c
index 8fca1909..8bc1048c 100644
--- a/sway/commands/exec_always.c
+++ b/sway/commands/exec_always.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <stdint.h> 2#include <stdint.h>
4#include <string.h> 3#include <string.h>
diff --git a/sway/commands/font.c b/sway/commands/font.c
index 74bb6b9f..9920d03e 100644
--- a/sway/commands/font.c
+++ b/sway/commands/font.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/gesture.c b/sway/commands/gesture.c
index d4442cc3..90a20716 100644
--- a/sway/commands/gesture.c
+++ b/sway/commands/gesture.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3 2
4#include "gesture.h" 3#include "gesture.h"
diff --git a/sway/commands/input/calibration_matrix.c b/sway/commands/input/calibration_matrix.c
index 38749fbb..53fe2c35 100644
--- a/sway/commands/input/calibration_matrix.c
+++ b/sway/commands/input/calibration_matrix.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/input/map_from_region.c b/sway/commands/input/map_from_region.c
index 4400e111..2f8f753d 100644
--- a/sway/commands/input/map_from_region.c
+++ b/sway/commands/input/map_from_region.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <string.h> 2#include <string.h>
4#include <strings.h> 3#include <strings.h>
diff --git a/sway/commands/input/map_to_output.c b/sway/commands/input/map_to_output.c
index f60fb7d5..a7266baa 100644
--- a/sway/commands/input/map_to_output.c
+++ b/sway/commands/input/map_to_output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/input/map_to_region.c b/sway/commands/input/map_to_region.c
index ad535db2..9087c589 100644
--- a/sway/commands/input/map_to_region.c
+++ b/sway/commands/input/map_to_region.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <string.h> 2#include <string.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/input/xkb_file.c b/sway/commands/input/xkb_file.c
index 493f94fb..056f00e5 100644
--- a/sway/commands/input/xkb_file.c
+++ b/sway/commands/input/xkb_file.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <unistd.h> 1#include <unistd.h>
3#include <errno.h> 2#include <errno.h>
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c
index 22626517..1d01886c 100644
--- a/sway/commands/input/xkb_layout.c
+++ b/sway/commands/input/xkb_layout.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c
index f4a33de3..a9144a8a 100644
--- a/sway/commands/input/xkb_model.c
+++ b/sway/commands/input/xkb_model.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/input/xkb_numlock.c b/sway/commands/input/xkb_numlock.c
index 87d3e60c..bbe848fe 100644
--- a/sway/commands/input/xkb_numlock.c
+++ b/sway/commands/input/xkb_numlock.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "util.h" 3#include "util.h"
diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c
index d609293f..7ca20777 100644
--- a/sway/commands/input/xkb_options.c
+++ b/sway/commands/input/xkb_options.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c
index 3b59622c..8fbd26fb 100644
--- a/sway/commands/input/xkb_rules.c
+++ b/sway/commands/input/xkb_rules.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/input/xkb_switch_layout.c b/sway/commands/input/xkb_switch_layout.c
index 3cce4ec8..ecac8e6c 100644
--- a/sway/commands/input/xkb_switch_layout.c
+++ b/sway/commands/input/xkb_switch_layout.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <wlr/interfaces/wlr_keyboard.h> 2#include <wlr/interfaces/wlr_keyboard.h>
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c
index d0e21d77..2d14ea9c 100644
--- a/sway/commands/input/xkb_variant.c
+++ b/sway/commands/input/xkb_variant.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/mark.c b/sway/commands/mark.c
index 30cf458c..2bfc86b3 100644
--- a/sway/commands/mark.c
+++ b/sway/commands/mark.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/mode.c b/sway/commands/mode.c
index 7263efcb..b3216967 100644
--- a/sway/commands/mode.c
+++ b/sway/commands/mode.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <string.h> 2#include <string.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 69ed06c0..8addf26e 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <math.h> 2#include <math.h>
4#include <stdbool.h> 3#include <stdbool.h>
@@ -770,15 +769,6 @@ static struct cmd_results *cmd_move_in_direction(
770 ipc_event_window(container, "move"); 769 ipc_event_window(container, "move");
771 } 770 }
772 771
773 // Hack to re-focus container
774 seat_set_raw_focus(config->handler_context.seat, &new_ws->node);
775 seat_set_focus_container(config->handler_context.seat, container);
776
777 if (old_ws != new_ws) {
778 ipc_event_workspace(old_ws, new_ws, "focus");
779 workspace_detect_urgent(old_ws);
780 workspace_detect_urgent(new_ws);
781 }
782 container_end_mouse_operation(container); 772 container_end_mouse_operation(container);
783 773
784 return cmd_results_new(CMD_SUCCESS, NULL); 774 return cmd_results_new(CMD_SUCCESS, NULL);
diff --git a/sway/commands/output.c b/sway/commands/output.c
index df32c673..462dffd2 100644
--- a/sway/commands/output.c
+++ b/sway/commands/output.c
@@ -111,7 +111,10 @@ struct cmd_results *cmd_output(int argc, char **argv) {
111 if (!config->reloading && !config->validating) { 111 if (!config->reloading && !config->validating) {
112 apply_output_config_to_outputs(output); 112 apply_output_config_to_outputs(output);
113 if (background) { 113 if (background) {
114 spawn_swaybg(); 114 if (!spawn_swaybg()) {
115 return cmd_results_new(CMD_FAILURE,
116 "Failed to apply background configuration");
117 }
115 } 118 }
116 } 119 }
117 120
diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c
index d691295f..55bd7671 100644
--- a/sway/commands/output/background.c
+++ b/sway/commands/output/background.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <libgen.h> 1#include <libgen.h>
3#include <stdio.h> 2#include <stdio.h>
4#include <string.h> 3#include <string.h>
diff --git a/sway/commands/primary_selection.c b/sway/commands/primary_selection.c
index 585b079d..9e2689c2 100644
--- a/sway/commands/primary_selection.c
+++ b/sway/commands/primary_selection.c
@@ -12,12 +12,14 @@ struct cmd_results *cmd_primary_selection(int argc, char **argv) {
12 12
13 bool primary_selection = parse_boolean(argv[0], true); 13 bool primary_selection = parse_boolean(argv[0], true);
14 14
15 // config->primary_selection is reset to the previous value on reload in
16 // load_main_config()
15 if (config->reloading && config->primary_selection != primary_selection) { 17 if (config->reloading && config->primary_selection != primary_selection) {
16 return cmd_results_new(CMD_FAILURE, 18 return cmd_results_new(CMD_FAILURE,
17 "primary_selection can only be enabled/disabled at launch"); 19 "primary_selection can only be enabled/disabled at launch");
18 } 20 }
19 21
20 config->primary_selection = parse_boolean(argv[0], true); 22 config->primary_selection = primary_selection;
21 23
22 return cmd_results_new(CMD_SUCCESS, NULL); 24 return cmd_results_new(CMD_SUCCESS, NULL);
23} 25}
diff --git a/sway/commands/reload.c b/sway/commands/reload.c
index 82967ca7..6c0aac26 100644
--- a/sway/commands/reload.c
+++ b/sway/commands/reload.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c
index 00bfdab6..47d18546 100644
--- a/sway/commands/seat/attach.c
+++ b/sway/commands/seat/attach.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c
index 5a8a3bc8..df7c379d 100644
--- a/sway/commands/seat/cursor.c
+++ b/sway/commands/seat/cursor.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <linux/input-event-codes.h> 1#include <linux/input-event-codes.h>
3 2
4#include <strings.h> 3#include <strings.h>
@@ -85,12 +84,12 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
85 84
86static struct cmd_results *press_or_release(struct sway_cursor *cursor, 85static struct cmd_results *press_or_release(struct sway_cursor *cursor,
87 char *action, char *button_str) { 86 char *action, char *button_str) {
88 enum wlr_button_state state; 87 enum wl_pointer_button_state state;
89 uint32_t button; 88 uint32_t button;
90 if (strcasecmp(action, "press") == 0) { 89 if (strcasecmp(action, "press") == 0) {
91 state = WLR_BUTTON_PRESSED; 90 state = WL_POINTER_BUTTON_STATE_PRESSED;
92 } else if (strcasecmp(action, "release") == 0) { 91 } else if (strcasecmp(action, "release") == 0) {
93 state = WLR_BUTTON_RELEASED; 92 state = WL_POINTER_BUTTON_STATE_RELEASED;
94 } else { 93 } else {
95 return cmd_results_new(CMD_INVALID, "%s", expected_syntax); 94 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
96 } 95 }
@@ -105,16 +104,16 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor,
105 } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN 104 } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN
106 || button == SWAY_SCROLL_LEFT || button == SWAY_SCROLL_RIGHT) { 105 || button == SWAY_SCROLL_LEFT || button == SWAY_SCROLL_RIGHT) {
107 // Dispatch axis event 106 // Dispatch axis event
108 enum wlr_axis_orientation orientation = 107 enum wl_pointer_axis orientation =
109 (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN) 108 (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN)
110 ? WLR_AXIS_ORIENTATION_VERTICAL 109 ? WL_POINTER_AXIS_VERTICAL_SCROLL
111 : WLR_AXIS_ORIENTATION_HORIZONTAL; 110 : WL_POINTER_AXIS_HORIZONTAL_SCROLL;
112 double delta = (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_LEFT) 111 double delta = (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_LEFT)
113 ? -1 : 1; 112 ? -1 : 1;
114 struct wlr_pointer_axis_event event = { 113 struct wlr_pointer_axis_event event = {
115 .pointer = NULL, 114 .pointer = NULL,
116 .time_msec = 0, 115 .time_msec = 0,
117 .source = WLR_AXIS_SOURCE_WHEEL, 116 .source = WL_POINTER_AXIS_SOURCE_WHEEL,
118 .orientation = orientation, 117 .orientation = orientation,
119 .delta = delta * 15, 118 .delta = delta * 15,
120 .delta_discrete = delta 119 .delta_discrete = delta
diff --git a/sway/commands/seat/hide_cursor.c b/sway/commands/seat/hide_cursor.c
index e09b82d9..f5177a47 100644
--- a/sway/commands/seat/hide_cursor.c
+++ b/sway/commands/seat/hide_cursor.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/seat/idle.c b/sway/commands/seat/idle.c
index 62b94db2..2974453e 100644
--- a/sway/commands/seat/idle.c
+++ b/sway/commands/seat/idle.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <limits.h> 1#include <limits.h>
3#include <string.h> 2#include <string.h>
4#include <strings.h> 3#include <strings.h>
diff --git a/sway/commands/seat/xcursor_theme.c b/sway/commands/seat/xcursor_theme.c
index 202f35b9..61322a57 100644
--- a/sway/commands/seat/xcursor_theme.c
+++ b/sway/commands/seat/xcursor_theme.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/set.c b/sway/commands/set.c
index c539e9fc..ba384c7c 100644
--- a/sway/commands/set.c
+++ b/sway/commands/set.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdio.h> 1#include <stdio.h>
3#include <string.h> 2#include <string.h>
4#include <strings.h> 3#include <strings.h>
diff --git a/sway/commands/show_marks.c b/sway/commands/show_marks.c
index fecb5ade..60cef9fa 100644
--- a/sway/commands/show_marks.c
+++ b/sway/commands/show_marks.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/swap.c b/sway/commands/swap.c
index d44eb006..e142eede 100644
--- a/sway/commands/swap.c
+++ b/sway/commands/swap.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <strings.h> 1#include <strings.h>
3#include "config.h" 2#include "config.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/title_format.c b/sway/commands/title_format.c
index a2446b7e..0b2ea265 100644
--- a/sway/commands/title_format.c
+++ b/sway/commands/title_format.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c
index c3a6ac4b..4aba5bae 100644
--- a/sway/commands/unmark.c
+++ b/sway/commands/unmark.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c
index 8536929e..37a201b4 100644
--- a/sway/commands/workspace.c
+++ b/sway/commands/workspace.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <limits.h> 2#include <limits.h>
4#include <string.h> 3#include <string.h>
diff --git a/sway/commands/xwayland.c b/sway/commands/xwayland.c
index 6ca26923..584a8e3a 100644
--- a/sway/commands/xwayland.c
+++ b/sway/commands/xwayland.c
@@ -20,6 +20,8 @@ struct cmd_results *cmd_xwayland(int argc, char **argv) {
20 xwayland = XWAYLAND_MODE_DISABLED; 20 xwayland = XWAYLAND_MODE_DISABLED;
21 } 21 }
22 22
23 // config->xwayland is reset to the previous value on reload in
24 // load_main_config()
23 if (config->reloading && config->xwayland != xwayland) { 25 if (config->reloading && config->xwayland != xwayland) {
24 return cmd_results_new(CMD_FAILURE, 26 return cmd_results_new(CMD_FAILURE,
25 "xwayland can only be enabled/disabled at launch"); 27 "xwayland can only be enabled/disabled at launch");
diff --git a/sway/config.c b/sway/config.c
index 4b51dc73..72fc41e7 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -1,3 +1,4 @@
1#undef _POSIX_C_SOURCE
1#define _XOPEN_SOURCE 700 // for realpath 2#define _XOPEN_SOURCE 700 // for realpath
2#include <stdio.h> 3#include <stdio.h>
3#include <stdbool.h> 4#include <stdbool.h>
@@ -36,19 +37,26 @@
36struct sway_config *config = NULL; 37struct sway_config *config = NULL;
37 38
38static struct xkb_state *keysym_translation_state_create( 39static struct xkb_state *keysym_translation_state_create(
39 struct xkb_rule_names rules) { 40 struct xkb_rule_names rules, uint32_t context_flags) {
40 struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_SECURE_GETENV); 41 struct xkb_context *context = xkb_context_new(context_flags | XKB_CONTEXT_NO_SECURE_GETENV);
41 struct xkb_keymap *xkb_keymap = xkb_keymap_new_from_names( 42 struct xkb_keymap *xkb_keymap = xkb_keymap_new_from_names(
42 context, 43 context,
43 &rules, 44 &rules,
44 XKB_KEYMAP_COMPILE_NO_FLAGS); 45 XKB_KEYMAP_COMPILE_NO_FLAGS);
45
46 xkb_context_unref(context); 46 xkb_context_unref(context);
47 if (xkb_keymap == NULL) {
48 sway_log(SWAY_ERROR, "Failed to compile keysym translation XKB keymap");
49 return NULL;
50 }
51
47 return xkb_state_new(xkb_keymap); 52 return xkb_state_new(xkb_keymap);
48} 53}
49 54
50static void keysym_translation_state_destroy( 55static void keysym_translation_state_destroy(
51 struct xkb_state *state) { 56 struct xkb_state *state) {
57 if (state == NULL) {
58 return;
59 }
52 xkb_keymap_unref(xkb_state_get_keymap(state)); 60 xkb_keymap_unref(xkb_state_get_keymap(state));
53 xkb_state_unref(state); 61 xkb_state_unref(state);
54} 62}
@@ -336,8 +344,14 @@ static void config_defaults(struct sway_config *config) {
336 344
337 // The keysym to keycode translation 345 // The keysym to keycode translation
338 struct xkb_rule_names rules = {0}; 346 struct xkb_rule_names rules = {0};
339 config->keysym_translation_state = 347 config->keysym_translation_state = keysym_translation_state_create(rules, 0);
340 keysym_translation_state_create(rules); 348 if (config->keysym_translation_state == NULL) {
349 config->keysym_translation_state = keysym_translation_state_create(rules,
350 XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
351 }
352 if (config->keysym_translation_state == NULL) {
353 goto cleanup;
354 }
341 355
342 return; 356 return;
343cleanup: 357cleanup:
@@ -352,13 +366,7 @@ static char *config_path(const char *prefix, const char *config_folder) {
352 if (!prefix || !prefix[0] || !config_folder || !config_folder[0]) { 366 if (!prefix || !prefix[0] || !config_folder || !config_folder[0]) {
353 return NULL; 367 return NULL;
354 } 368 }
355 369 return format_str("%s/%s/config", prefix, config_folder);
356 const char *filename = "config";
357
358 size_t size = 3 + strlen(prefix) + strlen(config_folder) + strlen(filename);
359 char *path = calloc(size, sizeof(char));
360 snprintf(path, size, "%s/%s/%s", prefix, config_folder, filename);
361 return path;
362} 370}
363 371
364static char *get_config_path(void) { 372static char *get_config_path(void) {
@@ -368,10 +376,7 @@ static char *get_config_path(void) {
368 376
369 const char *config_home = getenv("XDG_CONFIG_HOME"); 377 const char *config_home = getenv("XDG_CONFIG_HOME");
370 if ((config_home == NULL || config_home[0] == '\0') && home != NULL) { 378 if ((config_home == NULL || config_home[0] == '\0') && home != NULL) {
371 size_t size_fallback = 1 + strlen(home) + strlen("/.config"); 379 config_home_fallback = format_str("%s/.config", home);
372 config_home_fallback = calloc(size_fallback, sizeof(char));
373 if (config_home_fallback != NULL)
374 snprintf(config_home_fallback, size_fallback, "%s/.config", home);
375 config_home = config_home_fallback; 380 config_home = config_home_fallback;
376 } 381 }
377 382
@@ -475,6 +480,11 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
475 old_config->xwayland ? "enabled" : "disabled"); 480 old_config->xwayland ? "enabled" : "disabled");
476 config->xwayland = old_config->xwayland; 481 config->xwayland = old_config->xwayland;
477 482
483 // primary_selection can only be enabled/disabled at launch
484 sway_log(SWAY_DEBUG, "primary_selection will remain %s",
485 old_config->primary_selection ? "enabled" : "disabled");
486 config->primary_selection = old_config->primary_selection;
487
478 if (!config->validating) { 488 if (!config->validating) {
479 if (old_config->swaybg_client != NULL) { 489 if (old_config->swaybg_client != NULL) {
480 wl_client_destroy(old_config->swaybg_client); 490 wl_client_destroy(old_config->swaybg_client);
@@ -494,56 +504,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
494 504
495 config->reading = true; 505 config->reading = true;
496 506
497 // Read security configs 507 bool success = load_config(path, config, &config->swaynag_config_errors);
498 // TODO: Security
499 bool success = true;
500 /*
501 DIR *dir = opendir(SYSCONFDIR "/sway/security.d");
502 if (!dir) {
503 sway_log(SWAY_ERROR,
504 "%s does not exist, sway will have no security configuration"
505 " and will probably be broken", SYSCONFDIR "/sway/security.d");
506 } else {
507 list_t *secconfigs = create_list();
508 char *base = SYSCONFDIR "/sway/security.d/";
509 struct dirent *ent = readdir(dir);
510 struct stat s;
511 while (ent != NULL) {
512 char *_path = malloc(strlen(ent->d_name) + strlen(base) + 1);
513 strcpy(_path, base);
514 strcat(_path, ent->d_name);
515 lstat(_path, &s);
516 if (S_ISREG(s.st_mode) && ent->d_name[0] != '.') {
517 list_add(secconfigs, _path);
518 }
519 else {
520 free(_path);
521 }
522 ent = readdir(dir);
523 }
524 closedir(dir);
525
526 list_qsort(secconfigs, qstrcmp);
527 for (int i = 0; i < secconfigs->length; ++i) {
528 char *_path = secconfigs->items[i];
529 if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 ||
530 (((s.st_mode & 0777) != 0644) &&
531 (s.st_mode & 0777) != 0444)) {
532 sway_log(SWAY_ERROR,
533 "Refusing to load %s - it must be owned by root "
534 "and mode 644 or 444", _path);
535 success = false;
536 } else {
537 success = success && load_config(_path, config);
538 }
539 }
540
541 list_free_items_and_destroy(secconfigs);
542 }
543 */
544
545 success = success && load_config(path, config,
546 &config->swaynag_config_errors);
547 508
548 if (validating) { 509 if (validating) {
549 free_config(config); 510 free_config(config);
@@ -1037,8 +998,12 @@ void translate_keysyms(struct input_config *input_config) {
1037 998
1038 struct xkb_rule_names rules = {0}; 999 struct xkb_rule_names rules = {0};
1039 input_config_fill_rule_names(input_config, &rules); 1000 input_config_fill_rule_names(input_config, &rules);
1040 config->keysym_translation_state = 1001 config->keysym_translation_state = keysym_translation_state_create(rules, 0);
1041 keysym_translation_state_create(rules); 1002 if (config->keysym_translation_state == NULL) {
1003 sway_log(SWAY_ERROR, "Failed to create keysym translation XKB state "
1004 "for device '%s'", input_config->identifier);
1005 return;
1006 }
1042 1007
1043 for (int i = 0; i < config->modes->length; ++i) { 1008 for (int i = 0; i < config->modes->length; ++i) {
1044 struct sway_mode *mode = config->modes->items[i]; 1009 struct sway_mode *mode = config->modes->items[i];
diff --git a/sway/config/bar.c b/sway/config/bar.c
index a8389244..908b2865 100644
--- a/sway/config/bar.c
+++ b/sway/config/bar.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <signal.h> 1#include <signal.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdio.h> 3#include <stdio.h>
diff --git a/sway/config/input.c b/sway/config/input.c
index 44c2be28..de3b21ed 100644
--- a/sway/config/input.c
+++ b/sway/config/input.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <limits.h> 2#include <limits.h>
4#include <float.h> 3#include <float.h>
diff --git a/sway/config/output.c b/sway/config/output.c
index 1a5215fe..1b2332e9 100644
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <drm_fourcc.h> 2#include <drm_fourcc.h>
4#include <stdbool.h> 3#include <stdbool.h>
@@ -511,9 +510,6 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
511 510
512 struct wlr_output *wlr_output = output->wlr_output; 511 struct wlr_output *wlr_output = output->wlr_output;
513 512
514 // Flag to prevent the output mode event handler from calling us
515 output->enabling = (!oc || oc->enabled);
516
517 struct wlr_output_state pending = {0}; 513 struct wlr_output_state pending = {0};
518 queue_output_config(oc, output, &pending); 514 queue_output_config(oc, output, &pending);
519 515
@@ -523,12 +519,9 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
523 // Leave the output disabled for now and try again when the output gets 519 // Leave the output disabled for now and try again when the output gets
524 // the mode we asked for. 520 // the mode we asked for.
525 sway_log(SWAY_ERROR, "Failed to commit output %s", wlr_output->name); 521 sway_log(SWAY_ERROR, "Failed to commit output %s", wlr_output->name);
526 output->enabling = false;
527 return false; 522 return false;
528 } 523 }
529 524
530 output->enabling = false;
531
532 if (oc && !oc->enabled) { 525 if (oc && !oc->enabled) {
533 sway_log(SWAY_DEBUG, "Disabling output %s", oc->name); 526 sway_log(SWAY_DEBUG, "Disabling output %s", oc->name);
534 if (output->enabled) { 527 if (output->enabled) {
@@ -822,7 +815,9 @@ static bool _spawn_swaybg(char **command) {
822 setenv("WAYLAND_SOCKET", wayland_socket_str, true); 815 setenv("WAYLAND_SOCKET", wayland_socket_str, true);
823 816
824 execvp(command[0], command); 817 execvp(command[0], command);
825 sway_log_errno(SWAY_ERROR, "execvp failed"); 818 sway_log_errno(SWAY_ERROR, "failed to execute '%s' "
819 "(background configuration probably not applied)",
820 command[0]);
826 _exit(EXIT_FAILURE); 821 _exit(EXIT_FAILURE);
827 } 822 }
828 _exit(EXIT_SUCCESS); 823 _exit(EXIT_SUCCESS);
@@ -832,12 +827,13 @@ static bool _spawn_swaybg(char **command) {
832 sway_log_errno(SWAY_ERROR, "close failed"); 827 sway_log_errno(SWAY_ERROR, "close failed");
833 return false; 828 return false;
834 } 829 }
835 if (waitpid(pid, NULL, 0) < 0) { 830 int fork_status = 0;
831 if (waitpid(pid, &fork_status, 0) < 0) {
836 sway_log_errno(SWAY_ERROR, "waitpid failed"); 832 sway_log_errno(SWAY_ERROR, "waitpid failed");
837 return false; 833 return false;
838 } 834 }
839 835
840 return true; 836 return WIFEXITED(fork_status) && WEXITSTATUS(fork_status) == EXIT_SUCCESS;
841} 837}
842 838
843bool spawn_swaybg(void) { 839bool spawn_swaybg(void) {
diff --git a/sway/config/seat.c b/sway/config/seat.c
index 6d5d91ae..f2326189 100644
--- a/sway/config/seat.c
+++ b/sway/config/seat.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <limits.h> 1#include <limits.h>
3#include <stdlib.h> 2#include <stdlib.h>
4#include <string.h> 3#include <string.h>
diff --git a/sway/criteria.c b/sway/criteria.c
index 78ea8b8a..e16b4fa8 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <stdio.h> 2#include <stdio.h>
4#include <stdbool.h> 3#include <stdbool.h>
diff --git a/sway/desktop/launcher.c b/sway/desktop/launcher.c
index 00a7e38a..28043d19 100644
--- a/sway/desktop/launcher.c
+++ b/sway/desktop/launcher.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <string.h> 2#include <string.h>
4#include <wlr/types/wlr_xdg_activation_v1.h> 3#include <wlr/types/wlr_xdg_activation_v1.h>
@@ -67,6 +66,9 @@ void launcher_ctx_destroy(struct launcher_ctx *ctx) {
67 } 66 }
68 wl_list_remove(&ctx->node_destroy.link); 67 wl_list_remove(&ctx->node_destroy.link);
69 wl_list_remove(&ctx->token_destroy.link); 68 wl_list_remove(&ctx->token_destroy.link);
69 if (ctx->seat) {
70 wl_list_remove(&ctx->seat_destroy.link);
71 }
70 wl_list_remove(&ctx->link); 72 wl_list_remove(&ctx->link);
71 wlr_xdg_activation_token_v1_destroy(ctx->token); 73 wlr_xdg_activation_token_v1_destroy(ctx->token);
72 free(ctx->fallback_name); 74 free(ctx->fallback_name);
@@ -213,6 +215,8 @@ struct launcher_ctx *launcher_ctx_create(struct wlr_xdg_activation_token_v1 *tok
213 ctx->fallback_name = strdup(fallback_name); 215 ctx->fallback_name = strdup(fallback_name);
214 ctx->token = token; 216 ctx->token = token;
215 ctx->node = node; 217 ctx->node = node;
218 // Having surface set means that the focus check in wlroots has passed
219 ctx->had_focused_surface = token->surface != NULL;
216 220
217 ctx->node_destroy.notify = ctx_handle_node_destroy; 221 ctx->node_destroy.notify = ctx_handle_node_destroy;
218 wl_signal_add(&ctx->node->events.destroy, &ctx->node_destroy); 222 wl_signal_add(&ctx->node->events.destroy, &ctx->node_destroy);
@@ -227,6 +231,12 @@ struct launcher_ctx *launcher_ctx_create(struct wlr_xdg_activation_token_v1 *tok
227 return ctx; 231 return ctx;
228} 232}
229 233
234static void launch_ctx_handle_seat_destroy(struct wl_listener *listener, void *data) {
235 struct launcher_ctx *ctx = wl_container_of(listener, ctx, seat_destroy);
236 ctx->seat = NULL;
237 wl_list_remove(&ctx->seat_destroy.link);
238}
239
230// Creates a context with a new token for the internal launcher 240// Creates a context with a new token for the internal launcher
231struct launcher_ctx *launcher_ctx_create_internal(void) { 241struct launcher_ctx *launcher_ctx_create_internal(void) {
232 struct sway_seat *seat = input_manager_current_seat(); 242 struct sway_seat *seat = input_manager_current_seat();
@@ -238,13 +248,15 @@ struct launcher_ctx *launcher_ctx_create_internal(void) {
238 248
239 struct wlr_xdg_activation_token_v1 *token = 249 struct wlr_xdg_activation_token_v1 *token =
240 wlr_xdg_activation_token_v1_create(server.xdg_activation_v1); 250 wlr_xdg_activation_token_v1_create(server.xdg_activation_v1);
241 token->seat = seat->wlr_seat;
242 251
243 struct launcher_ctx *ctx = launcher_ctx_create(token, &ws->node); 252 struct launcher_ctx *ctx = launcher_ctx_create(token, &ws->node);
244 if (!ctx) { 253 if (!ctx) {
245 wlr_xdg_activation_token_v1_destroy(token); 254 wlr_xdg_activation_token_v1_destroy(token);
246 return NULL; 255 return NULL;
247 } 256 }
257 ctx->seat = seat;
258 ctx->seat_destroy.notify = launch_ctx_handle_seat_destroy;
259 wl_signal_add(&seat->wlr_seat->events.destroy, &ctx->seat_destroy);
248 260
249 return ctx; 261 return ctx;
250} 262}
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index c71abce7..4b2584b6 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -4,7 +4,9 @@
4#include <wayland-server-core.h> 4#include <wayland-server-core.h>
5#include <wlr/types/wlr_layer_shell_v1.h> 5#include <wlr/types/wlr_layer_shell_v1.h>
6#include <wlr/types/wlr_output.h> 6#include <wlr/types/wlr_output.h>
7#include <wlr/types/wlr_scene.h>
7#include <wlr/types/wlr_subcompositor.h> 8#include <wlr/types/wlr_subcompositor.h>
9#include <wlr/types/wlr_xdg_shell.h>
8#include "log.h" 10#include "log.h"
9#include "sway/scene_descriptor.h" 11#include "sway/scene_descriptor.h"
10#include "sway/desktop/transaction.h" 12#include "sway/desktop/transaction.h"
@@ -16,7 +18,6 @@
16#include "sway/server.h" 18#include "sway/server.h"
17#include "sway/tree/arrange.h" 19#include "sway/tree/arrange.h"
18#include "sway/tree/workspace.h" 20#include "sway/tree/workspace.h"
19#include <wlr/types/wlr_scene.h>
20 21
21struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( 22struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
22 struct wlr_surface *surface) { 23 struct wlr_surface *surface) {
@@ -85,6 +86,8 @@ void arrange_layers(struct sway_output *output) {
85 sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); 86 sway_log(SWAY_DEBUG, "Usable area changed, rearranging output");
86 output->usable_area = usable_area; 87 output->usable_area = usable_area;
87 arrange_output(output); 88 arrange_output(output);
89 } else {
90 arrange_popups(root->layers.popup);
88 } 91 }
89} 92}
90 93
@@ -120,10 +123,21 @@ static struct sway_layer_surface *sway_layer_surface_create(
120 return NULL; 123 return NULL;
121 } 124 }
122 125
126 surface->desc.relative = &scene->tree->node;
127
128 if (!scene_descriptor_assign(&popups->node,
129 SWAY_SCENE_DESC_POPUP, &surface->desc)) {
130 sway_log(SWAY_ERROR, "Failed to allocate a popup scene descriptor");
131 wlr_scene_node_destroy(&popups->node);
132 free(surface);
133 return NULL;
134 }
135
123 surface->tree = scene->tree; 136 surface->tree = scene->tree;
124 surface->scene = scene; 137 surface->scene = scene;
125 surface->layer_surface = scene->layer_surface; 138 surface->layer_surface = scene->layer_surface;
126 surface->popups = popups; 139 surface->popups = popups;
140 surface->layer_surface->data = surface;
127 141
128 return surface; 142 return surface;
129} 143}
@@ -197,6 +211,8 @@ static void handle_node_destroy(struct wl_listener *listener, void *data) {
197 wl_list_remove(&layer->node_destroy.link); 211 wl_list_remove(&layer->node_destroy.link);
198 wl_list_remove(&layer->output_destroy.link); 212 wl_list_remove(&layer->output_destroy.link);
199 213
214 layer->layer_surface->data = NULL;
215
200 free(layer); 216 free(layer);
201} 217}
202 218
@@ -222,10 +238,6 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
222 arrange_layers(surface->output); 238 arrange_layers(surface->output);
223 transaction_commit_dirty(); 239 transaction_commit_dirty();
224 } 240 }
225
226 int lx, ly;
227 wlr_scene_node_coords(&surface->scene->tree->node, &lx, &ly);
228 wlr_scene_node_set_position(&surface->popups->node, lx, ly);
229} 241}
230 242
231static void handle_map(struct wl_listener *listener, void *data) { 243static void handle_map(struct wl_listener *listener, void *data) {
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 9c4baafd..b8f2d32d 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <stdlib.h> 2#include <stdlib.h>
4#include <strings.h> 3#include <strings.h>
@@ -12,6 +11,8 @@
12#include <wlr/types/wlr_gamma_control_v1.h> 11#include <wlr/types/wlr_gamma_control_v1.h>
13#include <wlr/types/wlr_matrix.h> 12#include <wlr/types/wlr_matrix.h>
14#include <wlr/types/wlr_output_layout.h> 13#include <wlr/types/wlr_output_layout.h>
14#include <wlr/types/wlr_output_management_v1.h>
15#include <wlr/types/wlr_output_power_management_v1.h>
15#include <wlr/types/wlr_output.h> 16#include <wlr/types/wlr_output.h>
16#include <wlr/types/wlr_presentation_time.h> 17#include <wlr/types/wlr_presentation_time.h>
17#include <wlr/types/wlr_compositor.h> 18#include <wlr/types/wlr_compositor.h>
@@ -182,7 +183,15 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
182 } 183 }
183} 184}
184 185
185static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output) { 186static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
187 struct wlr_scene_buffer *buffer) {
188 // if we are scaling down, we should always choose linear
189 if (buffer->dst_width > 0 && buffer->dst_height > 0 && (
190 buffer->dst_width < buffer->buffer_width ||
191 buffer->dst_height < buffer->buffer_height)) {
192 return WLR_SCALE_FILTER_BILINEAR;
193 }
194
186 switch (output->scale_filter) { 195 switch (output->scale_filter) {
187 case SCALE_FILTER_LINEAR: 196 case SCALE_FILTER_LINEAR:
188 return WLR_SCALE_FILTER_BILINEAR; 197 return WLR_SCALE_FILTER_BILINEAR;
@@ -211,7 +220,7 @@ static void output_configure_scene(struct sway_output *output,
211 // hack: don't call the scene setter because that will damage all outputs 220 // hack: don't call the scene setter because that will damage all outputs
212 // We don't want to damage outputs that aren't our current output that 221 // We don't want to damage outputs that aren't our current output that
213 // we're configuring 222 // we're configuring
214 buffer->filter_mode = get_scale_filter(output); 223 buffer->filter_mode = get_scale_filter(output, buffer);
215 224
216 wlr_scene_buffer_set_opacity(buffer, opacity); 225 wlr_scene_buffer_set_opacity(buffer, opacity);
217 } else if (node->type == WLR_SCENE_NODE_TREE) { 226 } else if (node->type == WLR_SCENE_NODE_TREE) {
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index acc3e3f9..042141ab 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <stdlib.h> 2#include <stdlib.h>
4#include <string.h> 3#include <string.h>
@@ -606,21 +605,15 @@ static void arrange_output(struct sway_output *output, int width, int height) {
606 } 605 }
607} 606}
608 607
609static void arrange_popup(struct wlr_scene_tree *popup) { 608void arrange_popups(struct wlr_scene_tree *popups) {
610 struct wlr_scene_node *node; 609 struct wlr_scene_node *node;
611 wl_list_for_each(node, &popup->children, link) { 610 wl_list_for_each(node, &popups->children, link) {
612 struct sway_xdg_popup *popup = scene_descriptor_try_get(node, 611 struct sway_popup_desc *popup = scene_descriptor_try_get(node,
613 SWAY_SCENE_DESC_POPUP); 612 SWAY_SCENE_DESC_POPUP);
614 613
615 // the popup layer may have popups from layer_shell surfaces, in this 614 int lx, ly;
616 // case those don't have a scene descriptor, so lets skip those here. 615 wlr_scene_node_coords(popup->relative, &lx, &ly);
617 if (popup) { 616 wlr_scene_node_set_position(node, lx, ly);
618 struct wlr_scene_tree *tree = popup->view->content_tree;
619
620 int lx, ly;
621 wlr_scene_node_coords(&tree->node, &lx, &ly);
622 wlr_scene_node_set_position(&popup->scene_tree->node, lx, ly);
623 }
624 } 617 }
625} 618}
626 619
@@ -679,7 +672,7 @@ static void arrange_root(struct sway_root *root) {
679 } 672 }
680 } 673 }
681 674
682 arrange_popup(root->layers.popup); 675 arrange_popups(root->layers.popup);
683} 676}
684 677
685/** 678/**
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 7cdd97c8..7c417891 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 199309L
2#include <float.h> 1#include <float.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdlib.h> 3#include <stdlib.h>
@@ -36,6 +35,7 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) {
36 wl_list_remove(&popup->new_popup.link); 35 wl_list_remove(&popup->new_popup.link);
37 wl_list_remove(&popup->destroy.link); 36 wl_list_remove(&popup->destroy.link);
38 wl_list_remove(&popup->surface_commit.link); 37 wl_list_remove(&popup->surface_commit.link);
38 wl_list_remove(&popup->reposition.link);
39 wlr_scene_node_destroy(&popup->scene_tree->node); 39 wlr_scene_node_destroy(&popup->scene_tree->node);
40 free(popup); 40 free(popup);
41} 41}
@@ -71,6 +71,11 @@ static void popup_handle_surface_commit(struct wl_listener *listener, void *data
71 } 71 }
72} 72}
73 73
74static void popup_handle_reposition(struct wl_listener *listener, void *data) {
75 struct sway_xdg_popup *popup = wl_container_of(listener, popup, reposition);
76 popup_unconstrain(popup);
77}
78
74static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup, 79static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup,
75 struct sway_view *view, struct wlr_scene_tree *parent) { 80 struct sway_view *view, struct wlr_scene_tree *parent) {
76 struct wlr_xdg_surface *xdg_surface = wlr_popup->base; 81 struct wlr_xdg_surface *xdg_surface = wlr_popup->base;
@@ -97,8 +102,11 @@ static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup,
97 return NULL; 102 return NULL;
98 } 103 }
99 104
105 popup->desc.relative = &view->content_tree->node;
106 popup->desc.view = view;
107
100 if (!scene_descriptor_assign(&popup->scene_tree->node, 108 if (!scene_descriptor_assign(&popup->scene_tree->node,
101 SWAY_SCENE_DESC_POPUP, popup)) { 109 SWAY_SCENE_DESC_POPUP, &popup->desc)) {
102 sway_log(SWAY_ERROR, "Failed to allocate a popup scene descriptor"); 110 sway_log(SWAY_ERROR, "Failed to allocate a popup scene descriptor");
103 wlr_scene_node_destroy(&popup->scene_tree->node); 111 wlr_scene_node_destroy(&popup->scene_tree->node);
104 free(popup); 112 free(popup);
@@ -114,6 +122,8 @@ static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup,
114 popup->surface_commit.notify = popup_handle_surface_commit; 122 popup->surface_commit.notify = popup_handle_surface_commit;
115 wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); 123 wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup);
116 popup->new_popup.notify = popup_handle_new_popup; 124 popup->new_popup.notify = popup_handle_new_popup;
125 wl_signal_add(&wlr_popup->events.reposition, &popup->reposition);
126 popup->reposition.notify = popup_handle_reposition;
117 wl_signal_add(&wlr_popup->events.destroy, &popup->destroy); 127 wl_signal_add(&wlr_popup->events.destroy, &popup->destroy);
118 popup->destroy.notify = popup_handle_destroy; 128 popup->destroy.notify = popup_handle_destroy;
119 129
@@ -279,6 +289,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
279 } 289 }
280 // XXX: https://github.com/swaywm/sway/issues/2176 290 // XXX: https://github.com/swaywm/sway/issues/2176
281 wlr_xdg_surface_schedule_configure(xdg_surface); 291 wlr_xdg_surface_schedule_configure(xdg_surface);
292 // TODO: wlr_xdg_toplevel_set_bounds()
282 return; 293 return;
283 } 294 }
284 295
@@ -337,6 +348,7 @@ static void handle_set_app_id(struct wl_listener *listener, void *data) {
337 struct sway_xdg_shell_view *xdg_shell_view = 348 struct sway_xdg_shell_view *xdg_shell_view =
338 wl_container_of(listener, xdg_shell_view, set_app_id); 349 wl_container_of(listener, xdg_shell_view, set_app_id);
339 struct sway_view *view = &xdg_shell_view->view; 350 struct sway_view *view = &xdg_shell_view->view;
351 view_update_app_id(view);
340 view_execute_criteria(view); 352 view_execute_criteria(view);
341} 353}
342 354
@@ -563,4 +575,7 @@ void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
563 wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base); 575 wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base);
564 576
565 xdg_toplevel->base->data = xdg_shell_view; 577 xdg_toplevel->base->data = xdg_shell_view;
578
579 wlr_xdg_toplevel_set_wm_capabilities(xdg_toplevel,
580 XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
566} 581}
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 9f3f4d5f..270cf08f 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 199309L
2#include <float.h> 1#include <float.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdlib.h> 3#include <stdlib.h>
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 404c1eed..3d04826c 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>
@@ -9,6 +8,7 @@
9#include <wlr/types/wlr_cursor.h> 8#include <wlr/types/wlr_cursor.h>
10#include <wlr/types/wlr_cursor_shape_v1.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>
@@ -90,9 +90,9 @@ struct sway_node *node_at_coords(
90 } 90 }
91 91
92 if (!con) { 92 if (!con) {
93 struct sway_xdg_popup *popup = 93 struct sway_popup_desc *popup =
94 scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP); 94 scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP);
95 if (popup) { 95 if (popup && popup->view) {
96 con = popup->view->container; 96 con = popup->view->container;
97 } 97 }
98 } 98 }
@@ -243,7 +243,7 @@ static enum sway_input_idle_source idle_source_from_device(
243 return IDLE_SOURCE_POINTER; 243 return IDLE_SOURCE_POINTER;
244 case WLR_INPUT_DEVICE_TOUCH: 244 case WLR_INPUT_DEVICE_TOUCH:
245 return IDLE_SOURCE_TOUCH; 245 return IDLE_SOURCE_TOUCH;
246 case WLR_INPUT_DEVICE_TABLET_TOOL: 246 case WLR_INPUT_DEVICE_TABLET:
247 return IDLE_SOURCE_TABLET_TOOL; 247 return IDLE_SOURCE_TABLET_TOOL;
248 case WLR_INPUT_DEVICE_TABLET_PAD: 248 case WLR_INPUT_DEVICE_TABLET_PAD:
249 return IDLE_SOURCE_TABLET_PAD; 249 return IDLE_SOURCE_TABLET_PAD;
@@ -356,7 +356,7 @@ static void handle_pointer_motion_absolute(
356 356
357void dispatch_cursor_button(struct sway_cursor *cursor, 357void dispatch_cursor_button(struct sway_cursor *cursor,
358 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,
359 enum wlr_button_state state) { 359 enum wl_pointer_button_state state) {
360 if (time_msec == 0) { 360 if (time_msec == 0) {
361 time_msec = get_current_time_msec(); 361 time_msec = get_current_time_msec();
362 } 362 }
@@ -368,7 +368,7 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) {
368 struct sway_cursor *cursor = wl_container_of(listener, cursor, button); 368 struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
369 struct wlr_pointer_button_event *event = data; 369 struct wlr_pointer_button_event *event = data;
370 370
371 if (event->state == WLR_BUTTON_PRESSED) { 371 if (event->state == WL_POINTER_BUTTON_STATE_PRESSED) {
372 cursor->pressed_button_count++; 372 cursor->pressed_button_count++;
373 } else { 373 } else {
374 if (cursor->pressed_button_count > 0) { 374 if (cursor->pressed_button_count > 0) {
@@ -430,7 +430,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {
430 if (cursor->pointer_touch_id == cursor->seat->touch_id) { 430 if (cursor->pointer_touch_id == cursor->seat->touch_id) {
431 cursor->pointer_touch_up = true; 431 cursor->pointer_touch_up = true;
432 dispatch_cursor_button(cursor, &event->touch->base, 432 dispatch_cursor_button(cursor, &event->touch->base,
433 event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); 433 event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
434 } 434 }
435 } else { 435 } else {
436 seatop_touch_up(seat, event); 436 seatop_touch_up(seat, event);
@@ -448,7 +448,7 @@ static void handle_touch_cancel(struct wl_listener *listener, void *data) {
448 if (cursor->pointer_touch_id == cursor->seat->touch_id) { 448 if (cursor->pointer_touch_id == cursor->seat->touch_id) {
449 cursor->pointer_touch_up = true; 449 cursor->pointer_touch_up = true;
450 dispatch_cursor_button(cursor, &event->touch->base, 450 dispatch_cursor_button(cursor, &event->touch->base,
451 event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); 451 event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
452 } 452 }
453 } else { 453 } else {
454 seatop_touch_cancel(seat, event); 454 seatop_touch_cancel(seat, event);
@@ -518,7 +518,7 @@ static void apply_mapping_from_region(struct wlr_input_device *device,
518 double x1 = region->x1, x2 = region->x2; 518 double x1 = region->x1, x2 = region->x2;
519 double y1 = region->y1, y2 = region->y2; 519 double y1 = region->y1, y2 = region->y2;
520 520
521 if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET_TOOL) { 521 if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET) {
522 struct wlr_tablet *tablet = wlr_tablet_from_input_device(device); 522 struct wlr_tablet *tablet = wlr_tablet_from_input_device(device);
523 if (tablet->width_mm == 0 || tablet->height_mm == 0) { 523 if (tablet->width_mm == 0 || tablet->height_mm == 0) {
524 return; 524 return;
@@ -661,7 +661,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
661 event->state == WLR_TABLET_TOOL_TIP_UP) { 661 event->state == WLR_TABLET_TOOL_TIP_UP) {
662 cursor->simulating_pointer_from_tool_tip = false; 662 cursor->simulating_pointer_from_tool_tip = false;
663 dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec, 663 dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec,
664 BTN_LEFT, WLR_BUTTON_RELEASED); 664 BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
665 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 665 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
666 } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { 666 } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) {
667 // 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
@@ -673,7 +673,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
673 } else { 673 } else {
674 cursor->simulating_pointer_from_tool_tip = true; 674 cursor->simulating_pointer_from_tool_tip = true;
675 dispatch_cursor_button(cursor, &event->tablet->base, 675 dispatch_cursor_button(cursor, &event->tablet->base,
676 event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED); 676 event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
677 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 677 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
678 } 678 }
679 } else { 679 } else {
@@ -776,13 +776,13 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
776 case WLR_BUTTON_PRESSED: 776 case WLR_BUTTON_PRESSED:
777 if (cursor->tool_buttons == 0) { 777 if (cursor->tool_buttons == 0) {
778 dispatch_cursor_button(cursor, &event->tablet->base, 778 dispatch_cursor_button(cursor, &event->tablet->base,
779 event->time_msec, BTN_RIGHT, event->state); 779 event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_PRESSED);
780 } 780 }
781 break; 781 break;
782 case WLR_BUTTON_RELEASED: 782 case WLR_BUTTON_RELEASED:
783 if (cursor->tool_buttons <= 1) { 783 if (cursor->tool_buttons <= 1) {
784 dispatch_cursor_button(cursor, &event->tablet->base, 784 dispatch_cursor_button(cursor, &event->tablet->base,
785 event->time_msec, BTN_RIGHT, event->state); 785 event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_RELEASED);
786 } 786 }
787 break; 787 break;
788 } 788 }
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index c1bbdde0..248ca34e 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -1,9 +1,10 @@
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/config.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_virtual_keyboard_v1.h> 10#include <wlr/types/wlr_virtual_keyboard_v1.h>
@@ -66,8 +67,15 @@ struct sway_seat *input_manager_sway_seat_from_wlr_seat(struct wlr_seat *wlr_sea
66} 67}
67 68
68char *input_device_get_identifier(struct wlr_input_device *device) { 69char *input_device_get_identifier(struct wlr_input_device *device) {
69 int vendor = device->vendor; 70 int vendor = 0, product = 0;
70 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
71 char *name = strdup(device->name ? device->name : ""); 79 char *name = strdup(device->name ? device->name : "");
72 strip_whitespace(name); 80 strip_whitespace(name);
73 81
@@ -112,7 +120,7 @@ const char *input_device_get_type(struct sway_input_device *device) {
112 return "keyboard"; 120 return "keyboard";
113 case WLR_INPUT_DEVICE_TOUCH: 121 case WLR_INPUT_DEVICE_TOUCH:
114 return "touch"; 122 return "touch";
115 case WLR_INPUT_DEVICE_TABLET_TOOL: 123 case WLR_INPUT_DEVICE_TABLET:
116 return "tablet_tool"; 124 return "tablet_tool";
117 case WLR_INPUT_DEVICE_TABLET_PAD: 125 case WLR_INPUT_DEVICE_TABLET_PAD:
118 return "tablet_pad"; 126 return "tablet_pad";
@@ -425,6 +433,20 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) {
425 } 433 }
426} 434}
427 435
436static 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
428struct sway_input_manager *input_manager_create(struct sway_server *server) { 450struct sway_input_manager *input_manager_create(struct sway_server *server) {
429 struct sway_input_manager *input = 451 struct sway_input_manager *input =
430 calloc(1, sizeof(struct sway_input_manager)); 452 calloc(1, sizeof(struct sway_input_manager));
@@ -460,6 +482,15 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
460 482
461 input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display); 483 input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display);
462 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
463 return input; 494 return input;
464} 495}
465 496
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 75fea484..0c5672bc 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -1,4 +1,3 @@
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>
@@ -68,6 +67,12 @@ static void seat_node_destroy(struct sway_seat_node *seat_node) {
68} 67}
69 68
70void seat_destroy(struct sway_seat *seat) { 69void seat_destroy(struct sway_seat *seat) {
70 wlr_seat_destroy(seat->wlr_seat);
71}
72
73static void handle_seat_destroy(struct wl_listener *listener, void *data) {
74 struct sway_seat *seat = wl_container_of(listener, seat, destroy);
75
71 if (seat == config->handler_context.seat) { 76 if (seat == config->handler_context.seat) {
72 config->handler_context.seat = input_manager_get_default_seat(); 77 config->handler_context.seat = input_manager_get_default_seat();
73 } 78 }
@@ -88,7 +93,7 @@ void seat_destroy(struct sway_seat *seat) {
88 wl_list_remove(&seat->request_set_selection.link); 93 wl_list_remove(&seat->request_set_selection.link);
89 wl_list_remove(&seat->request_set_primary_selection.link); 94 wl_list_remove(&seat->request_set_primary_selection.link);
90 wl_list_remove(&seat->link); 95 wl_list_remove(&seat->link);
91 wlr_seat_destroy(seat->wlr_seat); 96 wl_list_remove(&seat->destroy.link);
92 for (int i = 0; i < seat->deferred_bindings->length; i++) { 97 for (int i = 0; i < seat->deferred_bindings->length; i++) {
93 free_sway_binding(seat->deferred_bindings->items[i]); 98 free_sway_binding(seat->deferred_bindings->items[i]);
94 } 99 }
@@ -535,6 +540,9 @@ struct sway_seat *seat_create(const char *seat_name) {
535 return NULL; 540 return NULL;
536 } 541 }
537 542
543 seat->destroy.notify = handle_seat_destroy;
544 wl_signal_add(&seat->wlr_seat->events.destroy, &seat->destroy);
545
538 seat->idle_inhibit_sources = seat->idle_wake_sources = 546 seat->idle_inhibit_sources = seat->idle_wake_sources =
539 IDLE_SOURCE_KEYBOARD | 547 IDLE_SOURCE_KEYBOARD |
540 IDLE_SOURCE_POINTER | 548 IDLE_SOURCE_POINTER |
@@ -608,7 +616,7 @@ static void seat_update_capabilities(struct sway_seat *seat) {
608 case WLR_INPUT_DEVICE_TOUCH: 616 case WLR_INPUT_DEVICE_TOUCH:
609 caps |= WL_SEAT_CAPABILITY_TOUCH; 617 caps |= WL_SEAT_CAPABILITY_TOUCH;
610 break; 618 break;
611 case WLR_INPUT_DEVICE_TABLET_TOOL: 619 case WLR_INPUT_DEVICE_TABLET:
612 caps |= WL_SEAT_CAPABILITY_POINTER; 620 caps |= WL_SEAT_CAPABILITY_POINTER;
613 break; 621 break;
614 case WLR_INPUT_DEVICE_SWITCH: 622 case WLR_INPUT_DEVICE_SWITCH:
@@ -666,7 +674,7 @@ static const char *get_builtin_output_name(void) {
666static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { 674static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) {
667 switch (seat_device->input_device->wlr_device->type) { 675 switch (seat_device->input_device->wlr_device->type) {
668 case WLR_INPUT_DEVICE_TOUCH: 676 case WLR_INPUT_DEVICE_TOUCH:
669 case WLR_INPUT_DEVICE_TABLET_TOOL: 677 case WLR_INPUT_DEVICE_TABLET:
670 return true; 678 return true;
671 default: 679 default:
672 return false; 680 return false;
@@ -681,7 +689,7 @@ static void seat_apply_input_mapping(struct sway_seat *seat,
681 switch (sway_device->input_device->wlr_device->type) { 689 switch (sway_device->input_device->wlr_device->type) {
682 case WLR_INPUT_DEVICE_POINTER: 690 case WLR_INPUT_DEVICE_POINTER:
683 case WLR_INPUT_DEVICE_TOUCH: 691 case WLR_INPUT_DEVICE_TOUCH:
684 case WLR_INPUT_DEVICE_TABLET_TOOL: 692 case WLR_INPUT_DEVICE_TABLET:
685 break; 693 break;
686 default: 694 default:
687 return; // these devices don't support mappings 695 return; // these devices don't support mappings
@@ -874,7 +882,7 @@ 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:
@@ -913,7 +921,7 @@ void seat_reset_device(struct sway_seat *seat,
913 case WLR_INPUT_DEVICE_TOUCH: 921 case WLR_INPUT_DEVICE_TOUCH:
914 seat_reset_input_config(seat, seat_device); 922 seat_reset_input_config(seat, seat_device);
915 break; 923 break;
916 case WLR_INPUT_DEVICE_TABLET_TOOL: 924 case WLR_INPUT_DEVICE_TABLET:
917 seat_reset_input_config(seat, seat_device); 925 seat_reset_input_config(seat, seat_device);
918 break; 926 break;
919 case WLR_INPUT_DEVICE_TABLET_PAD: 927 case WLR_INPUT_DEVICE_TABLET_PAD:
@@ -1521,7 +1529,7 @@ struct seat_config *seat_get_config_by_name(const char *name) {
1521} 1529}
1522 1530
1523void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, 1531void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec,
1524 uint32_t button, enum wlr_button_state state) { 1532 uint32_t button, enum wl_pointer_button_state state) {
1525 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,
1526 time_msec, button, state); 1534 time_msec, button, state);
1527} 1535}
@@ -1558,7 +1566,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con) {
1558 1566
1559void seatop_button(struct sway_seat *seat, uint32_t time_msec, 1567void seatop_button(struct sway_seat *seat, uint32_t time_msec,
1560 struct wlr_input_device *device, uint32_t button, 1568 struct wlr_input_device *device, uint32_t button,
1561 enum wlr_button_state state) { 1569 enum wl_pointer_button_state state) {
1562 if (seat->seatop_impl->button) { 1570 if (seat->seatop_impl->button) {
1563 seat->seatop_impl->button(seat, time_msec, device, button, state); 1571 seat->seatop_impl->button(seat, time_msec, device, button, state);
1564 } 1572 }
diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c
index c56330fd..0c6f7c5e 100644
--- a/sway/input/seatop_default.c
+++ b/sway/input/seatop_default.c
@@ -1,4 +1,3 @@
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>
@@ -291,7 +290,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
291 290
292static bool trigger_pointer_button_binding(struct sway_seat *seat, 291static bool trigger_pointer_button_binding(struct sway_seat *seat,
293 struct wlr_input_device *device, uint32_t button, 292 struct wlr_input_device *device, uint32_t button,
294 enum wlr_button_state state, uint32_t modifiers, 293 enum wl_pointer_button_state state, uint32_t modifiers,
295 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) {
296 // 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
297 // pointer input for one. Emulated input should not trigger bindings. The 296 // pointer input for one. Emulated input should not trigger bindings. The
@@ -305,7 +304,7 @@ static bool trigger_pointer_button_binding(struct sway_seat *seat,
305 char *device_identifier = device ? input_device_get_identifier(device) 304 char *device_identifier = device ? input_device_get_identifier(device)
306 : strdup("*"); 305 : strdup("*");
307 struct sway_binding *binding = NULL; 306 struct sway_binding *binding = NULL;
308 if (state == WLR_BUTTON_PRESSED) { 307 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
309 state_add_button(e, button); 308 state_add_button(e, button);
310 binding = get_active_mouse_binding(e, 309 binding = get_active_mouse_binding(e,
311 config->current_mode->mouse_bindings, modifiers, false, 310 config->current_mode->mouse_bindings, modifiers, false,
@@ -330,7 +329,7 @@ static bool trigger_pointer_button_binding(struct sway_seat *seat,
330 329
331static void handle_button(struct sway_seat *seat, uint32_t time_msec, 330static void handle_button(struct sway_seat *seat, uint32_t time_msec,
332 struct wlr_input_device *device, uint32_t button, 331 struct wlr_input_device *device, uint32_t button,
333 enum wlr_button_state state) { 332 enum wl_pointer_button_state state) {
334 struct sway_cursor *cursor = seat->cursor; 333 struct sway_cursor *cursor = seat->cursor;
335 334
336 // Determine what's under the cursor 335 // Determine what's under the cursor
@@ -363,7 +362,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
363 362
364 // Handle clicking an empty workspace 363 // Handle clicking an empty workspace
365 if (node && node->type == N_WORKSPACE) { 364 if (node && node->type == N_WORKSPACE) {
366 if (state == WLR_BUTTON_PRESSED) { 365 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
367 seat_set_focus(seat, node); 366 seat_set_focus(seat, node);
368 transaction_commit_dirty(); 367 transaction_commit_dirty();
369 } 368 }
@@ -378,7 +377,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
378 seat_set_focus_layer(seat, layer); 377 seat_set_focus_layer(seat, layer);
379 transaction_commit_dirty(); 378 transaction_commit_dirty();
380 } 379 }
381 if (state == WLR_BUTTON_PRESSED) { 380 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
382 seatop_begin_down_on_surface(seat, surface, sx, sy); 381 seatop_begin_down_on_surface(seat, surface, sx, sy);
383 } 382 }
384 seat_pointer_notify_button(seat, time_msec, button, state); 383 seat_pointer_notify_button(seat, time_msec, button, state);
@@ -387,7 +386,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
387 386
388 // Handle tiling resize via border 387 // Handle tiling resize via border
389 if (cont && resize_edge && button == BTN_LEFT && 388 if (cont && resize_edge && button == BTN_LEFT &&
390 state == WLR_BUTTON_PRESSED && !is_floating) { 389 state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating) {
391 // 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
392 // 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
393 // 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.
@@ -405,7 +404,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
405 // Handle tiling resize via mod 404 // Handle tiling resize via mod
406 bool mod_pressed = modifiers & config->floating_mod; 405 bool mod_pressed = modifiers & config->floating_mod;
407 if (cont && !is_floating_or_child && mod_pressed && 406 if (cont && !is_floating_or_child && mod_pressed &&
408 state == WLR_BUTTON_PRESSED) { 407 state == WL_POINTER_BUTTON_STATE_PRESSED) {
409 uint32_t btn_resize = config->floating_mod_inverse ? 408 uint32_t btn_resize = config->floating_mod_inverse ?
410 BTN_LEFT : BTN_RIGHT; 409 BTN_LEFT : BTN_RIGHT;
411 if (button == btn_resize) { 410 if (button == btn_resize) {
@@ -433,7 +432,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
433 } 432 }
434 433
435 // Handle changing focus when clicking on a container 434 // Handle changing focus when clicking on a container
436 if (cont && state == WLR_BUTTON_PRESSED) { 435 if (cont && state == WL_POINTER_BUTTON_STATE_PRESSED) {
437 // Default case: focus the container that was just clicked. 436 // Default case: focus the container that was just clicked.
438 node = &cont->node; 437 node = &cont->node;
439 438
@@ -454,7 +453,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
454 453
455 // Handle beginning floating move 454 // Handle beginning floating move
456 if (cont && is_floating_or_child && !is_fullscreen_or_child && 455 if (cont && is_floating_or_child && !is_fullscreen_or_child &&
457 state == WLR_BUTTON_PRESSED) { 456 state == WL_POINTER_BUTTON_STATE_PRESSED) {
458 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;
459 if (button == btn_move && (mod_pressed || on_titlebar)) { 458 if (button == btn_move && (mod_pressed || on_titlebar)) {
460 seatop_begin_move_floating(seat, container_toplevel_ancestor(cont)); 459 seatop_begin_move_floating(seat, container_toplevel_ancestor(cont));
@@ -464,7 +463,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
464 463
465 // Handle beginning floating resize 464 // Handle beginning floating resize
466 if (cont && is_floating_or_child && !is_fullscreen_or_child && 465 if (cont && is_floating_or_child && !is_fullscreen_or_child &&
467 state == WLR_BUTTON_PRESSED) { 466 state == WL_POINTER_BUTTON_STATE_PRESSED) {
468 // Via border 467 // Via border
469 if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) { 468 if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) {
470 seat_set_focus_container(seat, cont); 469 seat_set_focus_container(seat, cont);
@@ -490,7 +489,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
490 489
491 // Handle moving a tiling container 490 // Handle moving a tiling container
492 if (config->tiling_drag && (mod_pressed || on_titlebar) && 491 if (config->tiling_drag && (mod_pressed || on_titlebar) &&
493 state == WLR_BUTTON_PRESSED && !is_floating_or_child && 492 state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child &&
494 cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { 493 cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) {
495 // If moving a container by its title bar, use a threshold for the drag 494 // If moving a container by its title bar, use a threshold for the drag
496 if (!mod_pressed && config->tiling_drag_threshold > 0) { 495 if (!mod_pressed && config->tiling_drag_threshold > 0) {
@@ -503,14 +502,14 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
503 } 502 }
504 503
505 // Handle mousedown on a container surface 504 // Handle mousedown on a container surface
506 if (surface && cont && state == WLR_BUTTON_PRESSED) { 505 if (surface && cont && state == WL_POINTER_BUTTON_STATE_PRESSED) {
507 seatop_begin_down(seat, cont, sx, sy); 506 seatop_begin_down(seat, cont, sx, sy);
508 seat_pointer_notify_button(seat, time_msec, button, WLR_BUTTON_PRESSED); 507 seat_pointer_notify_button(seat, time_msec, button, WL_POINTER_BUTTON_STATE_PRESSED);
509 return; 508 return;
510 } 509 }
511 510
512 // Handle clicking a container surface or decorations 511 // Handle clicking a container surface or decorations
513 if (cont && state == WLR_BUTTON_PRESSED) { 512 if (cont && state == WL_POINTER_BUTTON_STATE_PRESSED) {
514 seat_pointer_notify_button(seat, time_msec, button, state); 513 seat_pointer_notify_button(seat, time_msec, button, state);
515 return; 514 return;
516 } 515 }
@@ -685,7 +684,7 @@ static void handle_touch_down(struct sway_seat *seat,
685 pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy, 684 pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy,
686 dx, dy); 685 dx, dy);
687 dispatch_cursor_button(cursor, &event->touch->base, event->time_msec, 686 dispatch_cursor_button(cursor, &event->touch->base, event->time_msec,
688 BTN_LEFT, WLR_BUTTON_PRESSED); 687 BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
689 } 688 }
690} 689}
691 690
@@ -695,9 +694,9 @@ static void handle_touch_down(struct sway_seat *seat,
695 694
696static uint32_t wl_axis_to_button(struct wlr_pointer_axis_event *event) { 695static uint32_t wl_axis_to_button(struct wlr_pointer_axis_event *event) {
697 switch (event->orientation) { 696 switch (event->orientation) {
698 case WLR_AXIS_ORIENTATION_VERTICAL: 697 case WL_POINTER_AXIS_VERTICAL_SCROLL:
699 return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN; 698 return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN;
700 case WLR_AXIS_ORIENTATION_HORIZONTAL: 699 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
701 return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT; 700 return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT;
702 default: 701 default:
703 sway_log(SWAY_DEBUG, "Unknown axis orientation"); 702 sway_log(SWAY_DEBUG, "Unknown axis orientation");
diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c
index b4421fe6..35fd3bcb 100644
--- a/sway/input/seatop_down.c
+++ b/sway/input/seatop_down.c
@@ -1,4 +1,3 @@
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>
@@ -143,7 +142,7 @@ static void handle_pointer_axis(struct sway_seat *seat,
143 142
144static void handle_button(struct sway_seat *seat, uint32_t time_msec, 143static void handle_button(struct sway_seat *seat, uint32_t time_msec,
145 struct wlr_input_device *device, uint32_t button, 144 struct wlr_input_device *device, uint32_t button,
146 enum wlr_button_state state) { 145 enum wl_pointer_button_state state) {
147 seat_pointer_notify_button(seat, time_msec, button, state); 146 seat_pointer_notify_button(seat, time_msec, button, state);
148 147
149 if (seat->cursor->pressed_button_count == 0) { 148 if (seat->cursor->pressed_button_count == 0) {
diff --git a/sway/input/seatop_move_floating.c b/sway/input/seatop_move_floating.c
index 21d048ce..83668d88 100644
--- a/sway/input/seatop_move_floating.c
+++ b/sway/input/seatop_move_floating.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 "sway/desktop/transaction.h" 2#include "sway/desktop/transaction.h"
4#include "sway/input/cursor.h" 3#include "sway/input/cursor.h"
@@ -22,7 +21,7 @@ static void finalize_move(struct sway_seat *seat) {
22 21
23static void handle_button(struct sway_seat *seat, uint32_t time_msec, 22static void handle_button(struct sway_seat *seat, uint32_t time_msec,
24 struct wlr_input_device *device, uint32_t button, 23 struct wlr_input_device *device, uint32_t button,
25 enum wlr_button_state state) { 24 enum wl_pointer_button_state state) {
26 if (seat->cursor->pressed_button_count == 0) { 25 if (seat->cursor->pressed_button_count == 0) {
27 finalize_move(seat); 26 finalize_move(seat);
28 } 27 }
diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c
index 7de39ff6..c525b77a 100644
--- a/sway/input/seatop_move_tiling.c
+++ b/sway/input/seatop_move_tiling.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/util/edges.h> 3#include <wlr/util/edges.h>
@@ -406,7 +405,7 @@ static void finalize_move(struct sway_seat *seat) {
406 405
407static void handle_button(struct sway_seat *seat, uint32_t time_msec, 406static void handle_button(struct sway_seat *seat, uint32_t time_msec,
408 struct wlr_input_device *device, uint32_t button, 407 struct wlr_input_device *device, uint32_t button,
409 enum wlr_button_state state) { 408 enum wl_pointer_button_state state) {
410 if (seat->cursor->pressed_button_count == 0) { 409 if (seat->cursor->pressed_button_count == 0) {
411 finalize_move(seat); 410 finalize_move(seat);
412 } 411 }
diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c
index df683026..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
22static void handle_button(struct sway_seat *seat, uint32_t time_msec, 21static 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
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
47static void handle_button(struct sway_seat *seat, uint32_t time_msec, 46static 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/tablet.c b/sway/input/tablet.c
index 902cb7ed..2863642a 100644
--- a/sway/input/tablet.c
+++ b/sway/input/tablet.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <wlr/config.h> 2#include <wlr/config.h>
4#include <wlr/types/wlr_tablet_v2.h> 3#include <wlr/types/wlr_tablet_v2.h>
diff --git a/sway/input/text_input.c b/sway/input/text_input.c
index 58911c2d..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"
12static void input_popup_update(struct sway_input_popup *popup);
6 13
7static struct sway_text_input *relay_get_focusable_text_input( 14static struct sway_text_input *relay_get_focusable_text_input(
8 struct sway_input_method_relay *relay) { 15 struct sway_input_method_relay *relay) {
@@ -102,6 +109,10 @@ static void handle_im_destroy(struct wl_listener *listener, void *data) {
102 input_method_destroy); 109 input_method_destroy);
103 struct wlr_input_method_v2 *context = data; 110 struct wlr_input_method_v2 *context = data;
104 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);
105 relay->input_method = NULL; 116 relay->input_method = NULL;
106 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);
107 if (text_input) { 118 if (text_input) {
@@ -133,6 +144,11 @@ static void relay_send_im_state(struct sway_input_method_relay *relay,
133 input->current.content_type.hint, 144 input->current.content_type.hint,
134 input->current.content_type.purpose); 145 input->current.content_type.purpose);
135 } 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 }
136 wlr_input_method_v2_send_done(input_method); 152 wlr_input_method_v2_send_done(input_method);
137 // TODO: pass intent, display popup size 153 // TODO: pass intent, display popup size
138} 154}
@@ -255,6 +271,211 @@ static void relay_handle_text_input(struct wl_listener *listener,
255 sway_text_input_create(relay, wlr_text_input); 271 sway_text_input_create(relay, wlr_text_input);
256} 272}
257 273
274static 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
395static 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
417static 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
428static 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
435static 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
442static 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
470static 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
258static void relay_handle_input_method(struct wl_listener *listener, 479static void relay_handle_input_method(struct wl_listener *listener,
259 void *data) { 480 void *data) {
260 struct sway_input_method_relay *relay = wl_container_of(listener, relay, 481 struct sway_input_method_relay *relay = wl_container_of(listener, relay,
@@ -280,10 +501,13 @@ static void relay_handle_input_method(struct wl_listener *listener,
280 wl_signal_add(&relay->input_method->events.destroy, 501 wl_signal_add(&relay->input_method->events.destroy,
281 &relay->input_method_destroy); 502 &relay->input_method_destroy);
282 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;
283 507
284 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);
285 if (text_input) { 509 if (text_input) {
286 wlr_text_input_v3_send_enter(text_input->input, 510 text_input_send_enter(text_input,
287 text_input->pending_focused_surface); 511 text_input->pending_focused_surface);
288 text_input_set_pending_focused_surface(text_input, NULL); 512 text_input_set_pending_focused_surface(text_input, NULL);
289 } 513 }
@@ -293,6 +517,7 @@ void sway_input_method_relay_init(struct sway_seat *seat,
293 struct sway_input_method_relay *relay) { 517 struct sway_input_method_relay *relay) {
294 relay->seat = seat; 518 relay->seat = seat;
295 wl_list_init(&relay->text_inputs); 519 wl_list_init(&relay->text_inputs);
520 wl_list_init(&relay->input_popups);
296 521
297 relay->text_input_new.notify = relay_handle_text_input; 522 relay->text_input_new.notify = relay_handle_text_input;
298 wl_signal_add(&server.text_input->events.text_input, 523 wl_signal_add(&server.text_input->events.text_input,
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 58356d4e..81ca3483 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -288,6 +288,8 @@ static json_object *ipc_json_create_node(int id, const char* type, char *name,
288 json_object_object_add(object, "focus", focus); 288 json_object_object_add(object, "focus", focus);
289 json_object_object_add(object, "fullscreen_mode", json_object_new_int(0)); 289 json_object_object_add(object, "fullscreen_mode", json_object_new_int(0));
290 json_object_object_add(object, "sticky", json_object_new_boolean(false)); 290 json_object_object_add(object, "sticky", json_object_new_boolean(false));
291 json_object_object_add(object, "floating", NULL);
292 json_object_object_add(object, "scratchpad_state", NULL);
291 293
292 return object; 294 return object;
293} 295}
@@ -675,7 +677,8 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
675static void ipc_json_describe_container(struct sway_container *c, json_object *object) { 677static void ipc_json_describe_container(struct sway_container *c, json_object *object) {
676 json_object_object_add(object, "name", 678 json_object_object_add(object, "name",
677 c->title ? json_object_new_string(c->title) : NULL); 679 c->title ? json_object_new_string(c->title) : NULL);
678 if (container_is_floating(c)) { 680 bool floating = container_is_floating(c);
681 if (floating) {
679 json_object_object_add(object, "type", 682 json_object_object_add(object, "type",
680 json_object_new_string("floating_con")); 683 json_object_new_string("floating_con"));
681 } 684 }
@@ -693,9 +696,17 @@ static void ipc_json_describe_container(struct sway_container *c, json_object *o
693 json_object_object_add(object, "urgent", json_object_new_boolean(urgent)); 696 json_object_object_add(object, "urgent", json_object_new_boolean(urgent));
694 json_object_object_add(object, "sticky", json_object_new_boolean(c->is_sticky)); 697 json_object_object_add(object, "sticky", json_object_new_boolean(c->is_sticky));
695 698
699 // sway doesn't track the floating reason, so we can't use "auto_on" or "user_off"
700 json_object_object_add(object, "floating",
701 json_object_new_string(floating ? "user_on" : "auto_off"));
702
696 json_object_object_add(object, "fullscreen_mode", 703 json_object_object_add(object, "fullscreen_mode",
697 json_object_new_int(c->pending.fullscreen_mode)); 704 json_object_new_int(c->pending.fullscreen_mode));
698 705
706 // sway doesn't track if window was resized in scratchpad, so we can't use "changed"
707 json_object_object_add(object, "scratchpad_state",
708 json_object_new_string(!c->scratchpad ? "none" : "fresh"));
709
699 struct sway_node *parent = node_get_parent(&c->node); 710 struct sway_node *parent = node_get_parent(&c->node);
700 struct wlr_box parent_box = {0, 0, 0, 0}; 711 struct wlr_box parent_box = {0, 0, 0, 0};
701 712
@@ -1086,10 +1097,6 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
1086 json_object_new_string(device->identifier)); 1097 json_object_new_string(device->identifier));
1087 json_object_object_add(object, "name", 1098 json_object_object_add(object, "name",
1088 json_object_new_string(device->wlr_device->name)); 1099 json_object_new_string(device->wlr_device->name));
1089 json_object_object_add(object, "vendor",
1090 json_object_new_int(device->wlr_device->vendor));
1091 json_object_object_add(object, "product",
1092 json_object_new_int(device->wlr_device->product));
1093 json_object_object_add(object, "type", 1100 json_object_object_add(object, "type",
1094 json_object_new_string( 1101 json_object_new_string(
1095 input_device_get_type(device))); 1102 input_device_get_type(device)));
@@ -1143,6 +1150,10 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
1143 libinput_dev = wlr_libinput_get_device_handle(device->wlr_device); 1150 libinput_dev = wlr_libinput_get_device_handle(device->wlr_device);
1144 json_object_object_add(object, "libinput", 1151 json_object_object_add(object, "libinput",
1145 describe_libinput_device(libinput_dev)); 1152 describe_libinput_device(libinput_dev));
1153 json_object_object_add(object, "vendor",
1154 json_object_new_int(libinput_device_get_id_vendor(libinput_dev)));
1155 json_object_object_add(object, "product",
1156 json_object_new_int(libinput_device_get_id_product(libinput_dev)));
1146 } 1157 }
1147#endif 1158#endif
1148 1159
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 9692a77f..7f353c0e 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -1,5 +1,4 @@
1// See https://i3wm.org/docs/ipc.html for protocol information 1// See https://i3wm.org/docs/ipc.html for protocol information
2#define _POSIX_C_SOURCE 200112L
3#include <linux/input-event-codes.h> 2#include <linux/input-event-codes.h>
4#include <assert.h> 3#include <assert.h>
5#include <errno.h> 4#include <errno.h>
diff --git a/sway/lock.c b/sway/lock.c
index 8ad9c3f6..289e8ca4 100644
--- a/sway/lock.c
+++ b/sway/lock.c
@@ -1,6 +1,6 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <wlr/types/wlr_scene.h> 2#include <wlr/types/wlr_scene.h>
3#include <wlr/types/wlr_session_lock_v1.h>
4#include "log.h" 4#include "log.h"
5#include "sway/input/cursor.h" 5#include "sway/input/cursor.h"
6#include "sway/input/keyboard.h" 6#include "sway/input/keyboard.h"
diff --git a/sway/main.c b/sway/main.c
index 73254dc2..1c4939aa 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <getopt.h> 1#include <getopt.h>
3#include <pango/pangocairo.h> 2#include <pango/pangocairo.h>
4#include <signal.h> 3#include <signal.h>
diff --git a/sway/server.c b/sway/server.c
index cc20e89d..d159dc9b 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdlib.h> 3#include <stdlib.h>
@@ -8,24 +7,32 @@
8#include <wlr/backend/headless.h> 7#include <wlr/backend/headless.h>
9#include <wlr/backend/multi.h> 8#include <wlr/backend/multi.h>
10#include <wlr/config.h> 9#include <wlr/config.h>
10#include <wlr/render/allocator.h>
11#include <wlr/render/wlr_renderer.h> 11#include <wlr/render/wlr_renderer.h>
12#include <wlr/types/wlr_compositor.h> 12#include <wlr/types/wlr_compositor.h>
13#include <wlr/types/wlr_content_type_v1.h> 13#include <wlr/types/wlr_content_type_v1.h>
14#include <wlr/types/wlr_cursor_shape_v1.h> 14#include <wlr/types/wlr_cursor_shape_v1.h>
15#include <wlr/types/wlr_data_control_v1.h> 15#include <wlr/types/wlr_data_control_v1.h>
16#include <wlr/types/wlr_data_device.h>
16#include <wlr/types/wlr_drm.h> 17#include <wlr/types/wlr_drm.h>
17#include <wlr/types/wlr_export_dmabuf_v1.h> 18#include <wlr/types/wlr_export_dmabuf_v1.h>
19#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
20#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
18#include <wlr/types/wlr_fractional_scale_v1.h> 21#include <wlr/types/wlr_fractional_scale_v1.h>
19#include <wlr/types/wlr_gamma_control_v1.h> 22#include <wlr/types/wlr_gamma_control_v1.h>
20#include <wlr/types/wlr_idle_notify_v1.h> 23#include <wlr/types/wlr_idle_notify_v1.h>
21#include <wlr/types/wlr_layer_shell_v1.h> 24#include <wlr/types/wlr_layer_shell_v1.h>
22#include <wlr/types/wlr_linux_dmabuf_v1.h> 25#include <wlr/types/wlr_linux_dmabuf_v1.h>
26#include <wlr/types/wlr_output_management_v1.h>
27#include <wlr/types/wlr_output_power_management_v1.h>
23#include <wlr/types/wlr_pointer_constraints_v1.h> 28#include <wlr/types/wlr_pointer_constraints_v1.h>
29#include <wlr/types/wlr_presentation_time.h>
24#include <wlr/types/wlr_primary_selection_v1.h> 30#include <wlr/types/wlr_primary_selection_v1.h>
25#include <wlr/types/wlr_relative_pointer_v1.h> 31#include <wlr/types/wlr_relative_pointer_v1.h>
26#include <wlr/types/wlr_screencopy_v1.h> 32#include <wlr/types/wlr_screencopy_v1.h>
27#include <wlr/types/wlr_security_context_v1.h> 33#include <wlr/types/wlr_security_context_v1.h>
28#include <wlr/types/wlr_server_decoration.h> 34#include <wlr/types/wlr_server_decoration.h>
35#include <wlr/types/wlr_session_lock_v1.h>
29#include <wlr/types/wlr_single_pixel_buffer_v1.h> 36#include <wlr/types/wlr_single_pixel_buffer_v1.h>
30#include <wlr/types/wlr_subcompositor.h> 37#include <wlr/types/wlr_subcompositor.h>
31#include <wlr/types/wlr_tablet_v2.h> 38#include <wlr/types/wlr_tablet_v2.h>
@@ -58,8 +65,9 @@
58#include <wlr/types/wlr_drm_lease_v1.h> 65#include <wlr/types/wlr_drm_lease_v1.h>
59#endif 66#endif
60 67
61#define SWAY_XDG_SHELL_VERSION 2 68#define SWAY_XDG_SHELL_VERSION 5
62#define SWAY_LAYER_SHELL_VERSION 4 69#define SWAY_LAYER_SHELL_VERSION 4
70#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1
63 71
64bool allow_unsupported_gpu = false; 72bool allow_unsupported_gpu = false;
65 73
@@ -93,6 +101,7 @@ static bool is_privileged(const struct wl_global *global) {
93 global == server.output_manager_v1->global || 101 global == server.output_manager_v1->global ||
94 global == server.output_power_manager_v1->global || 102 global == server.output_power_manager_v1->global ||
95 global == server.input_method->global || 103 global == server.input_method->global ||
104 global == server.foreign_toplevel_list->global ||
96 global == server.foreign_toplevel_manager->global || 105 global == server.foreign_toplevel_manager->global ||
97 global == server.data_control_manager_v1->global || 106 global == server.data_control_manager_v1->global ||
98 global == server.screencopy_manager_v1->global || 107 global == server.screencopy_manager_v1->global ||
@@ -103,7 +112,8 @@ static bool is_privileged(const struct wl_global *global) {
103 global == server.session_lock.manager->global || 112 global == server.session_lock.manager->global ||
104 global == server.input->keyboard_shortcuts_inhibit->global || 113 global == server.input->keyboard_shortcuts_inhibit->global ||
105 global == server.input->virtual_keyboard->global || 114 global == server.input->virtual_keyboard->global ||
106 global == server.input->virtual_pointer->global; 115 global == server.input->virtual_pointer->global ||
116 global == server.input->transient_seat_manager->global;
107} 117}
108 118
109static bool filter_global(const struct wl_client *client, 119static bool filter_global(const struct wl_client *client,
@@ -163,6 +173,45 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
163 drmFreeVersion(version); 173 drmFreeVersion(version);
164} 174}
165 175
176static void handle_renderer_lost(struct wl_listener *listener, void *data) {
177 struct sway_server *server = wl_container_of(listener, server, renderer_lost);
178
179 sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
180
181 struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
182 if (renderer == NULL) {
183 sway_log(SWAY_ERROR, "Unable to create renderer");
184 return;
185 }
186
187 struct wlr_allocator *allocator =
188 wlr_allocator_autocreate(server->backend, renderer);
189 if (allocator == NULL) {
190 sway_log(SWAY_ERROR, "Unable to create allocator");
191 wlr_renderer_destroy(renderer);
192 return;
193 }
194
195 struct wlr_renderer *old_renderer = server->renderer;
196 struct wlr_allocator *old_allocator = server->allocator;
197 server->renderer = renderer;
198 server->allocator = allocator;
199
200 wl_list_remove(&server->renderer_lost.link);
201 wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
202
203 wlr_compositor_set_renderer(server->compositor, renderer);
204
205 for (int i = 0; i < root->outputs->length; ++i) {
206 struct sway_output *output = root->outputs->items[i];
207 wlr_output_init_render(output->wlr_output,
208 server->allocator, server->renderer);
209 }
210
211 wlr_allocator_destroy(old_allocator);
212 wlr_renderer_destroy(old_renderer);
213}
214
166bool server_init(struct sway_server *server) { 215bool server_init(struct sway_server *server) {
167 sway_log(SWAY_DEBUG, "Initializing Wayland server"); 216 sway_log(SWAY_DEBUG, "Initializing Wayland server");
168 server->wl_display = wl_display_create(); 217 server->wl_display = wl_display_create();
@@ -186,6 +235,9 @@ bool server_init(struct sway_server *server) {
186 return false; 235 return false;
187 } 236 }
188 237
238 server->renderer_lost.notify = handle_renderer_lost;
239 wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
240
189 wlr_renderer_init_wl_shm(server->renderer, server->wl_display); 241 wlr_renderer_init_wl_shm(server->renderer, server->wl_display);
190 242
191 if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) { 243 if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) {
@@ -289,6 +341,8 @@ bool server_init(struct sway_server *server) {
289 &server->output_power_manager_set_mode); 341 &server->output_power_manager_set_mode);
290 server->input_method = wlr_input_method_manager_v2_create(server->wl_display); 342 server->input_method = wlr_input_method_manager_v2_create(server->wl_display);
291 server->text_input = wlr_text_input_manager_v3_create(server->wl_display); 343 server->text_input = wlr_text_input_manager_v3_create(server->wl_display);
344 server->foreign_toplevel_list =
345 wlr_ext_foreign_toplevel_list_v1_create(server->wl_display, SWAY_FOREIGN_TOPLEVEL_LIST_VERSION);
292 server->foreign_toplevel_manager = 346 server->foreign_toplevel_manager =
293 wlr_foreign_toplevel_manager_v1_create(server->wl_display); 347 wlr_foreign_toplevel_manager_v1_create(server->wl_display);
294 348
@@ -388,6 +442,7 @@ void server_fini(struct sway_server *server) {
388 wlr_xwayland_destroy(server->xwayland.wlr_xwayland); 442 wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
389#endif 443#endif
390 wl_display_destroy_clients(server->wl_display); 444 wl_display_destroy_clients(server->wl_display);
445 wlr_backend_destroy(server->backend);
391 wl_display_destroy(server->wl_display); 446 wl_display_destroy(server->wl_display);
392 list_free(server->dirty_nodes); 447 list_free(server->dirty_nodes);
393} 448}
diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd
index f4a5ccff..c9895e52 100644
--- a/sway/sway-ipc.7.scd
+++ b/sway/sway-ipc.7.scd
@@ -376,6 +376,12 @@ node and will have the following properties:
376: integer 376: integer
377: (Only containers and views) The fullscreen mode of the node. 0 means none, 1 means 377: (Only containers and views) The fullscreen mode of the node. 0 means none, 1 means
378 full workspace, and 2 means global fullscreen 378 full workspace, and 2 means global fullscreen
379|- floating
380: string
381: Floating state of container. Can be either "auto_off" or "user_on"
382|- scratchpad_state
383: string
384: Whether the window is in the scratchpad. Can be either "none" or "fresh"
379|- app_id 385|- app_id
380: string 386: string
381: (Only views) For an xdg-shell view, the name of the application, if set. 387: (Only views) For an xdg-shell view, the name of the application, if set.
diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd
index 028cb7ab..7d088d5d 100644
--- a/sway/sway-output.5.scd
+++ b/sway/sway-output.5.scd
@@ -72,13 +72,11 @@ must be separated by one space. For example:
72 72
73*output* <name> scale <factor> 73*output* <name> scale <factor>
74 Scales the specified output by the specified scale _factor_. An integer is 74 Scales the specified output by the specified scale _factor_. An integer is
75 recommended, but fractional values are also supported. If a fractional 75 recommended, but fractional values are also supported. You may be better
76 value are specified, be warned that it is not possible to faithfully 76 served by setting an integer scale factor and adjusting the font size of
77 represent the contents of your windows - they will be rendered at the next 77 your applications to taste. HiDPI isn't supported with Xwayland clients
78 highest integer scale factor and downscaled. You may be better served by 78 (windows will blur). A fractional scale may be slightly adjusted to match
79 setting an integer scale factor and adjusting the font size of your 79 requirements of the protocol.
80 applications to taste. HiDPI isn't supported with Xwayland clients (windows
81 will blur).
82 80
83*output* <name> scale_filter linear|nearest|smart 81*output* <name> scale_filter linear|nearest|smart
84 Indicates how to scale application buffers that are rendered at a scale 82 Indicates how to scale application buffers that are rendered at a scale
diff --git a/sway/sway_text_node.c b/sway/sway_text_node.c
index b9a77d94..5eba53ba 100644
--- a/sway/sway_text_node.c
+++ b/sway/sway_text_node.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <drm_fourcc.h> 1#include <drm_fourcc.h>
3#include <stdio.h> 2#include <stdio.h>
4#include <stdlib.h> 3#include <stdlib.h>
@@ -58,11 +57,11 @@ struct text_buffer {
58}; 57};
59 58
60static int get_text_width(struct sway_text_node *props) { 59static int get_text_width(struct sway_text_node *props) {
60 int width = props->width;
61 if (props->max_width) { 61 if (props->max_width) {
62 return MIN(props->max_width, props->width); 62 width = MIN(width, props->max_width);
63 } 63 }
64 64 return MAX(width, 0);
65 return props->width;
66} 65}
67 66
68static void update_source_box(struct text_buffer *buffer) { 67static void update_source_box(struct text_buffer *buffer) {
diff --git a/sway/swaynag.c b/sway/swaynag.c
index 6031174d..bc5e23ea 100644
--- a/sway/swaynag.c
+++ b/sway/swaynag.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <signal.h> 1#include <signal.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdlib.h> 3#include <stdlib.h>
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index af925d05..d4003fe6 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdlib.h> 3#include <stdlib.h>
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 30cb97ba..9224b4fb 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -1,9 +1,9 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <drm_fourcc.h> 2#include <drm_fourcc.h>
4#include <stdint.h> 3#include <stdint.h>
5#include <stdlib.h> 4#include <stdlib.h>
6#include <wayland-server-core.h> 5#include <wayland-server-core.h>
6#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
7#include <wlr/types/wlr_linux_dmabuf_v1.h> 7#include <wlr/types/wlr_linux_dmabuf_v1.h>
8#include <wlr/types/wlr_output_layout.h> 8#include <wlr/types/wlr_output_layout.h>
9#include <wlr/types/wlr_subcompositor.h> 9#include <wlr/types/wlr_subcompositor.h>
diff --git a/sway/tree/node.c b/sway/tree/node.c
index 213cf0a6..7aaf9762 100644
--- a/sway/tree/node.c
+++ b/sway/tree/node.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/output.h" 1#include "sway/output.h"
3#include "sway/server.h" 2#include "sway/server.h"
4#include "sway/tree/container.h" 3#include "sway/tree/container.h"
diff --git a/sway/tree/output.c b/sway/tree/output.c
index cd7bf0c2..2d11195e 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <ctype.h> 2#include <ctype.h>
4#include <string.h> 3#include <string.h>
diff --git a/sway/tree/root.c b/sway/tree/root.c
index e9cea5e2..ae3c3cb2 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <stdlib.h> 2#include <stdlib.h>
4#include <string.h> 3#include <string.h>
diff --git a/sway/tree/view.c b/sway/tree/view.c
index d6984178..35b4b73f 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -1,9 +1,10 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <strings.h> 2#include <strings.h>
4#include <wayland-server-core.h> 3#include <wayland-server-core.h>
5#include <wlr/render/wlr_renderer.h> 4#include <wlr/render/wlr_renderer.h>
6#include <wlr/types/wlr_buffer.h> 5#include <wlr/types/wlr_buffer.h>
6#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
7#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
7#include <wlr/types/wlr_output_layout.h> 8#include <wlr/types/wlr_output_layout.h>
8#include <wlr/types/wlr_server_decoration.h> 9#include <wlr/types/wlr_server_decoration.h>
9#include <wlr/types/wlr_subcompositor.h> 10#include <wlr/types/wlr_subcompositor.h>
@@ -410,6 +411,12 @@ void view_request_activate(struct sway_view *view, struct sway_seat *seat) {
410 transaction_commit_dirty(); 411 transaction_commit_dirty();
411} 412}
412 413
414void view_request_urgent(struct sway_view *view) {
415 if (config->focus_on_window_activation != FOWA_NONE) {
416 view_set_urgent(view, true);
417 }
418}
419
413void view_set_csd_from_server(struct sway_view *view, bool enabled) { 420void view_set_csd_from_server(struct sway_view *view, bool enabled) {
414 sway_log(SWAY_DEBUG, "Telling view %p to set CSD to %i", view, enabled); 421 sway_log(SWAY_DEBUG, "Telling view %p to set CSD to %i", view, enabled);
415 if (view->xdg_decoration) { 422 if (view->xdg_decoration) {
@@ -582,6 +589,14 @@ static struct sway_workspace *select_workspace(struct sway_view *view) {
582 return NULL; 589 return NULL;
583} 590}
584 591
592static void update_ext_foreign_toplevel(struct sway_view *view) {
593 struct wlr_ext_foreign_toplevel_handle_v1_state toplevel_state = {
594 .app_id = view_get_app_id(view),
595 .title = view_get_title(view),
596 };
597 wlr_ext_foreign_toplevel_handle_v1_update_state(view->ext_foreign_toplevel, &toplevel_state);
598}
599
585static bool should_focus(struct sway_view *view) { 600static bool should_focus(struct sway_view *view) {
586 struct sway_seat *seat = input_manager_current_seat(); 601 struct sway_seat *seat = input_manager_current_seat();
587 struct sway_container *prev_con = seat_get_focused_container(seat); 602 struct sway_container *prev_con = seat_get_focused_container(seat);
@@ -751,6 +766,13 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
751 } 766 }
752 } 767 }
753 768
769 struct wlr_ext_foreign_toplevel_handle_v1_state foreign_toplevel_state = {
770 .app_id = view_get_app_id(view),
771 .title = view_get_title(view),
772 };
773 view->ext_foreign_toplevel =
774 wlr_ext_foreign_toplevel_handle_v1_create(server.foreign_toplevel_list, &foreign_toplevel_state);
775
754 view->foreign_toplevel = 776 view->foreign_toplevel =
755 wlr_foreign_toplevel_handle_v1_create(server.foreign_toplevel_manager); 777 wlr_foreign_toplevel_handle_v1_create(server.foreign_toplevel_manager);
756 view->foreign_activate_request.notify = handle_foreign_activate_request; 778 view->foreign_activate_request.notify = handle_foreign_activate_request;
@@ -828,6 +850,10 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
828 input_manager_set_focus(&view->container->node); 850 input_manager_set_focus(&view->container->node);
829 } 851 }
830 852
853 if (view->ext_foreign_toplevel) {
854 update_ext_foreign_toplevel(view);
855 }
856
831 const char *app_id; 857 const char *app_id;
832 const char *class; 858 const char *class;
833 if ((app_id = view_get_app_id(view)) != NULL) { 859 if ((app_id = view_get_app_id(view)) != NULL) {
@@ -847,6 +873,11 @@ void view_unmap(struct sway_view *view) {
847 view->urgent_timer = NULL; 873 view->urgent_timer = NULL;
848 } 874 }
849 875
876 if (view->ext_foreign_toplevel) {
877 wlr_ext_foreign_toplevel_handle_v1_destroy(view->ext_foreign_toplevel);
878 view->ext_foreign_toplevel = NULL;
879 }
880
850 if (view->foreign_toplevel) { 881 if (view->foreign_toplevel) {
851 wlr_foreign_toplevel_handle_v1_destroy(view->foreign_toplevel); 882 wlr_foreign_toplevel_handle_v1_destroy(view->foreign_toplevel);
852 view->foreign_toplevel = NULL; 883 view->foreign_toplevel = NULL;
@@ -1014,6 +1045,18 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) {
1014 return len; 1045 return len;
1015} 1046}
1016 1047
1048void view_update_app_id(struct sway_view *view) {
1049 const char *app_id = view_get_app_id(view);
1050
1051 if (view->foreign_toplevel && app_id) {
1052 wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, app_id);
1053 }
1054
1055 if (view->ext_foreign_toplevel) {
1056 update_ext_foreign_toplevel(view);
1057 }
1058}
1059
1017void view_update_title(struct sway_view *view, bool force) { 1060void view_update_title(struct sway_view *view, bool force) {
1018 const char *title = view_get_title(view); 1061 const char *title = view_get_title(view);
1019 1062
@@ -1060,6 +1103,10 @@ void view_update_title(struct sway_view *view, bool force) {
1060 if (view->foreign_toplevel && title) { 1103 if (view->foreign_toplevel && title) {
1061 wlr_foreign_toplevel_handle_v1_set_title(view->foreign_toplevel, title); 1104 wlr_foreign_toplevel_handle_v1_set_title(view->foreign_toplevel, title);
1062 } 1105 }
1106
1107 if (view->ext_foreign_toplevel) {
1108 update_ext_foreign_toplevel(view);
1109 }
1063} 1110}
1064 1111
1065bool view_is_visible(struct sway_view *view) { 1112bool view_is_visible(struct sway_view *view) {
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 40d33435..a68dc927 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809
2#include <ctype.h> 1#include <ctype.h>
3#include <limits.h> 2#include <limits.h>
4#include <stdbool.h> 3#include <stdbool.h>
diff --git a/sway/xdg_activation_v1.c b/sway/xdg_activation_v1.c
index c26ee19a..b7c80dd4 100644
--- a/sway/xdg_activation_v1.c
+++ b/sway/xdg_activation_v1.c
@@ -1,4 +1,5 @@
1#include <wlr/types/wlr_xdg_activation_v1.h> 1#include <wlr/types/wlr_xdg_activation_v1.h>
2#include <wlr/types/wlr_xdg_shell.h>
2#include "sway/desktop/launcher.h" 3#include "sway/desktop/launcher.h"
3#include "sway/tree/view.h" 4#include "sway/tree/view.h"
4#include "sway/tree/workspace.h" 5#include "sway/tree/workspace.h"
@@ -17,11 +18,15 @@ void xdg_activation_v1_handle_request_activate(struct wl_listener *listener,
17 return; 18 return;
18 } 19 }
19 20
21 struct launcher_ctx *ctx = event->token->data;
22 if (ctx == NULL) {
23 return;
24 }
25
20 if (!xdg_surface->surface->mapped) { 26 if (!xdg_surface->surface->mapped) {
21 // This is a startup notification. If we are tracking it, the data 27 // This is a startup notification. If we are tracking it, the data
22 // field is a launcher_ctx. 28 // field is a launcher_ctx.
23 struct launcher_ctx *ctx = event->token->data; 29 if (ctx->activated) {
24 if (!ctx || ctx->activated) {
25 // This ctx has already been activated and cannot be used again 30 // This ctx has already been activated and cannot be used again
26 // for a startup notification. It will be destroyed 31 // for a startup notification. It will be destroyed
27 return; 32 return;
@@ -32,9 +37,19 @@ void xdg_activation_v1_handle_request_activate(struct wl_listener *listener,
32 return; 37 return;
33 } 38 }
34 39
35 struct wlr_seat *wlr_seat = event->token->seat; 40 // This is an activation request. If this context is internal we have ctx->seat.
36 struct sway_seat *seat = wlr_seat ? wlr_seat->data : NULL; 41 struct sway_seat *seat = ctx->seat;
37 view_request_activate(view, seat); 42 if (!seat) {
43 // Otherwise, use the seat indicated by the launcher client in set_serial
44 seat = ctx->token->seat ? ctx->token->seat->data : NULL;
45 }
46
47 if (seat && ctx->had_focused_surface) {
48 view_request_activate(view, seat);
49 } else {
50 // The token is valid, but cannot be used to activate a window
51 view_request_urgent(view);
52 }
38} 53}
39 54
40void xdg_activation_v1_handle_new_token(struct wl_listener *listener, void *data) { 55void xdg_activation_v1_handle_new_token(struct wl_listener *listener, void *data) {
diff --git a/swaybar/bar.c b/swaybar/bar.c
index 021fc3bd..5b1213a8 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <errno.h> 2#include <errno.h>
4#include <fcntl.h> 3#include <fcntl.h>
diff --git a/swaybar/config.c b/swaybar/config.c
index 5e828773..55bfcb72 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <string.h> 2#include <string.h>
4#include "swaybar/config.h" 3#include "swaybar/config.h"
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c
index ccd5a076..62c22d43 100644
--- a/swaybar/i3bar.c
+++ b/swaybar/i3bar.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <json.h> 1#include <json.h>
3#include <linux/input-event-codes.h> 2#include <linux/input-event-codes.h>
4#include <ctype.h> 3#include <ctype.h>
diff --git a/swaybar/ipc.c b/swaybar/ipc.c
index 33ae6544..03500bdf 100644
--- a/swaybar/ipc.c
+++ b/swaybar/ipc.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809
2#include <limits.h> 1#include <limits.h>
3#include <poll.h> 2#include <poll.h>
4#include <stdio.h> 3#include <stdio.h>
diff --git a/swaybar/main.c b/swaybar/main.c
index a44c1e63..3dc67233 100644
--- a/swaybar/main.c
+++ b/swaybar/main.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdio.h> 1#include <stdio.h>
3#include <stdlib.h> 2#include <stdlib.h>
4#include <string.h> 3#include <string.h>
diff --git a/swaybar/render.c b/swaybar/render.c
index 1113ca44..879a4e42 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -1,4 +1,3 @@
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 <limits.h> 3#include <limits.h>
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index 2e9bb7f1..e542e606 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <fcntl.h> 2#include <fcntl.h>
4#include <sys/ioctl.h> 3#include <sys/ioctl.h>
diff --git a/swaybar/tray/host.c b/swaybar/tray/host.c
index eea2caa5..79b54606 100644
--- a/swaybar/tray/host.c
+++ b/swaybar/tray/host.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <stdio.h> 2#include <stdio.h>
4#include <stdlib.h> 3#include <stdlib.h>
diff --git a/swaybar/tray/icon.c b/swaybar/tray/icon.c
index b513dca5..659edd86 100644
--- a/swaybar/tray/icon.c
+++ b/swaybar/tray/icon.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <dirent.h> 2#include <dirent.h>
4#include <stdbool.h> 3#include <stdbool.h>
diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c
index d5fe50b1..ca6c03ad 100644
--- a/swaybar/tray/item.c
+++ b/swaybar/tray/item.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <arpa/inet.h> 1#include <arpa/inet.h>
3#include <cairo.h> 2#include <cairo.h>
4#include <limits.h> 3#include <limits.h>
diff --git a/swaybar/tray/watcher.c b/swaybar/tray/watcher.c
index 2458a8c2..3cfea8d8 100644
--- a/swaybar/tray/watcher.c
+++ b/swaybar/tray/watcher.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <stddef.h> 2#include <stddef.h>
4#include <stdio.h> 3#include <stdio.h>
diff --git a/swaymsg/main.c b/swaymsg/main.c
index db9346c4..573a7b16 100644
--- a/swaymsg/main.c
+++ b/swaymsg/main.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2 1
3#include <limits.h> 2#include <limits.h>
4#include <stdio.h> 3#include <stdio.h>
diff --git a/swaynag/config.c b/swaynag/config.c
index cff3930f..efd71ce7 100644
--- a/swaynag/config.c
+++ b/swaynag/config.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <getopt.h> 1#include <getopt.h>
3#include <stdio.h> 2#include <stdio.h>
4#include <stdlib.h> 3#include <stdlib.h>
diff --git a/swaynag/main.c b/swaynag/main.c
index 20390207..634bddbf 100644
--- a/swaynag/main.c
+++ b/swaynag/main.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <signal.h> 2#include <signal.h>
4#include "log.h" 3#include "log.h"
diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c
index 6ea739e3..50eea148 100644
--- a/swaynag/swaynag.c
+++ b/swaynag/swaynag.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <assert.h> 2#include <assert.h>
4#include <sys/stat.h> 3#include <sys/stat.h>
diff --git a/swaynag/types.c b/swaynag/types.c
index 409cc668..821e5b21 100644
--- a/swaynag/types.c
+++ b/swaynag/types.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <getopt.h> 1#include <getopt.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdlib.h> 3#include <stdlib.h>