diff options
127 files changed, 1327 insertions, 646 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/config.h b/include/sway/config.h index f9da1967..5ccc3e77 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -292,6 +292,14 @@ struct output_config { | |||
292 | }; | 292 | }; |
293 | 293 | ||
294 | /** | 294 | /** |
295 | * An output config pre-matched to an output | ||
296 | */ | ||
297 | struct matched_output_config { | ||
298 | struct sway_output *output; | ||
299 | struct output_config *config; | ||
300 | }; | ||
301 | |||
302 | /** | ||
295 | * Stores size of gaps for each side | 303 | * Stores size of gaps for each side |
296 | */ | 304 | */ |
297 | struct side_gaps { | 305 | struct side_gaps { |
@@ -680,20 +688,25 @@ const char *sway_output_scale_filter_to_string(enum scale_filter_mode scale_filt | |||
680 | 688 | ||
681 | struct output_config *new_output_config(const char *name); | 689 | struct output_config *new_output_config(const char *name); |
682 | 690 | ||
683 | void merge_output_config(struct output_config *dst, struct output_config *src); | 691 | bool apply_output_configs(struct matched_output_config *configs, |
692 | size_t configs_len, bool test_only, bool degrade_to_off); | ||
684 | 693 | ||
685 | bool apply_output_config(struct output_config *oc, struct sway_output *output); | 694 | void apply_all_output_configs(void); |
686 | 695 | ||
687 | bool test_output_config(struct output_config *oc, struct sway_output *output); | 696 | void sort_output_configs_by_priority(struct matched_output_config *configs, |
697 | size_t configs_len); | ||
688 | 698 | ||
689 | struct output_config *store_output_config(struct output_config *oc); | 699 | /** |
700 | * store_output_config stores a new output config. An output may be matched by | ||
701 | * three different config types, in order of precedence: Identifier, name and | ||
702 | * wildcard. When storing a config type of lower precedence, assume that the | ||
703 | * user wants the config to take immediate effect by superseding (clearing) the | ||
704 | * same values from higher presedence configuration. | ||
705 | */ | ||
706 | void store_output_config(struct output_config *oc); | ||
690 | 707 | ||
691 | struct output_config *find_output_config(struct sway_output *output); | 708 | struct output_config *find_output_config(struct sway_output *output); |
692 | 709 | ||
693 | void apply_output_config_to_outputs(struct output_config *oc); | ||
694 | |||
695 | void reset_outputs(void); | ||
696 | |||
697 | void free_output_config(struct output_config *oc); | 710 | void free_output_config(struct output_config *oc); |
698 | 711 | ||
699 | bool spawn_swaybg(void); | 712 | bool spawn_swaybg(void); |
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 | ||
7 | struct launcher_ctx { | 8 | struct 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, | |||
58 | bool transaction_notify_view_ready_by_geometry(struct sway_view *view, | 59 | bool 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 | ||
62 | void 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 | ||
115 | void dispatch_cursor_button(struct sway_cursor *cursor, | 115 | void 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 | ||
119 | void dispatch_cursor_axis(struct sway_cursor *cursor, | 119 | void 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 | ||
36 | struct sway_input_manager *input_manager_create(struct sway_server *server); | 39 | struct 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; | |||
17 | struct sway_seatop_impl { | 17 | struct 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 | ||
288 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, | 289 | void 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 | ||
291 | void seat_consider_warp_to_focus(struct sway_seat *seat); | 292 | void seat_consider_warp_to_focus(struct sway_seat *seat); |
292 | 293 | ||
293 | void seatop_button(struct sway_seat *seat, uint32_t time_msec, | 294 | void 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 | ||
297 | void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec); | 298 | void 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 | |||
36 | struct sway_text_input { | 39 | struct 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 | |||
6 | struct 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 | ||
7 | struct sway_layer_surface { | 8 | struct 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 | ||
179 | struct sway_popup_desc { | ||
180 | struct wlr_scene_node *relative; | ||
181 | struct sway_view *view; | ||
182 | }; | ||
183 | |||
177 | struct sway_xdg_popup { | 184 | struct 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 | */ |
234 | void view_request_activate(struct sway_view *view, struct sway_seat *seat); | 244 | void view_request_activate(struct sway_view *view, struct sway_seat *seat); |
235 | 245 | ||
246 | /* | ||
247 | * Called when the view requests urgent state | ||
248 | */ | ||
249 | void 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 |
285 | struct sway_view *view_from_wlr_surface(struct wlr_surface *surface); | 300 | struct sway_view *view_from_wlr_surface(struct wlr_surface *surface); |
286 | 301 | ||
302 | void 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( | |||
14 | add_project_arguments( | 14 | add_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 | |||
3 | prev=$(git describe --tags --abbrev=0) | ||
4 | next=$(meson rewrite kwargs info project / 2>&1 >/dev/null | jq -r '.kwargs["project#/"].version') | ||
5 | |||
6 | case "$next" in | ||
7 | *-dev) | ||
8 | echo "This is a development version" | ||
9 | exit 1 | ||
10 | ;; | ||
11 | esac | ||
12 | |||
13 | if [ "$prev" = "$next" ]; then | ||
14 | echo "Version not bumped in meson.build" | ||
15 | exit 1 | ||
16 | fi | ||
17 | |||
18 | if ! git diff-index --quiet HEAD -- meson.build; then | ||
19 | echo "meson.build not committed" | ||
20 | exit 1 | ||
21 | fi | ||
22 | |||
23 | shortlog="$(git shortlog --no-merges "$prev..")" | ||
24 | (echo "sway $next"; echo ""; echo "$shortlog") | git tag "$next" -ase -F - | ||
25 | |||
26 | prefix=sway-$next | ||
27 | archive=$prefix.tar.gz | ||
28 | git archive --prefix="$prefix/" -o "$archive" "$next" | ||
29 | gpg --output "$archive".sig --detach-sig "$archive" | ||
30 | |||
31 | gh 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[] = { | |||
105 | static const struct cmd_handler config_handlers[] = { | 103 | static 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..5e5d31b3 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c | |||
@@ -103,15 +103,18 @@ struct cmd_results *cmd_output(int argc, char **argv) { | |||
103 | 103 | ||
104 | bool background = output->background; | 104 | bool background = output->background; |
105 | 105 | ||
106 | output = store_output_config(output); | 106 | store_output_config(output); |
107 | 107 | ||
108 | // If reloading, the output configs will be applied after reading the | 108 | // If reloading, the output configs will be applied after reading the |
109 | // entire config and before the deferred commands so that an auto generated | 109 | // entire config and before the deferred commands so that an auto generated |
110 | // workspace name is not given to re-enabled outputs. | 110 | // workspace name is not given to re-enabled outputs. |
111 | if (!config->reloading && !config->validating) { | 111 | if (!config->reloading && !config->validating) { |
112 | apply_output_config_to_outputs(output); | 112 | apply_all_output_configs(); |
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/output/toggle.c b/sway/commands/output/toggle.c index 6342d526..c6b72845 100644 --- a/sway/commands/output/toggle.c +++ b/sway/commands/output/toggle.c | |||
@@ -29,7 +29,7 @@ struct cmd_results *output_cmd_toggle(int argc, char **argv) { | |||
29 | config->handler_context.output_config->enabled = 1; | 29 | config->handler_context.output_config->enabled = 1; |
30 | } | 30 | } |
31 | 31 | ||
32 | free(oc); | 32 | free_output_config(oc); |
33 | config->handler_context.leftovers.argc = argc; | 33 | config->handler_context.leftovers.argc = argc; |
34 | config->handler_context.leftovers.argv = argv; | 34 | config->handler_context.leftovers.argv = argv; |
35 | return NULL; | 35 | return NULL; |
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 | ||
86 | static struct cmd_results *press_or_release(struct sway_cursor *cursor, | 85 | static 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..f9131e0f 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 @@ | |||
36 | struct sway_config *config = NULL; | 37 | struct sway_config *config = NULL; |
37 | 38 | ||
38 | static struct xkb_state *keysym_translation_state_create( | 39 | static 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 | ||
50 | static void keysym_translation_state_destroy( | 55 | static 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; |
343 | cleanup: | 357 | cleanup: |
@@ -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 | ||
364 | static char *get_config_path(void) { | 372 | static 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); |
@@ -571,7 +532,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) { | |||
571 | } | 532 | } |
572 | sway_switch_retrigger_bindings_for_all(); | 533 | sway_switch_retrigger_bindings_for_all(); |
573 | 534 | ||
574 | reset_outputs(); | 535 | apply_all_output_configs(); |
575 | spawn_swaybg(); | 536 | spawn_swaybg(); |
576 | 537 | ||
577 | config->reloading = false; | 538 | config->reloading = false; |
@@ -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..fb1956df 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> |
@@ -10,6 +9,7 @@ | |||
10 | #include <wlr/types/wlr_cursor.h> | 9 | #include <wlr/types/wlr_cursor.h> |
11 | #include <wlr/types/wlr_output_layout.h> | 10 | #include <wlr/types/wlr_output_layout.h> |
12 | #include <wlr/types/wlr_output.h> | 11 | #include <wlr/types/wlr_output.h> |
12 | #include <wlr/types/wlr_output_swapchain_manager.h> | ||
13 | #include "sway/config.h" | 13 | #include "sway/config.h" |
14 | #include "sway/input/cursor.h" | 14 | #include "sway/input/cursor.h" |
15 | #include "sway/output.h" | 15 | #include "sway/output.h" |
@@ -79,7 +79,72 @@ struct output_config *new_output_config(const char *name) { | |||
79 | return oc; | 79 | return oc; |
80 | } | 80 | } |
81 | 81 | ||
82 | void merge_output_config(struct output_config *dst, struct output_config *src) { | 82 | // supersede_output_config clears all fields in dst that were set in src |
83 | static void supersede_output_config(struct output_config *dst, struct output_config *src) { | ||
84 | if (src->enabled != -1) { | ||
85 | dst->enabled = -1; | ||
86 | } | ||
87 | if (src->width != -1) { | ||
88 | dst->width = -1; | ||
89 | } | ||
90 | if (src->height != -1) { | ||
91 | dst->height = -1; | ||
92 | } | ||
93 | if (src->x != -1) { | ||
94 | dst->x = -1; | ||
95 | } | ||
96 | if (src->y != -1) { | ||
97 | dst->y = -1; | ||
98 | } | ||
99 | if (src->scale != -1) { | ||
100 | dst->scale = -1; | ||
101 | } | ||
102 | if (src->scale_filter != SCALE_FILTER_DEFAULT) { | ||
103 | dst->scale_filter = SCALE_FILTER_DEFAULT; | ||
104 | } | ||
105 | if (src->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) { | ||
106 | dst->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; | ||
107 | } | ||
108 | if (src->refresh_rate != -1) { | ||
109 | dst->refresh_rate = -1; | ||
110 | } | ||
111 | if (src->custom_mode != -1) { | ||
112 | dst->custom_mode = -1; | ||
113 | } | ||
114 | if (src->drm_mode.type != (uint32_t) -1) { | ||
115 | dst->drm_mode.type = -1; | ||
116 | } | ||
117 | if (src->transform != -1) { | ||
118 | dst->transform = -1; | ||
119 | } | ||
120 | if (src->max_render_time != -1) { | ||
121 | dst->max_render_time = -1; | ||
122 | } | ||
123 | if (src->adaptive_sync != -1) { | ||
124 | dst->adaptive_sync = -1; | ||
125 | } | ||
126 | if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { | ||
127 | dst->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT; | ||
128 | } | ||
129 | if (src->background) { | ||
130 | free(dst->background); | ||
131 | dst->background = NULL; | ||
132 | } | ||
133 | if (src->background_option) { | ||
134 | free(dst->background_option); | ||
135 | dst->background_option = NULL; | ||
136 | } | ||
137 | if (src->background_fallback) { | ||
138 | free(dst->background_fallback); | ||
139 | dst->background_fallback = NULL; | ||
140 | } | ||
141 | if (src->power != -1) { | ||
142 | dst->power = -1; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | // merge_output_config sets all fields in dst that were set in src | ||
147 | static void merge_output_config(struct output_config *dst, struct output_config *src) { | ||
83 | if (src->enabled != -1) { | 148 | if (src->enabled != -1) { |
84 | dst->enabled = src->enabled; | 149 | dst->enabled = src->enabled; |
85 | } | 150 | } |
@@ -142,94 +207,42 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { | |||
142 | } | 207 | } |
143 | } | 208 | } |
144 | 209 | ||
145 | static void merge_wildcard_on_all(struct output_config *wildcard) { | 210 | void store_output_config(struct output_config *oc) { |
146 | for (int i = 0; i < config->output_configs->length; i++) { | 211 | bool merged = false; |
147 | struct output_config *oc = config->output_configs->items[i]; | 212 | bool wildcard = strcmp(oc->name, "*") == 0; |
148 | if (strcmp(wildcard->name, oc->name) != 0) { | 213 | struct sway_output *output = wildcard ? NULL : all_output_by_name_or_id(oc->name); |
149 | sway_log(SWAY_DEBUG, "Merging output * config on %s", oc->name); | ||
150 | merge_output_config(oc, wildcard); | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static void merge_id_on_name(struct output_config *oc) { | ||
156 | struct sway_output *output = all_output_by_name_or_id(oc->name); | ||
157 | if (output == NULL) { | ||
158 | return; | ||
159 | } | ||
160 | 214 | ||
161 | const char *name = output->wlr_output->name; | ||
162 | char id[128]; | 215 | char id[128]; |
163 | output_get_identifier(id, sizeof(id), output); | 216 | if (output) { |
164 | 217 | output_get_identifier(id, sizeof(id), output); | |
165 | char *id_on_name = format_str("%s on %s", id, name); | ||
166 | if (!id_on_name) { | ||
167 | return; | ||
168 | } | 218 | } |
169 | 219 | ||
170 | int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name); | 220 | for (int i = 0; i < config->output_configs->length; i++) { |
171 | if (i >= 0) { | 221 | struct output_config *old = config->output_configs->items[i]; |
172 | sway_log(SWAY_DEBUG, "Merging on top of existing id on name config"); | 222 | |
173 | merge_output_config(config->output_configs->items[i], oc); | 223 | // If the old config matches the new config's name, regardless of |
174 | } else { | 224 | // whether it was name or identifier, merge on top of the existing |
175 | // If both a name and identifier config, exist generate an id on name | 225 | // config. If the new config is a wildcard, this also merges on top of |
176 | int ni = list_seq_find(config->output_configs, output_name_cmp, name); | 226 | // old wildcard configs. |
177 | int ii = list_seq_find(config->output_configs, output_name_cmp, id); | 227 | if (strcmp(old->name, oc->name) == 0) { |
178 | if ((ni >= 0 && ii >= 0) || (ni >= 0 && strcmp(oc->name, id) == 0) | 228 | merge_output_config(old, oc); |
179 | || (ii >= 0 && strcmp(oc->name, name) == 0)) { | 229 | merged = true; |
180 | struct output_config *ion_oc = new_output_config(id_on_name); | 230 | continue; |
181 | if (ni >= 0) { | ||
182 | merge_output_config(ion_oc, config->output_configs->items[ni]); | ||
183 | } | ||
184 | if (ii >= 0) { | ||
185 | merge_output_config(ion_oc, config->output_configs->items[ii]); | ||
186 | } | ||
187 | merge_output_config(ion_oc, oc); | ||
188 | list_add(config->output_configs, ion_oc); | ||
189 | sway_log(SWAY_DEBUG, "Generated id on name output config \"%s\"" | ||
190 | " (enabled: %d) (%dx%d@%fHz position %d,%d scale %f " | ||
191 | "transform %d) (bg %s %s) (power %d) (max render time: %d)", | ||
192 | ion_oc->name, ion_oc->enabled, ion_oc->width, ion_oc->height, | ||
193 | ion_oc->refresh_rate, ion_oc->x, ion_oc->y, ion_oc->scale, | ||
194 | ion_oc->transform, ion_oc->background, | ||
195 | ion_oc->background_option, ion_oc->power, | ||
196 | ion_oc->max_render_time); | ||
197 | } | 231 | } |
198 | } | ||
199 | free(id_on_name); | ||
200 | } | ||
201 | 232 | ||
202 | struct output_config *store_output_config(struct output_config *oc) { | 233 | // If the new config is a wildcard config we supersede all non-wildcard |
203 | bool wildcard = strcmp(oc->name, "*") == 0; | 234 | // configs. Old wildcard configs have already been handled above. |
204 | if (wildcard) { | 235 | if (wildcard) { |
205 | merge_wildcard_on_all(oc); | 236 | supersede_output_config(old, oc); |
206 | } else { | 237 | continue; |
207 | merge_id_on_name(oc); | 238 | } |
208 | } | ||
209 | 239 | ||
210 | int i = list_seq_find(config->output_configs, output_name_cmp, oc->name); | 240 | // If the new config matches an output's name, and the old config |
211 | if (i >= 0) { | 241 | // matches on that output's identifier, supersede it. |
212 | sway_log(SWAY_DEBUG, "Merging on top of existing output config"); | 242 | if (output && strcmp(old->name, id) == 0 && |
213 | struct output_config *current = config->output_configs->items[i]; | 243 | strcmp(oc->name, output->wlr_output->name) == 0) { |
214 | merge_output_config(current, oc); | 244 | supersede_output_config(old, oc); |
215 | free_output_config(oc); | ||
216 | oc = current; | ||
217 | } else if (!wildcard) { | ||
218 | sway_log(SWAY_DEBUG, "Adding non-wildcard output config"); | ||
219 | i = list_seq_find(config->output_configs, output_name_cmp, "*"); | ||
220 | if (i >= 0) { | ||
221 | sway_log(SWAY_DEBUG, "Merging on top of output * config"); | ||
222 | struct output_config *current = new_output_config(oc->name); | ||
223 | merge_output_config(current, config->output_configs->items[i]); | ||
224 | merge_output_config(current, oc); | ||
225 | free_output_config(oc); | ||
226 | oc = current; | ||
227 | } | 245 | } |
228 | list_add(config->output_configs, oc); | ||
229 | } else { | ||
230 | // New wildcard config. Just add it | ||
231 | sway_log(SWAY_DEBUG, "Adding output * config"); | ||
232 | list_add(config->output_configs, oc); | ||
233 | } | 246 | } |
234 | 247 | ||
235 | sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " | 248 | sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " |
@@ -240,7 +253,13 @@ struct output_config *store_output_config(struct output_config *oc) { | |||
240 | oc->transform, oc->background, oc->background_option, oc->power, | 253 | oc->transform, oc->background, oc->background_option, oc->power, |
241 | oc->max_render_time); | 254 | oc->max_render_time); |
242 | 255 | ||
243 | return oc; | 256 | // If the configuration was not merged into an existing configuration, add |
257 | // it to the list. Otherwise we're done with it and can free it. | ||
258 | if (!merged) { | ||
259 | list_add(config->output_configs, oc); | ||
260 | } else { | ||
261 | free_output_config(oc); | ||
262 | } | ||
244 | } | 263 | } |
245 | 264 | ||
246 | static void set_mode(struct wlr_output *output, struct wlr_output_state *pending, | 265 | static void set_mode(struct wlr_output *output, struct wlr_output_state *pending, |
@@ -367,22 +386,18 @@ static int compute_default_scale(struct wlr_output *output, | |||
367 | return 2; | 386 | return 2; |
368 | } | 387 | } |
369 | 388 | ||
370 | /* Lists of formats to try, in order, when a specific render bit depth has | 389 | static bool render_format_is_10bit(uint32_t render_format) { |
371 | * been asked for. The second to last format in each list should always | 390 | return render_format == DRM_FORMAT_XRGB2101010 || |
372 | * be XRGB8888, as a reliable backup in case the others are not available; | 391 | render_format == DRM_FORMAT_XBGR2101010; |
373 | * the last should be DRM_FORMAT_INVALID, to indicate the end of the list. */ | 392 | } |
374 | static const uint32_t *bit_depth_preferences[] = { | 393 | |
375 | [RENDER_BIT_DEPTH_8] = (const uint32_t []){ | 394 | static bool render_format_is_bgr(uint32_t fmt) { |
376 | DRM_FORMAT_XRGB8888, | 395 | return fmt == DRM_FORMAT_XBGR2101010 || fmt == DRM_FORMAT_XBGR8888; |
377 | DRM_FORMAT_INVALID, | 396 | } |
378 | }, | 397 | |
379 | [RENDER_BIT_DEPTH_10] = (const uint32_t []){ | 398 | static bool output_config_is_disabling(struct output_config *oc) { |
380 | DRM_FORMAT_XRGB2101010, | 399 | return oc && (!oc->enabled || oc->power == 0); |
381 | DRM_FORMAT_XBGR2101010, | 400 | } |
382 | DRM_FORMAT_XRGB8888, | ||
383 | DRM_FORMAT_INVALID, | ||
384 | }, | ||
385 | }; | ||
386 | 401 | ||
387 | static void queue_output_config(struct output_config *oc, | 402 | static void queue_output_config(struct output_config *oc, |
388 | struct sway_output *output, struct wlr_output_state *pending) { | 403 | struct sway_output *output, struct wlr_output_state *pending) { |
@@ -392,7 +407,7 @@ static void queue_output_config(struct output_config *oc, | |||
392 | 407 | ||
393 | struct wlr_output *wlr_output = output->wlr_output; | 408 | struct wlr_output *wlr_output = output->wlr_output; |
394 | 409 | ||
395 | if (oc && (!oc->enabled || oc->power == 0)) { | 410 | if (output_config_is_disabling(oc)) { |
396 | sway_log(SWAY_DEBUG, "Turning off output %s", wlr_output->name); | 411 | sway_log(SWAY_DEBUG, "Turning off output %s", wlr_output->name); |
397 | wlr_output_state_set_enabled(pending, false); | 412 | wlr_output_state_set_enabled(pending, false); |
398 | return; | 413 | return; |
@@ -415,22 +430,6 @@ static void queue_output_config(struct output_config *oc, | |||
415 | struct wlr_output_mode *preferred_mode = | 430 | struct wlr_output_mode *preferred_mode = |
416 | wlr_output_preferred_mode(wlr_output); | 431 | wlr_output_preferred_mode(wlr_output); |
417 | wlr_output_state_set_mode(pending, preferred_mode); | 432 | wlr_output_state_set_mode(pending, preferred_mode); |
418 | |||
419 | if (!wlr_output_test_state(wlr_output, pending)) { | ||
420 | sway_log(SWAY_DEBUG, "Preferred mode rejected, " | ||
421 | "falling back to another mode"); | ||
422 | struct wlr_output_mode *mode; | ||
423 | wl_list_for_each(mode, &wlr_output->modes, link) { | ||
424 | if (mode == preferred_mode) { | ||
425 | continue; | ||
426 | } | ||
427 | |||
428 | wlr_output_state_set_mode(pending, mode); | ||
429 | if (wlr_output_test_state(wlr_output, pending)) { | ||
430 | break; | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | } | 433 | } |
435 | 434 | ||
436 | if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { | 435 | if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { |
@@ -481,54 +480,27 @@ static void queue_output_config(struct output_config *oc, | |||
481 | sway_log(SWAY_DEBUG, "Set %s adaptive sync to %d", wlr_output->name, | 480 | sway_log(SWAY_DEBUG, "Set %s adaptive sync to %d", wlr_output->name, |
482 | oc->adaptive_sync); | 481 | oc->adaptive_sync); |
483 | wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1); | 482 | wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1); |
484 | if (oc->adaptive_sync == 1 && !wlr_output_test_state(wlr_output, pending)) { | ||
485 | sway_log(SWAY_DEBUG, "Adaptive sync failed, ignoring"); | ||
486 | wlr_output_state_set_adaptive_sync_enabled(pending, false); | ||
487 | } | ||
488 | } | 483 | } |
489 | 484 | ||
490 | if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { | 485 | if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { |
491 | const uint32_t *fmts = bit_depth_preferences[oc->render_bit_depth]; | 486 | if (oc->render_bit_depth == RENDER_BIT_DEPTH_10 && |
492 | assert(fmts); | 487 | render_format_is_10bit(output->wlr_output->render_format)) { |
493 | 488 | // 10-bit was set successfully before, try to save some tests by reusing the format | |
494 | for (size_t i = 0; fmts[i] != DRM_FORMAT_INVALID; i++) { | 489 | wlr_output_state_set_render_format(pending, output->wlr_output->render_format); |
495 | wlr_output_state_set_render_format(pending, fmts[i]); | 490 | } else if (oc->render_bit_depth == RENDER_BIT_DEPTH_10) { |
496 | if (wlr_output_test_state(wlr_output, pending)) { | 491 | wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB2101010); |
497 | break; | 492 | } else { |
498 | } | 493 | wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB8888); |
499 | |||
500 | sway_log(SWAY_DEBUG, "Preferred output format 0x%08x " | ||
501 | "failed to work, falling back to next in " | ||
502 | "list, 0x%08x", fmts[i], fmts[i + 1]); | ||
503 | } | 494 | } |
504 | } | 495 | } |
505 | } | 496 | } |
506 | 497 | ||
507 | bool apply_output_config(struct output_config *oc, struct sway_output *output) { | 498 | static bool finalize_output_config(struct output_config *oc, struct sway_output *output) { |
508 | if (output == root->fallback_output) { | 499 | if (output == root->fallback_output) { |
509 | return false; | 500 | return false; |
510 | } | 501 | } |
511 | 502 | ||
512 | struct wlr_output *wlr_output = output->wlr_output; | 503 | struct wlr_output *wlr_output = output->wlr_output; |
513 | |||
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}; | ||
518 | queue_output_config(oc, output, &pending); | ||
519 | |||
520 | sway_log(SWAY_DEBUG, "Committing output %s", wlr_output->name); | ||
521 | if (!wlr_output_commit_state(wlr_output, &pending)) { | ||
522 | // Failed to commit output changes, maybe the output is missing a CRTC. | ||
523 | // Leave the output disabled for now and try again when the output gets | ||
524 | // the mode we asked for. | ||
525 | sway_log(SWAY_ERROR, "Failed to commit output %s", wlr_output->name); | ||
526 | output->enabling = false; | ||
527 | return false; | ||
528 | } | ||
529 | |||
530 | output->enabling = false; | ||
531 | |||
532 | if (oc && !oc->enabled) { | 504 | if (oc && !oc->enabled) { |
533 | sway_log(SWAY_DEBUG, "Disabling output %s", oc->name); | 505 | sway_log(SWAY_DEBUG, "Disabling output %s", oc->name); |
534 | if (output->enabled) { | 506 | if (output->enabled) { |
@@ -584,25 +556,9 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { | |||
584 | output->max_render_time = oc->max_render_time; | 556 | output->max_render_time = oc->max_render_time; |
585 | } | 557 | } |
586 | 558 | ||
587 | // Reconfigure all devices, since input config may have been applied before | ||
588 | // this output came online, and some config items (like map_to_output) are | ||
589 | // dependent on an output being present. | ||
590 | input_manager_configure_all_input_mappings(); | ||
591 | // Reconfigure the cursor images, since the scale may have changed. | ||
592 | input_manager_configure_xcursor(); | ||
593 | return true; | 559 | return true; |
594 | } | 560 | } |
595 | 561 | ||
596 | bool test_output_config(struct output_config *oc, struct sway_output *output) { | ||
597 | if (output == root->fallback_output) { | ||
598 | return false; | ||
599 | } | ||
600 | |||
601 | struct wlr_output_state pending = {0}; | ||
602 | queue_output_config(oc, output, &pending); | ||
603 | return wlr_output_test_state(output->wlr_output, &pending); | ||
604 | } | ||
605 | |||
606 | static void default_output_config(struct output_config *oc, | 562 | static void default_output_config(struct output_config *oc, |
607 | struct wlr_output *wlr_output) { | 563 | struct wlr_output *wlr_output) { |
608 | oc->enabled = 1; | 564 | oc->enabled = 1; |
@@ -622,140 +578,415 @@ static void default_output_config(struct output_config *oc, | |||
622 | oc->max_render_time = 0; | 578 | oc->max_render_time = 0; |
623 | } | 579 | } |
624 | 580 | ||
625 | static struct output_config *get_output_config(char *identifier, | 581 | // find_output_config returns a merged output_config containing all stored |
626 | struct sway_output *sway_output) { | 582 | // configuration that applies to the specified output. |
583 | struct output_config *find_output_config(struct sway_output *sway_output) { | ||
627 | const char *name = sway_output->wlr_output->name; | 584 | const char *name = sway_output->wlr_output->name; |
585 | struct output_config *oc = NULL; | ||
628 | 586 | ||
629 | struct output_config *oc_id_on_name = NULL; | 587 | struct output_config *result = new_output_config(name); |
630 | struct output_config *oc_name = NULL; | 588 | if (config->reloading) { |
631 | struct output_config *oc_id = NULL; | 589 | default_output_config(result, sway_output->wlr_output); |
590 | } | ||
632 | 591 | ||
633 | char *id_on_name = format_str("%s on %s", identifier, name); | 592 | char id[128]; |
634 | int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name); | 593 | output_get_identifier(id, sizeof(id), sway_output); |
635 | if (i >= 0) { | 594 | |
636 | oc_id_on_name = config->output_configs->items[i]; | 595 | int i; |
637 | } else { | 596 | bool match = false; |
638 | i = list_seq_find(config->output_configs, output_name_cmp, name); | 597 | if ((i = list_seq_find(config->output_configs, output_name_cmp, "*")) >= 0) { |
639 | if (i >= 0) { | 598 | match = true; |
640 | oc_name = config->output_configs->items[i]; | 599 | oc = config->output_configs->items[i]; |
600 | merge_output_config(result, oc); | ||
601 | } | ||
602 | if ((i = list_seq_find(config->output_configs, output_name_cmp, name)) >= 0) { | ||
603 | match = true; | ||
604 | oc = config->output_configs->items[i]; | ||
605 | merge_output_config(result, oc); | ||
606 | } | ||
607 | if ((i = list_seq_find(config->output_configs, output_name_cmp, id)) >= 0) { | ||
608 | match = true; | ||
609 | oc = config->output_configs->items[i]; | ||
610 | merge_output_config(result, oc); | ||
611 | } | ||
612 | |||
613 | if (!match && !config->reloading) { | ||
614 | // No name, identifier, or wildcard config. Since we are not | ||
615 | // reloading with defaults, the output config will be empty, so | ||
616 | // just return NULL | ||
617 | free_output_config(result); | ||
618 | return NULL; | ||
619 | } | ||
620 | |||
621 | return result; | ||
622 | } | ||
623 | |||
624 | static bool config_has_auto_mode(struct output_config *oc) { | ||
625 | if (!oc) { | ||
626 | return true; | ||
627 | } | ||
628 | if (oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t)-1) { | ||
629 | return true; | ||
630 | } else if (oc->width > 0 && oc->height > 0) { | ||
631 | return true; | ||
632 | } | ||
633 | return false; | ||
634 | } | ||
635 | |||
636 | struct search_context { | ||
637 | struct wlr_output_swapchain_manager *swapchain_mgr; | ||
638 | struct wlr_backend_output_state *states; | ||
639 | struct matched_output_config *configs; | ||
640 | size_t configs_len; | ||
641 | bool degrade_to_off; | ||
642 | }; | ||
643 | |||
644 | static void dump_output_state(struct wlr_output *wlr_output, struct wlr_output_state *state) { | ||
645 | sway_log(SWAY_DEBUG, "Output state for %s", wlr_output->name); | ||
646 | if (state->committed & WLR_OUTPUT_STATE_ENABLED) { | ||
647 | sway_log(SWAY_DEBUG, " enabled: %s", state->enabled ? "yes" : "no"); | ||
648 | } | ||
649 | if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { | ||
650 | sway_log(SWAY_DEBUG, " render_format: %d", state->render_format); | ||
651 | } | ||
652 | if (state->committed & WLR_OUTPUT_STATE_MODE) { | ||
653 | if (state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM) { | ||
654 | sway_log(SWAY_DEBUG, " custom mode: %dx%d@%dmHz", | ||
655 | state->custom_mode.width, state->custom_mode.height, state->custom_mode.refresh); | ||
656 | } else { | ||
657 | sway_log(SWAY_DEBUG, " mode: %dx%d@%dmHz%s", | ||
658 | state->mode->width, state->mode->height, state->mode->refresh, | ||
659 | state->mode->preferred ? " (preferred)" : ""); | ||
660 | } | ||
661 | } | ||
662 | if (state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { | ||
663 | sway_log(SWAY_DEBUG, " adaptive_sync: %s", | ||
664 | state->adaptive_sync_enabled ? "enabled": "disabled"); | ||
665 | } | ||
666 | } | ||
667 | |||
668 | static bool search_valid_config(struct search_context *ctx, size_t output_idx); | ||
669 | |||
670 | static void reset_output_state(struct wlr_output_state *state) { | ||
671 | wlr_output_state_finish(state); | ||
672 | wlr_output_state_init(state); | ||
673 | state->committed = 0; | ||
674 | } | ||
675 | |||
676 | static void clear_later_output_states(struct wlr_backend_output_state *states, | ||
677 | size_t configs_len, size_t output_idx) { | ||
678 | |||
679 | // Clear and disable all output states after this one to avoid conflict | ||
680 | // with previous tests. | ||
681 | for (size_t idx = output_idx+1; idx < configs_len; idx++) { | ||
682 | struct wlr_backend_output_state *backend_state = &states[idx]; | ||
683 | struct wlr_output_state *state = &backend_state->base; | ||
684 | |||
685 | reset_output_state(state); | ||
686 | wlr_output_state_set_enabled(state, false); | ||
687 | } | ||
688 | } | ||
689 | |||
690 | static bool search_finish(struct search_context *ctx, size_t output_idx) { | ||
691 | struct wlr_backend_output_state *backend_state = &ctx->states[output_idx]; | ||
692 | struct wlr_output_state *state = &backend_state->base; | ||
693 | struct wlr_output *wlr_output = backend_state->output; | ||
694 | |||
695 | clear_later_output_states(ctx->states, ctx->configs_len, output_idx); | ||
696 | dump_output_state(wlr_output, state); | ||
697 | return wlr_output_swapchain_manager_prepare(ctx->swapchain_mgr, ctx->states, ctx->configs_len) && | ||
698 | search_valid_config(ctx, output_idx+1); | ||
699 | } | ||
700 | |||
701 | static bool search_adaptive_sync(struct search_context *ctx, size_t output_idx) { | ||
702 | struct matched_output_config *cfg = &ctx->configs[output_idx]; | ||
703 | struct wlr_backend_output_state *backend_state = &ctx->states[output_idx]; | ||
704 | struct wlr_output_state *state = &backend_state->base; | ||
705 | |||
706 | if (cfg->config && cfg->config->adaptive_sync == 1) { | ||
707 | wlr_output_state_set_adaptive_sync_enabled(state, true); | ||
708 | if (search_finish(ctx, output_idx)) { | ||
709 | return true; | ||
710 | } | ||
711 | } | ||
712 | if (!cfg->config || cfg->config->adaptive_sync != -1) { | ||
713 | wlr_output_state_set_adaptive_sync_enabled(state, false); | ||
714 | if (search_finish(ctx, output_idx)) { | ||
715 | return true; | ||
641 | } | 716 | } |
717 | } | ||
718 | // If adaptive sync has not been set, or fallback in case we are on a | ||
719 | // backend that cannot disable adaptive sync such as the wayland backend. | ||
720 | state->committed &= ~WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED; | ||
721 | return search_finish(ctx, output_idx); | ||
722 | } | ||
723 | |||
724 | static bool search_mode(struct search_context *ctx, size_t output_idx) { | ||
725 | struct matched_output_config *cfg = &ctx->configs[output_idx]; | ||
726 | struct wlr_backend_output_state *backend_state = &ctx->states[output_idx]; | ||
727 | struct wlr_output_state *state = &backend_state->base; | ||
728 | struct wlr_output *wlr_output = backend_state->output; | ||
729 | |||
730 | if (!config_has_auto_mode(cfg->config)) { | ||
731 | return search_adaptive_sync(ctx, output_idx); | ||
732 | } | ||
642 | 733 | ||
643 | i = list_seq_find(config->output_configs, output_name_cmp, identifier); | 734 | struct wlr_output_mode *preferred_mode = wlr_output_preferred_mode(wlr_output); |
644 | if (i >= 0) { | 735 | if (preferred_mode) { |
645 | oc_id = config->output_configs->items[i]; | 736 | wlr_output_state_set_mode(state, preferred_mode); |
737 | if (search_adaptive_sync(ctx, output_idx)) { | ||
738 | return true; | ||
646 | } | 739 | } |
647 | } | 740 | } |
648 | 741 | ||
649 | struct output_config *result = new_output_config("temp"); | 742 | if (wl_list_empty(&wlr_output->modes)) { |
650 | if (config->reloading) { | 743 | state->committed &= ~WLR_OUTPUT_STATE_MODE; |
651 | default_output_config(result, sway_output->wlr_output); | 744 | return search_adaptive_sync(ctx, output_idx); |
652 | } | 745 | } |
653 | if (oc_id_on_name) { | 746 | |
654 | // Already have an identifier on name config, use that | 747 | struct wlr_output_mode *mode; |
655 | free(result->name); | 748 | wl_list_for_each(mode, &backend_state->output->modes, link) { |
656 | result->name = strdup(id_on_name); | 749 | if (mode == preferred_mode) { |
657 | merge_output_config(result, oc_id_on_name); | 750 | continue; |
658 | } else if (oc_name && oc_id) { | 751 | } |
659 | // Generate a config named `<identifier> on <name>` which contains a | 752 | wlr_output_state_set_mode(state, mode); |
660 | // merged copy of the identifier on name. This will make sure that both | 753 | if (search_adaptive_sync(ctx, output_idx)) { |
661 | // identifier and name configs are respected, with identifier getting | 754 | return true; |
662 | // priority | ||
663 | struct output_config *temp = new_output_config(id_on_name); | ||
664 | merge_output_config(temp, oc_name); | ||
665 | merge_output_config(temp, oc_id); | ||
666 | list_add(config->output_configs, temp); | ||
667 | |||
668 | free(result->name); | ||
669 | result->name = strdup(id_on_name); | ||
670 | merge_output_config(result, temp); | ||
671 | |||
672 | sway_log(SWAY_DEBUG, "Generated output config \"%s\" (enabled: %d)" | ||
673 | " (%dx%d@%fHz position %d,%d scale %f transform %d) (bg %s %s)" | ||
674 | " (power %d) (max render time: %d)", result->name, result->enabled, | ||
675 | result->width, result->height, result->refresh_rate, | ||
676 | result->x, result->y, result->scale, result->transform, | ||
677 | result->background, result->background_option, result->power, | ||
678 | result->max_render_time); | ||
679 | } else if (oc_name) { | ||
680 | // No identifier config, just return a copy of the name config | ||
681 | free(result->name); | ||
682 | result->name = strdup(name); | ||
683 | merge_output_config(result, oc_name); | ||
684 | } else if (oc_id) { | ||
685 | // No name config, just return a copy of the identifier config | ||
686 | free(result->name); | ||
687 | result->name = strdup(identifier); | ||
688 | merge_output_config(result, oc_id); | ||
689 | } else { | ||
690 | i = list_seq_find(config->output_configs, output_name_cmp, "*"); | ||
691 | if (i >= 0) { | ||
692 | // No name or identifier config, but there is a wildcard config | ||
693 | free(result->name); | ||
694 | result->name = strdup("*"); | ||
695 | merge_output_config(result, config->output_configs->items[i]); | ||
696 | } else if (!config->reloading) { | ||
697 | // No name, identifier, or wildcard config. Since we are not | ||
698 | // reloading with defaults, the output config will be empty, so | ||
699 | // just return NULL | ||
700 | free_output_config(result); | ||
701 | result = NULL; | ||
702 | } | 755 | } |
703 | } | 756 | } |
704 | 757 | ||
705 | free(id_on_name); | 758 | return false; |
706 | return result; | ||
707 | } | 759 | } |
708 | 760 | ||
709 | struct output_config *find_output_config(struct sway_output *output) { | 761 | static bool search_render_format(struct search_context *ctx, size_t output_idx) { |
710 | char id[128]; | 762 | struct matched_output_config *cfg = &ctx->configs[output_idx]; |
711 | output_get_identifier(id, sizeof(id), output); | 763 | struct wlr_backend_output_state *backend_state = &ctx->states[output_idx]; |
712 | return get_output_config(id, output); | 764 | struct wlr_output_state *state = &backend_state->base; |
765 | struct wlr_output *wlr_output = backend_state->output; | ||
766 | |||
767 | uint32_t fmts[] = { | ||
768 | DRM_FORMAT_XRGB2101010, | ||
769 | DRM_FORMAT_XBGR2101010, | ||
770 | DRM_FORMAT_XRGB8888, | ||
771 | DRM_FORMAT_INVALID, | ||
772 | }; | ||
773 | if (render_format_is_bgr(wlr_output->render_format)) { | ||
774 | // Start with BGR in the unlikely event that we previously required it. | ||
775 | fmts[0] = DRM_FORMAT_XBGR2101010; | ||
776 | fmts[1] = DRM_FORMAT_XRGB2101010; | ||
777 | } | ||
778 | |||
779 | const struct wlr_drm_format_set *primary_formats = | ||
780 | wlr_output_get_primary_formats(wlr_output, WLR_BUFFER_CAP_DMABUF); | ||
781 | bool need_10bit = cfg->config && cfg->config->render_bit_depth == RENDER_BIT_DEPTH_10; | ||
782 | for (size_t idx = 0; fmts[idx] != DRM_FORMAT_INVALID; idx++) { | ||
783 | if (!need_10bit && render_format_is_10bit(fmts[idx])) { | ||
784 | continue; | ||
785 | } | ||
786 | if (!wlr_drm_format_set_get(primary_formats, fmts[idx])) { | ||
787 | // This is not a supported format for this output | ||
788 | continue; | ||
789 | } | ||
790 | wlr_output_state_set_render_format(state, fmts[idx]); | ||
791 | if (search_mode(ctx, output_idx)) { | ||
792 | return true; | ||
793 | } | ||
794 | } | ||
795 | return false; | ||
713 | } | 796 | } |
714 | 797 | ||
715 | void apply_output_config_to_outputs(struct output_config *oc) { | 798 | static bool search_valid_config(struct search_context *ctx, size_t output_idx) { |
716 | // Try to find the output container and apply configuration now. If | 799 | if (output_idx >= ctx->configs_len) { |
717 | // this is during startup then there will be no container and config | 800 | // We reached the end of the search, all good! |
718 | // will be applied during normal "new output" event from wlroots. | 801 | return true; |
719 | bool wildcard = strcmp(oc->name, "*") == 0; | 802 | } |
720 | struct sway_output *sway_output, *tmp; | ||
721 | wl_list_for_each_safe(sway_output, tmp, &root->all_outputs, link) { | ||
722 | if (output_match_name_or_id(sway_output, oc->name)) { | ||
723 | char id[128]; | ||
724 | output_get_identifier(id, sizeof(id), sway_output); | ||
725 | struct output_config *current = get_output_config(id, sway_output); | ||
726 | if (!current) { | ||
727 | // No stored output config matched, apply oc directly | ||
728 | sway_log(SWAY_DEBUG, "Applying oc directly"); | ||
729 | current = new_output_config(oc->name); | ||
730 | merge_output_config(current, oc); | ||
731 | } | ||
732 | apply_output_config(current, sway_output); | ||
733 | free_output_config(current); | ||
734 | 803 | ||
735 | if (!wildcard) { | 804 | struct matched_output_config *cfg = &ctx->configs[output_idx]; |
736 | // Stop looking if the output config isn't applicable to all | 805 | struct wlr_backend_output_state *backend_state = &ctx->states[output_idx]; |
737 | // outputs | 806 | struct wlr_output_state *state = &backend_state->base; |
738 | break; | 807 | struct wlr_output *wlr_output = backend_state->output; |
739 | } | 808 | |
809 | if (!output_config_is_disabling(cfg->config)) { | ||
810 | // Search through our possible configurations, doing a depth-first | ||
811 | // through render_format, modes, adaptive_sync and the next output's | ||
812 | // config. | ||
813 | queue_output_config(cfg->config, cfg->output, &backend_state->base); | ||
814 | if (search_render_format(ctx, output_idx)) { | ||
815 | return true; | ||
816 | } else if (!ctx->degrade_to_off) { | ||
817 | return false; | ||
818 | } | ||
819 | // We could not get anything to work, try to disable this output to see | ||
820 | // if we can at least make the outputs before us work. | ||
821 | sway_log(SWAY_DEBUG, "Unable to find valid config with output %s, disabling", | ||
822 | wlr_output->name); | ||
823 | reset_output_state(state); | ||
824 | } | ||
825 | |||
826 | wlr_output_state_set_enabled(state, false); | ||
827 | return search_finish(ctx, output_idx); | ||
828 | } | ||
829 | |||
830 | static int compare_matched_output_config_priority(const void *a, const void *b) { | ||
831 | |||
832 | const struct matched_output_config *amc = a; | ||
833 | const struct matched_output_config *bmc = b; | ||
834 | bool a_disabling = output_config_is_disabling(amc->config); | ||
835 | bool b_disabling = output_config_is_disabling(bmc->config); | ||
836 | bool a_enabled = amc->output->enabled; | ||
837 | bool b_enabled = bmc->output->enabled; | ||
838 | |||
839 | // We want to give priority to existing enabled outputs. To do so, we want | ||
840 | // the configuration order to be: | ||
841 | // 1. Existing, enabled outputs | ||
842 | // 2. Outputs that need to be enabled | ||
843 | // 3. Disabled or disabling outputs | ||
844 | if (a_enabled && !a_disabling) { | ||
845 | return -1; | ||
846 | } else if (b_enabled && !b_disabling) { | ||
847 | return 1; | ||
848 | } else if (b_disabling && !a_disabling) { | ||
849 | return -1; | ||
850 | } else if (a_disabling && !b_disabling) { | ||
851 | return 1; | ||
852 | } | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | void sort_output_configs_by_priority(struct matched_output_config *configs, | ||
857 | size_t configs_len) { | ||
858 | qsort(configs, configs_len, sizeof(*configs), compare_matched_output_config_priority); | ||
859 | } | ||
860 | |||
861 | bool apply_output_configs(struct matched_output_config *configs, | ||
862 | size_t configs_len, bool test_only, bool degrade_to_off) { | ||
863 | struct wlr_backend_output_state *states = calloc(configs_len, sizeof(*states)); | ||
864 | if (!states) { | ||
865 | return false; | ||
866 | } | ||
867 | |||
868 | sway_log(SWAY_DEBUG, "Committing %zd outputs", configs_len); | ||
869 | for (size_t idx = 0; idx < configs_len; idx++) { | ||
870 | struct matched_output_config *cfg = &configs[idx]; | ||
871 | struct wlr_backend_output_state *backend_state = &states[idx]; | ||
872 | |||
873 | backend_state->output = cfg->output->wlr_output; | ||
874 | wlr_output_state_init(&backend_state->base); | ||
875 | |||
876 | sway_log(SWAY_DEBUG, "Preparing config for %s", | ||
877 | cfg->output->wlr_output->name); | ||
878 | queue_output_config(cfg->config, cfg->output, &backend_state->base); | ||
879 | } | ||
880 | |||
881 | struct wlr_output_swapchain_manager swapchain_mgr; | ||
882 | wlr_output_swapchain_manager_init(&swapchain_mgr, server.backend); | ||
883 | |||
884 | bool ok = wlr_output_swapchain_manager_prepare(&swapchain_mgr, states, configs_len); | ||
885 | if (!ok) { | ||
886 | sway_log(SWAY_ERROR, "Requested backend configuration failed, searching for valid fallbacks"); | ||
887 | struct search_context ctx = { | ||
888 | .swapchain_mgr = &swapchain_mgr, | ||
889 | .states = states, | ||
890 | .configs = configs, | ||
891 | .configs_len = configs_len, | ||
892 | .degrade_to_off = degrade_to_off, | ||
893 | }; | ||
894 | if (!search_valid_config(&ctx, 0)) { | ||
895 | sway_log(SWAY_ERROR, "Search for valid config failed"); | ||
896 | goto out; | ||
897 | } | ||
898 | } | ||
899 | |||
900 | if (test_only) { | ||
901 | // The swapchain manager already did a test for us | ||
902 | goto out; | ||
903 | } | ||
904 | |||
905 | for (size_t idx = 0; idx < configs_len; idx++) { | ||
906 | struct matched_output_config *cfg = &configs[idx]; | ||
907 | struct wlr_backend_output_state *backend_state = &states[idx]; | ||
908 | |||
909 | struct wlr_scene_output_state_options opts = { | ||
910 | .swapchain = wlr_output_swapchain_manager_get_swapchain( | ||
911 | &swapchain_mgr, backend_state->output), | ||
912 | }; | ||
913 | struct wlr_scene_output *scene_output = cfg->output->scene_output; | ||
914 | struct wlr_output_state *state = &backend_state->base; | ||
915 | if (!wlr_scene_output_build_state(scene_output, state, &opts)) { | ||
916 | sway_log(SWAY_ERROR, "Building output state for '%s' failed", | ||
917 | backend_state->output->name); | ||
918 | goto out; | ||
740 | } | 919 | } |
741 | } | 920 | } |
742 | 921 | ||
922 | ok = wlr_backend_commit(server.backend, states, configs_len); | ||
923 | if (!ok) { | ||
924 | sway_log(SWAY_ERROR, "Backend commit failed"); | ||
925 | goto out; | ||
926 | } | ||
927 | |||
928 | sway_log(SWAY_DEBUG, "Commit of %zd outputs succeeded", configs_len); | ||
929 | |||
930 | wlr_output_swapchain_manager_apply(&swapchain_mgr); | ||
931 | |||
932 | for (size_t idx = 0; idx < configs_len; idx++) { | ||
933 | struct matched_output_config *cfg = &configs[idx]; | ||
934 | sway_log(SWAY_DEBUG, "Finalizing config for %s", | ||
935 | cfg->output->wlr_output->name); | ||
936 | finalize_output_config(cfg->config, cfg->output); | ||
937 | } | ||
938 | |||
939 | out: | ||
940 | wlr_output_swapchain_manager_finish(&swapchain_mgr); | ||
941 | for (size_t idx = 0; idx < configs_len; idx++) { | ||
942 | struct wlr_backend_output_state *backend_state = &states[idx]; | ||
943 | wlr_output_state_finish(&backend_state->base); | ||
944 | } | ||
945 | free(states); | ||
946 | |||
947 | // Reconfigure all devices, since input config may have been applied before | ||
948 | // this output came online, and some config items (like map_to_output) are | ||
949 | // dependent on an output being present. | ||
950 | input_manager_configure_all_input_mappings(); | ||
951 | // Reconfigure the cursor images, since the scale may have changed. | ||
952 | input_manager_configure_xcursor(); | ||
953 | |||
743 | struct sway_seat *seat; | 954 | struct sway_seat *seat; |
744 | wl_list_for_each(seat, &server.input->seats, link) { | 955 | wl_list_for_each(seat, &server.input->seats, link) { |
745 | wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); | 956 | wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); |
746 | cursor_rebase(seat->cursor); | 957 | cursor_rebase(seat->cursor); |
747 | } | 958 | } |
959 | |||
960 | return ok; | ||
748 | } | 961 | } |
749 | 962 | ||
750 | void reset_outputs(void) { | 963 | void apply_all_output_configs(void) { |
751 | struct output_config *oc = NULL; | 964 | size_t configs_len = wl_list_length(&root->all_outputs); |
752 | int i = list_seq_find(config->output_configs, output_name_cmp, "*"); | 965 | struct matched_output_config *configs = calloc(configs_len, sizeof(*configs)); |
753 | if (i >= 0) { | 966 | if (!configs) { |
754 | oc = config->output_configs->items[i]; | 967 | return; |
755 | } else { | ||
756 | oc = store_output_config(new_output_config("*")); | ||
757 | } | 968 | } |
758 | apply_output_config_to_outputs(oc); | 969 | |
970 | int config_idx = 0; | ||
971 | struct sway_output *sway_output; | ||
972 | wl_list_for_each(sway_output, &root->all_outputs, link) { | ||
973 | if (sway_output == root->fallback_output) { | ||
974 | configs_len--; | ||
975 | continue; | ||
976 | } | ||
977 | |||
978 | struct matched_output_config *config = &configs[config_idx++]; | ||
979 | config->output = sway_output; | ||
980 | config->config = find_output_config(sway_output); | ||
981 | } | ||
982 | |||
983 | sort_output_configs_by_priority(configs, configs_len); | ||
984 | apply_output_configs(configs, configs_len, false, true); | ||
985 | for (size_t idx = 0; idx < configs_len; idx++) { | ||
986 | struct matched_output_config *cfg = &configs[idx]; | ||
987 | free_output_config(cfg->config); | ||
988 | } | ||
989 | free(configs); | ||
759 | } | 990 | } |
760 | 991 | ||
761 | void free_output_config(struct output_config *oc) { | 992 | void free_output_config(struct output_config *oc) { |
@@ -822,7 +1053,9 @@ static bool _spawn_swaybg(char **command) { | |||
822 | setenv("WAYLAND_SOCKET", wayland_socket_str, true); | 1053 | setenv("WAYLAND_SOCKET", wayland_socket_str, true); |
823 | 1054 | ||
824 | execvp(command[0], command); | 1055 | execvp(command[0], command); |
825 | sway_log_errno(SWAY_ERROR, "execvp failed"); | 1056 | sway_log_errno(SWAY_ERROR, "failed to execute '%s' " |
1057 | "(background configuration probably not applied)", | ||
1058 | command[0]); | ||
826 | _exit(EXIT_FAILURE); | 1059 | _exit(EXIT_FAILURE); |
827 | } | 1060 | } |
828 | _exit(EXIT_SUCCESS); | 1061 | _exit(EXIT_SUCCESS); |
@@ -832,12 +1065,13 @@ static bool _spawn_swaybg(char **command) { | |||
832 | sway_log_errno(SWAY_ERROR, "close failed"); | 1065 | sway_log_errno(SWAY_ERROR, "close failed"); |
833 | return false; | 1066 | return false; |
834 | } | 1067 | } |
835 | if (waitpid(pid, NULL, 0) < 0) { | 1068 | int fork_status = 0; |
1069 | if (waitpid(pid, &fork_status, 0) < 0) { | ||
836 | sway_log_errno(SWAY_ERROR, "waitpid failed"); | 1070 | sway_log_errno(SWAY_ERROR, "waitpid failed"); |
837 | return false; | 1071 | return false; |
838 | } | 1072 | } |
839 | 1073 | ||
840 | return true; | 1074 | return WIFEXITED(fork_status) && WEXITSTATUS(fork_status) == EXIT_SUCCESS; |
841 | } | 1075 | } |
842 | 1076 | ||
843 | bool spawn_swaybg(void) { | 1077 | bool 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 | ||
234 | static 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 |
231 | struct launcher_ctx *launcher_ctx_create_internal(void) { | 241 | struct 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..6221b7b9 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -2,9 +2,12 @@ | |||
2 | #include <stdlib.h> | 2 | #include <stdlib.h> |
3 | #include <string.h> | 3 | #include <string.h> |
4 | #include <wayland-server-core.h> | 4 | #include <wayland-server-core.h> |
5 | #include <wlr/types/wlr_fractional_scale_v1.h> | ||
5 | #include <wlr/types/wlr_layer_shell_v1.h> | 6 | #include <wlr/types/wlr_layer_shell_v1.h> |
6 | #include <wlr/types/wlr_output.h> | 7 | #include <wlr/types/wlr_output.h> |
8 | #include <wlr/types/wlr_scene.h> | ||
7 | #include <wlr/types/wlr_subcompositor.h> | 9 | #include <wlr/types/wlr_subcompositor.h> |
10 | #include <wlr/types/wlr_xdg_shell.h> | ||
8 | #include "log.h" | 11 | #include "log.h" |
9 | #include "sway/scene_descriptor.h" | 12 | #include "sway/scene_descriptor.h" |
10 | #include "sway/desktop/transaction.h" | 13 | #include "sway/desktop/transaction.h" |
@@ -16,7 +19,6 @@ | |||
16 | #include "sway/server.h" | 19 | #include "sway/server.h" |
17 | #include "sway/tree/arrange.h" | 20 | #include "sway/tree/arrange.h" |
18 | #include "sway/tree/workspace.h" | 21 | #include "sway/tree/workspace.h" |
19 | #include <wlr/types/wlr_scene.h> | ||
20 | 22 | ||
21 | struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( | 23 | struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface( |
22 | struct wlr_surface *surface) { | 24 | struct wlr_surface *surface) { |
@@ -85,6 +87,8 @@ void arrange_layers(struct sway_output *output) { | |||
85 | sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); | 87 | sway_log(SWAY_DEBUG, "Usable area changed, rearranging output"); |
86 | output->usable_area = usable_area; | 88 | output->usable_area = usable_area; |
87 | arrange_output(output); | 89 | arrange_output(output); |
90 | } else { | ||
91 | arrange_popups(root->layers.popup); | ||
88 | } | 92 | } |
89 | } | 93 | } |
90 | 94 | ||
@@ -120,10 +124,21 @@ static struct sway_layer_surface *sway_layer_surface_create( | |||
120 | return NULL; | 124 | return NULL; |
121 | } | 125 | } |
122 | 126 | ||
127 | surface->desc.relative = &scene->tree->node; | ||
128 | |||
129 | if (!scene_descriptor_assign(&popups->node, | ||
130 | SWAY_SCENE_DESC_POPUP, &surface->desc)) { | ||
131 | sway_log(SWAY_ERROR, "Failed to allocate a popup scene descriptor"); | ||
132 | wlr_scene_node_destroy(&popups->node); | ||
133 | free(surface); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
123 | surface->tree = scene->tree; | 137 | surface->tree = scene->tree; |
124 | surface->scene = scene; | 138 | surface->scene = scene; |
125 | surface->layer_surface = scene->layer_surface; | 139 | surface->layer_surface = scene->layer_surface; |
126 | surface->popups = popups; | 140 | surface->popups = popups; |
141 | surface->layer_surface->data = surface; | ||
127 | 142 | ||
128 | return surface; | 143 | return surface; |
129 | } | 144 | } |
@@ -197,6 +212,8 @@ static void handle_node_destroy(struct wl_listener *listener, void *data) { | |||
197 | wl_list_remove(&layer->node_destroy.link); | 212 | wl_list_remove(&layer->node_destroy.link); |
198 | wl_list_remove(&layer->output_destroy.link); | 213 | wl_list_remove(&layer->output_destroy.link); |
199 | 214 | ||
215 | layer->layer_surface->data = NULL; | ||
216 | |||
200 | free(layer); | 217 | free(layer); |
201 | } | 218 | } |
202 | 219 | ||
@@ -222,10 +239,6 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { | |||
222 | arrange_layers(surface->output); | 239 | arrange_layers(surface->output); |
223 | transaction_commit_dirty(); | 240 | transaction_commit_dirty(); |
224 | } | 241 | } |
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 | } | 242 | } |
230 | 243 | ||
231 | static void handle_map(struct wl_listener *listener, void *data) { | 244 | static void handle_map(struct wl_listener *listener, void *data) { |
@@ -420,6 +433,12 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
420 | 433 | ||
421 | surface->output = output; | 434 | surface->output = output; |
422 | 435 | ||
436 | // now that the surface's output is known, we can advertise its scale | ||
437 | wlr_fractional_scale_v1_notify_scale(surface->layer_surface->surface, | ||
438 | layer_surface->output->scale); | ||
439 | wlr_surface_set_preferred_buffer_scale(surface->layer_surface->surface, | ||
440 | ceil(layer_surface->output->scale)); | ||
441 | |||
423 | surface->surface_commit.notify = handle_surface_commit; | 442 | surface->surface_commit.notify = handle_surface_commit; |
424 | wl_signal_add(&layer_surface->surface->events.commit, | 443 | wl_signal_add(&layer_surface->surface->events.commit, |
425 | &surface->surface_commit); | 444 | &surface->surface_commit); |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9c4baafd..2722e556 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 | ||
185 | static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output) { | 186 | static 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) { |
@@ -512,9 +521,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
512 | sway_session_lock_add_output(server->session_lock.lock, output); | 521 | sway_session_lock_add_output(server->session_lock.lock, output); |
513 | } | 522 | } |
514 | 523 | ||
515 | struct output_config *oc = find_output_config(output); | 524 | apply_all_output_configs(); |
516 | apply_output_config(oc, output); | ||
517 | free_output_config(oc); | ||
518 | 525 | ||
519 | transaction_commit_dirty(); | 526 | transaction_commit_dirty(); |
520 | 527 | ||
@@ -543,63 +550,89 @@ void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) { | |||
543 | wlr_output_schedule_frame(output->wlr_output); | 550 | wlr_output_schedule_frame(output->wlr_output); |
544 | } | 551 | } |
545 | 552 | ||
553 | static struct output_config *output_config_for_config_head( | ||
554 | struct wlr_output_configuration_head_v1 *config_head, | ||
555 | struct sway_output *output) { | ||
556 | struct output_config *oc = new_output_config(output->wlr_output->name); | ||
557 | oc->enabled = config_head->state.enabled; | ||
558 | if (!oc->enabled) { | ||
559 | return oc; | ||
560 | } | ||
561 | |||
562 | if (config_head->state.mode != NULL) { | ||
563 | struct wlr_output_mode *mode = config_head->state.mode; | ||
564 | oc->width = mode->width; | ||
565 | oc->height = mode->height; | ||
566 | oc->refresh_rate = mode->refresh / 1000.f; | ||
567 | } else { | ||
568 | oc->width = config_head->state.custom_mode.width; | ||
569 | oc->height = config_head->state.custom_mode.height; | ||
570 | oc->refresh_rate = | ||
571 | config_head->state.custom_mode.refresh / 1000.f; | ||
572 | } | ||
573 | oc->x = config_head->state.x; | ||
574 | oc->y = config_head->state.y; | ||
575 | oc->transform = config_head->state.transform; | ||
576 | oc->scale = config_head->state.scale; | ||
577 | oc->adaptive_sync = config_head->state.adaptive_sync_enabled; | ||
578 | return oc; | ||
579 | } | ||
580 | |||
546 | static void output_manager_apply(struct sway_server *server, | 581 | static void output_manager_apply(struct sway_server *server, |
547 | struct wlr_output_configuration_v1 *config, bool test_only) { | 582 | struct wlr_output_configuration_v1 *config, bool test_only) { |
548 | // TODO: perform atomic tests on the whole backend atomically | 583 | size_t configs_len = wl_list_length(&root->all_outputs); |
549 | 584 | struct matched_output_config *configs = calloc(configs_len, sizeof(*configs)); | |
550 | struct wlr_output_configuration_head_v1 *config_head; | 585 | if (!configs) { |
551 | // First disable outputs we need to disable | 586 | return; |
552 | bool ok = true; | 587 | } |
553 | wl_list_for_each(config_head, &config->heads, link) { | 588 | |
554 | struct wlr_output *wlr_output = config_head->state.output; | 589 | int config_idx = 0; |
555 | struct sway_output *output = wlr_output->data; | 590 | struct sway_output *sway_output; |
556 | if (!output->enabled || config_head->state.enabled) { | 591 | wl_list_for_each(sway_output, &root->all_outputs, link) { |
592 | if (sway_output == root->fallback_output) { | ||
593 | configs_len--; | ||
557 | continue; | 594 | continue; |
558 | } | 595 | } |
559 | struct output_config *oc = new_output_config(output->wlr_output->name); | ||
560 | oc->enabled = false; | ||
561 | 596 | ||
562 | if (test_only) { | 597 | struct matched_output_config *cfg = &configs[config_idx++]; |
563 | ok &= test_output_config(oc, output); | 598 | cfg->output = sway_output; |
564 | } else { | 599 | |
565 | oc = store_output_config(oc); | 600 | struct wlr_output_configuration_head_v1 *config_head; |
566 | ok &= apply_output_config(oc, output); | 601 | wl_list_for_each(config_head, &config->heads, link) { |
602 | if (config_head->state.output == sway_output->wlr_output) { | ||
603 | cfg->config = output_config_for_config_head(config_head, sway_output); | ||
604 | break; | ||
605 | } | ||
606 | } | ||
607 | if (!cfg->config) { | ||
608 | cfg->config = find_output_config(sway_output); | ||
567 | } | 609 | } |
568 | } | 610 | } |
569 | 611 | ||
570 | // Then enable outputs that need to | 612 | sort_output_configs_by_priority(configs, configs_len); |
571 | wl_list_for_each(config_head, &config->heads, link) { | 613 | bool ok = apply_output_configs(configs, configs_len, test_only, false); |
572 | struct wlr_output *wlr_output = config_head->state.output; | 614 | for (size_t idx = 0; idx < configs_len; idx++) { |
573 | struct sway_output *output = wlr_output->data; | 615 | struct matched_output_config *cfg = &configs[idx]; |
574 | if (!config_head->state.enabled) { | 616 | |
575 | continue; | 617 | // Only store new configs for successful non-test commits. Old configs, |
576 | } | 618 | // test-only and failed commits just get freed. |
577 | struct output_config *oc = new_output_config(output->wlr_output->name); | 619 | bool store_config = false; |
578 | oc->enabled = true; | 620 | if (!test_only && ok) { |
579 | if (config_head->state.mode != NULL) { | 621 | struct wlr_output_configuration_head_v1 *config_head; |
580 | struct wlr_output_mode *mode = config_head->state.mode; | 622 | wl_list_for_each(config_head, &config->heads, link) { |
581 | oc->width = mode->width; | 623 | if (config_head->state.output == cfg->output->wlr_output) { |
582 | oc->height = mode->height; | 624 | store_config = true; |
583 | oc->refresh_rate = mode->refresh / 1000.f; | 625 | break; |
584 | } else { | 626 | } |
585 | oc->width = config_head->state.custom_mode.width; | 627 | } |
586 | oc->height = config_head->state.custom_mode.height; | ||
587 | oc->refresh_rate = | ||
588 | config_head->state.custom_mode.refresh / 1000.f; | ||
589 | } | 628 | } |
590 | oc->x = config_head->state.x; | 629 | if (store_config) { |
591 | oc->y = config_head->state.y; | 630 | store_output_config(cfg->config); |
592 | oc->transform = config_head->state.transform; | ||
593 | oc->scale = config_head->state.scale; | ||
594 | oc->adaptive_sync = config_head->state.adaptive_sync_enabled; | ||
595 | |||
596 | if (test_only) { | ||
597 | ok &= test_output_config(oc, output); | ||
598 | } else { | 631 | } else { |
599 | oc = store_output_config(oc); | 632 | free_output_config(cfg->config); |
600 | ok &= apply_output_config(oc, output); | ||
601 | } | 633 | } |
602 | } | 634 | } |
635 | free(configs); | ||
603 | 636 | ||
604 | if (ok) { | 637 | if (ok) { |
605 | wlr_output_configuration_v1_send_succeeded(config); | 638 | wlr_output_configuration_v1_send_succeeded(config); |
@@ -643,6 +676,6 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener, | |||
643 | oc->power = 1; | 676 | oc->power = 1; |
644 | break; | 677 | break; |
645 | } | 678 | } |
646 | oc = store_output_config(oc); | 679 | store_output_config(oc); |
647 | apply_output_config(oc, output); | 680 | apply_all_output_configs(); |
648 | } | 681 | } |
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 | ||
609 | static void arrange_popup(struct wlr_scene_tree *popup) { | 608 | void 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 | ||
74 | static 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 | |||
74 | static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup, | 79 | static 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 | ||
357 | void dispatch_cursor_button(struct sway_cursor *cursor, | 357 | void 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 | ||
68 | char *input_device_get_identifier(struct wlr_input_device *device) { | 69 | char *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 | ||
436 | static void handle_transient_seat_manager_create_seat( | ||
437 | struct wl_listener *listener, void *data) { | ||
438 | struct wlr_transient_seat_v1 *transient_seat = data; | ||
439 | static uint64_t i; | ||
440 | char name[256]; | ||
441 | snprintf(name, sizeof(name), "transient-%"PRIx64, i++); | ||
442 | struct sway_seat *seat = seat_create(name); | ||
443 | if (seat && seat->wlr_seat) { | ||
444 | wlr_transient_seat_v1_ready(transient_seat, seat->wlr_seat); | ||
445 | } else { | ||
446 | wlr_transient_seat_v1_deny(transient_seat); | ||
447 | } | ||
448 | } | ||
449 | |||
428 | struct sway_input_manager *input_manager_create(struct sway_server *server) { | 450 | struct 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/keyboard.c b/sway/input/keyboard.c index b97f0152..f74d0658 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -32,6 +32,7 @@ static struct modifier_key { | |||
32 | { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 }, | 32 | { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 }, |
33 | { "Mod3", WLR_MODIFIER_MOD3 }, | 33 | { "Mod3", WLR_MODIFIER_MOD3 }, |
34 | { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO }, | 34 | { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO }, |
35 | { "Super", WLR_MODIFIER_LOGO }, | ||
35 | { "Mod5", WLR_MODIFIER_MOD5 }, | 36 | { "Mod5", WLR_MODIFIER_MOD5 }, |
36 | }; | 37 | }; |
37 | 38 | ||
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 | ||
70 | void seat_destroy(struct sway_seat *seat) { | 69 | void seat_destroy(struct sway_seat *seat) { |
70 | wlr_seat_destroy(seat->wlr_seat); | ||
71 | } | ||
72 | |||
73 | static void handle_seat_destroy(struct wl_listener *listener, void *data) { | ||
74 | struct sway_seat *seat = wl_container_of(listener, seat, destroy); | ||
75 | |||
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) { | |||
666 | static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { | 674 | static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { |
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 | ||
1523 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, | 1531 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, |
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 | ||
1559 | void seatop_button(struct sway_seat *seat, uint32_t time_msec, | 1567 | void 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 | ||
292 | static bool trigger_pointer_button_binding(struct sway_seat *seat, | 291 | static 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 | ||
331 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 330 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
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 | ||
696 | static uint32_t wl_axis_to_button(struct wlr_pointer_axis_event *event) { | 695 | static 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..340e334b 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> |
@@ -118,7 +117,11 @@ static void handle_touch_cancel(struct sway_seat *seat, | |||
118 | } | 117 | } |
119 | 118 | ||
120 | if (e->surface) { | 119 | if (e->surface) { |
121 | wlr_seat_touch_notify_cancel(seat->wlr_seat, e->surface); | 120 | struct wl_client *client = wl_resource_get_client(e->surface->resource); |
121 | struct wlr_seat_client *seat_client = wlr_seat_client_for_wl_client(seat->wlr_seat, client); | ||
122 | if (seat_client != NULL) { | ||
123 | wlr_seat_touch_notify_cancel(seat->wlr_seat, seat_client); | ||
124 | } | ||
122 | } | 125 | } |
123 | 126 | ||
124 | if (wl_list_empty(&e->point_events)) { | 127 | if (wl_list_empty(&e->point_events)) { |
@@ -143,7 +146,7 @@ static void handle_pointer_axis(struct sway_seat *seat, | |||
143 | 146 | ||
144 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 147 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
145 | struct wlr_input_device *device, uint32_t button, | 148 | struct wlr_input_device *device, uint32_t button, |
146 | enum wlr_button_state state) { | 149 | enum wl_pointer_button_state state) { |
147 | seat_pointer_notify_button(seat, time_msec, button, state); | 150 | seat_pointer_notify_button(seat, time_msec, button, state); |
148 | 151 | ||
149 | if (seat->cursor->pressed_button_count == 0) { | 152 | 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 | ||
23 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 22 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
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 | ||
407 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 406 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
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 | ||
22 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 21 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
23 | struct wlr_input_device *device, uint32_t button, | 22 | struct wlr_input_device *device, uint32_t button, |
24 | enum wlr_button_state state) { | 23 | enum wl_pointer_button_state state) { |
25 | struct seatop_resize_floating_event *e = seat->seatop_data; | 24 | struct seatop_resize_floating_event *e = seat->seatop_data; |
26 | struct sway_container *con = e->con; | 25 | struct sway_container *con = e->con; |
27 | 26 | ||
diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c index 869d11b5..15fd333b 100644 --- a/sway/input/seatop_resize_tiling.c +++ b/sway/input/seatop_resize_tiling.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <wlr/types/wlr_cursor.h> | 1 | #include <wlr/types/wlr_cursor.h> |
3 | #include <wlr/util/edges.h> | 2 | #include <wlr/util/edges.h> |
4 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
@@ -46,7 +45,7 @@ static struct sway_container *container_get_resize_sibling( | |||
46 | 45 | ||
47 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, | 46 | static void handle_button(struct sway_seat *seat, uint32_t time_msec, |
48 | struct wlr_input_device *device, uint32_t button, | 47 | struct wlr_input_device *device, uint32_t button, |
49 | enum wlr_button_state state) { | 48 | enum wl_pointer_button_state state) { |
50 | struct seatop_resize_tiling_event *e = seat->seatop_data; | 49 | struct seatop_resize_tiling_event *e = seat->seatop_data; |
51 | 50 | ||
52 | if (seat->cursor->pressed_button_count == 0) { | 51 | if (seat->cursor->pressed_button_count == 0) { |
diff --git a/sway/input/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" | ||
12 | static void input_popup_update(struct sway_input_popup *popup); | ||
6 | 13 | ||
7 | static struct sway_text_input *relay_get_focusable_text_input( | 14 | static struct sway_text_input *relay_get_focusable_text_input( |
8 | struct sway_input_method_relay *relay) { | 15 | struct sway_input_method_relay *relay) { |
@@ -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 | ||
274 | static void input_popup_update(struct sway_input_popup *popup) { | ||
275 | struct sway_text_input *text_input = | ||
276 | relay_get_focused_text_input(popup->relay); | ||
277 | |||
278 | if (text_input == NULL || text_input->input->focused_surface == NULL) { | ||
279 | return; | ||
280 | } | ||
281 | |||
282 | if (popup->scene_tree != NULL) { | ||
283 | wlr_scene_node_destroy(&popup->scene_tree->node); | ||
284 | popup->scene_tree = NULL; | ||
285 | } | ||
286 | if (popup->desc.relative != NULL) { | ||
287 | wlr_scene_node_destroy(popup->desc.relative); | ||
288 | popup->desc.relative = NULL; | ||
289 | } | ||
290 | popup->desc.view = NULL; | ||
291 | |||
292 | if (!popup->popup_surface->surface->mapped) { | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | bool cursor_rect = text_input->input->current.features | ||
297 | & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE; | ||
298 | struct wlr_surface *focused_surface = text_input->input->focused_surface; | ||
299 | struct wlr_box cursor_area = text_input->input->current.cursor_rectangle; | ||
300 | |||
301 | struct wlr_box output_box; | ||
302 | struct wlr_box parent = {0}; | ||
303 | struct wlr_layer_surface_v1 *layer_surface = | ||
304 | wlr_layer_surface_v1_try_from_wlr_surface(focused_surface); | ||
305 | struct wlr_scene_tree *relative_parent; | ||
306 | |||
307 | struct wlr_box geo = {0}; | ||
308 | |||
309 | popup->scene_tree = wlr_scene_subsurface_tree_create(root->layers.popup, popup->popup_surface->surface); | ||
310 | if (layer_surface != NULL) { | ||
311 | struct sway_layer_surface *layer = | ||
312 | layer_surface->data; | ||
313 | if (layer == NULL) { | ||
314 | return; | ||
315 | } | ||
316 | |||
317 | relative_parent = layer->scene->tree; | ||
318 | struct wlr_output *output = layer->layer_surface->output; | ||
319 | wlr_output_layout_get_box(root->output_layout, output, &output_box); | ||
320 | int lx, ly; | ||
321 | wlr_scene_node_coords(&layer->tree->node, &lx, &ly); | ||
322 | parent.x = lx; | ||
323 | parent.y = ly; | ||
324 | popup->desc.view = NULL; | ||
325 | } else { | ||
326 | struct sway_view *view = view_from_wlr_surface(focused_surface); | ||
327 | relative_parent = view->scene_tree; | ||
328 | geo = view->geometry; | ||
329 | int lx, ly; | ||
330 | wlr_scene_node_coords(&view->scene_tree->node, &lx, &ly); | ||
331 | struct wlr_output *output = wlr_output_layout_output_at(root->output_layout, | ||
332 | view->container->pending.content_x + view->geometry.x, | ||
333 | view->container->pending.content_y + view->geometry.y); | ||
334 | wlr_output_layout_get_box(root->output_layout, output, &output_box); | ||
335 | parent.x = lx; | ||
336 | parent.y = ly; | ||
337 | |||
338 | parent.width = view->geometry.width; | ||
339 | parent.height = view->geometry.height; | ||
340 | popup->desc.view = view; | ||
341 | } | ||
342 | |||
343 | struct wlr_scene_tree *relative = wlr_scene_tree_create(relative_parent); | ||
344 | |||
345 | popup->desc.relative = &relative->node; | ||
346 | if (!scene_descriptor_assign(&popup->scene_tree->node, | ||
347 | SWAY_SCENE_DESC_POPUP, &popup->desc)) { | ||
348 | wlr_scene_node_destroy(&popup->scene_tree->node); | ||
349 | popup->scene_tree = NULL; | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | if (!cursor_rect) { | ||
354 | cursor_area.x = 0; | ||
355 | cursor_area.y = 0; | ||
356 | cursor_area.width = parent.width; | ||
357 | cursor_area.height = parent.height; | ||
358 | } | ||
359 | |||
360 | int popup_width = popup->popup_surface->surface->current.width; | ||
361 | int popup_height = popup->popup_surface->surface->current.height; | ||
362 | int x1 = parent.x + cursor_area.x; | ||
363 | int x2 = parent.x + cursor_area.x + cursor_area.width; | ||
364 | int y1 = parent.y + cursor_area.y; | ||
365 | int y2 = parent.y + cursor_area.y + cursor_area.height; | ||
366 | int x = x1; | ||
367 | int y = y2; | ||
368 | |||
369 | int available_right = output_box.x + output_box.width - x1; | ||
370 | int available_left = x2 - output_box.x; | ||
371 | if (available_right < popup_width && available_left > available_right) { | ||
372 | x = x2 - popup_width; | ||
373 | } | ||
374 | |||
375 | int available_down = output_box.y + output_box.height - y2; | ||
376 | int available_up = y1 - output_box.y; | ||
377 | if (available_down < popup_height && available_up > available_down) { | ||
378 | y = y1 - popup_height; | ||
379 | } | ||
380 | |||
381 | wlr_scene_node_set_position(&relative->node, x - parent.x - geo.x, y - parent.y - geo.y); | ||
382 | if (cursor_rect) { | ||
383 | struct wlr_box box = { | ||
384 | .x = x1 - x, | ||
385 | .y = y1 - y, | ||
386 | .width = cursor_area.width, | ||
387 | .height = cursor_area.height, | ||
388 | }; | ||
389 | wlr_input_popup_surface_v2_send_text_input_rectangle( | ||
390 | popup->popup_surface, &box); | ||
391 | } | ||
392 | wlr_scene_node_set_position(&popup->scene_tree->node, x - geo.x, y - geo.y); | ||
393 | } | ||
394 | |||
395 | static void input_popup_set_focus(struct sway_input_popup *popup, | ||
396 | struct wlr_surface *surface) { | ||
397 | wl_list_remove(&popup->focused_surface_unmap.link); | ||
398 | |||
399 | if (surface == NULL) { | ||
400 | wl_list_init(&popup->focused_surface_unmap.link); | ||
401 | input_popup_update(popup); | ||
402 | return; | ||
403 | } | ||
404 | struct wlr_layer_surface_v1 *layer_surface = | ||
405 | wlr_layer_surface_v1_try_from_wlr_surface(surface); | ||
406 | if (layer_surface != NULL) { | ||
407 | wl_signal_add( | ||
408 | &layer_surface->surface->events.unmap, &popup->focused_surface_unmap); | ||
409 | input_popup_update(popup); | ||
410 | return; | ||
411 | } | ||
412 | |||
413 | struct sway_view *view = view_from_wlr_surface(surface); | ||
414 | wl_signal_add(&view->events.unmap, &popup->focused_surface_unmap); | ||
415 | } | ||
416 | |||
417 | static void handle_im_popup_destroy(struct wl_listener *listener, void *data) { | ||
418 | struct sway_input_popup *popup = | ||
419 | wl_container_of(listener, popup, popup_destroy); | ||
420 | wl_list_remove(&popup->focused_surface_unmap.link); | ||
421 | wl_list_remove(&popup->popup_surface_commit.link); | ||
422 | wl_list_remove(&popup->popup_destroy.link); | ||
423 | wl_list_remove(&popup->link); | ||
424 | |||
425 | free(popup); | ||
426 | } | ||
427 | |||
428 | static void handle_im_popup_surface_commit(struct wl_listener *listener, | ||
429 | void *data) { | ||
430 | struct sway_input_popup *popup = | ||
431 | wl_container_of(listener, popup, popup_surface_commit); | ||
432 | input_popup_update(popup); | ||
433 | } | ||
434 | |||
435 | static void handle_im_focused_surface_unmap( | ||
436 | struct wl_listener *listener, void *data) { | ||
437 | struct sway_input_popup *popup = | ||
438 | wl_container_of(listener, popup, focused_surface_unmap); | ||
439 | input_popup_update(popup); | ||
440 | } | ||
441 | |||
442 | static void handle_im_new_popup_surface(struct wl_listener *listener, | ||
443 | void *data) { | ||
444 | struct sway_input_method_relay *relay = wl_container_of(listener, relay, | ||
445 | input_method_new_popup_surface); | ||
446 | struct sway_input_popup *popup = calloc(1, sizeof(*popup)); | ||
447 | popup->relay = relay; | ||
448 | popup->popup_surface = data; | ||
449 | popup->popup_surface->data = popup; | ||
450 | |||
451 | wl_signal_add( | ||
452 | &popup->popup_surface->events.destroy, &popup->popup_destroy); | ||
453 | popup->popup_destroy.notify = handle_im_popup_destroy; | ||
454 | wl_signal_add(&popup->popup_surface->surface->events.commit, | ||
455 | &popup->popup_surface_commit); | ||
456 | popup->popup_surface_commit.notify = handle_im_popup_surface_commit; | ||
457 | wl_list_init(&popup->focused_surface_unmap.link); | ||
458 | popup->focused_surface_unmap.notify = handle_im_focused_surface_unmap; | ||
459 | |||
460 | struct sway_text_input *text_input = relay_get_focused_text_input(relay); | ||
461 | if (text_input != NULL) { | ||
462 | input_popup_set_focus(popup, text_input->input->focused_surface); | ||
463 | } else { | ||
464 | input_popup_set_focus(popup, NULL); | ||
465 | } | ||
466 | |||
467 | wl_list_insert(&relay->input_popups, &popup->link); | ||
468 | } | ||
469 | |||
470 | static void text_input_send_enter(struct sway_text_input *text_input, | ||
471 | struct wlr_surface *surface) { | ||
472 | wlr_text_input_v3_send_enter(text_input->input, surface); | ||
473 | struct sway_input_popup *popup; | ||
474 | wl_list_for_each(popup, &text_input->relay->input_popups, link) { | ||
475 | input_popup_set_focus(popup, surface); | ||
476 | } | ||
477 | } | ||
478 | |||
258 | static void relay_handle_input_method(struct wl_listener *listener, | 479 | static 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 | |||
675 | static void ipc_json_describe_container(struct sway_container *c, json_object *object) { | 677 | static 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..180d3a6b 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 | ||
64 | bool allow_unsupported_gpu = false; | 72 | bool 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 | ||
109 | static bool filter_global(const struct wl_client *client, | 119 | static 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 | ||
176 | static 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 | |||
166 | bool server_init(struct sway_server *server) { | 215 | bool 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,15 +235,17 @@ 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_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) { |
192 | server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer( | 244 | server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer( |
193 | server->wl_display, 4, server->renderer); | 245 | server->wl_display, 4, server->renderer); |
194 | } | 246 | if (debug.legacy_wl_drm) { |
195 | if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL && | 247 | wlr_drm_create(server->wl_display, server->renderer); |
196 | debug.legacy_wl_drm) { | 248 | } |
197 | wlr_drm_create(server->wl_display, server->renderer); | ||
198 | } | 249 | } |
199 | 250 | ||
200 | server->allocator = wlr_allocator_autocreate(server->backend, | 251 | server->allocator = wlr_allocator_autocreate(server->backend, |
@@ -289,6 +340,8 @@ bool server_init(struct sway_server *server) { | |||
289 | &server->output_power_manager_set_mode); | 340 | &server->output_power_manager_set_mode); |
290 | server->input_method = wlr_input_method_manager_v2_create(server->wl_display); | 341 | 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); | 342 | server->text_input = wlr_text_input_manager_v3_create(server->wl_display); |
343 | server->foreign_toplevel_list = | ||
344 | wlr_ext_foreign_toplevel_list_v1_create(server->wl_display, SWAY_FOREIGN_TOPLEVEL_LIST_VERSION); | ||
292 | server->foreign_toplevel_manager = | 345 | server->foreign_toplevel_manager = |
293 | wlr_foreign_toplevel_manager_v1_create(server->wl_display); | 346 | wlr_foreign_toplevel_manager_v1_create(server->wl_display); |
294 | 347 | ||
@@ -388,6 +441,7 @@ void server_fini(struct sway_server *server) { | |||
388 | wlr_xwayland_destroy(server->xwayland.wlr_xwayland); | 441 | wlr_xwayland_destroy(server->xwayland.wlr_xwayland); |
389 | #endif | 442 | #endif |
390 | wl_display_destroy_clients(server->wl_display); | 443 | wl_display_destroy_clients(server->wl_display); |
444 | wlr_backend_destroy(server->backend); | ||
391 | wl_display_destroy(server->wl_display); | 445 | wl_display_destroy(server->wl_display); |
392 | list_free(server->dirty_nodes); | 446 | list_free(server->dirty_nodes); |
393 | } | 447 | } |
diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index f4a5ccff..2f697248 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. |
@@ -1040,7 +1046,7 @@ An object with a single string property containing the contents of the config | |||
1040 | *Example Reply:* | 1046 | *Example Reply:* |
1041 | ``` | 1047 | ``` |
1042 | { | 1048 | { |
1043 | "config": "set $mod Mod4\nbindsym $mod+q exit\n" | 1049 | "config": "set $mod Mod4\\nbindsym $mod+q exit\\n" |
1044 | } | 1050 | } |
1045 | ``` | 1051 | ``` |
1046 | 1052 | ||
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.5.scd b/sway/sway.5.scd index 7e58b528..9f823947 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -400,6 +400,12 @@ runtime. | |||
400 | only be available for that group. By default, if you overwrite a binding, | 400 | only be available for that group. By default, if you overwrite a binding, |
401 | swaynag will give you a warning. To silence this, use the _--no-warn_ flag. | 401 | swaynag will give you a warning. To silence this, use the _--no-warn_ flag. |
402 | 402 | ||
403 | For specifying modifier keys, you can use the XKB modifier names _Shift_, | ||
404 | _Lock_ (for Caps Lock), _Control_, _Mod1_ (for Alt), _Mod2_ (for Num Lock), | ||
405 | _Mod3_ (for XKB modifier Mod3), _Mod4_ (for the Logo key), and _Mod5_ (for | ||
406 | AltGr). In addition, you can use the aliases _Ctrl_ (for Control), _Alt_ | ||
407 | (for Alt), and _Super_ (for the Logo key). | ||
408 | |||
403 | Unless the flag _--locked_ is set, the command will not be run when a | 409 | Unless the flag _--locked_ is set, the command will not be run when a |
404 | screen locking program is active. If there is a matching binding with | 410 | screen locking program is active. If there is a matching binding with |
405 | and without _--locked_, the one with will be preferred when locked and the | 411 | and without _--locked_, the one with will be preferred when locked and the |
diff --git a/sway/sway_text_node.c b/sway/sway_text_node.c index b9a77d94..4b7ee999 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 | ||
60 | static int get_text_width(struct sway_text_node *props) { | 59 | static int get_text_width(struct sway_text_node *props) { |
61 | if (props->max_width) { | 60 | int width = props->width; |
62 | return MIN(props->max_width, props->width); | 61 | if (props->max_width >= 0) { |
62 | width = MIN(width, props->max_width); | ||
63 | } | 63 | } |
64 | 64 | return MAX(width, 0); | |
65 | return props->width; | ||
66 | } | 65 | } |
67 | 66 | ||
68 | static void update_source_box(struct text_buffer *buffer) { | 67 | static void update_source_box(struct text_buffer *buffer) { |
@@ -82,6 +81,11 @@ static void render_backing_buffer(struct text_buffer *buffer) { | |||
82 | return; | 81 | return; |
83 | } | 82 | } |
84 | 83 | ||
84 | if (buffer->props.max_width == 0) { | ||
85 | wlr_scene_buffer_set_buffer(buffer->buffer_node, NULL); | ||
86 | return; | ||
87 | } | ||
88 | |||
85 | float scale = buffer->scale; | 89 | float scale = buffer->scale; |
86 | int width = ceil(buffer->props.width * scale); | 90 | int width = ceil(buffer->props.width * scale); |
87 | int height = ceil(buffer->props.height * scale); | 91 | int height = ceil(buffer->props.height * scale); |
@@ -237,6 +241,7 @@ struct sway_text_node *sway_text_node_create(struct wlr_scene_tree *parent, | |||
237 | 241 | ||
238 | buffer->buffer_node = node; | 242 | buffer->buffer_node = node; |
239 | buffer->props.node = &node->node; | 243 | buffer->props.node = &node->node; |
244 | buffer->props.max_width = -1; | ||
240 | buffer->text = strdup(text); | 245 | buffer->text = strdup(text); |
241 | if (!buffer->text) { | 246 | if (!buffer->text) { |
242 | free(buffer); | 247 | free(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..80ef34fe 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> |
@@ -352,6 +352,8 @@ void container_arrange_title_bar(struct sway_container *con) { | |||
352 | 352 | ||
353 | int alloc_width = MIN((int)node->width, | 353 | int alloc_width = MIN((int)node->width, |
354 | width - h_padding - config->titlebar_h_padding); | 354 | width - h_padding - config->titlebar_h_padding); |
355 | alloc_width = MAX(alloc_width, 0); | ||
356 | |||
355 | sway_text_node_set_max_width(node, alloc_width); | 357 | sway_text_node_set_max_width(node, alloc_width); |
356 | wlr_scene_node_set_position(node->node, | 358 | wlr_scene_node_set_position(node->node, |
357 | h_padding, (height - node->height) >> 1); | 359 | h_padding, (height - node->height) >> 1); |
@@ -376,6 +378,8 @@ void container_arrange_title_bar(struct sway_container *con) { | |||
376 | 378 | ||
377 | int alloc_width = MIN((int) node->width, | 379 | int alloc_width = MIN((int) node->width, |
378 | width - h_padding - config->titlebar_h_padding); | 380 | width - h_padding - config->titlebar_h_padding); |
381 | alloc_width = MAX(alloc_width, 0); | ||
382 | |||
379 | sway_text_node_set_max_width(node, alloc_width); | 383 | sway_text_node_set_max_width(node, alloc_width); |
380 | wlr_scene_node_set_position(node->node, | 384 | wlr_scene_node_set_position(node->node, |
381 | h_padding, (height - node->height) >> 1); | 385 | h_padding, (height - node->height) >> 1); |
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 | ||
414 | void 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 | |||
413 | void view_set_csd_from_server(struct sway_view *view, bool enabled) { | 420 | void 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 | ||
592 | static 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 | |||
585 | static bool should_focus(struct sway_view *view) { | 600 | static 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 | ||
1048 | void 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 | |||
1017 | void view_update_title(struct sway_view *view, bool force) { | 1060 | void 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 | ||
1065 | bool view_is_visible(struct sway_view *view) { | 1112 | bool 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 | ||
40 | void xdg_activation_v1_handle_new_token(struct wl_listener *listener, void *data) { | 55 | void 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> |