diff options
69 files changed, 963 insertions, 592 deletions
diff --git a/common/background-image.c b/common/background-image.c index 5ede55e3..72f39a79 100644 --- a/common/background-image.c +++ b/common/background-image.c | |||
@@ -24,7 +24,7 @@ enum background_mode parse_background_mode(const char *mode) { | |||
24 | 24 | ||
25 | cairo_surface_t *load_background_image(const char *path) { | 25 | cairo_surface_t *load_background_image(const char *path) { |
26 | cairo_surface_t *image; | 26 | cairo_surface_t *image; |
27 | #ifdef HAVE_GDK_PIXBUF | 27 | #if HAVE_GDK_PIXBUF |
28 | GError *err = NULL; | 28 | GError *err = NULL; |
29 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); | 29 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); |
30 | if (!pixbuf) { | 30 | if (!pixbuf) { |
@@ -36,17 +36,17 @@ cairo_surface_t *load_background_image(const char *path) { | |||
36 | g_object_unref(pixbuf); | 36 | g_object_unref(pixbuf); |
37 | #else | 37 | #else |
38 | image = cairo_image_surface_create_from_png(path); | 38 | image = cairo_image_surface_create_from_png(path); |
39 | #endif //HAVE_GDK_PIXBUF | 39 | #endif // HAVE_GDK_PIXBUF |
40 | if (!image) { | 40 | if (!image) { |
41 | wlr_log(WLR_ERROR, "Failed to read background image."); | 41 | wlr_log(WLR_ERROR, "Failed to read background image."); |
42 | return NULL; | 42 | return NULL; |
43 | } | 43 | } |
44 | if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { | 44 | if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { |
45 | wlr_log(WLR_ERROR, "Failed to read background image: %s." | 45 | wlr_log(WLR_ERROR, "Failed to read background image: %s." |
46 | #ifndef HAVE_GDK_PIXBUF | 46 | #if !HAVE_GDK_PIXBUF |
47 | "\nSway was compiled without gdk_pixbuf support, so only" | 47 | "\nSway was compiled without gdk_pixbuf support, so only" |
48 | "\nPNG images can be loaded. This is the likely cause." | 48 | "\nPNG images can be loaded. This is the likely cause." |
49 | #endif //HAVE_GDK_PIXBUF | 49 | #endif // !HAVE_GDK_PIXBUF |
50 | , cairo_status_to_string(cairo_surface_status(image))); | 50 | , cairo_status_to_string(cairo_surface_status(image))); |
51 | return NULL; | 51 | return NULL; |
52 | } | 52 | } |
diff --git a/common/cairo.c b/common/cairo.c index e8231484..f2ad54c1 100644 --- a/common/cairo.c +++ b/common/cairo.c | |||
@@ -1,7 +1,7 @@ | |||
1 | #include <stdint.h> | 1 | #include <stdint.h> |
2 | #include <cairo/cairo.h> | 2 | #include <cairo/cairo.h> |
3 | #include "cairo.h" | 3 | #include "cairo.h" |
4 | #ifdef HAVE_GDK_PIXBUF | 4 | #if HAVE_GDK_PIXBUF |
5 | #include <gdk-pixbuf/gdk-pixbuf.h> | 5 | #include <gdk-pixbuf/gdk-pixbuf.h> |
6 | #endif | 6 | #endif |
7 | 7 | ||
@@ -46,7 +46,7 @@ cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, | |||
46 | return new; | 46 | return new; |
47 | } | 47 | } |
48 | 48 | ||
49 | #ifdef HAVE_GDK_PIXBUF | 49 | #if HAVE_GDK_PIXBUF |
50 | cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { | 50 | cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { |
51 | int chan = gdk_pixbuf_get_n_channels(gdkbuf); | 51 | int chan = gdk_pixbuf_get_n_channels(gdkbuf); |
52 | if (chan < 3) { | 52 | if (chan < 3) { |
@@ -140,4 +140,4 @@ cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdk | |||
140 | cairo_surface_mark_dirty(cs); | 140 | cairo_surface_mark_dirty(cs); |
141 | return cs; | 141 | return cs; |
142 | } | 142 | } |
143 | #endif //HAVE_GDK_PIXBUF | 143 | #endif // HAVE_GDK_PIXBUF |
diff --git a/common/util.c b/common/util.c index abaca17f..40c64230 100644 --- a/common/util.c +++ b/common/util.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <sys/types.h> | 3 | #include <sys/types.h> |
4 | #include <sys/stat.h> | 4 | #include <sys/stat.h> |
5 | #include <unistd.h> | 5 | #include <unistd.h> |
6 | #include <float.h> | ||
6 | #include <math.h> | 7 | #include <math.h> |
7 | #include <stdint.h> | 8 | #include <stdint.h> |
8 | #include <stdio.h> | 9 | #include <stdio.h> |
@@ -141,6 +142,17 @@ bool parse_boolean(const char *boolean, bool current) { | |||
141 | return false; | 142 | return false; |
142 | } | 143 | } |
143 | 144 | ||
145 | float parse_float(const char *value) { | ||
146 | errno = 0; | ||
147 | char *end; | ||
148 | float flt = strtof(value, &end); | ||
149 | if (*end || errno) { | ||
150 | wlr_log(WLR_DEBUG, "Invalid float value '%s', defaulting to NAN", value); | ||
151 | return NAN; | ||
152 | } | ||
153 | return flt; | ||
154 | } | ||
155 | |||
144 | enum wlr_direction opposite_direction(enum wlr_direction d) { | 156 | enum wlr_direction opposite_direction(enum wlr_direction d) { |
145 | switch (d) { | 157 | switch (d) { |
146 | case WLR_DIRECTION_UP: | 158 | case WLR_DIRECTION_UP: |
@@ -21,7 +21,7 @@ set $menu dmenu_path | dmenu | xargs swaymsg exec | |||
21 | 21 | ||
22 | ### Output configuration | 22 | ### Output configuration |
23 | # | 23 | # |
24 | # Default wallpaper (more resolutions are available in __DATADIR__/backgrounds/sway/) | 24 | # Default wallpaper (more resolutions are available in @datadir@/backgrounds/sway/) |
25 | output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill | 25 | output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill |
26 | # | 26 | # |
27 | # Example configuration: | 27 | # Example configuration: |
diff --git a/include/cairo.h b/include/cairo.h index 86530b60..f28c072f 100644 --- a/include/cairo.h +++ b/include/cairo.h | |||
@@ -1,8 +1,13 @@ | |||
1 | #ifndef _SWAY_CAIRO_H | 1 | #ifndef _SWAY_CAIRO_H |
2 | #define _SWAY_CAIRO_H | 2 | #define _SWAY_CAIRO_H |
3 | |||
4 | #include "config.h" | ||
3 | #include <stdint.h> | 5 | #include <stdint.h> |
4 | #include <cairo/cairo.h> | 6 | #include <cairo/cairo.h> |
5 | #include <wlr/types/wlr_output.h> | 7 | #include <wlr/types/wlr_output.h> |
8 | #if HAVE_GDK_PIXBUF | ||
9 | #include <gdk-pixbuf/gdk-pixbuf.h> | ||
10 | #endif | ||
6 | 11 | ||
7 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color); | 12 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color); |
8 | cairo_subpixel_order_t to_cairo_subpixel_order(enum wl_output_subpixel subpixel); | 13 | cairo_subpixel_order_t to_cairo_subpixel_order(enum wl_output_subpixel subpixel); |
@@ -10,12 +15,11 @@ cairo_subpixel_order_t to_cairo_subpixel_order(enum wl_output_subpixel subpixel) | |||
10 | cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, | 15 | cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, |
11 | int width, int height); | 16 | int width, int height); |
12 | 17 | ||
13 | #include "config.h" | 18 | #if HAVE_GDK_PIXBUF |
14 | #ifdef HAVE_GDK_PIXBUF | ||
15 | #include <gdk-pixbuf/gdk-pixbuf.h> | ||
16 | 19 | ||
17 | cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( | 20 | cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( |
18 | const GdkPixbuf *gdkbuf); | 21 | const GdkPixbuf *gdkbuf); |
19 | #endif //WITH_GDK_PIXBUF | 22 | |
23 | #endif // HAVE_GDK_PIXBUF | ||
20 | 24 | ||
21 | #endif | 25 | #endif |
diff --git a/include/stringop.h b/include/stringop.h index 01bbdaa9..919e605c 100644 --- a/include/stringop.h +++ b/include/stringop.h | |||
@@ -1,12 +1,7 @@ | |||
1 | #ifndef _SWAY_STRINGOP_H | 1 | #ifndef _SWAY_STRINGOP_H |
2 | #define _SWAY_STRINGOP_H | 2 | #define _SWAY_STRINGOP_H |
3 | #include <stdlib.h> | ||
4 | #include "list.h" | ||
5 | 3 | ||
6 | #if !HAVE_DECL_SETENV | 4 | #include "list.h" |
7 | // Not sure why we need to provide this | ||
8 | extern int setenv(const char *, const char *, int); | ||
9 | #endif | ||
10 | 5 | ||
11 | // array of whitespace characters to use for delims | 6 | // array of whitespace characters to use for delims |
12 | extern const char whitespace[]; | 7 | extern const char whitespace[]; |
diff --git a/include/sway/commands.h b/include/sway/commands.h index 45f9addd..b0339313 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -230,6 +230,7 @@ sway_cmd input_cmd_map_to_output; | |||
230 | sway_cmd input_cmd_middle_emulation; | 230 | sway_cmd input_cmd_middle_emulation; |
231 | sway_cmd input_cmd_natural_scroll; | 231 | sway_cmd input_cmd_natural_scroll; |
232 | sway_cmd input_cmd_pointer_accel; | 232 | sway_cmd input_cmd_pointer_accel; |
233 | sway_cmd input_cmd_scroll_factor; | ||
233 | sway_cmd input_cmd_repeat_delay; | 234 | sway_cmd input_cmd_repeat_delay; |
234 | sway_cmd input_cmd_repeat_rate; | 235 | sway_cmd input_cmd_repeat_rate; |
235 | sway_cmd input_cmd_scroll_button; | 236 | sway_cmd input_cmd_scroll_button; |
diff --git a/include/sway/config.h b/include/sway/config.h index 5a355139..4927b8e0 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -100,6 +100,7 @@ struct input_config { | |||
100 | int middle_emulation; | 100 | int middle_emulation; |
101 | int natural_scroll; | 101 | int natural_scroll; |
102 | float pointer_accel; | 102 | float pointer_accel; |
103 | float scroll_factor; | ||
103 | int repeat_delay; | 104 | int repeat_delay; |
104 | int repeat_rate; | 105 | int repeat_rate; |
105 | int scroll_button; | 106 | int scroll_button; |
@@ -168,14 +169,24 @@ struct output_config { | |||
168 | }; | 169 | }; |
169 | 170 | ||
170 | /** | 171 | /** |
172 | * Stores size of gaps for each side | ||
173 | */ | ||
174 | struct side_gaps { | ||
175 | int top; | ||
176 | int right; | ||
177 | int bottom; | ||
178 | int left; | ||
179 | }; | ||
180 | |||
181 | /** | ||
171 | * Stores configuration for a workspace, regardless of whether the workspace | 182 | * Stores configuration for a workspace, regardless of whether the workspace |
172 | * exists. | 183 | * exists. |
173 | */ | 184 | */ |
174 | struct workspace_config { | 185 | struct workspace_config { |
175 | char *workspace; | 186 | char *workspace; |
176 | char *output; | 187 | list_t *outputs; |
177 | int gaps_inner; | 188 | int gaps_inner; |
178 | int gaps_outer; | 189 | struct side_gaps gaps_outer; |
179 | }; | 190 | }; |
180 | 191 | ||
181 | struct bar_config { | 192 | struct bar_config { |
@@ -328,6 +339,12 @@ struct ipc_policy { | |||
328 | uint32_t features; | 339 | uint32_t features; |
329 | }; | 340 | }; |
330 | 341 | ||
342 | enum focus_follows_mouse_mode { | ||
343 | FOLLOWS_NO, | ||
344 | FOLLOWS_YES, | ||
345 | FOLLOWS_ALWAYS | ||
346 | }; | ||
347 | |||
331 | enum focus_wrapping_mode { | 348 | enum focus_wrapping_mode { |
332 | WRAP_NO, | 349 | WRAP_NO, |
333 | WRAP_YES, | 350 | WRAP_YES, |
@@ -379,7 +396,7 @@ struct sway_config { | |||
379 | enum sway_popup_during_fullscreen popup_during_fullscreen; | 396 | enum sway_popup_during_fullscreen popup_during_fullscreen; |
380 | 397 | ||
381 | // Flags | 398 | // Flags |
382 | bool focus_follows_mouse; | 399 | enum focus_follows_mouse_mode focus_follows_mouse; |
383 | enum mouse_warping_mode mouse_warping; | 400 | enum mouse_warping_mode mouse_warping; |
384 | enum focus_wrapping_mode focus_wrapping; | 401 | enum focus_wrapping_mode focus_wrapping; |
385 | bool active; | 402 | bool active; |
@@ -393,7 +410,7 @@ struct sway_config { | |||
393 | 410 | ||
394 | bool smart_gaps; | 411 | bool smart_gaps; |
395 | int gaps_inner; | 412 | int gaps_inner; |
396 | int gaps_outer; | 413 | struct side_gaps gaps_outer; |
397 | 414 | ||
398 | list_t *config_chain; | 415 | list_t *config_chain; |
399 | const char *current_config_path; | 416 | const char *current_config_path; |
diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 323ba01d..3eb583d5 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h | |||
@@ -25,7 +25,7 @@ struct criteria { | |||
25 | pcre *app_id; | 25 | pcre *app_id; |
26 | pcre *con_mark; | 26 | pcre *con_mark; |
27 | uint32_t con_id; // internal ID | 27 | uint32_t con_id; // internal ID |
28 | #ifdef HAVE_XWAYLAND | 28 | #if HAVE_XWAYLAND |
29 | pcre *class; | 29 | pcre *class; |
30 | uint32_t id; // X11 window ID | 30 | uint32_t id; // X11 window ID |
31 | pcre *instance; | 31 | pcre *instance; |
diff --git a/include/sway/output.h b/include/sway/output.h index 5efe1660..43c1ab96 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -119,7 +119,7 @@ void output_layer_for_each_surface(struct sway_output *output, | |||
119 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, | 119 | struct wl_list *layer_surfaces, sway_surface_iterator_func_t iterator, |
120 | void *user_data); | 120 | void *user_data); |
121 | 121 | ||
122 | #ifdef HAVE_XWAYLAND | 122 | #if HAVE_XWAYLAND |
123 | void output_unmanaged_for_each_surface(struct sway_output *output, | 123 | void output_unmanaged_for_each_surface(struct sway_output *output, |
124 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, | 124 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, |
125 | void *user_data); | 125 | void *user_data); |
diff --git a/include/sway/server.h b/include/sway/server.h index 5fced224..a3233d66 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <wlr/types/wlr_xdg_shell.h> | 14 | #include <wlr/types/wlr_xdg_shell.h> |
15 | #include "config.h" | 15 | #include "config.h" |
16 | #include "list.h" | 16 | #include "list.h" |
17 | #ifdef HAVE_XWAYLAND | 17 | #if HAVE_XWAYLAND |
18 | #include "sway/xwayland.h" | 18 | #include "sway/xwayland.h" |
19 | #endif | 19 | #endif |
20 | 20 | ||
@@ -44,7 +44,7 @@ struct sway_server { | |||
44 | struct wlr_xdg_shell *xdg_shell; | 44 | struct wlr_xdg_shell *xdg_shell; |
45 | struct wl_listener xdg_shell_surface; | 45 | struct wl_listener xdg_shell_surface; |
46 | 46 | ||
47 | #ifdef HAVE_XWAYLAND | 47 | #if HAVE_XWAYLAND |
48 | struct sway_xwayland xwayland; | 48 | struct sway_xwayland xwayland; |
49 | struct wl_listener xwayland_surface; | 49 | struct wl_listener xwayland_surface; |
50 | struct wl_listener xwayland_ready; | 50 | struct wl_listener xwayland_ready; |
@@ -80,7 +80,7 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data); | |||
80 | void handle_layer_shell_surface(struct wl_listener *listener, void *data); | 80 | void handle_layer_shell_surface(struct wl_listener *listener, void *data); |
81 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); | 81 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); |
82 | void handle_xdg_shell_surface(struct wl_listener *listener, void *data); | 82 | void handle_xdg_shell_surface(struct wl_listener *listener, void *data); |
83 | #ifdef HAVE_XWAYLAND | 83 | #if HAVE_XWAYLAND |
84 | void handle_xwayland_surface(struct wl_listener *listener, void *data); | 84 | void handle_xwayland_surface(struct wl_listener *listener, void *data); |
85 | #endif | 85 | #endif |
86 | void handle_server_decoration(struct wl_listener *listener, void *data); | 86 | void handle_server_decoration(struct wl_listener *listener, void *data); |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 4366a010..f907aad2 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -41,8 +41,8 @@ enum wlr_direction; | |||
41 | struct sway_container_state { | 41 | struct sway_container_state { |
42 | // Container properties | 42 | // Container properties |
43 | enum sway_container_layout layout; | 43 | enum sway_container_layout layout; |
44 | double con_x, con_y; | 44 | double x, y; |
45 | double con_width, con_height; | 45 | double width, height; |
46 | 46 | ||
47 | bool is_fullscreen; | 47 | bool is_fullscreen; |
48 | 48 | ||
@@ -60,9 +60,8 @@ struct sway_container_state { | |||
60 | bool border_left; | 60 | bool border_left; |
61 | bool border_right; | 61 | bool border_right; |
62 | 62 | ||
63 | // View properties | 63 | double content_x, content_y; |
64 | double view_x, view_y; | 64 | double content_width, content_height; |
65 | double view_width, view_height; | ||
66 | }; | 65 | }; |
67 | 66 | ||
68 | struct sway_container { | 67 | struct sway_container { |
@@ -89,6 +88,9 @@ struct sway_container { | |||
89 | double saved_x, saved_y; | 88 | double saved_x, saved_y; |
90 | double saved_width, saved_height; | 89 | double saved_width, saved_height; |
91 | 90 | ||
91 | double content_x, content_y; | ||
92 | int content_width, content_height; | ||
93 | |||
92 | bool is_fullscreen; | 94 | bool is_fullscreen; |
93 | 95 | ||
94 | enum sway_container_border border; | 96 | enum sway_container_border border; |
@@ -104,7 +106,12 @@ struct sway_container { | |||
104 | bool border_right; | 106 | bool border_right; |
105 | 107 | ||
106 | // The gaps currently applied to the container. | 108 | // The gaps currently applied to the container. |
107 | double current_gaps; | 109 | struct { |
110 | int top; | ||
111 | int right; | ||
112 | int bottom; | ||
113 | int left; | ||
114 | } current_gaps; | ||
108 | 115 | ||
109 | struct sway_workspace *workspace; // NULL when hidden in the scratchpad | 116 | struct sway_workspace *workspace; // NULL when hidden in the scratchpad |
110 | struct sway_container *parent; // NULL if container in root of workspace | 117 | struct sway_container *parent; // NULL if container in root of workspace |
@@ -205,7 +212,7 @@ void container_init_floating(struct sway_container *container); | |||
205 | 212 | ||
206 | void container_set_floating(struct sway_container *container, bool enable); | 213 | void container_set_floating(struct sway_container *container, bool enable); |
207 | 214 | ||
208 | void container_set_geometry_from_floating_view(struct sway_container *con); | 215 | void container_set_geometry_from_content(struct sway_container *con); |
209 | 216 | ||
210 | /** | 217 | /** |
211 | * Determine if the given container is itself floating. | 218 | * Determine if the given container is itself floating. |
diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h index a2d464f9..ceccc920 100644 --- a/include/sway/tree/root.h +++ b/include/sway/tree/root.h | |||
@@ -16,7 +16,7 @@ struct sway_root { | |||
16 | struct wlr_output_layout *output_layout; | 16 | struct wlr_output_layout *output_layout; |
17 | 17 | ||
18 | struct wl_listener output_layout_change; | 18 | struct wl_listener output_layout_change; |
19 | #ifdef HAVE_XWAYLAND | 19 | #if HAVE_XWAYLAND |
20 | struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link | 20 | struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link |
21 | #endif | 21 | #endif |
22 | struct wl_list drag_icons; // sway_drag_icon::link | 22 | struct wl_list drag_icons; // sway_drag_icon::link |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 4a8c3cb1..4716c688 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <wlr/types/wlr_surface.h> | 4 | #include <wlr/types/wlr_surface.h> |
5 | #include <wlr/types/wlr_xdg_shell_v6.h> | 5 | #include <wlr/types/wlr_xdg_shell_v6.h> |
6 | #include "config.h" | 6 | #include "config.h" |
7 | #ifdef HAVE_XWAYLAND | 7 | #if HAVE_XWAYLAND |
8 | #include <wlr/xwayland.h> | 8 | #include <wlr/xwayland.h> |
9 | #endif | 9 | #endif |
10 | #include "sway/input/input-manager.h" | 10 | #include "sway/input/input-manager.h" |
@@ -16,7 +16,7 @@ struct sway_xdg_decoration; | |||
16 | enum sway_view_type { | 16 | enum sway_view_type { |
17 | SWAY_VIEW_XDG_SHELL_V6, | 17 | SWAY_VIEW_XDG_SHELL_V6, |
18 | SWAY_VIEW_XDG_SHELL, | 18 | SWAY_VIEW_XDG_SHELL, |
19 | #ifdef HAVE_XWAYLAND | 19 | #if HAVE_XWAYLAND |
20 | SWAY_VIEW_XWAYLAND, | 20 | SWAY_VIEW_XWAYLAND, |
21 | #endif | 21 | #endif |
22 | }; | 22 | }; |
@@ -28,7 +28,7 @@ enum sway_view_prop { | |||
28 | VIEW_PROP_INSTANCE, | 28 | VIEW_PROP_INSTANCE, |
29 | VIEW_PROP_WINDOW_TYPE, | 29 | VIEW_PROP_WINDOW_TYPE, |
30 | VIEW_PROP_WINDOW_ROLE, | 30 | VIEW_PROP_WINDOW_ROLE, |
31 | #ifdef HAVE_XWAYLAND | 31 | #if HAVE_XWAYLAND |
32 | VIEW_PROP_X11_WINDOW_ID, | 32 | VIEW_PROP_X11_WINDOW_ID, |
33 | VIEW_PROP_X11_PARENT_ID, | 33 | VIEW_PROP_X11_PARENT_ID, |
34 | #endif | 34 | #endif |
@@ -67,10 +67,6 @@ struct sway_view { | |||
67 | 67 | ||
68 | pid_t pid; | 68 | pid_t pid; |
69 | 69 | ||
70 | // Geometry of the view itself (excludes borders) in layout coordinates | ||
71 | double x, y; | ||
72 | int width, height; | ||
73 | |||
74 | double saved_x, saved_y; | 70 | double saved_x, saved_y; |
75 | int saved_width, saved_height; | 71 | int saved_width, saved_height; |
76 | 72 | ||
@@ -104,7 +100,7 @@ struct sway_view { | |||
104 | union { | 100 | union { |
105 | struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; | 101 | struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; |
106 | struct wlr_xdg_surface *wlr_xdg_surface; | 102 | struct wlr_xdg_surface *wlr_xdg_surface; |
107 | #ifdef HAVE_XWAYLAND | 103 | #if HAVE_XWAYLAND |
108 | struct wlr_xwayland_surface *wlr_xwayland_surface; | 104 | struct wlr_xwayland_surface *wlr_xwayland_surface; |
109 | #endif | 105 | #endif |
110 | struct wlr_wl_shell_surface *wlr_wl_shell_surface; | 106 | struct wlr_wl_shell_surface *wlr_wl_shell_surface; |
@@ -148,7 +144,7 @@ struct sway_xdg_shell_view { | |||
148 | struct wl_listener unmap; | 144 | struct wl_listener unmap; |
149 | struct wl_listener destroy; | 145 | struct wl_listener destroy; |
150 | }; | 146 | }; |
151 | #ifdef HAVE_XWAYLAND | 147 | #if HAVE_XWAYLAND |
152 | struct sway_xwayland_view { | 148 | struct sway_xwayland_view { |
153 | struct sway_view view; | 149 | struct sway_view view; |
154 | 150 | ||
@@ -327,7 +323,7 @@ struct sway_view *view_from_wlr_xdg_surface( | |||
327 | struct wlr_xdg_surface *xdg_surface); | 323 | struct wlr_xdg_surface *xdg_surface); |
328 | struct sway_view *view_from_wlr_xdg_surface_v6( | 324 | struct sway_view *view_from_wlr_xdg_surface_v6( |
329 | struct wlr_xdg_surface_v6 *xdg_surface_v6); | 325 | struct wlr_xdg_surface_v6 *xdg_surface_v6); |
330 | #ifdef HAVE_XWAYLAND | 326 | #if HAVE_XWAYLAND |
331 | struct sway_view *view_from_wlr_xwayland_surface( | 327 | struct sway_view *view_from_wlr_xwayland_surface( |
332 | struct wlr_xwayland_surface *xsurface); | 328 | struct wlr_xwayland_surface *xsurface); |
333 | #endif | 329 | #endif |
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index b5ae92f3..7abfbff1 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h | |||
@@ -32,9 +32,9 @@ struct sway_workspace { | |||
32 | enum sway_container_layout layout; | 32 | enum sway_container_layout layout; |
33 | enum sway_container_layout prev_split_layout; | 33 | enum sway_container_layout prev_split_layout; |
34 | 34 | ||
35 | int current_gaps; | 35 | struct side_gaps current_gaps; |
36 | int gaps_inner; | 36 | int gaps_inner; |
37 | int gaps_outer; | 37 | struct side_gaps gaps_outer; |
38 | 38 | ||
39 | struct sway_output *output; // NULL if no outputs are connected | 39 | struct sway_output *output; // NULL if no outputs are connected |
40 | list_t *floating; // struct sway_container | 40 | list_t *floating; // struct sway_container |
diff --git a/include/util.h b/include/util.h index f143d0c0..84318fe7 100644 --- a/include/util.h +++ b/include/util.h | |||
@@ -59,6 +59,12 @@ uint32_t parse_color(const char *color); | |||
59 | */ | 59 | */ |
60 | bool parse_boolean(const char *boolean, bool current); | 60 | bool parse_boolean(const char *boolean, bool current); |
61 | 61 | ||
62 | /** | ||
63 | * Given a string that represents a floating point value, return a float. | ||
64 | * Returns NAN on error. | ||
65 | */ | ||
66 | float parse_float(const char *value); | ||
67 | |||
62 | enum wlr_direction opposite_direction(enum wlr_direction d); | 68 | enum wlr_direction opposite_direction(enum wlr_direction d); |
63 | 69 | ||
64 | #endif | 70 | #endif |
diff --git a/meson.build b/meson.build index 6b23b4e3..bb60bc89 100644 --- a/meson.build +++ b/meson.build | |||
@@ -9,11 +9,17 @@ project( | |||
9 | ], | 9 | ], |
10 | ) | 10 | ) |
11 | 11 | ||
12 | add_project_arguments('-Wno-unused-parameter', language: 'c') | 12 | add_project_arguments( |
13 | add_project_arguments('-Wno-unused-function', language: 'c') | 13 | [ |
14 | add_project_arguments('-Wno-unused-result', language: 'c') | 14 | '-DWL_HIDE_DEPRECATED', |
15 | add_project_arguments('-DWL_HIDE_DEPRECATED', language: 'c') | 15 | '-DWLR_USE_UNSTABLE', |
16 | add_project_arguments('-DWLR_USE_UNSTABLE', language: 'c') | 16 | |
17 | '-Wno-unused-parameter', | ||
18 | '-Wno-unused-result', | ||
19 | '-Wundef', | ||
20 | ], | ||
21 | language: 'c', | ||
22 | ) | ||
17 | 23 | ||
18 | cc = meson.get_compiler('c') | 24 | cc = meson.get_compiler('c') |
19 | 25 | ||
@@ -53,30 +59,18 @@ git = find_program('git', required: false) | |||
53 | 59 | ||
54 | conf_data = configuration_data() | 60 | conf_data = configuration_data() |
55 | 61 | ||
62 | conf_data.set10('HAVE_XWAYLAND', get_option('enable-xwayland')) | ||
56 | if get_option('enable-xwayland') | 63 | if get_option('enable-xwayland') |
57 | conf_data.set('HAVE_XWAYLAND', true) | ||
58 | xcb = dependency('xcb') | 64 | xcb = dependency('xcb') |
59 | else | ||
60 | conf_data.set('HAVE_XWAYLAND', false) | ||
61 | endif | ||
62 | |||
63 | if gdk_pixbuf.found() | ||
64 | conf_data.set('HAVE_GDK_PIXBUF', true) | ||
65 | endif | ||
66 | |||
67 | if systemd.found() | ||
68 | conf_data.set('SWAY_IDLE_HAS_SYSTEMD', true) | ||
69 | swayidle_deps += systemd | ||
70 | endif | 65 | endif |
71 | 66 | ||
72 | if elogind.found() | 67 | conf_data.set10('HAVE_GDK_PIXBUF', gdk_pixbuf.found()) |
73 | conf_data.set('SWAY_IDLE_HAS_ELOGIND', true) | 68 | conf_data.set10('HAVE_SYSTEMD', systemd.found()) |
74 | swayidle_deps += elogind | 69 | conf_data.set10('HAVE_ELOGIND', elogind.found()) |
75 | endif | ||
76 | 70 | ||
77 | if not systemd.found() and not elogind.found() | 71 | if not systemd.found() and not elogind.found() |
78 | warning('The sway binary must be setuid when compiled without (e)logind') | 72 | warning('The sway binary must be setuid when compiled without (e)logind') |
79 | warning('You must do this manually post-install: chmod a+s /path/to/sway') | 73 | warning('You must do this manually post-install: chmod a+s /path/to/sway') |
80 | endif | 74 | endif |
81 | 75 | ||
82 | scdoc = find_program('scdoc', required: false) | 76 | scdoc = find_program('scdoc', required: false) |
diff --git a/sway/commands.c b/sway/commands.c index 37c7169a..4b86c2fa 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -353,12 +353,14 @@ struct cmd_results *config_command(char *exec) { | |||
353 | struct cmd_results *results = NULL; | 353 | struct cmd_results *results = NULL; |
354 | int argc; | 354 | int argc; |
355 | char **argv = split_args(exec, &argc); | 355 | char **argv = split_args(exec, &argc); |
356 | |||
357 | // Check for empty lines | ||
356 | if (!argc) { | 358 | if (!argc) { |
357 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); | 359 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); |
358 | goto cleanup; | 360 | goto cleanup; |
359 | } | 361 | } |
360 | 362 | ||
361 | // Start block | 363 | // Check for the start of a block |
362 | if (argc > 1 && strcmp(argv[argc - 1], "{") == 0) { | 364 | if (argc > 1 && strcmp(argv[argc - 1], "{") == 0) { |
363 | char *block = join_args(argv, argc - 1); | 365 | char *block = join_args(argv, argc - 1); |
364 | results = cmd_results_new(CMD_BLOCK, block, NULL); | 366 | results = cmd_results_new(CMD_BLOCK, block, NULL); |
@@ -366,22 +368,54 @@ struct cmd_results *config_command(char *exec) { | |||
366 | goto cleanup; | 368 | goto cleanup; |
367 | } | 369 | } |
368 | 370 | ||
369 | // Endblock | 371 | // Check for the end of a block |
370 | if (strcmp(argv[argc - 1], "}") == 0) { | 372 | if (strcmp(argv[argc - 1], "}") == 0) { |
371 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); | 373 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); |
372 | goto cleanup; | 374 | goto cleanup; |
373 | } | 375 | } |
374 | wlr_log(WLR_INFO, "handling config command '%s'", exec); | 376 | |
377 | // Make sure the command is not stored in a variable | ||
378 | if (*argv[0] == '$') { | ||
379 | argv[0] = do_var_replacement(argv[0]); | ||
380 | char *temp = join_args(argv, argc); | ||
381 | free_argv(argc, argv); | ||
382 | argv = split_args(temp, &argc); | ||
383 | free(temp); | ||
384 | if (!argc) { | ||
385 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
386 | goto cleanup; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | // Determine the command handler | ||
391 | wlr_log(WLR_INFO, "Config command: %s", exec); | ||
375 | struct cmd_handler *handler = find_handler(argv[0], NULL, 0); | 392 | struct cmd_handler *handler = find_handler(argv[0], NULL, 0); |
376 | if (!handler) { | 393 | if (!handler || !handler->handle) { |
377 | char *input = argv[0] ? argv[0] : "(empty)"; | 394 | char *input = argv[0] ? argv[0] : "(empty)"; |
378 | results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); | 395 | char *error = handler |
396 | ? "This command is shimmed, but unimplemented" | ||
397 | : "Unknown/invalid command"; | ||
398 | results = cmd_results_new(CMD_INVALID, input, error); | ||
379 | goto cleanup; | 399 | goto cleanup; |
380 | } | 400 | } |
381 | int i; | 401 | |
382 | // Var replacement, for all but first argument of set | 402 | // Do variable replacement |
383 | // TODO commands | 403 | if (handler->handle == cmd_set && argc > 1 && *argv[1] == '$') { |
384 | for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { | 404 | // Escape the variable name so it does not get replaced by one shorter |
405 | char *temp = calloc(1, strlen(argv[1]) + 2); | ||
406 | temp[0] = '$'; | ||
407 | strcpy(&temp[1], argv[1]); | ||
408 | free(argv[1]); | ||
409 | argv[1] = temp; | ||
410 | } | ||
411 | char *command = do_var_replacement(join_args(argv, argc)); | ||
412 | wlr_log(WLR_INFO, "After replacement: %s", command); | ||
413 | free_argv(argc, argv); | ||
414 | argv = split_args(command, &argc); | ||
415 | free(command); | ||
416 | |||
417 | // Strip quotes and unescape the string | ||
418 | for (int i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { | ||
385 | if (handler->handle != cmd_exec && handler->handle != cmd_exec_always | 419 | if (handler->handle != cmd_exec && handler->handle != cmd_exec_always |
386 | && handler->handle != cmd_bindsym | 420 | && handler->handle != cmd_bindsym |
387 | && handler->handle != cmd_bindcode | 421 | && handler->handle != cmd_bindcode |
@@ -389,14 +423,11 @@ struct cmd_results *config_command(char *exec) { | |||
389 | && (*argv[i] == '\"' || *argv[i] == '\'')) { | 423 | && (*argv[i] == '\"' || *argv[i] == '\'')) { |
390 | strip_quotes(argv[i]); | 424 | strip_quotes(argv[i]); |
391 | } | 425 | } |
392 | argv[i] = do_var_replacement(argv[i]); | ||
393 | unescape_string(argv[i]); | 426 | unescape_string(argv[i]); |
394 | } | 427 | } |
395 | if (handler->handle) { | 428 | |
396 | results = handler->handle(argc-1, argv+1); | 429 | // Run command |
397 | } else { | 430 | results = handler->handle(argc - 1, argv + 1); |
398 | results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented"); | ||
399 | } | ||
400 | 431 | ||
401 | cleanup: | 432 | cleanup: |
402 | free_argv(argc, argv); | 433 | free_argv(argc, argv); |
diff --git a/sway/commands/bar/binding_mode_indicator.c b/sway/commands/bar/binding_mode_indicator.c index f18b8d7c..b048b7b9 100644 --- a/sway/commands/bar/binding_mode_indicator.c +++ b/sway/commands/bar/binding_mode_indicator.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <strings.h> | 2 | #include <strings.h> |
3 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
4 | #include "log.h" | 4 | #include "log.h" |
5 | #include "util.h" | ||
5 | 6 | ||
6 | struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { | 7 | struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { |
7 | struct cmd_results *error = NULL; | 8 | struct cmd_results *error = NULL; |
@@ -13,17 +14,14 @@ struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { | |||
13 | return cmd_results_new(CMD_FAILURE, | 14 | return cmd_results_new(CMD_FAILURE, |
14 | "binding_mode_indicator", "No bar defined."); | 15 | "binding_mode_indicator", "No bar defined."); |
15 | } | 16 | } |
16 | if (strcasecmp("yes", argv[0]) == 0) { | 17 | config->current_bar->binding_mode_indicator = |
17 | config->current_bar->binding_mode_indicator = true; | 18 | parse_boolean(argv[0], config->current_bar->binding_mode_indicator); |
19 | if (config->current_bar->binding_mode_indicator) { | ||
18 | wlr_log(WLR_DEBUG, "Enabling binding mode indicator on bar: %s", | 20 | wlr_log(WLR_DEBUG, "Enabling binding mode indicator on bar: %s", |
19 | config->current_bar->id); | 21 | config->current_bar->id); |
20 | } else if (strcasecmp("no", argv[0]) == 0) { | 22 | } else { |
21 | config->current_bar->binding_mode_indicator = false; | ||
22 | wlr_log(WLR_DEBUG, "Disabling binding mode indicator on bar: %s", | 23 | wlr_log(WLR_DEBUG, "Disabling binding mode indicator on bar: %s", |
23 | config->current_bar->id); | 24 | config->current_bar->id); |
24 | } else { | ||
25 | return cmd_results_new(CMD_INVALID, "binding_mode_indicator", | ||
26 | "Invalid value %s", argv[0]); | ||
27 | } | 25 | } |
28 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 26 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
29 | } | 27 | } |
diff --git a/sway/commands/bar/pango_markup.c b/sway/commands/bar/pango_markup.c index 857571fb..d57cc45c 100644 --- a/sway/commands/bar/pango_markup.c +++ b/sway/commands/bar/pango_markup.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <strings.h> | 2 | #include <strings.h> |
3 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
4 | #include "log.h" | 4 | #include "log.h" |
5 | #include "util.h" | ||
5 | 6 | ||
6 | struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { | 7 | struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { |
7 | struct cmd_results *error = NULL; | 8 | struct cmd_results *error = NULL; |
@@ -11,18 +12,14 @@ struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { | |||
11 | if (!config->current_bar) { | 12 | if (!config->current_bar) { |
12 | return cmd_results_new(CMD_FAILURE, "pango_markup", "No bar defined."); | 13 | return cmd_results_new(CMD_FAILURE, "pango_markup", "No bar defined."); |
13 | } | 14 | } |
14 | if (strcasecmp("enabled", argv[0]) == 0) { | 15 | config->current_bar->pango_markup |
15 | config->current_bar->pango_markup = true; | 16 | = parse_boolean(argv[0], config->current_bar->pango_markup); |
17 | if (config->current_bar->pango_markup) { | ||
16 | wlr_log(WLR_DEBUG, "Enabling pango markup for bar: %s", | 18 | wlr_log(WLR_DEBUG, "Enabling pango markup for bar: %s", |
17 | config->current_bar->id); | 19 | config->current_bar->id); |
18 | } else if (strcasecmp("disabled", argv[0]) == 0) { | 20 | } else { |
19 | config->current_bar->pango_markup = false; | ||
20 | wlr_log(WLR_DEBUG, "Disabling pango markup for bar: %s", | 21 | wlr_log(WLR_DEBUG, "Disabling pango markup for bar: %s", |
21 | config->current_bar->id); | 22 | config->current_bar->id); |
22 | } else { | ||
23 | error = cmd_results_new(CMD_INVALID, "pango_markup", | ||
24 | "Invalid value %s", argv[0]); | ||
25 | return error; | ||
26 | } | 23 | } |
27 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 24 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
28 | } | 25 | } |
diff --git a/sway/commands/bar/workspace_buttons.c b/sway/commands/bar/workspace_buttons.c index a4079b2a..cd001e20 100644 --- a/sway/commands/bar/workspace_buttons.c +++ b/sway/commands/bar/workspace_buttons.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <strings.h> | 2 | #include <strings.h> |
3 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
4 | #include "log.h" | 4 | #include "log.h" |
5 | #include "util.h" | ||
5 | 6 | ||
6 | struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { | 7 | struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { |
7 | struct cmd_results *error = NULL; | 8 | struct cmd_results *error = NULL; |
@@ -12,17 +13,14 @@ struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { | |||
12 | return cmd_results_new(CMD_FAILURE, | 13 | return cmd_results_new(CMD_FAILURE, |
13 | "workspace_buttons", "No bar defined."); | 14 | "workspace_buttons", "No bar defined."); |
14 | } | 15 | } |
15 | if (strcasecmp("yes", argv[0]) == 0) { | 16 | config->current_bar->workspace_buttons = |
16 | config->current_bar->workspace_buttons = true; | 17 | parse_boolean(argv[0], config->current_bar->workspace_buttons); |
18 | if (config->current_bar->workspace_buttons) { | ||
17 | wlr_log(WLR_DEBUG, "Enabling workspace buttons on bar: %s", | 19 | wlr_log(WLR_DEBUG, "Enabling workspace buttons on bar: %s", |
18 | config->current_bar->id); | 20 | config->current_bar->id); |
19 | } else if (strcasecmp("no", argv[0]) == 0) { | 21 | } else { |
20 | config->current_bar->workspace_buttons = false; | ||
21 | wlr_log(WLR_DEBUG, "Disabling workspace buttons on bar: %s", | 22 | wlr_log(WLR_DEBUG, "Disabling workspace buttons on bar: %s", |
22 | config->current_bar->id); | 23 | config->current_bar->id); |
23 | } else { | ||
24 | return cmd_results_new(CMD_INVALID, "workspace_buttons", | ||
25 | "Invalid value %s", argv[0]); | ||
26 | } | 24 | } |
27 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
28 | } | 26 | } |
diff --git a/sway/commands/bar/wrap_scroll.c b/sway/commands/bar/wrap_scroll.c index 701de00a..04a4e6b8 100644 --- a/sway/commands/bar/wrap_scroll.c +++ b/sway/commands/bar/wrap_scroll.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <strings.h> | 2 | #include <strings.h> |
3 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
4 | #include "log.h" | 4 | #include "log.h" |
5 | #include "util.h" | ||
5 | 6 | ||
6 | struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { | 7 | struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { |
7 | struct cmd_results *error = NULL; | 8 | struct cmd_results *error = NULL; |
@@ -11,17 +12,14 @@ struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { | |||
11 | if (!config->current_bar) { | 12 | if (!config->current_bar) { |
12 | return cmd_results_new(CMD_FAILURE, "wrap_scroll", "No bar defined."); | 13 | return cmd_results_new(CMD_FAILURE, "wrap_scroll", "No bar defined."); |
13 | } | 14 | } |
14 | if (strcasecmp("yes", argv[0]) == 0) { | 15 | config->current_bar->wrap_scroll = |
15 | config->current_bar->wrap_scroll = true; | 16 | parse_boolean(argv[0], config->current_bar->wrap_scroll); |
17 | if (config->current_bar->wrap_scroll) { | ||
16 | wlr_log(WLR_DEBUG, "Enabling wrap scroll on bar: %s", | 18 | wlr_log(WLR_DEBUG, "Enabling wrap scroll on bar: %s", |
17 | config->current_bar->id); | 19 | config->current_bar->id); |
18 | } else if (strcasecmp("no", argv[0]) == 0) { | 20 | } else { |
19 | config->current_bar->wrap_scroll = false; | ||
20 | wlr_log(WLR_DEBUG, "Disabling wrap scroll on bar: %s", | 21 | wlr_log(WLR_DEBUG, "Disabling wrap scroll on bar: %s", |
21 | config->current_bar->id); | 22 | config->current_bar->id); |
22 | } else { | ||
23 | return cmd_results_new(CMD_INVALID, | ||
24 | "wrap_scroll", "Invalid value %s", argv[0]); | ||
25 | } | 23 | } |
26 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 24 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
27 | } | 25 | } |
diff --git a/sway/commands/border.c b/sway/commands/border.c index b6eab550..d51741d2 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c | |||
@@ -93,7 +93,7 @@ struct cmd_results *cmd_border(int argc, char **argv) { | |||
93 | } | 93 | } |
94 | 94 | ||
95 | if (container_is_floating(container)) { | 95 | if (container_is_floating(container)) { |
96 | container_set_geometry_from_floating_view(container); | 96 | container_set_geometry_from_content(container); |
97 | } | 97 | } |
98 | 98 | ||
99 | arrange_container(container); | 99 | arrange_container(container); |
diff --git a/sway/commands/create_output.c b/sway/commands/create_output.c index 1c2464ea..3f870acb 100644 --- a/sway/commands/create_output.c +++ b/sway/commands/create_output.c | |||
@@ -1,7 +1,7 @@ | |||
1 | #include <wlr/config.h> | 1 | #include <wlr/config.h> |
2 | #include <wlr/backend/multi.h> | 2 | #include <wlr/backend/multi.h> |
3 | #include <wlr/backend/wayland.h> | 3 | #include <wlr/backend/wayland.h> |
4 | #ifdef WLR_HAS_X11_BACKEND | 4 | #if WLR_HAS_X11_BACKEND |
5 | #include <wlr/backend/x11.h> | 5 | #include <wlr/backend/x11.h> |
6 | #endif | 6 | #endif |
7 | #include "sway/commands.h" | 7 | #include "sway/commands.h" |
@@ -18,7 +18,7 @@ static void create_output(struct wlr_backend *backend, void *data) { | |||
18 | wlr_wl_output_create(backend); | 18 | wlr_wl_output_create(backend); |
19 | *done = true; | 19 | *done = true; |
20 | } | 20 | } |
21 | #ifdef WLR_HAS_X11_BACKEND | 21 | #if WLR_HAS_X11_BACKEND |
22 | else if (wlr_backend_is_x11(backend)) { | 22 | else if (wlr_backend_is_x11(backend)) { |
23 | wlr_x11_output_create(backend); | 23 | wlr_x11_output_create(backend); |
24 | *done = true; | 24 | *done = true; |
diff --git a/sway/commands/floating.c b/sway/commands/floating.c index 81bb86f8..4b82921c 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "sway/tree/view.h" | 9 | #include "sway/tree/view.h" |
10 | #include "sway/tree/workspace.h" | 10 | #include "sway/tree/workspace.h" |
11 | #include "list.h" | 11 | #include "list.h" |
12 | #include "util.h" | ||
12 | 13 | ||
13 | struct cmd_results *cmd_floating(int argc, char **argv) { | 14 | struct cmd_results *cmd_floating(int argc, char **argv) { |
14 | struct cmd_results *error = NULL; | 15 | struct cmd_results *error = NULL; |
@@ -40,17 +41,8 @@ struct cmd_results *cmd_floating(int argc, char **argv) { | |||
40 | } | 41 | } |
41 | } | 42 | } |
42 | 43 | ||
43 | bool wants_floating; | 44 | bool wants_floating = |
44 | if (strcasecmp(argv[0], "enable") == 0) { | 45 | parse_boolean(argv[0], container_is_floating(container)); |
45 | wants_floating = true; | ||
46 | } else if (strcasecmp(argv[0], "disable") == 0) { | ||
47 | wants_floating = false; | ||
48 | } else if (strcasecmp(argv[0], "toggle") == 0) { | ||
49 | wants_floating = !container_is_floating(container); | ||
50 | } else { | ||
51 | return cmd_results_new(CMD_FAILURE, "floating", | ||
52 | "Expected 'floating <enable|disable|toggle>'"); | ||
53 | } | ||
54 | 46 | ||
55 | container_set_floating(container, wants_floating); | 47 | container_set_floating(container, wants_floating); |
56 | 48 | ||
diff --git a/sway/commands/focus_follows_mouse.c b/sway/commands/focus_follows_mouse.c index 0b0e334c..d0d2cb8a 100644 --- a/sway/commands/focus_follows_mouse.c +++ b/sway/commands/focus_follows_mouse.c | |||
@@ -7,8 +7,15 @@ struct cmd_results *cmd_focus_follows_mouse(int argc, char **argv) { | |||
7 | struct cmd_results *error = NULL; | 7 | struct cmd_results *error = NULL; |
8 | if ((error = checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1))) { | 8 | if ((error = checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1))) { |
9 | return error; | 9 | return error; |
10 | } else if(strcmp(argv[0], "no") == 0) { | ||
11 | config->focus_follows_mouse = FOLLOWS_NO; | ||
12 | } else if(strcmp(argv[0], "yes") == 0) { | ||
13 | config->focus_follows_mouse = FOLLOWS_YES; | ||
14 | } else if(strcmp(argv[0], "always") == 0) { | ||
15 | config->focus_follows_mouse = FOLLOWS_ALWAYS; | ||
16 | } else { | ||
17 | return cmd_results_new(CMD_FAILURE, "focus_follows_mouse", | ||
18 | "Expected 'focus_follows_mouse no|yes|always'"); | ||
10 | } | 19 | } |
11 | config->focus_follows_mouse = | ||
12 | parse_boolean(argv[0], config->focus_follows_mouse); | ||
13 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 20 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
14 | } | 21 | } |
diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c index 3f0ef155..faaeab37 100644 --- a/sway/commands/gaps.c +++ b/sway/commands/gaps.c | |||
@@ -16,73 +16,128 @@ enum gaps_op { | |||
16 | 16 | ||
17 | struct gaps_data { | 17 | struct gaps_data { |
18 | bool inner; | 18 | bool inner; |
19 | struct { | ||
20 | bool top; | ||
21 | bool right; | ||
22 | bool bottom; | ||
23 | bool left; | ||
24 | } outer; | ||
19 | enum gaps_op operation; | 25 | enum gaps_op operation; |
20 | int amount; | 26 | int amount; |
21 | }; | 27 | }; |
22 | 28 | ||
23 | // gaps inner|outer <px> | 29 | // Prevent negative outer gaps from moving windows out of the workspace. |
30 | static void prevent_invalid_outer_gaps(void) { | ||
31 | if (config->gaps_outer.top < -config->gaps_inner) { | ||
32 | config->gaps_outer.top = -config->gaps_inner; | ||
33 | } | ||
34 | if (config->gaps_outer.right < -config->gaps_inner) { | ||
35 | config->gaps_outer.right = -config->gaps_inner; | ||
36 | } | ||
37 | if (config->gaps_outer.bottom < -config->gaps_inner) { | ||
38 | config->gaps_outer.bottom = -config->gaps_inner; | ||
39 | } | ||
40 | if (config->gaps_outer.left < -config->gaps_inner) { | ||
41 | config->gaps_outer.left = -config->gaps_inner; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | // gaps inner|outer|horizontal|vertical|top|right|bottom|left <px> | ||
46 | static const char *expected_defaults = | ||
47 | "'gaps inner|outer|horizontal|vertical|top|right|bottom|left <px>'"; | ||
24 | static struct cmd_results *gaps_set_defaults(int argc, char **argv) { | 48 | static struct cmd_results *gaps_set_defaults(int argc, char **argv) { |
25 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2); | 49 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2); |
26 | if (error) { | 50 | if (error) { |
27 | return error; | 51 | return error; |
28 | } | 52 | } |
29 | 53 | ||
30 | bool inner; | ||
31 | if (strcasecmp(argv[0], "inner") == 0) { | ||
32 | inner = true; | ||
33 | } else if (strcasecmp(argv[0], "outer") == 0) { | ||
34 | inner = false; | ||
35 | } else { | ||
36 | return cmd_results_new(CMD_INVALID, "gaps", | ||
37 | "Expected 'gaps inner|outer <px>'"); | ||
38 | } | ||
39 | |||
40 | char *end; | 54 | char *end; |
41 | int amount = strtol(argv[1], &end, 10); | 55 | int amount = strtol(argv[1], &end, 10); |
42 | if (strlen(end) && strcasecmp(end, "px") != 0) { | 56 | if (strlen(end) && strcasecmp(end, "px") != 0) { |
43 | return cmd_results_new(CMD_INVALID, "gaps", | 57 | return cmd_results_new(CMD_INVALID, "gaps", |
44 | "Expected 'gaps inner|outer <px>'"); | 58 | "Expected %s", expected_defaults); |
45 | } | 59 | } |
46 | if (inner) { | 60 | |
61 | bool valid = false; | ||
62 | if (!strcasecmp(argv[0], "inner")) { | ||
63 | valid = true; | ||
47 | config->gaps_inner = (amount >= 0) ? amount : 0; | 64 | config->gaps_inner = (amount >= 0) ? amount : 0; |
48 | } else { | 65 | } else { |
49 | config->gaps_outer = amount; | 66 | if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "vertical") |
50 | } | 67 | || !strcasecmp(argv[0], "top")) { |
51 | 68 | valid = true; | |
52 | // Prevent negative outer gaps from moving windows out of the workspace. | 69 | config->gaps_outer.top = amount; |
53 | if (config->gaps_outer < -config->gaps_inner) { | 70 | } |
54 | config->gaps_outer = -config->gaps_inner; | 71 | if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "horizontal") |
72 | || !strcasecmp(argv[0], "right")) { | ||
73 | valid = true; | ||
74 | config->gaps_outer.right = amount; | ||
75 | } | ||
76 | if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "vertical") | ||
77 | || !strcasecmp(argv[0], "bottom")) { | ||
78 | valid = true; | ||
79 | config->gaps_outer.bottom = amount; | ||
80 | } | ||
81 | if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "horizontal") | ||
82 | || !strcasecmp(argv[0], "left")) { | ||
83 | valid = true; | ||
84 | config->gaps_outer.left = amount; | ||
85 | } | ||
86 | } | ||
87 | if (!valid) { | ||
88 | return cmd_results_new(CMD_INVALID, "gaps", | ||
89 | "Expected %s", expected_defaults); | ||
55 | } | 90 | } |
56 | 91 | ||
92 | prevent_invalid_outer_gaps(); | ||
57 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 93 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
58 | } | 94 | } |
59 | 95 | ||
60 | static void configure_gaps(struct sway_workspace *ws, void *_data) { | 96 | static void apply_gaps_op(int *prop, enum gaps_op op, int amount) { |
61 | struct gaps_data *data = _data; | 97 | switch (op) { |
62 | int *prop = data->inner ? &ws->gaps_inner : &ws->gaps_outer; | ||
63 | |||
64 | switch (data->operation) { | ||
65 | case GAPS_OP_SET: | 98 | case GAPS_OP_SET: |
66 | *prop = data->amount; | 99 | *prop = amount; |
67 | break; | 100 | break; |
68 | case GAPS_OP_ADD: | 101 | case GAPS_OP_ADD: |
69 | *prop += data->amount; | 102 | *prop += amount; |
70 | break; | 103 | break; |
71 | case GAPS_OP_SUBTRACT: | 104 | case GAPS_OP_SUBTRACT: |
72 | *prop -= data->amount; | 105 | *prop -= amount; |
73 | break; | 106 | break; |
74 | } | 107 | } |
108 | } | ||
109 | |||
110 | static void configure_gaps(struct sway_workspace *ws, void *_data) { | ||
111 | // Apply operation to gaps | ||
112 | struct gaps_data *data = _data; | ||
113 | if (data->inner) { | ||
114 | apply_gaps_op(&ws->gaps_inner, data->operation, data->amount); | ||
115 | } | ||
116 | if (data->outer.top) { | ||
117 | apply_gaps_op(&(ws->gaps_outer.top), data->operation, data->amount); | ||
118 | } | ||
119 | if (data->outer.right) { | ||
120 | apply_gaps_op(&(ws->gaps_outer.right), data->operation, data->amount); | ||
121 | } | ||
122 | if (data->outer.bottom) { | ||
123 | apply_gaps_op(&(ws->gaps_outer.bottom), data->operation, data->amount); | ||
124 | } | ||
125 | if (data->outer.left) { | ||
126 | apply_gaps_op(&(ws->gaps_outer.left), data->operation, data->amount); | ||
127 | } | ||
128 | |||
75 | // Prevent invalid gaps configurations. | 129 | // Prevent invalid gaps configurations. |
76 | if (ws->gaps_inner < 0) { | 130 | if (ws->gaps_inner < 0) { |
77 | ws->gaps_inner = 0; | 131 | ws->gaps_inner = 0; |
78 | } | 132 | } |
79 | if (ws->gaps_outer < -ws->gaps_inner) { | 133 | prevent_invalid_outer_gaps(); |
80 | ws->gaps_outer = -ws->gaps_inner; | ||
81 | } | ||
82 | arrange_workspace(ws); | 134 | arrange_workspace(ws); |
83 | } | 135 | } |
84 | 136 | ||
85 | // gaps inner|outer current|all set|plus|minus <px> | 137 | // gaps inner|outer|horizontal|vertical|top|right|bottom|left current|all |
138 | // set|plus|minus <px> | ||
139 | static const char *expected_runtime = "'gaps inner|outer|horizontal|vertical|" | ||
140 | "top|right|bottom|left current|all set|plus|minus <px>'"; | ||
86 | static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | 141 | static struct cmd_results *gaps_set_runtime(int argc, char **argv) { |
87 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); | 142 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); |
88 | if (error) { | 143 | if (error) { |
@@ -93,15 +148,24 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | |||
93 | "Can't run this command while there's no outputs connected."); | 148 | "Can't run this command while there's no outputs connected."); |
94 | } | 149 | } |
95 | 150 | ||
96 | struct gaps_data data; | 151 | struct gaps_data data = {0}; |
97 | 152 | ||
98 | if (strcasecmp(argv[0], "inner") == 0) { | 153 | if (strcasecmp(argv[0], "inner") == 0) { |
99 | data.inner = true; | 154 | data.inner = true; |
100 | } else if (strcasecmp(argv[0], "outer") == 0) { | ||
101 | data.inner = false; | ||
102 | } else { | 155 | } else { |
156 | data.outer.top = !strcasecmp(argv[0], "outer") || | ||
157 | !strcasecmp(argv[0], "vertical") || !strcasecmp(argv[0], "top"); | ||
158 | data.outer.right = !strcasecmp(argv[0], "outer") || | ||
159 | !strcasecmp(argv[0], "horizontal") || !strcasecmp(argv[0], "right"); | ||
160 | data.outer.bottom = !strcasecmp(argv[0], "outer") || | ||
161 | !strcasecmp(argv[0], "vertical") || !strcasecmp(argv[0], "bottom"); | ||
162 | data.outer.left = !strcasecmp(argv[0], "outer") || | ||
163 | !strcasecmp(argv[0], "horizontal") || !strcasecmp(argv[0], "left"); | ||
164 | } | ||
165 | if (!data.inner && !data.outer.top && !data.outer.right && | ||
166 | !data.outer.bottom && !data.outer.left) { | ||
103 | return cmd_results_new(CMD_INVALID, "gaps", | 167 | return cmd_results_new(CMD_INVALID, "gaps", |
104 | "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); | 168 | "Expected %s", expected_runtime); |
105 | } | 169 | } |
106 | 170 | ||
107 | bool all; | 171 | bool all; |
@@ -111,7 +175,7 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | |||
111 | all = true; | 175 | all = true; |
112 | } else { | 176 | } else { |
113 | return cmd_results_new(CMD_INVALID, "gaps", | 177 | return cmd_results_new(CMD_INVALID, "gaps", |
114 | "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); | 178 | "Expected %s", expected_runtime); |
115 | } | 179 | } |
116 | 180 | ||
117 | if (strcasecmp(argv[2], "set") == 0) { | 181 | if (strcasecmp(argv[2], "set") == 0) { |
@@ -122,14 +186,14 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | |||
122 | data.operation = GAPS_OP_SUBTRACT; | 186 | data.operation = GAPS_OP_SUBTRACT; |
123 | } else { | 187 | } else { |
124 | return cmd_results_new(CMD_INVALID, "gaps", | 188 | return cmd_results_new(CMD_INVALID, "gaps", |
125 | "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); | 189 | "Expected %s", expected_runtime); |
126 | } | 190 | } |
127 | 191 | ||
128 | char *end; | 192 | char *end; |
129 | data.amount = strtol(argv[3], &end, 10); | 193 | data.amount = strtol(argv[3], &end, 10); |
130 | if (strlen(end) && strcasecmp(end, "px") != 0) { | 194 | if (strlen(end) && strcasecmp(end, "px") != 0) { |
131 | return cmd_results_new(CMD_INVALID, "gaps", | 195 | return cmd_results_new(CMD_INVALID, "gaps", |
132 | "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); | 196 | "Expected %s", expected_runtime); |
133 | } | 197 | } |
134 | 198 | ||
135 | if (all) { | 199 | if (all) { |
@@ -141,8 +205,10 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { | |||
141 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 205 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
142 | } | 206 | } |
143 | 207 | ||
144 | // gaps inner|outer <px> - sets defaults for workspaces | 208 | // gaps inner|outer|<dir>|<side> <px> - sets defaults for workspaces |
145 | // gaps inner|outer current|all set|plus|minus <px> - runtime only | 209 | // gaps inner|outer|<dir>|<side> current|all set|plus|minus <px> - runtime only |
210 | // <dir> = horizontal|vertical | ||
211 | // <side> = top|right|bottom|left | ||
146 | struct cmd_results *cmd_gaps(int argc, char **argv) { | 212 | struct cmd_results *cmd_gaps(int argc, char **argv) { |
147 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2); | 213 | struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2); |
148 | if (error) { | 214 | if (error) { |
@@ -159,9 +225,8 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { | |||
159 | } | 225 | } |
160 | if (config_loading) { | 226 | if (config_loading) { |
161 | return cmd_results_new(CMD_INVALID, "gaps", | 227 | return cmd_results_new(CMD_INVALID, "gaps", |
162 | "Expected 'gaps inner|outer <px>'"); | 228 | "Expected %s", expected_defaults); |
163 | } | 229 | } |
164 | return cmd_results_new(CMD_INVALID, "gaps", | 230 | return cmd_results_new(CMD_INVALID, "gaps", |
165 | "Expected 'gaps inner|outer <px>' or " | 231 | "Expected %s or %s", expected_runtime, expected_defaults); |
166 | "'gaps inner|outer current|all set|plus|minus <px>'"); | ||
167 | } | 232 | } |
diff --git a/sway/commands/input.c b/sway/commands/input.c index c50926a8..b5765c38 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c | |||
@@ -22,6 +22,7 @@ static struct cmd_handler input_handlers[] = { | |||
22 | { "repeat_delay", input_cmd_repeat_delay }, | 22 | { "repeat_delay", input_cmd_repeat_delay }, |
23 | { "repeat_rate", input_cmd_repeat_rate }, | 23 | { "repeat_rate", input_cmd_repeat_rate }, |
24 | { "scroll_button", input_cmd_scroll_button }, | 24 | { "scroll_button", input_cmd_scroll_button }, |
25 | { "scroll_factor", input_cmd_scroll_factor }, | ||
25 | { "scroll_method", input_cmd_scroll_method }, | 26 | { "scroll_method", input_cmd_scroll_method }, |
26 | { "tap", input_cmd_tap }, | 27 | { "tap", input_cmd_tap }, |
27 | { "tap_button_map", input_cmd_tap_button_map }, | 28 | { "tap_button_map", input_cmd_tap_button_map }, |
diff --git a/sway/commands/input/pointer_accel.c b/sway/commands/input/pointer_accel.c index df487b1c..efd81ee6 100644 --- a/sway/commands/input/pointer_accel.c +++ b/sway/commands/input/pointer_accel.c | |||
@@ -1,8 +1,10 @@ | |||
1 | #include <math.h> | ||
1 | #include <stdlib.h> | 2 | #include <stdlib.h> |
2 | #include <string.h> | 3 | #include <string.h> |
3 | #include "sway/config.h" | 4 | #include "sway/config.h" |
4 | #include "sway/commands.h" | 5 | #include "sway/commands.h" |
5 | #include "sway/input/input-manager.h" | 6 | #include "sway/input/input-manager.h" |
7 | #include "util.h" | ||
6 | 8 | ||
7 | struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { | 9 | struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { |
8 | struct cmd_results *error = NULL; | 10 | struct cmd_results *error = NULL; |
@@ -15,8 +17,11 @@ struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { | |||
15 | "pointer_accel", "No input device defined."); | 17 | "pointer_accel", "No input device defined."); |
16 | } | 18 | } |
17 | 19 | ||
18 | float pointer_accel = atof(argv[0]); | 20 | float pointer_accel = parse_float(argv[0]); |
19 | if (pointer_accel < -1 || pointer_accel > 1) { | 21 | if (isnan(pointer_accel)) { |
22 | return cmd_results_new(CMD_INVALID, "pointer_accel", | ||
23 | "Invalid pointer accel; expected float."); | ||
24 | } if (pointer_accel < -1 || pointer_accel > 1) { | ||
20 | return cmd_results_new(CMD_INVALID, "pointer_accel", | 25 | return cmd_results_new(CMD_INVALID, "pointer_accel", |
21 | "Input out of range [-1, 1]"); | 26 | "Input out of range [-1, 1]"); |
22 | } | 27 | } |
diff --git a/sway/commands/input/scroll_factor.c b/sway/commands/input/scroll_factor.c new file mode 100644 index 00000000..52d943b0 --- /dev/null +++ b/sway/commands/input/scroll_factor.c | |||
@@ -0,0 +1,32 @@ | |||
1 | #include <errno.h> | ||
2 | #include <math.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include "sway/config.h" | ||
6 | #include "sway/commands.h" | ||
7 | #include "sway/input/input-manager.h" | ||
8 | #include "util.h" | ||
9 | |||
10 | struct cmd_results *input_cmd_scroll_factor(int argc, char **argv) { | ||
11 | struct cmd_results *error = NULL; | ||
12 | if ((error = checkarg(argc, "scroll_factor", EXPECTED_AT_LEAST, 1))) { | ||
13 | return error; | ||
14 | } | ||
15 | struct input_config *ic = config->handler_context.input_config; | ||
16 | if (!ic) { | ||
17 | return cmd_results_new(CMD_FAILURE, | ||
18 | "scroll_factor", "No input device defined."); | ||
19 | } | ||
20 | |||
21 | float scroll_factor = parse_float(argv[0]); | ||
22 | if (isnan(scroll_factor)) { | ||
23 | return cmd_results_new(CMD_INVALID, "scroll_factor", | ||
24 | "Invalid scroll factor; expected float."); | ||
25 | } else if (scroll_factor < 0) { | ||
26 | return cmd_results_new(CMD_INVALID, "scroll_factor", | ||
27 | "Scroll factor cannot be negative."); | ||
28 | } | ||
29 | ic->scroll_factor = scroll_factor; | ||
30 | |||
31 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
32 | } | ||
diff --git a/sway/commands/input/xkb_capslock.c b/sway/commands/input/xkb_capslock.c index 669b4ea9..a939c72f 100644 --- a/sway/commands/input/xkb_capslock.c +++ b/sway/commands/input/xkb_capslock.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "sway/config.h" | 3 | #include "sway/config.h" |
4 | #include "sway/commands.h" | 4 | #include "sway/commands.h" |
5 | #include "sway/input/input-manager.h" | 5 | #include "sway/input/input-manager.h" |
6 | #include "util.h" | ||
6 | 7 | ||
7 | struct cmd_results *input_cmd_xkb_capslock(int argc, char **argv) { | 8 | struct cmd_results *input_cmd_xkb_capslock(int argc, char **argv) { |
8 | struct cmd_results *error = NULL; | 9 | struct cmd_results *error = NULL; |
@@ -15,14 +16,7 @@ struct cmd_results *input_cmd_xkb_capslock(int argc, char **argv) { | |||
15 | "No input device defined."); | 16 | "No input device defined."); |
16 | } | 17 | } |
17 | 18 | ||
18 | if (strcasecmp(argv[0], "enabled") == 0) { | 19 | ic->xkb_capslock = parse_boolean(argv[0], false); |
19 | ic->xkb_capslock = 1; | ||
20 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
21 | ic->xkb_capslock = 0; | ||
22 | } else { | ||
23 | return cmd_results_new(CMD_INVALID, "xkb_capslock", | ||
24 | "Expected 'xkb_capslock <enabled|disabled>'"); | ||
25 | } | ||
26 | 20 | ||
27 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 21 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
28 | } | 22 | } |
diff --git a/sway/commands/input/xkb_numlock.c b/sway/commands/input/xkb_numlock.c index 1367da44..2e962c5b 100644 --- a/sway/commands/input/xkb_numlock.c +++ b/sway/commands/input/xkb_numlock.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "sway/config.h" | 3 | #include "sway/config.h" |
4 | #include "sway/commands.h" | 4 | #include "sway/commands.h" |
5 | #include "sway/input/input-manager.h" | 5 | #include "sway/input/input-manager.h" |
6 | #include "util.h" | ||
6 | 7 | ||
7 | struct cmd_results *input_cmd_xkb_numlock(int argc, char **argv) { | 8 | struct cmd_results *input_cmd_xkb_numlock(int argc, char **argv) { |
8 | struct cmd_results *error = NULL; | 9 | struct cmd_results *error = NULL; |
@@ -15,14 +16,7 @@ struct cmd_results *input_cmd_xkb_numlock(int argc, char **argv) { | |||
15 | "No input device defined."); | 16 | "No input device defined."); |
16 | } | 17 | } |
17 | 18 | ||
18 | if (strcasecmp(argv[0], "enabled") == 0) { | 19 | ic->xkb_numlock = parse_boolean(argv[0], false); |
19 | ic->xkb_numlock = 1; | ||
20 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
21 | ic->xkb_numlock = 0; | ||
22 | } else { | ||
23 | return cmd_results_new(CMD_INVALID, "xkb_numlock", | ||
24 | "Expected 'xkb_numlock <enabled|disabled>'"); | ||
25 | } | ||
26 | 20 | ||
27 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 21 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
28 | } | 22 | } |
diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 8635b309..a90d578e 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c | |||
@@ -404,13 +404,10 @@ static struct cmd_results *resize_adjust_floating(enum resize_axis axis, | |||
404 | con->width += grow_width; | 404 | con->width += grow_width; |
405 | con->height += grow_height; | 405 | con->height += grow_height; |
406 | 406 | ||
407 | if (con->view) { | 407 | con->content_x += grow_x; |
408 | struct sway_view *view = con->view; | 408 | con->content_y += grow_y; |
409 | view->x += grow_x; | 409 | con->content_width += grow_width; |
410 | view->y += grow_y; | 410 | con->content_height += grow_height; |
411 | view->width += grow_width; | ||
412 | view->height += grow_height; | ||
413 | } | ||
414 | 411 | ||
415 | arrange_container(con); | 412 | arrange_container(con); |
416 | 413 | ||
@@ -499,7 +496,7 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, | |||
499 | } | 496 | } |
500 | if (height->unit == RESIZE_UNIT_PX) { | 497 | if (height->unit == RESIZE_UNIT_PX) { |
501 | resize_tiled(con, height->amount - con->height, | 498 | resize_tiled(con, height->amount - con->height, |
502 | RESIZE_AXIS_HORIZONTAL); | 499 | RESIZE_AXIS_VERTICAL); |
503 | } | 500 | } |
504 | } | 501 | } |
505 | 502 | ||
@@ -511,25 +508,46 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, | |||
511 | */ | 508 | */ |
512 | static struct cmd_results *resize_set_floating(struct sway_container *con, | 509 | static struct cmd_results *resize_set_floating(struct sway_container *con, |
513 | struct resize_amount *width, struct resize_amount *height) { | 510 | struct resize_amount *width, struct resize_amount *height) { |
514 | int min_width, max_width, min_height, max_height; | 511 | int min_width, max_width, min_height, max_height, grow_width = 0, grow_height = 0; |
515 | calculate_constraints(&min_width, &max_width, &min_height, &max_height); | 512 | calculate_constraints(&min_width, &max_width, &min_height, &max_height); |
516 | width->amount = fmax(min_width, fmin(width->amount, max_width)); | 513 | |
517 | height->amount = fmax(min_height, fmin(height->amount, max_height)); | 514 | if (width->amount) { |
518 | int grow_width = width->amount - con->width; | 515 | if (width->unit == RESIZE_UNIT_PPT || |
519 | int grow_height = height->amount - con->height; | 516 | width->unit == RESIZE_UNIT_DEFAULT) { |
520 | con->x -= grow_width / 2; | 517 | // Convert to px |
521 | con->y -= grow_height / 2; | 518 | width->amount = con->workspace->width * width->amount / 100; |
522 | con->width = width->amount; | 519 | width->unit = RESIZE_UNIT_PX; |
523 | con->height = height->amount; | 520 | } |
524 | 521 | if (width->unit == RESIZE_UNIT_PX) { | |
525 | if (con->view) { | 522 | width->amount = fmax(min_width, fmin(width->amount, max_width)); |
526 | struct sway_view *view = con->view; | 523 | grow_width = width->amount - con->width; |
527 | view->x -= grow_width / 2; | 524 | |
528 | view->y -= grow_height / 2; | 525 | con->x -= grow_width / 2; |
529 | view->width += grow_width; | 526 | con->width = width->amount; |
530 | view->height += grow_height; | 527 | } |
531 | } | 528 | } |
532 | 529 | ||
530 | if (height->amount) { | ||
531 | if (height->unit == RESIZE_UNIT_PPT || | ||
532 | height->unit == RESIZE_UNIT_DEFAULT) { | ||
533 | // Convert to px | ||
534 | height->amount = con->workspace->height * height->amount / 100; | ||
535 | height->unit = RESIZE_UNIT_PX; | ||
536 | } | ||
537 | if (height->unit == RESIZE_UNIT_PX) { | ||
538 | height->amount = fmax(min_height, fmin(height->amount, max_height)); | ||
539 | grow_height = height->amount - con->height; | ||
540 | |||
541 | con->y -= grow_height / 2; | ||
542 | con->height = height->amount; | ||
543 | } | ||
544 | } | ||
545 | |||
546 | con->content_x -= grow_width / 2; | ||
547 | con->content_y -= grow_height / 2; | ||
548 | con->content_width += grow_width; | ||
549 | con->content_height += grow_height; | ||
550 | |||
533 | arrange_container(con); | 551 | arrange_container(con); |
534 | 552 | ||
535 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 553 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
@@ -538,34 +556,45 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, | |||
538 | /** | 556 | /** |
539 | * resize set <args> | 557 | * resize set <args> |
540 | * | 558 | * |
541 | * args: <width> [px|ppt] <height> [px|ppt] | 559 | * args: [width] <width> [px|ppt] |
560 | * : height <height> [px|ppt] | ||
561 | * : [width] <width> [px|ppt] [height] <height> [px|ppt] | ||
542 | */ | 562 | */ |
543 | static struct cmd_results *cmd_resize_set(int argc, char **argv) { | 563 | static struct cmd_results *cmd_resize_set(int argc, char **argv) { |
544 | struct cmd_results *error; | 564 | struct cmd_results *error; |
545 | if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { | 565 | if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 1))) { |
546 | return error; | 566 | return error; |
547 | } | 567 | } |
548 | const char *usage = "Expected 'resize set <width> <height>'"; | 568 | const char *usage = "Expected 'resize set [width] <width> [px|ppt]' or " |
569 | "'resize set height <height> [px|ppt]' or " | ||
570 | "'resize set [width] <width> [px|ppt] [height] <height> [px|ppt]'"; | ||
549 | 571 | ||
550 | // Width | 572 | // Width |
551 | struct resize_amount width; | 573 | struct resize_amount width = {0}; |
552 | int num_consumed_args = parse_resize_amount(argc, argv, &width); | 574 | if (argc >= 2 && !strcmp(argv[0], "width") && strcmp(argv[1], "height")) { |
553 | argc -= num_consumed_args; | 575 | argc--; argv++; |
554 | argv += num_consumed_args; | ||
555 | if (width.unit == RESIZE_UNIT_INVALID) { | ||
556 | return cmd_results_new(CMD_INVALID, "resize", usage); | ||
557 | } | 576 | } |
558 | if (!argc) { | 577 | if (strcmp(argv[0], "height")) { |
559 | return cmd_results_new(CMD_INVALID, "resize", usage); | 578 | int num_consumed_args = parse_resize_amount(argc, argv, &width); |
579 | argc -= num_consumed_args; | ||
580 | argv += num_consumed_args; | ||
581 | if (width.unit == RESIZE_UNIT_INVALID) { | ||
582 | return cmd_results_new(CMD_INVALID, "resize set", usage); | ||
583 | } | ||
560 | } | 584 | } |
561 | 585 | ||
562 | // Height | 586 | // Height |
563 | struct resize_amount height; | 587 | struct resize_amount height = {0}; |
564 | num_consumed_args = parse_resize_amount(argc, argv, &height); | 588 | if (argc) { |
565 | argc -= num_consumed_args; | 589 | if (argc >= 2 && !strcmp(argv[0], "height")) { |
566 | argv += num_consumed_args; | 590 | argc--; argv++; |
567 | if (height.unit == RESIZE_UNIT_INVALID) { | 591 | } |
568 | return cmd_results_new(CMD_INVALID, "resize", usage); | 592 | int num_consumed_args = parse_resize_amount(argc, argv, &height); |
593 | argc -= num_consumed_args; | ||
594 | argv += num_consumed_args; | ||
595 | if (width.unit == RESIZE_UNIT_INVALID) { | ||
596 | return cmd_results_new(CMD_INVALID, "resize set", usage); | ||
597 | } | ||
569 | } | 598 | } |
570 | 599 | ||
571 | // If 0, don't resize that dimension | 600 | // If 0, don't resize that dimension |
diff --git a/sway/commands/seat/fallback.c b/sway/commands/seat/fallback.c index 11f5a08c..a0ddf3ef 100644 --- a/sway/commands/seat/fallback.c +++ b/sway/commands/seat/fallback.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "sway/config.h" | 3 | #include "sway/config.h" |
4 | #include "sway/commands.h" | 4 | #include "sway/commands.h" |
5 | #include "sway/input/input-manager.h" | 5 | #include "sway/input/input-manager.h" |
6 | #include "util.h" | ||
6 | 7 | ||
7 | struct cmd_results *seat_cmd_fallback(int argc, char **argv) { | 8 | struct cmd_results *seat_cmd_fallback(int argc, char **argv) { |
8 | struct cmd_results *error = NULL; | 9 | struct cmd_results *error = NULL; |
@@ -16,16 +17,8 @@ struct cmd_results *seat_cmd_fallback(int argc, char **argv) { | |||
16 | } | 17 | } |
17 | struct seat_config *new_config = | 18 | struct seat_config *new_config = |
18 | new_seat_config(current_seat_config->name); | 19 | new_seat_config(current_seat_config->name); |
19 | 20 | ||
20 | if (strcasecmp(argv[0], "true") == 0) { | 21 | new_config->fallback = parse_boolean(argv[0], false); |
21 | new_config->fallback = 1; | ||
22 | } else if (strcasecmp(argv[0], "false") == 0) { | ||
23 | new_config->fallback = 0; | ||
24 | } else { | ||
25 | free_seat_config(new_config); | ||
26 | return cmd_results_new(CMD_INVALID, "fallback", | ||
27 | "Expected 'fallback <true|false>'"); | ||
28 | } | ||
29 | 22 | ||
30 | if (!config->validating) { | 23 | if (!config->validating) { |
31 | apply_seat_config(new_config); | 24 | apply_seat_config(new_config); |
diff --git a/sway/commands/smart_gaps.c b/sway/commands/smart_gaps.c index 273905df..f14b6760 100644 --- a/sway/commands/smart_gaps.c +++ b/sway/commands/smart_gaps.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "sway/tree/container.h" | 6 | #include "sway/tree/container.h" |
7 | #include "log.h" | 7 | #include "log.h" |
8 | #include "stringop.h" | 8 | #include "stringop.h" |
9 | #include "util.h" | ||
9 | 10 | ||
10 | struct cmd_results *cmd_smart_gaps(int argc, char **argv) { | 11 | struct cmd_results *cmd_smart_gaps(int argc, char **argv) { |
11 | struct cmd_results *error = checkarg(argc, "smart_gaps", EXPECTED_AT_LEAST, 1); | 12 | struct cmd_results *error = checkarg(argc, "smart_gaps", EXPECTED_AT_LEAST, 1); |
@@ -14,14 +15,7 @@ struct cmd_results *cmd_smart_gaps(int argc, char **argv) { | |||
14 | return error; | 15 | return error; |
15 | } | 16 | } |
16 | 17 | ||
17 | if (strcmp(argv[0], "on") == 0) { | 18 | config->smart_gaps = parse_boolean(argv[0], config->smart_gaps); |
18 | config->smart_gaps = true; | ||
19 | } else if (strcmp(argv[0], "off") == 0) { | ||
20 | config->smart_gaps = false; | ||
21 | } else { | ||
22 | return cmd_results_new(CMD_INVALID, "smart_gaps", | ||
23 | "Expected 'smart_gaps <on|off>' "); | ||
24 | } | ||
25 | 19 | ||
26 | arrange_root(); | 20 | arrange_root(); |
27 | 21 | ||
diff --git a/sway/commands/sticky.c b/sway/commands/sticky.c index f18322b7..7cd358a4 100644 --- a/sway/commands/sticky.c +++ b/sway/commands/sticky.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "sway/tree/view.h" | 9 | #include "sway/tree/view.h" |
10 | #include "sway/tree/workspace.h" | 10 | #include "sway/tree/workspace.h" |
11 | #include "list.h" | 11 | #include "list.h" |
12 | #include "util.h" | ||
12 | 13 | ||
13 | struct cmd_results *cmd_sticky(int argc, char **argv) { | 14 | struct cmd_results *cmd_sticky(int argc, char **argv) { |
14 | struct cmd_results *error = NULL; | 15 | struct cmd_results *error = NULL; |
@@ -26,21 +27,9 @@ struct cmd_results *cmd_sticky(int argc, char **argv) { | |||
26 | "Can't set sticky on a tiled container"); | 27 | "Can't set sticky on a tiled container"); |
27 | } | 28 | } |
28 | 29 | ||
29 | bool wants_sticky; | 30 | container->is_sticky = parse_boolean(argv[0], container->is_sticky); |
30 | if (strcasecmp(argv[0], "enable") == 0) { | ||
31 | wants_sticky = true; | ||
32 | } else if (strcasecmp(argv[0], "disable") == 0) { | ||
33 | wants_sticky = false; | ||
34 | } else if (strcasecmp(argv[0], "toggle") == 0) { | ||
35 | wants_sticky = !container->is_sticky; | ||
36 | } else { | ||
37 | return cmd_results_new(CMD_FAILURE, "sticky", | ||
38 | "Expected 'sticky <enable|disable|toggle>'"); | ||
39 | } | ||
40 | |||
41 | container->is_sticky = wants_sticky; | ||
42 | 31 | ||
43 | if (wants_sticky) { | 32 | if (container->is_sticky) { |
44 | // move container to active workspace | 33 | // move container to active workspace |
45 | struct sway_workspace *active_workspace = | 34 | struct sway_workspace *active_workspace = |
46 | output_get_active_workspace(container->workspace->output); | 35 | output_get_active_workspace(container->workspace->output); |
diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 23e8d583..08860264 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c | |||
@@ -144,19 +144,18 @@ static void container_swap(struct sway_container *con1, | |||
144 | } | 144 | } |
145 | } | 145 | } |
146 | 146 | ||
147 | static bool test_con_id(struct sway_container *container, void *con_id) { | 147 | static bool test_con_id(struct sway_container *container, void *data) { |
148 | return container->node.id == (size_t)con_id; | 148 | size_t *con_id = data; |
149 | return container->node.id == *con_id; | ||
149 | } | 150 | } |
150 | 151 | ||
151 | static bool test_id(struct sway_container *container, void *id) { | 152 | #if HAVE_XWAYLAND |
152 | #ifdef HAVE_XWAYLAND | 153 | static bool test_id(struct sway_container *container, void *data) { |
153 | xcb_window_t *wid = id; | 154 | xcb_window_t *wid = data; |
154 | return (container->view && container->view->type == SWAY_VIEW_XWAYLAND | 155 | return (container->view && container->view->type == SWAY_VIEW_XWAYLAND |
155 | && container->view->wlr_xwayland_surface->window_id == *wid); | 156 | && container->view->wlr_xwayland_surface->window_id == *wid); |
156 | #else | ||
157 | return false; | ||
158 | #endif | ||
159 | } | 157 | } |
158 | #endif | ||
160 | 159 | ||
161 | static bool test_mark(struct sway_container *container, void *mark) { | 160 | static bool test_mark(struct sway_container *container, void *mark) { |
162 | if (container->marks->length) { | 161 | if (container->marks->length) { |
@@ -181,19 +180,19 @@ struct cmd_results *cmd_swap(int argc, char **argv) { | |||
181 | } | 180 | } |
182 | 181 | ||
183 | struct sway_container *current = config->handler_context.container; | 182 | struct sway_container *current = config->handler_context.container; |
184 | struct sway_container *other; | 183 | struct sway_container *other = NULL; |
185 | 184 | ||
186 | char *value = join_args(argv + 3, argc - 3); | 185 | char *value = join_args(argv + 3, argc - 3); |
187 | if (strcasecmp(argv[2], "id") == 0) { | 186 | if (strcasecmp(argv[2], "id") == 0) { |
188 | #ifdef HAVE_XWAYLAND | 187 | #if HAVE_XWAYLAND |
189 | xcb_window_t id = strtol(value, NULL, 0); | 188 | xcb_window_t id = strtol(value, NULL, 0); |
190 | other = root_find_container(test_id, (void *)&id); | 189 | other = root_find_container(test_id, &id); |
191 | #endif | 190 | #endif |
192 | } else if (strcasecmp(argv[2], "con_id") == 0) { | 191 | } else if (strcasecmp(argv[2], "con_id") == 0) { |
193 | size_t con_id = atoi(value); | 192 | size_t con_id = atoi(value); |
194 | other = root_find_container(test_con_id, (void *)con_id); | 193 | other = root_find_container(test_con_id, &con_id); |
195 | } else if (strcasecmp(argv[2], "mark") == 0) { | 194 | } else if (strcasecmp(argv[2], "mark") == 0) { |
196 | other = root_find_container(test_mark, (void *)value); | 195 | other = root_find_container(test_mark, value); |
197 | } else { | 196 | } else { |
198 | free(value); | 197 | free(value); |
199 | return cmd_results_new(CMD_INVALID, "swap", EXPECTED_SYNTAX); | 198 | return cmd_results_new(CMD_INVALID, "swap", EXPECTED_SYNTAX); |
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 5abbb676..92118ecf 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c | |||
@@ -21,18 +21,105 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) { | |||
21 | return NULL; | 21 | return NULL; |
22 | } | 22 | } |
23 | wsc->workspace = strdup(ws_name); | 23 | wsc->workspace = strdup(ws_name); |
24 | wsc->outputs = create_list(); | ||
24 | wsc->gaps_inner = INT_MIN; | 25 | wsc->gaps_inner = INT_MIN; |
25 | wsc->gaps_outer = INT_MIN; | 26 | wsc->gaps_outer.top = INT_MIN; |
27 | wsc->gaps_outer.right = INT_MIN; | ||
28 | wsc->gaps_outer.bottom = INT_MIN; | ||
29 | wsc->gaps_outer.left = INT_MIN; | ||
26 | list_add(config->workspace_configs, wsc); | 30 | list_add(config->workspace_configs, wsc); |
27 | return wsc; | 31 | return wsc; |
28 | } | 32 | } |
29 | 33 | ||
30 | void free_workspace_config(struct workspace_config *wsc) { | 34 | void free_workspace_config(struct workspace_config *wsc) { |
31 | free(wsc->workspace); | 35 | free(wsc->workspace); |
32 | free(wsc->output); | 36 | free_flat_list(wsc->outputs); |
33 | free(wsc); | 37 | free(wsc); |
34 | } | 38 | } |
35 | 39 | ||
40 | static void prevent_invalid_outer_gaps(struct workspace_config *wsc) { | ||
41 | if (wsc->gaps_outer.top != INT_MIN && | ||
42 | wsc->gaps_outer.top < -wsc->gaps_inner) { | ||
43 | wsc->gaps_outer.top = -wsc->gaps_inner; | ||
44 | } | ||
45 | if (wsc->gaps_outer.right != INT_MIN && | ||
46 | wsc->gaps_outer.right < -wsc->gaps_inner) { | ||
47 | wsc->gaps_outer.right = -wsc->gaps_inner; | ||
48 | } | ||
49 | if (wsc->gaps_outer.bottom != INT_MIN && | ||
50 | wsc->gaps_outer.bottom < -wsc->gaps_inner) { | ||
51 | wsc->gaps_outer.bottom = -wsc->gaps_inner; | ||
52 | } | ||
53 | if (wsc->gaps_outer.left != INT_MIN && | ||
54 | wsc->gaps_outer.left < -wsc->gaps_inner) { | ||
55 | wsc->gaps_outer.left = -wsc->gaps_inner; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | static struct cmd_results *cmd_workspace_gaps(int argc, char **argv, | ||
60 | int gaps_location) { | ||
61 | const char *expected = "Expected 'workspace <name> gaps " | ||
62 | "inner|outer|horizontal|vertical|top|right|bottom|left <px>'"; | ||
63 | struct cmd_results *error = NULL; | ||
64 | if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, | ||
65 | gaps_location + 3))) { | ||
66 | return error; | ||
67 | } | ||
68 | char *ws_name = join_args(argv, argc - 3); | ||
69 | struct workspace_config *wsc = workspace_config_find_or_create(ws_name); | ||
70 | free(ws_name); | ||
71 | if (!wsc) { | ||
72 | return cmd_results_new(CMD_FAILURE, "workspace gaps", | ||
73 | "Unable to allocate workspace output"); | ||
74 | } | ||
75 | |||
76 | char *end; | ||
77 | int amount = strtol(argv[gaps_location + 2], &end, 10); | ||
78 | if (strlen(end)) { | ||
79 | free(end); | ||
80 | return cmd_results_new(CMD_FAILURE, "workspace gaps", expected); | ||
81 | } | ||
82 | |||
83 | bool valid = false; | ||
84 | char *type = argv[gaps_location + 1]; | ||
85 | if (!strcasecmp(type, "inner")) { | ||
86 | valid = true; | ||
87 | wsc->gaps_inner = (amount >= 0) ? amount : 0; | ||
88 | } else { | ||
89 | if (!strcasecmp(type, "outer") || !strcasecmp(type, "vertical") | ||
90 | || !strcasecmp(type, "top")) { | ||
91 | valid = true; | ||
92 | wsc->gaps_outer.top = amount; | ||
93 | } | ||
94 | if (!strcasecmp(type, "outer") || !strcasecmp(type, "horizontal") | ||
95 | || !strcasecmp(type, "right")) { | ||
96 | valid = true; | ||
97 | wsc->gaps_outer.right = amount; | ||
98 | } | ||
99 | if (!strcasecmp(type, "outer") || !strcasecmp(type, "vertical") | ||
100 | || !strcasecmp(type, "bottom")) { | ||
101 | valid = true; | ||
102 | wsc->gaps_outer.bottom = amount; | ||
103 | } | ||
104 | if (!strcasecmp(type, "outer") || !strcasecmp(type, "horizontal") | ||
105 | || !strcasecmp(type, "left")) { | ||
106 | valid = true; | ||
107 | wsc->gaps_outer.left = amount; | ||
108 | } | ||
109 | } | ||
110 | if (!valid) { | ||
111 | return cmd_results_new(CMD_INVALID, "workspace gaps", expected); | ||
112 | } | ||
113 | |||
114 | // Prevent invalid gaps configurations. | ||
115 | if (wsc->gaps_inner != INT_MIN && wsc->gaps_inner < 0) { | ||
116 | wsc->gaps_inner = 0; | ||
117 | } | ||
118 | prevent_invalid_outer_gaps(wsc); | ||
119 | |||
120 | return error; | ||
121 | } | ||
122 | |||
36 | struct cmd_results *cmd_workspace(int argc, char **argv) { | 123 | struct cmd_results *cmd_workspace(int argc, char **argv) { |
37 | struct cmd_results *error = NULL; | 124 | struct cmd_results *error = NULL; |
38 | if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) { | 125 | if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) { |
@@ -55,56 +142,24 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { | |||
55 | } | 142 | } |
56 | } | 143 | } |
57 | if (output_location >= 0) { | 144 | if (output_location >= 0) { |
58 | if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { | 145 | if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, |
146 | output_location + 2))) { | ||
59 | return error; | 147 | return error; |
60 | } | 148 | } |
61 | char *ws_name = join_args(argv, argc - 2); | 149 | char *ws_name = join_args(argv, output_location); |
62 | struct workspace_config *wsc = workspace_config_find_or_create(ws_name); | 150 | struct workspace_config *wsc = workspace_config_find_or_create(ws_name); |
63 | free(ws_name); | 151 | free(ws_name); |
64 | if (!wsc) { | 152 | if (!wsc) { |
65 | return cmd_results_new(CMD_FAILURE, "workspace output", | 153 | return cmd_results_new(CMD_FAILURE, "workspace output", |
66 | "Unable to allocate workspace output"); | 154 | "Unable to allocate workspace output"); |
67 | } | 155 | } |
68 | free(wsc->output); | 156 | for (int i = output_location + 1; i < argc; ++i) { |
69 | wsc->output = strdup(argv[output_location + 1]); | 157 | list_add(wsc->outputs, strdup(argv[i])); |
158 | } | ||
70 | } else if (gaps_location >= 0) { | 159 | } else if (gaps_location >= 0) { |
71 | if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, gaps_location + 3))) { | 160 | if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) { |
72 | return error; | 161 | return error; |
73 | } | 162 | } |
74 | char *ws_name = join_args(argv, argc - 3); | ||
75 | struct workspace_config *wsc = workspace_config_find_or_create(ws_name); | ||
76 | free(ws_name); | ||
77 | if (!wsc) { | ||
78 | return cmd_results_new(CMD_FAILURE, "workspace gaps", | ||
79 | "Unable to allocate workspace output"); | ||
80 | } | ||
81 | int *prop = NULL; | ||
82 | if (strcasecmp(argv[gaps_location + 1], "inner") == 0) { | ||
83 | prop = &wsc->gaps_inner; | ||
84 | } else if (strcasecmp(argv[gaps_location + 1], "outer") == 0) { | ||
85 | prop = &wsc->gaps_outer; | ||
86 | } else { | ||
87 | return cmd_results_new(CMD_FAILURE, "workspace gaps", | ||
88 | "Expected 'workspace <ws> gaps inner|outer <px>'"); | ||
89 | } | ||
90 | char *end; | ||
91 | int val = strtol(argv[gaps_location + 2], &end, 10); | ||
92 | |||
93 | if (strlen(end)) { | ||
94 | free(end); | ||
95 | return cmd_results_new(CMD_FAILURE, "workspace gaps", | ||
96 | "Expected 'workspace <ws> gaps inner|outer <px>'"); | ||
97 | } | ||
98 | *prop = val; | ||
99 | |||
100 | // Prevent invalid gaps configurations. | ||
101 | if (wsc->gaps_inner < 0) { | ||
102 | wsc->gaps_inner = 0; | ||
103 | } | ||
104 | if (wsc->gaps_outer < -wsc->gaps_inner) { | ||
105 | wsc->gaps_outer = -wsc->gaps_inner; | ||
106 | } | ||
107 | |||
108 | } else { | 163 | } else { |
109 | if (config->reading || !config->active) { | 164 | if (config->reading || !config->active) { |
110 | return cmd_results_new(CMD_DEFER, "workspace", NULL); | 165 | return cmd_results_new(CMD_DEFER, "workspace", NULL); |
diff --git a/sway/commands/ws_auto_back_and_forth.c b/sway/commands/ws_auto_back_and_forth.c index 2485db35..adb851c2 100644 --- a/sway/commands/ws_auto_back_and_forth.c +++ b/sway/commands/ws_auto_back_and_forth.c | |||
@@ -1,12 +1,14 @@ | |||
1 | #include <string.h> | 1 | #include <string.h> |
2 | #include <strings.h> | 2 | #include <strings.h> |
3 | #include "sway/commands.h" | 3 | #include "sway/commands.h" |
4 | #include "util.h" | ||
4 | 5 | ||
5 | struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) { | 6 | struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) { |
6 | struct cmd_results *error = NULL; | 7 | struct cmd_results *error = NULL; |
7 | if ((error = checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1))) { | 8 | if ((error = checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1))) { |
8 | return error; | 9 | return error; |
9 | } | 10 | } |
10 | config->auto_back_and_forth = !strcasecmp(argv[0], "yes"); | 11 | config->auto_back_and_forth = |
12 | parse_boolean(argv[0], config->auto_back_and_forth); | ||
11 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 13 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
12 | } | 14 | } |
diff --git a/sway/config.c b/sway/config.c index 7ef3ef38..c1320acf 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -220,7 +220,7 @@ static void config_defaults(struct sway_config *config) { | |||
220 | config->floating_minimum_height = 50; | 220 | config->floating_minimum_height = 50; |
221 | 221 | ||
222 | // Flags | 222 | // Flags |
223 | config->focus_follows_mouse = true; | 223 | config->focus_follows_mouse = FOLLOWS_YES; |
224 | config->mouse_warping = WARP_OUTPUT; | 224 | config->mouse_warping = WARP_OUTPUT; |
225 | config->focus_wrapping = WRAP_YES; | 225 | config->focus_wrapping = WRAP_YES; |
226 | config->validating = false; | 226 | config->validating = false; |
@@ -234,7 +234,10 @@ static void config_defaults(struct sway_config *config) { | |||
234 | 234 | ||
235 | config->smart_gaps = false; | 235 | config->smart_gaps = false; |
236 | config->gaps_inner = 0; | 236 | config->gaps_inner = 0; |
237 | config->gaps_outer = 0; | 237 | config->gaps_outer.top = 0; |
238 | config->gaps_outer.right = 0; | ||
239 | config->gaps_outer.bottom = 0; | ||
240 | config->gaps_outer.left = 0; | ||
238 | 241 | ||
239 | if (!(config->active_bar_modifiers = create_list())) goto cleanup; | 242 | if (!(config->active_bar_modifiers = create_list())) goto cleanup; |
240 | 243 | ||
@@ -254,7 +257,6 @@ static void config_defaults(struct sway_config *config) { | |||
254 | 257 | ||
255 | // border colors | 258 | // border colors |
256 | set_color(config->border_colors.focused.border, 0x4C7899); | 259 | set_color(config->border_colors.focused.border, 0x4C7899); |
257 | set_color(config->border_colors.focused.border, 0x4C7899); | ||
258 | set_color(config->border_colors.focused.background, 0x285577); | 260 | set_color(config->border_colors.focused.background, 0x285577); |
259 | set_color(config->border_colors.focused.text, 0xFFFFFFFF); | 261 | set_color(config->border_colors.focused.text, 0xFFFFFFFF); |
260 | set_color(config->border_colors.focused.indicator, 0x2E9EF4); | 262 | set_color(config->border_colors.focused.indicator, 0x2E9EF4); |
diff --git a/sway/config/bar.c b/sway/config/bar.c index 94405a92..7009d0a0 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c | |||
@@ -46,6 +46,7 @@ void free_bar_config(struct bar_config *bar) { | |||
46 | free(bar->position); | 46 | free(bar->position); |
47 | free(bar->hidden_state); | 47 | free(bar->hidden_state); |
48 | free(bar->status_command); | 48 | free(bar->status_command); |
49 | free(bar->swaybar_command); | ||
49 | free(bar->font); | 50 | free(bar->font); |
50 | free(bar->separator_symbol); | 51 | free(bar->separator_symbol); |
51 | for (int i = 0; i < bar->bindings->length; i++) { | 52 | for (int i = 0; i < bar->bindings->length; i++) { |
diff --git a/sway/config/input.c b/sway/config/input.c index 794d5194..d5d2d90b 100644 --- a/sway/config/input.c +++ b/sway/config/input.c | |||
@@ -29,6 +29,7 @@ struct input_config *new_input_config(const char* identifier) { | |||
29 | input->natural_scroll = INT_MIN; | 29 | input->natural_scroll = INT_MIN; |
30 | input->accel_profile = INT_MIN; | 30 | input->accel_profile = INT_MIN; |
31 | input->pointer_accel = FLT_MIN; | 31 | input->pointer_accel = FLT_MIN; |
32 | input->scroll_factor = FLT_MIN; | ||
32 | input->scroll_button = INT_MIN; | 33 | input->scroll_button = INT_MIN; |
33 | input->scroll_method = INT_MIN; | 34 | input->scroll_method = INT_MIN; |
34 | input->left_handed = INT_MIN; | 35 | input->left_handed = INT_MIN; |
@@ -68,6 +69,9 @@ void merge_input_config(struct input_config *dst, struct input_config *src) { | |||
68 | if (src->pointer_accel != FLT_MIN) { | 69 | if (src->pointer_accel != FLT_MIN) { |
69 | dst->pointer_accel = src->pointer_accel; | 70 | dst->pointer_accel = src->pointer_accel; |
70 | } | 71 | } |
72 | if (src->scroll_factor != FLT_MIN) { | ||
73 | dst->scroll_factor = src->scroll_factor; | ||
74 | } | ||
71 | if (src->repeat_delay != INT_MIN) { | 75 | if (src->repeat_delay != INT_MIN) { |
72 | dst->repeat_delay = src->repeat_delay; | 76 | dst->repeat_delay = src->repeat_delay; |
73 | } | 77 | } |
diff --git a/sway/config/output.c b/sway/config/output.c index 2b041353..07543e3c 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -326,6 +326,7 @@ void free_output_config(struct output_config *oc) { | |||
326 | free(oc->name); | 326 | free(oc->name); |
327 | free(oc->background); | 327 | free(oc->background); |
328 | free(oc->background_option); | 328 | free(oc->background_option); |
329 | free(oc->background_fallback); | ||
329 | free(oc); | 330 | free(oc); |
330 | } | 331 | } |
331 | 332 | ||
diff --git a/sway/criteria.c b/sway/criteria.c index 2f9992e9..3393852c 100644 --- a/sway/criteria.c +++ b/sway/criteria.c | |||
@@ -21,7 +21,7 @@ bool criteria_is_empty(struct criteria *criteria) { | |||
21 | && !criteria->app_id | 21 | && !criteria->app_id |
22 | && !criteria->con_mark | 22 | && !criteria->con_mark |
23 | && !criteria->con_id | 23 | && !criteria->con_id |
24 | #ifdef HAVE_XWAYLAND | 24 | #if HAVE_XWAYLAND |
25 | && !criteria->class | 25 | && !criteria->class |
26 | && !criteria->id | 26 | && !criteria->id |
27 | && !criteria->instance | 27 | && !criteria->instance |
@@ -35,18 +35,19 @@ bool criteria_is_empty(struct criteria *criteria) { | |||
35 | } | 35 | } |
36 | 36 | ||
37 | void criteria_destroy(struct criteria *criteria) { | 37 | void criteria_destroy(struct criteria *criteria) { |
38 | free(criteria->raw); | ||
39 | free(criteria->cmdlist); | ||
40 | free(criteria->target); | ||
38 | pcre_free(criteria->title); | 41 | pcre_free(criteria->title); |
39 | pcre_free(criteria->shell); | 42 | pcre_free(criteria->shell); |
40 | pcre_free(criteria->app_id); | 43 | pcre_free(criteria->app_id); |
41 | #ifdef HAVE_XWAYLAND | 44 | pcre_free(criteria->con_mark); |
45 | #if HAVE_XWAYLAND | ||
42 | pcre_free(criteria->class); | 46 | pcre_free(criteria->class); |
43 | pcre_free(criteria->instance); | 47 | pcre_free(criteria->instance); |
44 | pcre_free(criteria->window_role); | 48 | pcre_free(criteria->window_role); |
45 | #endif | 49 | #endif |
46 | pcre_free(criteria->con_mark); | ||
47 | free(criteria->workspace); | 50 | free(criteria->workspace); |
48 | free(criteria->cmdlist); | ||
49 | free(criteria->raw); | ||
50 | free(criteria); | 51 | free(criteria); |
51 | } | 52 | } |
52 | 53 | ||
@@ -54,7 +55,7 @@ static int regex_cmp(const char *item, const pcre *regex) { | |||
54 | return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); | 55 | return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); |
55 | } | 56 | } |
56 | 57 | ||
57 | #ifdef HAVE_XWAYLAND | 58 | #if HAVE_XWAYLAND |
58 | static bool view_has_window_type(struct sway_view *view, enum atom_name name) { | 59 | static bool view_has_window_type(struct sway_view *view, enum atom_name name) { |
59 | if (view->type != SWAY_VIEW_XWAYLAND) { | 60 | if (view->type != SWAY_VIEW_XWAYLAND) { |
60 | return false; | 61 | return false; |
@@ -139,7 +140,7 @@ static bool criteria_matches_view(struct criteria *criteria, | |||
139 | } | 140 | } |
140 | } | 141 | } |
141 | 142 | ||
142 | #ifdef HAVE_XWAYLAND | 143 | #if HAVE_XWAYLAND |
143 | if (criteria->id) { // X11 window ID | 144 | if (criteria->id) { // X11 window ID |
144 | uint32_t x11_window_id = view_get_x11_window_id(view); | 145 | uint32_t x11_window_id = view_get_x11_window_id(view); |
145 | if (!x11_window_id || x11_window_id != criteria->id) { | 146 | if (!x11_window_id || x11_window_id != criteria->id) { |
@@ -275,7 +276,7 @@ static bool generate_regex(pcre **regex, char *value) { | |||
275 | return true; | 276 | return true; |
276 | } | 277 | } |
277 | 278 | ||
278 | #ifdef HAVE_XWAYLAND | 279 | #if HAVE_XWAYLAND |
279 | static enum atom_name parse_window_type(const char *type) { | 280 | static enum atom_name parse_window_type(const char *type) { |
280 | if (strcasecmp(type, "normal") == 0) { | 281 | if (strcasecmp(type, "normal") == 0) { |
281 | return NET_WM_WINDOW_TYPE_NORMAL; | 282 | return NET_WM_WINDOW_TYPE_NORMAL; |
@@ -307,7 +308,7 @@ enum criteria_token { | |||
307 | T_CON_ID, | 308 | T_CON_ID, |
308 | T_CON_MARK, | 309 | T_CON_MARK, |
309 | T_FLOATING, | 310 | T_FLOATING, |
310 | #ifdef HAVE_XWAYLAND | 311 | #if HAVE_XWAYLAND |
311 | T_CLASS, | 312 | T_CLASS, |
312 | T_ID, | 313 | T_ID, |
313 | T_INSTANCE, | 314 | T_INSTANCE, |
@@ -330,7 +331,7 @@ static enum criteria_token token_from_name(char *name) { | |||
330 | return T_CON_ID; | 331 | return T_CON_ID; |
331 | } else if (strcmp(name, "con_mark") == 0) { | 332 | } else if (strcmp(name, "con_mark") == 0) { |
332 | return T_CON_MARK; | 333 | return T_CON_MARK; |
333 | #ifdef HAVE_XWAYLAND | 334 | #if HAVE_XWAYLAND |
334 | } else if (strcmp(name, "class") == 0) { | 335 | } else if (strcmp(name, "class") == 0) { |
335 | return T_CLASS; | 336 | return T_CLASS; |
336 | } else if (strcmp(name, "id") == 0) { | 337 | } else if (strcmp(name, "id") == 0) { |
@@ -401,7 +402,7 @@ static char *get_focused_prop(enum criteria_token token) { | |||
401 | snprintf(id_str, id_size, "%zu", id); | 402 | snprintf(id_str, id_size, "%zu", id); |
402 | value = id_str; | 403 | value = id_str; |
403 | break; | 404 | break; |
404 | #ifdef HAVE_XWAYLAND | 405 | #if HAVE_XWAYLAND |
405 | case T_CLASS: | 406 | case T_CLASS: |
406 | value = view_get_class(view); | 407 | value = view_get_class(view); |
407 | break; | 408 | break; |
@@ -473,7 +474,7 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { | |||
473 | case T_CON_MARK: | 474 | case T_CON_MARK: |
474 | generate_regex(&criteria->con_mark, effective_value); | 475 | generate_regex(&criteria->con_mark, effective_value); |
475 | break; | 476 | break; |
476 | #ifdef HAVE_XWAYLAND | 477 | #if HAVE_XWAYLAND |
477 | case T_CLASS: | 478 | case T_CLASS: |
478 | generate_regex(&criteria->class, effective_value); | 479 | generate_regex(&criteria->class, effective_value); |
479 | break; | 480 | break; |
@@ -576,7 +577,7 @@ struct criteria *criteria_parse(char *raw, char **error_arg) { | |||
576 | ++head; | 577 | ++head; |
577 | 578 | ||
578 | struct criteria *criteria = calloc(1, sizeof(struct criteria)); | 579 | struct criteria *criteria = calloc(1, sizeof(struct criteria)); |
579 | #ifdef HAVE_XWAYLAND | 580 | #if HAVE_XWAYLAND |
580 | criteria->window_type = ATOM_LAST; // default value | 581 | criteria->window_type = ATOM_LAST; // default value |
581 | #endif | 582 | #endif |
582 | char *name = NULL, *value = NULL; | 583 | char *name = NULL, *value = NULL; |
diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c index 771b58fe..d8dd0240 100644 --- a/sway/desktop/desktop.c +++ b/sway/desktop/desktop.c | |||
@@ -28,8 +28,8 @@ void desktop_damage_box(struct wlr_box *box) { | |||
28 | void desktop_damage_view(struct sway_view *view) { | 28 | void desktop_damage_view(struct sway_view *view) { |
29 | desktop_damage_whole_container(view->container); | 29 | desktop_damage_whole_container(view->container); |
30 | struct wlr_box box = { | 30 | struct wlr_box box = { |
31 | .x = view->container->current.view_x - view->geometry.x, | 31 | .x = view->container->current.content_x - view->geometry.x, |
32 | .y = view->container->current.view_y - view->geometry.y, | 32 | .y = view->container->current.content_y - view->geometry.y, |
33 | .width = view->surface->current.width, | 33 | .width = view->surface->current.width, |
34 | .height = view->surface->current.height, | 34 | .height = view->surface->current.height, |
35 | }; | 35 | }; |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index d48ddef3..d649100f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -160,12 +160,12 @@ void output_view_for_each_surface(struct sway_output *output, | |||
160 | .user_iterator = iterator, | 160 | .user_iterator = iterator, |
161 | .user_data = user_data, | 161 | .user_data = user_data, |
162 | .output = output, | 162 | .output = output, |
163 | .ox = view->container->current.view_x - output->wlr_output->lx | 163 | .ox = view->container->current.content_x - output->wlr_output->lx |
164 | - view->geometry.x, | 164 | - view->geometry.x, |
165 | .oy = view->container->current.view_y - output->wlr_output->ly | 165 | .oy = view->container->current.content_y - output->wlr_output->ly |
166 | - view->geometry.y, | 166 | - view->geometry.y, |
167 | .width = view->container->current.view_width, | 167 | .width = view->container->current.content_width, |
168 | .height = view->container->current.view_height, | 168 | .height = view->container->current.content_height, |
169 | .rotation = 0, // TODO | 169 | .rotation = 0, // TODO |
170 | }; | 170 | }; |
171 | 171 | ||
@@ -179,12 +179,12 @@ void output_view_for_each_popup(struct sway_output *output, | |||
179 | .user_iterator = iterator, | 179 | .user_iterator = iterator, |
180 | .user_data = user_data, | 180 | .user_data = user_data, |
181 | .output = output, | 181 | .output = output, |
182 | .ox = view->container->current.view_x - output->wlr_output->lx | 182 | .ox = view->container->current.content_x - output->wlr_output->lx |
183 | - view->geometry.x, | 183 | - view->geometry.x, |
184 | .oy = view->container->current.view_y - output->wlr_output->ly | 184 | .oy = view->container->current.content_y - output->wlr_output->ly |
185 | - view->geometry.y, | 185 | - view->geometry.y, |
186 | .width = view->container->current.view_width, | 186 | .width = view->container->current.content_width, |
187 | .height = view->container->current.view_height, | 187 | .height = view->container->current.content_height, |
188 | .rotation = 0, // TODO | 188 | .rotation = 0, // TODO |
189 | }; | 189 | }; |
190 | 190 | ||
@@ -204,7 +204,7 @@ void output_layer_for_each_surface(struct sway_output *output, | |||
204 | } | 204 | } |
205 | } | 205 | } |
206 | 206 | ||
207 | #ifdef HAVE_XWAYLAND | 207 | #if HAVE_XWAYLAND |
208 | void output_unmanaged_for_each_surface(struct sway_output *output, | 208 | void output_unmanaged_for_each_surface(struct sway_output *output, |
209 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, | 209 | struct wl_list *unmanaged, sway_surface_iterator_func_t iterator, |
210 | void *user_data) { | 210 | void *user_data) { |
@@ -274,7 +274,7 @@ static void output_for_each_surface(struct sway_output *output, | |||
274 | for_each_surface_container_iterator(floater, &data); | 274 | for_each_surface_container_iterator(floater, &data); |
275 | } | 275 | } |
276 | } | 276 | } |
277 | #ifdef HAVE_XWAYLAND | 277 | #if HAVE_XWAYLAND |
278 | output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged, | 278 | output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged, |
279 | iterator, user_data); | 279 | iterator, user_data); |
280 | #endif | 280 | #endif |
@@ -289,7 +289,7 @@ static void output_for_each_surface(struct sway_output *output, | |||
289 | workspace_for_each_container(workspace, | 289 | workspace_for_each_container(workspace, |
290 | for_each_surface_container_iterator, &data); | 290 | for_each_surface_container_iterator, &data); |
291 | 291 | ||
292 | #ifdef HAVE_XWAYLAND | 292 | #if HAVE_XWAYLAND |
293 | output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged, | 293 | output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged, |
294 | iterator, user_data); | 294 | iterator, user_data); |
295 | #endif | 295 | #endif |
@@ -469,23 +469,14 @@ void output_damage_box(struct sway_output *output, struct wlr_box *_box) { | |||
469 | wlr_output_damage_add_box(output->damage, &box); | 469 | wlr_output_damage_add_box(output->damage, &box); |
470 | } | 470 | } |
471 | 471 | ||
472 | static void output_damage_whole_container_iterator(struct sway_container *con, | ||
473 | void *data) { | ||
474 | if (!sway_assert(con->view, "expected a view")) { | ||
475 | return; | ||
476 | } | ||
477 | struct sway_output *output = data; | ||
478 | output_damage_view(output, con->view, true); | ||
479 | } | ||
480 | |||
481 | void output_damage_whole_container(struct sway_output *output, | 472 | void output_damage_whole_container(struct sway_output *output, |
482 | struct sway_container *con) { | 473 | struct sway_container *con) { |
483 | // Pad the box by 1px, because the width is a double and might be a fraction | 474 | // Pad the box by 1px, because the width is a double and might be a fraction |
484 | struct wlr_box box = { | 475 | struct wlr_box box = { |
485 | .x = con->current.con_x - output->wlr_output->lx - 1, | 476 | .x = con->current.x - output->wlr_output->lx - 1, |
486 | .y = con->current.con_y - output->wlr_output->ly - 1, | 477 | .y = con->current.y - output->wlr_output->ly - 1, |
487 | .width = con->current.con_width + 2, | 478 | .width = con->current.width + 2, |
488 | .height = con->current.con_height + 2, | 479 | .height = con->current.height + 2, |
489 | }; | 480 | }; |
490 | scale_box(&box, output->wlr_output->scale); | 481 | scale_box(&box, output->wlr_output->scale); |
491 | wlr_output_damage_add_box(output->damage, &box); | 482 | wlr_output_damage_add_box(output->damage, &box); |
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index cf6da682..8d4a701b 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c | |||
@@ -140,7 +140,7 @@ static void render_layer(struct sway_output *output, | |||
140 | render_surface_iterator, &data); | 140 | render_surface_iterator, &data); |
141 | } | 141 | } |
142 | 142 | ||
143 | #ifdef HAVE_XWAYLAND | 143 | #if HAVE_XWAYLAND |
144 | static void render_unmanaged(struct sway_output *output, | 144 | static void render_unmanaged(struct sway_output *output, |
145 | pixman_region32_t *damage, struct wl_list *unmanaged) { | 145 | pixman_region32_t *damage, struct wl_list *unmanaged) { |
146 | struct render_data data = { | 146 | struct render_data data = { |
@@ -211,9 +211,9 @@ static void render_view_toplevels(struct sway_view *view, | |||
211 | .alpha = alpha, | 211 | .alpha = alpha, |
212 | }; | 212 | }; |
213 | // Render all toplevels without descending into popups | 213 | // Render all toplevels without descending into popups |
214 | double ox = view->container->current.view_x - | 214 | double ox = view->container->current.content_x - |
215 | output->wlr_output->lx - view->geometry.x; | 215 | output->wlr_output->lx - view->geometry.x; |
216 | double oy = view->container->current.view_y - | 216 | double oy = view->container->current.content_y - |
217 | output->wlr_output->ly - view->geometry.y; | 217 | output->wlr_output->ly - view->geometry.y; |
218 | output_surface_for_each_surface(output, view->surface, ox, oy, | 218 | output_surface_for_each_surface(output, view->surface, ox, oy, |
219 | render_surface_iterator, &data); | 219 | render_surface_iterator, &data); |
@@ -247,9 +247,9 @@ static void render_saved_view(struct sway_view *view, | |||
247 | return; | 247 | return; |
248 | } | 248 | } |
249 | struct wlr_box box = { | 249 | struct wlr_box box = { |
250 | .x = view->container->current.view_x - output->wlr_output->lx - | 250 | .x = view->container->current.content_x - output->wlr_output->lx - |
251 | view->saved_geometry.x, | 251 | view->saved_geometry.x, |
252 | .y = view->container->current.view_y - output->wlr_output->ly - | 252 | .y = view->container->current.content_y - output->wlr_output->ly - |
253 | view->saved_geometry.y, | 253 | view->saved_geometry.y, |
254 | .width = view->saved_buffer_width, | 254 | .width = view->saved_buffer_width, |
255 | .height = view->saved_buffer_height, | 255 | .height = view->saved_buffer_height, |
@@ -300,10 +300,10 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, | |||
300 | if (state->border_left) { | 300 | if (state->border_left) { |
301 | memcpy(&color, colors->child_border, sizeof(float) * 4); | 301 | memcpy(&color, colors->child_border, sizeof(float) * 4); |
302 | premultiply_alpha(color, con->alpha); | 302 | premultiply_alpha(color, con->alpha); |
303 | box.x = state->con_x; | 303 | box.x = state->x; |
304 | box.y = state->view_y; | 304 | box.y = state->content_y; |
305 | box.width = state->border_thickness; | 305 | box.width = state->border_thickness; |
306 | box.height = state->view_height; | 306 | box.height = state->content_height; |
307 | scale_box(&box, output_scale); | 307 | scale_box(&box, output_scale); |
308 | render_rect(output->wlr_output, damage, &box, color); | 308 | render_rect(output->wlr_output, damage, &box, color); |
309 | } | 309 | } |
@@ -319,10 +319,10 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, | |||
319 | memcpy(&color, colors->child_border, sizeof(float) * 4); | 319 | memcpy(&color, colors->child_border, sizeof(float) * 4); |
320 | } | 320 | } |
321 | premultiply_alpha(color, con->alpha); | 321 | premultiply_alpha(color, con->alpha); |
322 | box.x = state->view_x + state->view_width; | 322 | box.x = state->content_x + state->content_width; |
323 | box.y = state->view_y; | 323 | box.y = state->content_y; |
324 | box.width = state->border_thickness; | 324 | box.width = state->border_thickness; |
325 | box.height = state->view_height; | 325 | box.height = state->content_height; |
326 | scale_box(&box, output_scale); | 326 | scale_box(&box, output_scale); |
327 | render_rect(output->wlr_output, damage, &box, color); | 327 | render_rect(output->wlr_output, damage, &box, color); |
328 | } | 328 | } |
@@ -334,9 +334,9 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, | |||
334 | memcpy(&color, colors->child_border, sizeof(float) * 4); | 334 | memcpy(&color, colors->child_border, sizeof(float) * 4); |
335 | } | 335 | } |
336 | premultiply_alpha(color, con->alpha); | 336 | premultiply_alpha(color, con->alpha); |
337 | box.x = state->con_x; | 337 | box.x = state->x; |
338 | box.y = state->view_y + state->view_height; | 338 | box.y = state->content_y + state->content_height; |
339 | box.width = state->con_width; | 339 | box.width = state->width; |
340 | box.height = state->border_thickness; | 340 | box.height = state->border_thickness; |
341 | scale_box(&box, output_scale); | 341 | scale_box(&box, output_scale); |
342 | render_rect(output->wlr_output, damage, &box, color); | 342 | render_rect(output->wlr_output, damage, &box, color); |
@@ -585,9 +585,9 @@ static void render_top_border(struct sway_output *output, | |||
585 | // Child border - top edge | 585 | // Child border - top edge |
586 | memcpy(&color, colors->child_border, sizeof(float) * 4); | 586 | memcpy(&color, colors->child_border, sizeof(float) * 4); |
587 | premultiply_alpha(color, con->alpha); | 587 | premultiply_alpha(color, con->alpha); |
588 | box.x = state->con_x; | 588 | box.x = state->x; |
589 | box.y = state->con_y; | 589 | box.y = state->y; |
590 | box.width = state->con_width; | 590 | box.width = state->width; |
591 | box.height = state->border_thickness; | 591 | box.height = state->border_thickness; |
592 | scale_box(&box, output_scale); | 592 | scale_box(&box, output_scale); |
593 | render_rect(output->wlr_output, output_damage, &box, color); | 593 | render_rect(output->wlr_output, output_damage, &box, color); |
@@ -641,8 +641,8 @@ static void render_containers_linear(struct sway_output *output, | |||
641 | } | 641 | } |
642 | 642 | ||
643 | if (state->border == B_NORMAL) { | 643 | if (state->border == B_NORMAL) { |
644 | render_titlebar(output, damage, child, state->con_x, | 644 | render_titlebar(output, damage, child, state->x, |
645 | state->con_y, state->con_width, colors, | 645 | state->y, state->width, colors, |
646 | title_texture, marks_texture); | 646 | title_texture, marks_texture); |
647 | } else if (state->border == B_PIXEL) { | 647 | } else if (state->border == B_PIXEL) { |
648 | render_top_border(output, damage, child, colors); | 648 | render_top_border(output, damage, child, colors); |
@@ -696,7 +696,7 @@ static void render_containers_tabbed(struct sway_output *output, | |||
696 | marks_texture = child->marks_unfocused; | 696 | marks_texture = child->marks_unfocused; |
697 | } | 697 | } |
698 | 698 | ||
699 | int x = cstate->con_x + tab_width * i; | 699 | int x = cstate->x + tab_width * i; |
700 | 700 | ||
701 | // Make last tab use the remaining width of the parent | 701 | // Make last tab use the remaining width of the parent |
702 | if (i == parent->children->length - 1) { | 702 | if (i == parent->children->length - 1) { |
@@ -801,10 +801,10 @@ static void render_container(struct sway_output *output, | |||
801 | struct parent_data data = { | 801 | struct parent_data data = { |
802 | .layout = con->current.layout, | 802 | .layout = con->current.layout, |
803 | .box = { | 803 | .box = { |
804 | .x = con->current.con_x, | 804 | .x = con->current.x, |
805 | .y = con->current.con_y, | 805 | .y = con->current.y, |
806 | .width = con->current.con_width, | 806 | .width = con->current.width, |
807 | .height = con->current.con_height, | 807 | .height = con->current.height, |
808 | }, | 808 | }, |
809 | .children = con->current.children, | 809 | .children = con->current.children, |
810 | .focused = focused, | 810 | .focused = focused, |
@@ -853,8 +853,8 @@ static void render_floating_container(struct sway_output *soutput, | |||
853 | } | 853 | } |
854 | 854 | ||
855 | if (con->current.border == B_NORMAL) { | 855 | if (con->current.border == B_NORMAL) { |
856 | render_titlebar(soutput, damage, con, con->current.con_x, | 856 | render_titlebar(soutput, damage, con, con->current.x, |
857 | con->current.con_y, con->current.con_width, colors, | 857 | con->current.y, con->current.width, colors, |
858 | title_texture, marks_texture); | 858 | title_texture, marks_texture); |
859 | } else if (con->current.border == B_PIXEL) { | 859 | } else if (con->current.border == B_PIXEL) { |
860 | render_top_border(soutput, damage, con, colors); | 860 | render_top_border(soutput, damage, con, colors); |
@@ -966,7 +966,7 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
966 | render_floating_container(output, damage, floater); | 966 | render_floating_container(output, damage, floater); |
967 | } | 967 | } |
968 | } | 968 | } |
969 | #ifdef HAVE_XWAYLAND | 969 | #if HAVE_XWAYLAND |
970 | render_unmanaged(output, damage, &root->xwayland_unmanaged); | 970 | render_unmanaged(output, damage, &root->xwayland_unmanaged); |
971 | #endif | 971 | #endif |
972 | } else { | 972 | } else { |
@@ -986,7 +986,7 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
986 | 986 | ||
987 | render_workspace(output, damage, workspace, workspace->current.focused); | 987 | render_workspace(output, damage, workspace, workspace->current.focused); |
988 | render_floating(output, damage); | 988 | render_floating(output, damage); |
989 | #ifdef HAVE_XWAYLAND | 989 | #if HAVE_XWAYLAND |
990 | render_unmanaged(output, damage, &root->xwayland_unmanaged); | 990 | render_unmanaged(output, damage, &root->xwayland_unmanaged); |
991 | #endif | 991 | #endif |
992 | render_layer(output, damage, | 992 | render_layer(output, damage, |
@@ -1019,6 +1019,7 @@ renderer_end: | |||
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | wlr_renderer_scissor(renderer, NULL); | 1021 | wlr_renderer_scissor(renderer, NULL); |
1022 | wlr_output_render_software_cursors(wlr_output, damage); | ||
1022 | wlr_renderer_end(renderer); | 1023 | wlr_renderer_end(renderer); |
1023 | if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { | 1024 | if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { |
1024 | return; | 1025 | return; |
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 44156d41..bf0038b4 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c | |||
@@ -130,10 +130,10 @@ static void copy_container_state(struct sway_container *container, | |||
130 | struct sway_container_state *state = &instruction->container_state; | 130 | struct sway_container_state *state = &instruction->container_state; |
131 | 131 | ||
132 | state->layout = container->layout; | 132 | state->layout = container->layout; |
133 | state->con_x = container->x; | 133 | state->x = container->x; |
134 | state->con_y = container->y; | 134 | state->y = container->y; |
135 | state->con_width = container->width; | 135 | state->width = container->width; |
136 | state->con_height = container->height; | 136 | state->height = container->height; |
137 | state->is_fullscreen = container->is_fullscreen; | 137 | state->is_fullscreen = container->is_fullscreen; |
138 | state->parent = container->parent; | 138 | state->parent = container->parent; |
139 | state->workspace = container->workspace; | 139 | state->workspace = container->workspace; |
@@ -143,14 +143,12 @@ static void copy_container_state(struct sway_container *container, | |||
143 | state->border_left = container->border_left; | 143 | state->border_left = container->border_left; |
144 | state->border_right = container->border_right; | 144 | state->border_right = container->border_right; |
145 | state->border_bottom = container->border_bottom; | 145 | state->border_bottom = container->border_bottom; |
146 | state->content_x = container->content_x; | ||
147 | state->content_y = container->content_y; | ||
148 | state->content_width = container->content_width; | ||
149 | state->content_height = container->content_height; | ||
146 | 150 | ||
147 | if (container->view) { | 151 | if (!container->view) { |
148 | struct sway_view *view = container->view; | ||
149 | state->view_x = view->x; | ||
150 | state->view_y = view->y; | ||
151 | state->view_width = view->width; | ||
152 | state->view_height = view->height; | ||
153 | } else { | ||
154 | state->children = create_list(); | 152 | state->children = create_list(); |
155 | list_cat(state->children, container->children); | 153 | list_cat(state->children, container->children); |
156 | } | 154 | } |
@@ -217,8 +215,8 @@ static void apply_container_state(struct sway_container *container, | |||
217 | desktop_damage_whole_container(container); | 215 | desktop_damage_whole_container(container); |
218 | if (view && view->saved_buffer) { | 216 | if (view && view->saved_buffer) { |
219 | struct wlr_box box = { | 217 | struct wlr_box box = { |
220 | .x = container->current.view_x - view->saved_geometry.x, | 218 | .x = container->current.content_x - view->saved_geometry.x, |
221 | .y = container->current.view_y - view->saved_geometry.y, | 219 | .y = container->current.content_y - view->saved_geometry.y, |
222 | .width = view->saved_buffer_width, | 220 | .width = view->saved_buffer_width, |
223 | .height = view->saved_buffer_height, | 221 | .height = view->saved_buffer_height, |
224 | }; | 222 | }; |
@@ -245,8 +243,8 @@ static void apply_container_state(struct sway_container *container, | |||
245 | if (view && view->surface) { | 243 | if (view && view->surface) { |
246 | struct wlr_surface *surface = view->surface; | 244 | struct wlr_surface *surface = view->surface; |
247 | struct wlr_box box = { | 245 | struct wlr_box box = { |
248 | .x = container->current.view_x - view->geometry.x, | 246 | .x = container->current.content_x - view->geometry.x, |
249 | .y = container->current.view_y - view->geometry.y, | 247 | .y = container->current.content_y - view->geometry.y, |
250 | .width = surface->current.width, | 248 | .width = surface->current.width, |
251 | .height = surface->current.height, | 249 | .height = surface->current.height, |
252 | }; | 250 | }; |
@@ -382,18 +380,18 @@ static bool should_configure(struct sway_node *node, | |||
382 | } | 380 | } |
383 | struct sway_container_state *cstate = &node->sway_container->current; | 381 | struct sway_container_state *cstate = &node->sway_container->current; |
384 | struct sway_container_state *istate = &instruction->container_state; | 382 | struct sway_container_state *istate = &instruction->container_state; |
385 | #ifdef HAVE_XWAYLAND | 383 | #if HAVE_XWAYLAND |
386 | // Xwayland views are position-aware and need to be reconfigured | 384 | // Xwayland views are position-aware and need to be reconfigured |
387 | // when their position changes. | 385 | // when their position changes. |
388 | if (node->sway_container->view->type == SWAY_VIEW_XWAYLAND) { | 386 | if (node->sway_container->view->type == SWAY_VIEW_XWAYLAND) { |
389 | if (cstate->view_x != istate->view_x || | 387 | if (cstate->content_x != istate->content_x || |
390 | cstate->view_y != istate->view_y) { | 388 | cstate->content_y != istate->content_y) { |
391 | return true; | 389 | return true; |
392 | } | 390 | } |
393 | } | 391 | } |
394 | #endif | 392 | #endif |
395 | if (cstate->view_width == istate->view_width && | 393 | if (cstate->content_width == istate->content_width && |
396 | cstate->view_height == istate->view_height) { | 394 | cstate->content_height == istate->content_height) { |
397 | return false; | 395 | return false; |
398 | } | 396 | } |
399 | return true; | 397 | return true; |
@@ -409,10 +407,10 @@ static void transaction_commit(struct sway_transaction *transaction) { | |||
409 | struct sway_node *node = instruction->node; | 407 | struct sway_node *node = instruction->node; |
410 | if (should_configure(node, instruction)) { | 408 | if (should_configure(node, instruction)) { |
411 | instruction->serial = view_configure(node->sway_container->view, | 409 | instruction->serial = view_configure(node->sway_container->view, |
412 | instruction->container_state.view_x, | 410 | instruction->container_state.content_x, |
413 | instruction->container_state.view_y, | 411 | instruction->container_state.content_y, |
414 | instruction->container_state.view_width, | 412 | instruction->container_state.content_width, |
415 | instruction->container_state.view_height); | 413 | instruction->container_state.content_height); |
416 | ++transaction->num_waiting; | 414 | ++transaction->num_waiting; |
417 | 415 | ||
418 | // From here on we are rendering a saved buffer of the view, which | 416 | // From here on we are rendering a saved buffer of the view, which |
@@ -504,8 +502,8 @@ void transaction_notify_view_ready_by_size(struct sway_view *view, | |||
504 | int width, int height) { | 502 | int width, int height) { |
505 | struct sway_transaction_instruction *instruction = | 503 | struct sway_transaction_instruction *instruction = |
506 | view->container->node.instruction; | 504 | view->container->node.instruction; |
507 | if (instruction->container_state.view_width == width && | 505 | if (instruction->container_state.content_width == width && |
508 | instruction->container_state.view_height == height) { | 506 | instruction->container_state.content_height == height) { |
509 | set_instruction_ready(instruction); | 507 | set_instruction_ready(instruction); |
510 | } | 508 | } |
511 | } | 509 | } |
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 0b2ebc96..801dcee0 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -75,8 +75,8 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) { | |||
75 | // the output box expressed in the coordinate system of the toplevel parent | 75 | // the output box expressed in the coordinate system of the toplevel parent |
76 | // of the popup | 76 | // of the popup |
77 | struct wlr_box output_toplevel_sx_box = { | 77 | struct wlr_box output_toplevel_sx_box = { |
78 | .x = output->lx - view->x, | 78 | .x = output->lx - view->container->content_x, |
79 | .y = output->ly - view->y, | 79 | .y = output->ly - view->container->content_y, |
80 | .width = output->width, | 80 | .width = output->width, |
81 | .height = output->height, | 81 | .height = output->height, |
82 | }; | 82 | }; |
@@ -286,9 +286,11 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
286 | } else { | 286 | } else { |
287 | struct wlr_box new_geo; | 287 | struct wlr_box new_geo; |
288 | wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); | 288 | wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); |
289 | struct sway_container *con = view->container; | ||
289 | 290 | ||
290 | if ((new_geo.width != view->width || new_geo.height != view->height) && | 291 | if ((new_geo.width != con->content_width || |
291 | container_is_floating(view->container)) { | 292 | new_geo.height != con->content_height) && |
293 | container_is_floating(con)) { | ||
292 | // A floating view has unexpectedly sent a new size | 294 | // A floating view has unexpectedly sent a new size |
293 | desktop_damage_view(view); | 295 | desktop_damage_view(view); |
294 | view_update_size(view, new_geo.width, new_geo.height); | 296 | view_update_size(view, new_geo.width, new_geo.height); |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 692cfbf5..4bc83b8e 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -74,8 +74,8 @@ static void popup_unconstrain(struct sway_xdg_popup_v6 *popup) { | |||
74 | // the output box expressed in the coordinate system of the toplevel parent | 74 | // the output box expressed in the coordinate system of the toplevel parent |
75 | // of the popup | 75 | // of the popup |
76 | struct wlr_box output_toplevel_sx_box = { | 76 | struct wlr_box output_toplevel_sx_box = { |
77 | .x = output->lx - view->x, | 77 | .x = output->lx - view->container->content_x, |
78 | .y = output->ly - view->y, | 78 | .y = output->ly - view->container->content_y, |
79 | .width = output->width, | 79 | .width = output->width, |
80 | .height = output->height, | 80 | .height = output->height, |
81 | }; | 81 | }; |
@@ -283,9 +283,11 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
283 | } else { | 283 | } else { |
284 | struct wlr_box new_geo; | 284 | struct wlr_box new_geo; |
285 | wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &new_geo); | 285 | wlr_xdg_surface_v6_get_geometry(xdg_surface_v6, &new_geo); |
286 | struct sway_container *con = view->container; | ||
286 | 287 | ||
287 | if ((new_geo.width != view->width || new_geo.height != view->height) && | 288 | if ((new_geo.width != con->content_width || |
288 | container_is_floating(view->container)) { | 289 | new_geo.height != con->content_height) && |
290 | container_is_floating(con)) { | ||
289 | // A floating view has unexpectedly sent a new size | 291 | // A floating view has unexpectedly sent a new size |
290 | desktop_damage_view(view); | 292 | desktop_damage_view(view); |
291 | view_update_size(view, new_geo.width, new_geo.height); | 293 | view_update_size(view, new_geo.width, new_geo.height); |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 0c41d960..1838ad32 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -332,9 +332,11 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
332 | } else { | 332 | } else { |
333 | struct wlr_box new_geo; | 333 | struct wlr_box new_geo; |
334 | get_geometry(view, &new_geo); | 334 | get_geometry(view, &new_geo); |
335 | struct sway_container *con = view->container; | ||
335 | 336 | ||
336 | if ((new_geo.width != view->width || new_geo.height != view->height) && | 337 | if ((new_geo.width != con->content_width || |
337 | container_is_floating(view->container)) { | 338 | new_geo.height != con->content_height) && |
339 | container_is_floating(con)) { | ||
338 | // A floating view has unexpectedly sent a new size | 340 | // A floating view has unexpectedly sent a new size |
339 | // eg. The Firefox "Save As" dialog when downloading a file | 341 | // eg. The Firefox "Save As" dialog when downloading a file |
340 | desktop_damage_view(view); | 342 | desktop_damage_view(view); |
@@ -432,13 +434,13 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { | |||
432 | return; | 434 | return; |
433 | } | 435 | } |
434 | if (container_is_floating(view->container)) { | 436 | if (container_is_floating(view->container)) { |
435 | configure(view, view->container->current.view_x, | 437 | configure(view, view->container->current.content_x, |
436 | view->container->current.view_y, ev->width, ev->height); | 438 | view->container->current.content_y, ev->width, ev->height); |
437 | } else { | 439 | } else { |
438 | configure(view, view->container->current.view_x, | 440 | configure(view, view->container->current.content_x, |
439 | view->container->current.view_y, | 441 | view->container->current.content_y, |
440 | view->container->current.view_width, | 442 | view->container->current.content_width, |
441 | view->container->current.view_height); | 443 | view->container->current.content_height); |
442 | } | 444 | } |
443 | } | 445 | } |
444 | 446 | ||
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index c539df40..d89f64d8 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #elif __FreeBSD__ | 5 | #elif __FreeBSD__ |
6 | #include <dev/evdev/input-event-codes.h> | 6 | #include <dev/evdev/input-event-codes.h> |
7 | #endif | 7 | #endif |
8 | #include <float.h> | ||
8 | #include <limits.h> | 9 | #include <limits.h> |
9 | #include <wlr/types/wlr_cursor.h> | 10 | #include <wlr/types/wlr_cursor.h> |
10 | #include <wlr/types/wlr_xcursor_manager.h> | 11 | #include <wlr/types/wlr_xcursor_manager.h> |
@@ -63,7 +64,7 @@ static struct sway_node *node_at_coords( | |||
63 | struct sway_seat *seat, double lx, double ly, | 64 | struct sway_seat *seat, double lx, double ly, |
64 | struct wlr_surface **surface, double *sx, double *sy) { | 65 | struct wlr_surface **surface, double *sx, double *sy) { |
65 | // check for unmanaged views first | 66 | // check for unmanaged views first |
66 | #ifdef HAVE_XWAYLAND | 67 | #if HAVE_XWAYLAND |
67 | struct wl_list *unmanaged = &root->xwayland_unmanaged; | 68 | struct wl_list *unmanaged = &root->xwayland_unmanaged; |
68 | struct sway_xwayland_unmanaged *unmanaged_surface; | 69 | struct sway_xwayland_unmanaged *unmanaged_surface; |
69 | wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { | 70 | wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { |
@@ -348,7 +349,7 @@ static void handle_move_tiling_motion(struct sway_seat *seat, | |||
348 | } | 349 | } |
349 | 350 | ||
350 | // Find the closest edge | 351 | // Find the closest edge |
351 | size_t thickness = fmin(con->view->width, con->view->height) * 0.3; | 352 | size_t thickness = fmin(con->content_width, con->content_height) * 0.3; |
352 | size_t closest_dist = INT_MAX; | 353 | size_t closest_dist = INT_MAX; |
353 | size_t dist; | 354 | size_t dist; |
354 | seat->op_target_edge = WLR_EDGE_NONE; | 355 | seat->op_target_edge = WLR_EDGE_NONE; |
@@ -374,10 +375,10 @@ static void handle_move_tiling_motion(struct sway_seat *seat, | |||
374 | } | 375 | } |
375 | 376 | ||
376 | seat->op_target_node = node; | 377 | seat->op_target_node = node; |
377 | seat->op_drop_box.x = con->view->x; | 378 | seat->op_drop_box.x = con->content_x; |
378 | seat->op_drop_box.y = con->view->y; | 379 | seat->op_drop_box.y = con->content_y; |
379 | seat->op_drop_box.width = con->view->width; | 380 | seat->op_drop_box.width = con->content_width; |
380 | seat->op_drop_box.height = con->view->height; | 381 | seat->op_drop_box.height = con->content_height; |
381 | resize_box(&seat->op_drop_box, seat->op_target_edge, thickness); | 382 | resize_box(&seat->op_drop_box, seat->op_target_edge, thickness); |
382 | desktop_damage_box(&seat->op_drop_box); | 383 | desktop_damage_box(&seat->op_drop_box); |
383 | } | 384 | } |
@@ -498,13 +499,10 @@ static void handle_resize_floating_motion(struct sway_seat *seat, | |||
498 | con->width += relative_grow_width; | 499 | con->width += relative_grow_width; |
499 | con->height += relative_grow_height; | 500 | con->height += relative_grow_height; |
500 | 501 | ||
501 | if (con->view) { | 502 | con->content_x += relative_grow_x; |
502 | struct sway_view *view = con->view; | 503 | con->content_y += relative_grow_y; |
503 | view->x += relative_grow_x; | 504 | con->content_width += relative_grow_width; |
504 | view->y += relative_grow_y; | 505 | con->content_height += relative_grow_height; |
505 | view->width += relative_grow_width; | ||
506 | view->height += relative_grow_height; | ||
507 | } | ||
508 | 506 | ||
509 | arrange_container(con); | 507 | arrange_container(con); |
510 | } | 508 | } |
@@ -637,7 +635,8 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
637 | cursor->previous.y = cursor->cursor->y; | 635 | cursor->previous.y = cursor->cursor->y; |
638 | cursor->previous.node = node; | 636 | cursor->previous.node = node; |
639 | 637 | ||
640 | if (node && config->focus_follows_mouse) { | 638 | if (node && (config->focus_follows_mouse == FOLLOWS_YES || |
639 | config->focus_follows_mouse == FOLLOWS_ALWAYS)) { | ||
641 | struct sway_node *focus = seat_get_focus(seat); | 640 | struct sway_node *focus = seat_get_focus(seat); |
642 | if (focus && node->type == N_WORKSPACE) { | 641 | if (focus && node->type == N_WORKSPACE) { |
643 | // Only follow the mouse if it would move to a new output | 642 | // Only follow the mouse if it would move to a new output |
@@ -652,9 +651,10 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
652 | // - cursor is over a new view, i.e. entered a new window; and | 651 | // - cursor is over a new view, i.e. entered a new window; and |
653 | // - the new view is visible, i.e. not hidden in a stack or tab; and | 652 | // - the new view is visible, i.e. not hidden in a stack or tab; and |
654 | // - the seat does not have a keyboard grab | 653 | // - the seat does not have a keyboard grab |
655 | if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) && | 654 | if ((!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) && |
656 | node != prev_node && | 655 | node != prev_node && |
657 | view_is_visible(node->sway_container->view)) { | 656 | view_is_visible(node->sway_container->view)) || |
657 | config->focus_follows_mouse == FOLLOWS_ALWAYS) { | ||
658 | seat_set_focus(seat, node); | 658 | seat_set_focus(seat, node); |
659 | } else { | 659 | } else { |
660 | struct sway_node *next_focus = | 660 | struct sway_node *next_focus = |
@@ -861,8 +861,8 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
861 | } | 861 | } |
862 | 862 | ||
863 | // Handle tiling resize via border | 863 | // Handle tiling resize via border |
864 | if (resize_edge && button == BTN_LEFT && state == WLR_BUTTON_PRESSED && | 864 | if (cont && resize_edge && button == BTN_LEFT && |
865 | !is_floating) { | 865 | state == WLR_BUTTON_PRESSED && !is_floating) { |
866 | seat_set_focus_container(seat, cont); | 866 | seat_set_focus_container(seat, cont); |
867 | seat_begin_resize_tiling(seat, cont, button, edge); | 867 | seat_begin_resize_tiling(seat, cont, button, edge); |
868 | return; | 868 | return; |
@@ -871,7 +871,8 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
871 | // Handle tiling resize via mod | 871 | // Handle tiling resize via mod |
872 | bool mod_pressed = keyboard && | 872 | bool mod_pressed = keyboard && |
873 | (wlr_keyboard_get_modifiers(keyboard) & config->floating_mod); | 873 | (wlr_keyboard_get_modifiers(keyboard) & config->floating_mod); |
874 | if (!is_floating_or_child && mod_pressed && state == WLR_BUTTON_PRESSED) { | 874 | if (cont && !is_floating_or_child && mod_pressed && |
875 | state == WLR_BUTTON_PRESSED) { | ||
875 | uint32_t btn_resize = config->floating_mod_inverse ? | 876 | uint32_t btn_resize = config->floating_mod_inverse ? |
876 | BTN_LEFT : BTN_RIGHT; | 877 | BTN_LEFT : BTN_RIGHT; |
877 | if (button == btn_resize) { | 878 | if (button == btn_resize) { |
@@ -899,7 +900,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
899 | } | 900 | } |
900 | 901 | ||
901 | // Handle beginning floating move | 902 | // Handle beginning floating move |
902 | if (is_floating_or_child && !is_fullscreen_or_child && | 903 | if (cont && is_floating_or_child && !is_fullscreen_or_child && |
903 | state == WLR_BUTTON_PRESSED) { | 904 | state == WLR_BUTTON_PRESSED) { |
904 | uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; | 905 | uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; |
905 | if (button == btn_move && state == WLR_BUTTON_PRESSED && | 906 | if (button == btn_move && state == WLR_BUTTON_PRESSED && |
@@ -914,7 +915,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
914 | } | 915 | } |
915 | 916 | ||
916 | // Handle beginning floating resize | 917 | // Handle beginning floating resize |
917 | if (is_floating_or_child && !is_fullscreen_or_child && | 918 | if (cont && is_floating_or_child && !is_fullscreen_or_child && |
918 | state == WLR_BUTTON_PRESSED) { | 919 | state == WLR_BUTTON_PRESSED) { |
919 | // Via border | 920 | // Via border |
920 | if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) { | 921 | if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) { |
@@ -979,6 +980,8 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
979 | static void dispatch_cursor_axis(struct sway_cursor *cursor, | 980 | static void dispatch_cursor_axis(struct sway_cursor *cursor, |
980 | struct wlr_event_pointer_axis *event) { | 981 | struct wlr_event_pointer_axis *event) { |
981 | struct sway_seat *seat = cursor->seat; | 982 | struct sway_seat *seat = cursor->seat; |
983 | struct sway_input_device *input_device = event->device->data; | ||
984 | struct input_config *ic = input_device_get_config(input_device); | ||
982 | 985 | ||
983 | // Determine what's under the cursor | 986 | // Determine what's under the cursor |
984 | struct wlr_surface *surface = NULL; | 987 | struct wlr_surface *surface = NULL; |
@@ -990,6 +993,8 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor, | |||
990 | enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE; | 993 | enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE; |
991 | bool on_border = edge != WLR_EDGE_NONE; | 994 | bool on_border = edge != WLR_EDGE_NONE; |
992 | bool on_titlebar = cont && !on_border && !surface; | 995 | bool on_titlebar = cont && !on_border && !surface; |
996 | float scroll_factor = | ||
997 | (ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor; | ||
993 | 998 | ||
994 | // Scrolling on a tabbed or stacked title bar | 999 | // Scrolling on a tabbed or stacked title bar |
995 | if (on_titlebar) { | 1000 | if (on_titlebar) { |
@@ -1000,7 +1005,7 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor, | |||
1000 | seat_get_active_tiling_child(seat, tabcontainer); | 1005 | seat_get_active_tiling_child(seat, tabcontainer); |
1001 | list_t *siblings = container_get_siblings(cont); | 1006 | list_t *siblings = container_get_siblings(cont); |
1002 | int desired = list_find(siblings, active->sway_container) + | 1007 | int desired = list_find(siblings, active->sway_container) + |
1003 | event->delta_discrete; | 1008 | round(scroll_factor * event->delta_discrete); |
1004 | if (desired < 0) { | 1009 | if (desired < 0) { |
1005 | desired = 0; | 1010 | desired = 0; |
1006 | } else if (desired >= siblings->length) { | 1011 | } else if (desired >= siblings->length) { |
@@ -1024,7 +1029,8 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor, | |||
1024 | } | 1029 | } |
1025 | 1030 | ||
1026 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, | 1031 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, |
1027 | event->orientation, event->delta, event->delta_discrete, event->source); | 1032 | event->orientation, scroll_factor * event->delta, |
1033 | round(scroll_factor * event->delta_discrete), event->source); | ||
1028 | } | 1034 | } |
1029 | 1035 | ||
1030 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { | 1036 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 54fdf40b..663c5140 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -92,7 +92,7 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) { | |||
92 | node->sway_container->view : NULL; | 92 | node->sway_container->view : NULL; |
93 | 93 | ||
94 | if (view && seat_is_input_allowed(seat, view->surface)) { | 94 | if (view && seat_is_input_allowed(seat, view->surface)) { |
95 | #ifdef HAVE_XWAYLAND | 95 | #if HAVE_XWAYLAND |
96 | if (view->type == SWAY_VIEW_XWAYLAND) { | 96 | if (view->type == SWAY_VIEW_XWAYLAND) { |
97 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; | 97 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; |
98 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 98 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index cf1b42a6..05e453ec 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "sway/input/seat.h" | 12 | #include "sway/input/seat.h" |
13 | #include <wlr/types/wlr_box.h> | 13 | #include <wlr/types/wlr_box.h> |
14 | #include <wlr/types/wlr_output.h> | 14 | #include <wlr/types/wlr_output.h> |
15 | #include <xkbcommon/xkbcommon.h> | ||
15 | #include "wlr-layer-shell-unstable-v1-protocol.h" | 16 | #include "wlr-layer-shell-unstable-v1-protocol.h" |
16 | 17 | ||
17 | static const char *ipc_json_layout_description(enum sway_container_layout l) { | 18 | static const char *ipc_json_layout_description(enum sway_container_layout l) { |
@@ -245,10 +246,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
245 | json_object_object_add(object, "marks", marks); | 246 | json_object_object_add(object, "marks", marks); |
246 | 247 | ||
247 | struct wlr_box window_box = { | 248 | struct wlr_box window_box = { |
248 | c->view->x - c->x, | 249 | c->content_x - c->x, |
249 | (c->current.border == B_PIXEL) ? c->current.border_thickness : 0, | 250 | (c->current.border == B_PIXEL) ? c->current.border_thickness : 0, |
250 | c->view->width, | 251 | c->content_width, |
251 | c->view->height | 252 | c->content_height |
252 | }; | 253 | }; |
253 | 254 | ||
254 | json_object_object_add(object, "window_rect", ipc_json_create_rect(&window_box)); | 255 | json_object_object_add(object, "window_rect", ipc_json_create_rect(&window_box)); |
@@ -257,7 +258,7 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
257 | 258 | ||
258 | if (c->current.border == B_NORMAL) { | 259 | if (c->current.border == B_NORMAL) { |
259 | deco_box.width = c->width; | 260 | deco_box.width = c->width; |
260 | deco_box.height = c->view->y - c->y; | 261 | deco_box.height = c->content_y - c->y; |
261 | } | 262 | } |
262 | 263 | ||
263 | json_object_object_add(object, "deco_rect", ipc_json_create_rect(&deco_box)); | 264 | json_object_object_add(object, "deco_rect", ipc_json_create_rect(&deco_box)); |
@@ -265,7 +266,7 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object | |||
265 | struct wlr_box geometry = {0, 0, c->view->natural_width, c->view->natural_height}; | 266 | struct wlr_box geometry = {0, 0, c->view->natural_width, c->view->natural_height}; |
266 | json_object_object_add(object, "geometry", ipc_json_create_rect(&geometry)); | 267 | json_object_object_add(object, "geometry", ipc_json_create_rect(&geometry)); |
267 | 268 | ||
268 | #ifdef HAVE_XWAYLAND | 269 | #if HAVE_XWAYLAND |
269 | if (c->view->type == SWAY_VIEW_XWAYLAND) { | 270 | if (c->view->type == SWAY_VIEW_XWAYLAND) { |
270 | json_object_object_add(object, "window", | 271 | json_object_object_add(object, "window", |
271 | json_object_new_int(view_get_x11_window_id(c->view))); | 272 | json_object_new_int(view_get_x11_window_id(c->view))); |
@@ -503,6 +504,27 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { | |||
503 | json_object_object_add(object, "type", | 504 | json_object_object_add(object, "type", |
504 | json_object_new_string(describe_device_type(device))); | 505 | json_object_new_string(describe_device_type(device))); |
505 | 506 | ||
507 | if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { | ||
508 | struct wlr_keyboard *keyboard = device->wlr_device->keyboard; | ||
509 | struct xkb_keymap *keymap = keyboard->keymap; | ||
510 | struct xkb_state *state = keyboard->xkb_state; | ||
511 | xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(keymap); | ||
512 | xkb_layout_index_t layout_idx; | ||
513 | for (layout_idx = 0; layout_idx < num_layouts; layout_idx++) { | ||
514 | bool is_active = | ||
515 | xkb_state_layout_index_is_active(state, | ||
516 | layout_idx, | ||
517 | XKB_STATE_LAYOUT_EFFECTIVE); | ||
518 | if (is_active) { | ||
519 | const char *layout = | ||
520 | xkb_keymap_layout_get_name(keymap, layout_idx); | ||
521 | json_object_object_add(object, "xkb_active_layout_name", | ||
522 | json_object_new_string(layout)); | ||
523 | break; | ||
524 | } | ||
525 | } | ||
526 | } | ||
527 | |||
506 | return object; | 528 | return object; |
507 | } | 529 | } |
508 | 530 | ||
diff --git a/sway/meson.build b/sway/meson.build index debd7a91..14822dbd 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -136,6 +136,7 @@ sway_sources = files( | |||
136 | 'commands/input/repeat_delay.c', | 136 | 'commands/input/repeat_delay.c', |
137 | 'commands/input/repeat_rate.c', | 137 | 'commands/input/repeat_rate.c', |
138 | 'commands/input/scroll_button.c', | 138 | 'commands/input/scroll_button.c', |
139 | 'commands/input/scroll_factor.c', | ||
139 | 'commands/input/scroll_method.c', | 140 | 'commands/input/scroll_method.c', |
140 | 'commands/input/tap.c', | 141 | 'commands/input/tap.c', |
141 | 'commands/input/tap_button_map.c', | 142 | 'commands/input/tap_button_map.c', |
diff --git a/sway/server.c b/sway/server.c index f06173d1..cd3fcdf6 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include "sway/server.h" | 26 | #include "sway/server.h" |
27 | #include "sway/tree/root.h" | 27 | #include "sway/tree/root.h" |
28 | #include "config.h" | 28 | #include "config.h" |
29 | #ifdef HAVE_XWAYLAND | 29 | #if HAVE_XWAYLAND |
30 | #include "sway/xwayland.h" | 30 | #include "sway/xwayland.h" |
31 | #endif | 31 | #endif |
32 | 32 | ||
@@ -94,7 +94,7 @@ bool server_init(struct sway_server *server) { | |||
94 | setenv("XCURSOR_THEME", cursor_theme, 1); | 94 | setenv("XCURSOR_THEME", cursor_theme, 1); |
95 | } | 95 | } |
96 | 96 | ||
97 | #ifdef HAVE_XWAYLAND | 97 | #if HAVE_XWAYLAND |
98 | server->xwayland.wlr_xwayland = | 98 | server->xwayland.wlr_xwayland = |
99 | wlr_xwayland_create(server->wl_display, server->compositor, true); | 99 | wlr_xwayland_create(server->wl_display, server->compositor, true); |
100 | wl_signal_add(&server->xwayland.wlr_xwayland->events.new_surface, | 100 | wl_signal_add(&server->xwayland.wlr_xwayland->events.new_surface, |
@@ -164,7 +164,7 @@ bool server_init(struct sway_server *server) { | |||
164 | 164 | ||
165 | void server_fini(struct sway_server *server) { | 165 | void server_fini(struct sway_server *server) { |
166 | // TODO: free sway-specific resources | 166 | // TODO: free sway-specific resources |
167 | #ifdef HAVE_XWAYLAND | 167 | #if HAVE_XWAYLAND |
168 | wlr_xwayland_destroy(server->xwayland.wlr_xwayland); | 168 | wlr_xwayland_destroy(server->xwayland.wlr_xwayland); |
169 | #endif | 169 | #endif |
170 | wl_display_destroy_clients(server->wl_display); | 170 | wl_display_destroy_clients(server->wl_display); |
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd index 82273ef3..45994644 100644 --- a/sway/sway-input.5.scd +++ b/sway/sway-input.5.scd | |||
@@ -105,14 +105,18 @@ The following commands may only be used in the configuration file. | |||
105 | *input* <identifier> repeat\_rate <characters per second> | 105 | *input* <identifier> repeat\_rate <characters per second> |
106 | Sets the frequency of key repeats once the repeat\_delay has passed. | 106 | Sets the frequency of key repeats once the repeat\_delay has passed. |
107 | 107 | ||
108 | *input* <identifier> scroll\_method none|two\_finger|edge|on\_button\_down | ||
109 | Changes the scroll method for the specified input device. | ||
110 | |||
111 | *input* <identifier> scroll\_button <button\_identifier> | 108 | *input* <identifier> scroll\_button <button\_identifier> |
112 | Sets button used for scroll\_method on\_button\_down. The button identifier | 109 | Sets button used for scroll\_method on\_button\_down. The button identifier |
113 | can be obtained from `libinput debug-events`. | 110 | can be obtained from `libinput debug-events`. |
114 | If set to 0, it disables the scroll\_button on\_button\_down. | 111 | If set to 0, it disables the scroll\_button on\_button\_down. |
115 | 112 | ||
113 | *input* <identifier> scroll\_factor <floating point value> | ||
114 | Changes the scroll factor for the specified input device. Scroll speed will | ||
115 | be scaled by the given value, which must be non-negative. | ||
116 | |||
117 | *input* <identifier> scroll\_method none|two\_finger|edge|on\_button\_down | ||
118 | Changes the scroll method for the specified input device. | ||
119 | |||
116 | *input* <identifier> tap enabled|disabled | 120 | *input* <identifier> tap enabled|disabled |
117 | Enables or disables tap for specified input device. | 121 | Enables or disables tap for specified input device. |
118 | 122 | ||
diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 4a645837..1a11015f 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd | |||
@@ -133,9 +133,12 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). | |||
133 | *fullscreen* | 133 | *fullscreen* |
134 | Toggles fullscreen for the focused view. | 134 | Toggles fullscreen for the focused view. |
135 | 135 | ||
136 | *gaps* inner|outer all|current set|plus|minus <amount> | 136 | *gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current |
137 | set|plus|minus <amount> | ||
137 | Changes the _inner_ or _outer_ gaps for either _all_ workspaces or the | 138 | Changes the _inner_ or _outer_ gaps for either _all_ workspaces or the |
138 | _current_ workspace. | 139 | _current_ workspace. _outer_ gaps can be altered per side with _top_, |
140 | _right_, _bottom_, and _left_ or per direction with _horizontal_ and | ||
141 | _vertical_. | ||
139 | 142 | ||
140 | *layout* default|splith|splitv|stacking|tabbed | 143 | *layout* default|splith|splitv|stacking|tabbed |
141 | Sets the layout mode of the focused container. | 144 | Sets the layout mode of the focused container. |
@@ -207,11 +210,23 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). | |||
207 | percentage points. If the units are omitted, floating containers are resized | 210 | percentage points. If the units are omitted, floating containers are resized |
208 | in px and tiled containers by ppt. _amount_ will default to 10 if omitted. | 211 | in px and tiled containers by ppt. _amount_ will default to 10 if omitted. |
209 | 212 | ||
210 | *resize set* <width> [px|ppt] <height> [px|ppt] | 213 | *resize set* height <height> [px|ppt] |
211 | Sets the width and height of the currently focused container to _width_ and | 214 | Sets the height of the container to _height_, specified in pixels or |
212 | _height_, specified in pixels or percentage points. If the units are | 215 | percentage points. If the units are omitted, floating containers are |
213 | omitted, floating containers are resized in px and tiled containers by ppt. | 216 | resized in px and tiled containers by ppt. If _height_ is 0, the container |
214 | If _width_ or _height_ is 0, no resize is done on that axis. | 217 | will not be resized. |
218 | |||
219 | *resize set* [width] <width> [px|ppt] | ||
220 | Sets the width of the container to _width_, specified in pixels or | ||
221 | percentage points. If the units are omitted, floating containers are | ||
222 | resized in px and tiled containers by ppt. If _width_ is 0, the container | ||
223 | will not be resized. | ||
224 | |||
225 | *resize set* [width] <width> [px|ppt] [height] <height> [px|ppt] | ||
226 | Sets the width and height of the container to _width_ and _height_, | ||
227 | specified in pixels or percentage points. If the units are omitted, | ||
228 | floating containers are resized in px and tiled containers by ppt. If | ||
229 | _width_ or _height_ is 0, the container will not be resized on that axis. | ||
215 | 230 | ||
216 | *scratchpad show* | 231 | *scratchpad show* |
217 | Shows a window from the scratchpad. Repeatedly using this command will | 232 | Shows a window from the scratchpad. Repeatedly using this command will |
@@ -404,8 +419,10 @@ The default colors are: | |||
404 | specified direction while holding the floating modifier. Resets the | 419 | specified direction while holding the floating modifier. Resets the |
405 | command, when given no arguments. | 420 | command, when given no arguments. |
406 | 421 | ||
407 | *focus\_follows\_mouse* yes|no | 422 | *focus\_follows\_mouse* yes|no|always |
408 | If set to _yes_, moving your mouse over a window will focus that window. | 423 | If set to _yes_, moving your mouse over a window will focus that window. If |
424 | set to _always_, the window under the cursor will always be focused, even | ||
425 | after switching between workspaces. | ||
409 | 426 | ||
410 | *focus\_wrapping* yes|no|force | 427 | *focus\_wrapping* yes|no|force |
411 | This option determines what to do when attempting to focus over the edge | 428 | This option determines what to do when attempting to focus over the edge |
@@ -429,14 +446,16 @@ The default colors are: | |||
429 | _focus\_wrapping force_. This is only available for convenience. Please | 446 | _focus\_wrapping force_. This is only available for convenience. Please |
430 | use _focus\_wrapping_ instead when possible. | 447 | use _focus\_wrapping_ instead when possible. |
431 | 448 | ||
432 | *gaps* inner|outer <amount> | 449 | *gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount> |
433 | Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner | 450 | Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner |
434 | affects spacing around each view and outer affects the spacing around each | 451 | affects spacing around each view and outer affects the spacing around each |
435 | workspace. Outer gaps are in addition to inner gaps. To reduce or remove | 452 | workspace. Outer gaps are in addition to inner gaps. To reduce or remove |
436 | outer gaps, outer gaps can be set to a negative value. | 453 | outer gaps, outer gaps can be set to a negative value. _outer_ gaps can |
454 | also be specified per side with _top_, _right_, _bottom_, and _left_ or | ||
455 | per direction with _horizontal_ and _vertical_. | ||
437 | 456 | ||
438 | This affects new workspaces only, and is used when the workspace doesn't | 457 | This affects new workspaces only, and is used when the workspace doesn't |
439 | have its own gaps settings (see: workspace <ws> gaps inner|outer <amount>). | 458 | have its own gaps settings (see: workspace <ws> gaps ...). |
440 | 459 | ||
441 | *hide\_edge\_borders* none|vertical|horizontal|both|smart|smart\_no\_gaps | 460 | *hide\_edge\_borders* none|vertical|horizontal|both|smart|smart\_no\_gaps |
442 | Hides window borders adjacent to the screen edges. Default is _none_. | 461 | Hides window borders adjacent to the screen edges. Default is _none_. |
@@ -549,12 +568,17 @@ The default colors are: | |||
549 | *workspace* back\_and\_forth | 568 | *workspace* back\_and\_forth |
550 | Switches to the previously focused workspace. | 569 | Switches to the previously focused workspace. |
551 | 570 | ||
552 | *workspace* <name> gaps inner|outer <amount> | 571 | *workspace* <name> gaps inner|outer|horizontal|vertical|top|right|bottom|left |
572 | <amount> | ||
553 | Specifies that workspace _name_ should have the given gaps settings when it | 573 | Specifies that workspace _name_ should have the given gaps settings when it |
554 | is created. | 574 | is created. |
555 | 575 | ||
556 | *workspace* <name> output <output> | 576 | *workspace* <name> output <outputs...> |
557 | Specifies that workspace _name_ should be shown on the specified _output_. | 577 | Specifies that workspace _name_ should be shown on the specified _outputs_. |
578 | Multiple outputs can be listed and the first available will be used. If the | ||
579 | workspace gets placed on an output further down the list and an output that | ||
580 | is higher on the list becomes available, the workspace will be move to the | ||
581 | higher priority output. | ||
558 | 582 | ||
559 | *workspace\_auto\_back\_and\_forth* yes|no | 583 | *workspace\_auto\_back\_and\_forth* yes|no |
560 | When _yes_, repeating a workspace switch command will switch back to the | 584 | When _yes_, repeating a workspace switch command will switch back to the |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 458ed7ff..cf6f5b54 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -165,13 +165,13 @@ static struct sway_container *surface_at_view(struct sway_container *con, double | |||
165 | return NULL; | 165 | return NULL; |
166 | } | 166 | } |
167 | struct sway_view *view = con->view; | 167 | struct sway_view *view = con->view; |
168 | double view_sx = lx - view->x + view->geometry.x; | 168 | double view_sx = lx - con->content_x + view->geometry.x; |
169 | double view_sy = ly - view->y + view->geometry.y; | 169 | double view_sy = ly - con->content_y + view->geometry.y; |
170 | 170 | ||
171 | double _sx, _sy; | 171 | double _sx, _sy; |
172 | struct wlr_surface *_surface = NULL; | 172 | struct wlr_surface *_surface = NULL; |
173 | switch (view->type) { | 173 | switch (view->type) { |
174 | #ifdef HAVE_XWAYLAND | 174 | #if HAVE_XWAYLAND |
175 | case SWAY_VIEW_XWAYLAND: | 175 | case SWAY_VIEW_XWAYLAND: |
176 | _surface = wlr_surface_surface_at(view->surface, | 176 | _surface = wlr_surface_surface_at(view->surface, |
177 | view_sx, view_sy, &_sx, &_sy); | 177 | view_sx, view_sy, &_sx, &_sy); |
@@ -641,16 +641,18 @@ void container_init_floating(struct sway_container *con) { | |||
641 | con->y = ws->y + (ws->height - con->height) / 2; | 641 | con->y = ws->y + (ws->height - con->height) / 2; |
642 | } else { | 642 | } else { |
643 | struct sway_view *view = con->view; | 643 | struct sway_view *view = con->view; |
644 | view->width = fmax(min_width, fmin(view->natural_width, max_width)); | 644 | con->content_width = |
645 | view->height = fmax(min_height, fmin(view->natural_height, max_height)); | 645 | fmax(min_width, fmin(view->natural_width, max_width)); |
646 | view->x = ws->x + (ws->width - view->width) / 2; | 646 | con->content_height = |
647 | view->y = ws->y + (ws->height - view->height) / 2; | 647 | fmax(min_height, fmin(view->natural_height, max_height)); |
648 | con->content_x = ws->x + (ws->width - con->content_width) / 2; | ||
649 | con->content_y = ws->y + (ws->height - con->content_height) / 2; | ||
648 | 650 | ||
649 | // If the view's border is B_NONE then these properties are ignored. | 651 | // If the view's border is B_NONE then these properties are ignored. |
650 | con->border_top = con->border_bottom = true; | 652 | con->border_top = con->border_bottom = true; |
651 | con->border_left = con->border_right = true; | 653 | con->border_left = con->border_right = true; |
652 | 654 | ||
653 | container_set_geometry_from_floating_view(con); | 655 | container_set_geometry_from_content(con); |
654 | } | 656 | } |
655 | } | 657 | } |
656 | 658 | ||
@@ -707,14 +709,13 @@ void container_set_floating(struct sway_container *container, bool enable) { | |||
707 | ipc_event_window(container, "floating"); | 709 | ipc_event_window(container, "floating"); |
708 | } | 710 | } |
709 | 711 | ||
710 | void container_set_geometry_from_floating_view(struct sway_container *con) { | 712 | void container_set_geometry_from_content(struct sway_container *con) { |
711 | if (!sway_assert(con->view, "Expected a view")) { | 713 | if (!sway_assert(con->view, "Expected a view")) { |
712 | return; | 714 | return; |
713 | } | 715 | } |
714 | if (!sway_assert(container_is_floating(con), "Expected a floating view")) { | 716 | if (!sway_assert(container_is_floating(con), "Expected a floating view")) { |
715 | return; | 717 | return; |
716 | } | 718 | } |
717 | struct sway_view *view = con->view; | ||
718 | size_t border_width = 0; | 719 | size_t border_width = 0; |
719 | size_t top = 0; | 720 | size_t top = 0; |
720 | 721 | ||
@@ -724,10 +725,10 @@ void container_set_geometry_from_floating_view(struct sway_container *con) { | |||
724 | container_titlebar_height() : border_width; | 725 | container_titlebar_height() : border_width; |
725 | } | 726 | } |
726 | 727 | ||
727 | con->x = view->x - border_width; | 728 | con->x = con->content_x - border_width; |
728 | con->y = view->y - top; | 729 | con->y = con->content_y - top; |
729 | con->width = view->width + border_width * 2; | 730 | con->width = con->content_width + border_width * 2; |
730 | con->height = top + view->height + border_width; | 731 | con->height = top + con->content_height + border_width; |
731 | node_set_dirty(&con->node); | 732 | node_set_dirty(&con->node); |
732 | } | 733 | } |
733 | 734 | ||
@@ -756,15 +757,16 @@ void container_floating_translate(struct sway_container *con, | |||
756 | double x_amount, double y_amount) { | 757 | double x_amount, double y_amount) { |
757 | con->x += x_amount; | 758 | con->x += x_amount; |
758 | con->y += y_amount; | 759 | con->y += y_amount; |
759 | if (con->view) { | 760 | con->content_x += x_amount; |
760 | con->view->x += x_amount; | 761 | con->content_y += y_amount; |
761 | con->view->y += y_amount; | 762 | |
762 | } else { | 763 | if (con->children) { |
763 | for (int i = 0; i < con->children->length; ++i) { | 764 | for (int i = 0; i < con->children->length; ++i) { |
764 | struct sway_container *child = con->children->items[i]; | 765 | struct sway_container *child = con->children->items[i]; |
765 | container_floating_translate(child, x_amount, y_amount); | 766 | container_floating_translate(child, x_amount, y_amount); |
766 | } | 767 | } |
767 | } | 768 | } |
769 | |||
768 | node_set_dirty(&con->node); | 770 | node_set_dirty(&con->node); |
769 | } | 771 | } |
770 | 772 | ||
@@ -964,10 +966,10 @@ static void surface_send_leave_iterator(struct wlr_surface *surface, | |||
964 | 966 | ||
965 | void container_discover_outputs(struct sway_container *con) { | 967 | void container_discover_outputs(struct sway_container *con) { |
966 | struct wlr_box con_box = { | 968 | struct wlr_box con_box = { |
967 | .x = con->current.con_x, | 969 | .x = con->current.x, |
968 | .y = con->current.con_y, | 970 | .y = con->current.y, |
969 | .width = con->current.con_width, | 971 | .width = con->current.width, |
970 | .height = con->current.con_height, | 972 | .height = con->current.height, |
971 | }; | 973 | }; |
972 | struct sway_output *old_output = container_get_effective_output(con); | 974 | struct sway_output *old_output = container_get_effective_output(con); |
973 | 975 | ||
@@ -1009,19 +1011,25 @@ void container_discover_outputs(struct sway_container *con) { | |||
1009 | } | 1011 | } |
1010 | 1012 | ||
1011 | void container_remove_gaps(struct sway_container *c) { | 1013 | void container_remove_gaps(struct sway_container *c) { |
1012 | if (c->current_gaps == 0) { | 1014 | if (c->current_gaps.top == 0 && c->current_gaps.right == 0 && |
1015 | c->current_gaps.bottom == 0 && c->current_gaps.left == 0) { | ||
1013 | return; | 1016 | return; |
1014 | } | 1017 | } |
1015 | 1018 | ||
1016 | c->width += c->current_gaps * 2; | 1019 | c->width += c->current_gaps.left + c->current_gaps.right; |
1017 | c->height += c->current_gaps * 2; | 1020 | c->height += c->current_gaps.top + c->current_gaps.bottom; |
1018 | c->x -= c->current_gaps; | 1021 | c->x -= c->current_gaps.left; |
1019 | c->y -= c->current_gaps; | 1022 | c->y -= c->current_gaps.top; |
1020 | c->current_gaps = 0; | 1023 | |
1024 | c->current_gaps.top = 0; | ||
1025 | c->current_gaps.right = 0; | ||
1026 | c->current_gaps.bottom = 0; | ||
1027 | c->current_gaps.left = 0; | ||
1021 | } | 1028 | } |
1022 | 1029 | ||
1023 | void container_add_gaps(struct sway_container *c) { | 1030 | void container_add_gaps(struct sway_container *c) { |
1024 | if (c->current_gaps > 0) { | 1031 | if (c->current_gaps.top > 0 || c->current_gaps.right > 0 || |
1032 | c->current_gaps.bottom > 0 || c->current_gaps.left > 0) { | ||
1025 | return; | 1033 | return; |
1026 | } | 1034 | } |
1027 | // Linear containers don't have gaps because it'd create double gaps | 1035 | // Linear containers don't have gaps because it'd create double gaps |
@@ -1054,11 +1062,15 @@ void container_add_gaps(struct sway_container *c) { | |||
1054 | 1062 | ||
1055 | struct sway_workspace *ws = c->workspace; | 1063 | struct sway_workspace *ws = c->workspace; |
1056 | 1064 | ||
1057 | c->current_gaps = ws->gaps_inner; | 1065 | c->current_gaps.top = c->y == ws->y ? ws->gaps_inner : 0; |
1058 | c->x += c->current_gaps; | 1066 | c->current_gaps.right = ws->gaps_inner; |
1059 | c->y += c->current_gaps; | 1067 | c->current_gaps.bottom = ws->gaps_inner; |
1060 | c->width -= 2 * c->current_gaps; | 1068 | c->current_gaps.left = c->x == ws->x ? ws->gaps_inner : 0; |
1061 | c->height -= 2 * c->current_gaps; | 1069 | |
1070 | c->x += c->current_gaps.left; | ||
1071 | c->y += c->current_gaps.top; | ||
1072 | c->width -= c->current_gaps.left + c->current_gaps.right; | ||
1073 | c->height -= c->current_gaps.top + c->current_gaps.bottom; | ||
1062 | } | 1074 | } |
1063 | 1075 | ||
1064 | enum sway_container_layout container_parent_layout(struct sway_container *con) { | 1076 | enum sway_container_layout container_parent_layout(struct sway_container *con) { |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 2704920d..3c4614a8 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -31,6 +31,13 @@ static void restore_workspaces(struct sway_output *output) { | |||
31 | j--; | 31 | j--; |
32 | } | 32 | } |
33 | } | 33 | } |
34 | |||
35 | if (other->workspaces->length == 0) { | ||
36 | char *next = workspace_next_name(other->wlr_output->name); | ||
37 | struct sway_workspace *ws = workspace_create(other, next); | ||
38 | free(next); | ||
39 | ipc_event_workspace(NULL, ws, "init"); | ||
40 | } | ||
34 | } | 41 | } |
35 | 42 | ||
36 | // Saved workspaces | 43 | // Saved workspaces |
diff --git a/sway/tree/root.c b/sway/tree/root.c index 9bda7c28..544d666a 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c | |||
@@ -31,7 +31,7 @@ struct sway_root *root_create(void) { | |||
31 | node_init(&root->node, N_ROOT, root); | 31 | node_init(&root->node, N_ROOT, root); |
32 | root->output_layout = wlr_output_layout_create(); | 32 | root->output_layout = wlr_output_layout_create(); |
33 | wl_list_init(&root->all_outputs); | 33 | wl_list_init(&root->all_outputs); |
34 | #ifdef HAVE_XWAYLAND | 34 | #if HAVE_XWAYLAND |
35 | wl_list_init(&root->xwayland_unmanaged); | 35 | wl_list_init(&root->xwayland_unmanaged); |
36 | #endif | 36 | #endif |
37 | wl_list_init(&root->drag_icons); | 37 | wl_list_init(&root->drag_icons); |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 1aa59e68..d7110619 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -8,7 +8,7 @@ | |||
8 | #include <wlr/types/wlr_server_decoration.h> | 8 | #include <wlr/types/wlr_server_decoration.h> |
9 | #include <wlr/types/wlr_xdg_decoration_v1.h> | 9 | #include <wlr/types/wlr_xdg_decoration_v1.h> |
10 | #include "config.h" | 10 | #include "config.h" |
11 | #ifdef HAVE_XWAYLAND | 11 | #if HAVE_XWAYLAND |
12 | #include <wlr/xwayland.h> | 12 | #include <wlr/xwayland.h> |
13 | #endif | 13 | #endif |
14 | #include "list.h" | 14 | #include "list.h" |
@@ -101,7 +101,7 @@ const char *view_get_instance(struct sway_view *view) { | |||
101 | } | 101 | } |
102 | return NULL; | 102 | return NULL; |
103 | } | 103 | } |
104 | #ifdef HAVE_XWAYLAND | 104 | #if HAVE_XWAYLAND |
105 | uint32_t view_get_x11_window_id(struct sway_view *view) { | 105 | uint32_t view_get_x11_window_id(struct sway_view *view) { |
106 | if (view->impl->get_int_prop) { | 106 | if (view->impl->get_int_prop) { |
107 | return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID); | 107 | return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID); |
@@ -136,7 +136,7 @@ const char *view_get_shell(struct sway_view *view) { | |||
136 | return "xdg_shell_v6"; | 136 | return "xdg_shell_v6"; |
137 | case SWAY_VIEW_XDG_SHELL: | 137 | case SWAY_VIEW_XDG_SHELL: |
138 | return "xdg_shell"; | 138 | return "xdg_shell"; |
139 | #ifdef HAVE_XWAYLAND | 139 | #if HAVE_XWAYLAND |
140 | case SWAY_VIEW_XWAYLAND: | 140 | case SWAY_VIEW_XWAYLAND: |
141 | return "xwayland"; | 141 | return "xwayland"; |
142 | #endif | 142 | #endif |
@@ -185,31 +185,33 @@ bool view_is_only_visible(struct sway_view *view) { | |||
185 | static bool gaps_to_edge(struct sway_view *view) { | 185 | static bool gaps_to_edge(struct sway_view *view) { |
186 | struct sway_container *con = view->container; | 186 | struct sway_container *con = view->container; |
187 | while (con) { | 187 | while (con) { |
188 | if (con->current_gaps > 0) { | 188 | if (con->current_gaps.top > 0 || con->current_gaps.right > 0 || |
189 | con->current_gaps.bottom > 0 || con->current_gaps.left > 0) { | ||
189 | return true; | 190 | return true; |
190 | } | 191 | } |
191 | con = con->parent; | 192 | con = con->parent; |
192 | } | 193 | } |
193 | return view->container->workspace->current_gaps > 0; | 194 | struct side_gaps gaps = view->container->workspace->current_gaps; |
195 | return gaps.top > 0 || gaps.right > 0 || gaps.bottom > 0 || gaps.left > 0; | ||
194 | } | 196 | } |
195 | 197 | ||
196 | void view_autoconfigure(struct sway_view *view) { | 198 | void view_autoconfigure(struct sway_view *view) { |
197 | if (!view->container->workspace) { | 199 | struct sway_container *con = view->container; |
200 | if (!con->workspace) { | ||
198 | // Hidden in the scratchpad | 201 | // Hidden in the scratchpad |
199 | return; | 202 | return; |
200 | } | 203 | } |
201 | struct sway_output *output = view->container->workspace->output; | 204 | struct sway_output *output = con->workspace->output; |
202 | 205 | ||
203 | if (view->container->is_fullscreen) { | 206 | if (con->is_fullscreen) { |
204 | view->x = output->lx; | 207 | con->content_x = output->lx; |
205 | view->y = output->ly; | 208 | con->content_y = output->ly; |
206 | view->width = output->width; | 209 | con->content_width = output->width; |
207 | view->height = output->height; | 210 | con->content_height = output->height; |
208 | return; | 211 | return; |
209 | } | 212 | } |
210 | 213 | ||
211 | struct sway_workspace *ws = view->container->workspace; | 214 | struct sway_workspace *ws = view->container->workspace; |
212 | struct sway_container *con = view->container; | ||
213 | 215 | ||
214 | bool smart = config->hide_edge_borders == E_SMART || | 216 | bool smart = config->hide_edge_borders == E_SMART || |
215 | config->hide_edge_borders == E_SMART_NO_GAPS; | 217 | config->hide_edge_borders == E_SMART_NO_GAPS; |
@@ -222,15 +224,15 @@ void view_autoconfigure(struct sway_view *view) { | |||
222 | if (config->hide_edge_borders == E_BOTH | 224 | if (config->hide_edge_borders == E_BOTH |
223 | || config->hide_edge_borders == E_VERTICAL | 225 | || config->hide_edge_borders == E_VERTICAL |
224 | || (smart && !other_views && no_gaps)) { | 226 | || (smart && !other_views && no_gaps)) { |
225 | con->border_left = con->x - con->current_gaps != ws->x; | 227 | con->border_left = con->x - con->current_gaps.left != ws->x; |
226 | int right_x = con->x + con->width + con->current_gaps; | 228 | int right_x = con->x + con->width + con->current_gaps.right; |
227 | con->border_right = right_x != ws->x + ws->width; | 229 | con->border_right = right_x != ws->x + ws->width; |
228 | } | 230 | } |
229 | if (config->hide_edge_borders == E_BOTH | 231 | if (config->hide_edge_borders == E_BOTH |
230 | || config->hide_edge_borders == E_HORIZONTAL | 232 | || config->hide_edge_borders == E_HORIZONTAL |
231 | || (smart && !other_views && no_gaps)) { | 233 | || (smart && !other_views && no_gaps)) { |
232 | con->border_top = con->y - con->current_gaps != ws->y; | 234 | con->border_top = con->y - con->current_gaps.top != ws->y; |
233 | int bottom_y = con->y + con->height + con->current_gaps; | 235 | int bottom_y = con->y + con->height + con->current_gaps.bottom; |
234 | con->border_bottom = bottom_y != ws->y + ws->height; | 236 | con->border_bottom = bottom_y != ws->y + ws->height; |
235 | } | 237 | } |
236 | 238 | ||
@@ -287,10 +289,10 @@ void view_autoconfigure(struct sway_view *view) { | |||
287 | break; | 289 | break; |
288 | } | 290 | } |
289 | 291 | ||
290 | view->x = x; | 292 | con->content_x = x; |
291 | view->y = y; | 293 | con->content_y = y; |
292 | view->width = width; | 294 | con->content_width = width; |
293 | view->height = height; | 295 | con->content_height = height; |
294 | } | 296 | } |
295 | 297 | ||
296 | void view_set_activated(struct sway_view *view, bool activated) { | 298 | void view_set_activated(struct sway_view *view, bool activated) { |
@@ -482,7 +484,7 @@ static struct sway_workspace *select_workspace(struct sway_view *view) { | |||
482 | 484 | ||
483 | // Check if there's a PID mapping | 485 | // Check if there's a PID mapping |
484 | pid_t pid; | 486 | pid_t pid; |
485 | #ifdef HAVE_XWAYLAND | 487 | #if HAVE_XWAYLAND |
486 | if (view->type == SWAY_VIEW_XWAYLAND) { | 488 | if (view->type == SWAY_VIEW_XWAYLAND) { |
487 | struct wlr_xwayland_surface *surf = | 489 | struct wlr_xwayland_surface *surf = |
488 | wlr_xwayland_surface_from_wlr_surface(view->surface); | 490 | wlr_xwayland_surface_from_wlr_surface(view->surface); |
@@ -665,11 +667,11 @@ void view_update_size(struct sway_view *view, int width, int height) { | |||
665 | "Expected a floating container")) { | 667 | "Expected a floating container")) { |
666 | return; | 668 | return; |
667 | } | 669 | } |
668 | view->width = width; | 670 | view->container->content_width = width; |
669 | view->height = height; | 671 | view->container->content_height = height; |
670 | view->container->current.view_width = width; | 672 | view->container->current.content_width = width; |
671 | view->container->current.view_height = height; | 673 | view->container->current.content_height = height; |
672 | container_set_geometry_from_floating_view(view->container); | 674 | container_set_geometry_from_content(view->container); |
673 | } | 675 | } |
674 | 676 | ||
675 | static void subsurface_get_root_coords(struct sway_view_child *child, | 677 | static void subsurface_get_root_coords(struct sway_view_child *child, |
@@ -705,7 +707,8 @@ static void view_child_damage(struct sway_view_child *child, bool whole) { | |||
705 | int sx, sy; | 707 | int sx, sy; |
706 | child->impl->get_root_coords(child, &sx, &sy); | 708 | child->impl->get_root_coords(child, &sx, &sy); |
707 | desktop_damage_surface(child->surface, | 709 | desktop_damage_surface(child->surface, |
708 | child->view->x + sx, child->view->y + sy, whole); | 710 | child->view->container->content_x + sx, |
711 | child->view->container->content_y + sy, whole); | ||
709 | } | 712 | } |
710 | 713 | ||
711 | static void view_child_handle_surface_commit(struct wl_listener *listener, | 714 | static void view_child_handle_surface_commit(struct wl_listener *listener, |
@@ -799,7 +802,7 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { | |||
799 | wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); | 802 | wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); |
800 | return view_from_wlr_xdg_surface_v6(xdg_surface_v6); | 803 | return view_from_wlr_xdg_surface_v6(xdg_surface_v6); |
801 | } | 804 | } |
802 | #ifdef HAVE_XWAYLAND | 805 | #if HAVE_XWAYLAND |
803 | if (wlr_surface_is_xwayland_surface(wlr_surface)) { | 806 | if (wlr_surface_is_xwayland_surface(wlr_surface)) { |
804 | struct wlr_xwayland_surface *xsurface = | 807 | struct wlr_xwayland_surface *xsurface = |
805 | wlr_xwayland_surface_from_wlr_surface(wlr_surface); | 808 | wlr_xwayland_surface_from_wlr_surface(wlr_surface); |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 05cda5c0..4be63311 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -33,14 +33,15 @@ struct workspace_config *workspace_find_config(const char *ws_name) { | |||
33 | struct sway_output *workspace_get_initial_output(const char *name) { | 33 | struct sway_output *workspace_get_initial_output(const char *name) { |
34 | // Check workspace configs for a workspace<->output pair | 34 | // Check workspace configs for a workspace<->output pair |
35 | struct workspace_config *wsc = workspace_find_config(name); | 35 | struct workspace_config *wsc = workspace_find_config(name); |
36 | if (wsc && wsc->output) { | 36 | if (wsc) { |
37 | struct sway_output *output = output_by_name(wsc->output); | 37 | for (int i = 0; i < wsc->outputs->length; i++) { |
38 | if (!output) { | 38 | struct sway_output *output = output_by_name(wsc->outputs->items[i]); |
39 | output = output_by_identifier(wsc->output); | 39 | if (!output) { |
40 | } | 40 | output = output_by_identifier(wsc->outputs->items[i]); |
41 | 41 | } | |
42 | if (output) { | 42 | if (output) { |
43 | return output; | 43 | return output; |
44 | } | ||
44 | } | 45 | } |
45 | } | 46 | } |
46 | // Otherwise put it on the focused output | 47 | // Otherwise put it on the focused output |
@@ -49,6 +50,21 @@ struct sway_output *workspace_get_initial_output(const char *name) { | |||
49 | return focus->output; | 50 | return focus->output; |
50 | } | 51 | } |
51 | 52 | ||
53 | static void prevent_invalid_outer_gaps(struct sway_workspace *ws) { | ||
54 | if (ws->gaps_outer.top < -ws->gaps_inner) { | ||
55 | ws->gaps_outer.top = -ws->gaps_inner; | ||
56 | } | ||
57 | if (ws->gaps_outer.right < -ws->gaps_inner) { | ||
58 | ws->gaps_outer.right = -ws->gaps_inner; | ||
59 | } | ||
60 | if (ws->gaps_outer.bottom < -ws->gaps_inner) { | ||
61 | ws->gaps_outer.bottom = -ws->gaps_inner; | ||
62 | } | ||
63 | if (ws->gaps_outer.left < -ws->gaps_inner) { | ||
64 | ws->gaps_outer.left = -ws->gaps_inner; | ||
65 | } | ||
66 | } | ||
67 | |||
52 | struct sway_workspace *workspace_create(struct sway_output *output, | 68 | struct sway_workspace *workspace_create(struct sway_output *output, |
53 | const char *name) { | 69 | const char *name) { |
54 | if (output == NULL) { | 70 | if (output == NULL) { |
@@ -70,22 +86,41 @@ struct sway_workspace *workspace_create(struct sway_output *output, | |||
70 | ws->floating = create_list(); | 86 | ws->floating = create_list(); |
71 | ws->tiling = create_list(); | 87 | ws->tiling = create_list(); |
72 | ws->output_priority = create_list(); | 88 | ws->output_priority = create_list(); |
73 | workspace_output_add_priority(ws, output); | ||
74 | 89 | ||
75 | ws->gaps_outer = config->gaps_outer; | 90 | ws->gaps_outer = config->gaps_outer; |
76 | ws->gaps_inner = config->gaps_inner; | 91 | ws->gaps_inner = config->gaps_inner; |
77 | if (name) { | 92 | if (name) { |
78 | struct workspace_config *wsc = workspace_find_config(name); | 93 | struct workspace_config *wsc = workspace_find_config(name); |
79 | if (wsc) { | 94 | if (wsc) { |
80 | if (wsc->gaps_outer != INT_MIN) { | 95 | if (wsc->gaps_outer.top != INT_MIN) { |
81 | ws->gaps_outer = wsc->gaps_outer; | 96 | ws->gaps_outer.top = wsc->gaps_outer.top; |
97 | } | ||
98 | if (wsc->gaps_outer.right != INT_MIN) { | ||
99 | ws->gaps_outer.right = wsc->gaps_outer.right; | ||
100 | } | ||
101 | if (wsc->gaps_outer.bottom != INT_MIN) { | ||
102 | ws->gaps_outer.bottom = wsc->gaps_outer.bottom; | ||
103 | } | ||
104 | if (wsc->gaps_outer.left != INT_MIN) { | ||
105 | ws->gaps_outer.left = wsc->gaps_outer.left; | ||
82 | } | 106 | } |
83 | if (wsc->gaps_inner != INT_MIN) { | 107 | if (wsc->gaps_inner != INT_MIN) { |
84 | ws->gaps_inner = wsc->gaps_inner; | 108 | ws->gaps_inner = wsc->gaps_inner; |
85 | } | 109 | } |
110 | // Since default outer gaps can be smaller than the negation of | ||
111 | // workspace specific inner gaps, check outer gaps again | ||
112 | prevent_invalid_outer_gaps(ws); | ||
113 | |||
114 | // Add output priorities | ||
115 | for (int i = 0; i < wsc->outputs->length; ++i) { | ||
116 | list_add(ws->output_priority, strdup(wsc->outputs->items[i])); | ||
117 | } | ||
86 | } | 118 | } |
87 | } | 119 | } |
88 | 120 | ||
121 | // If not already added, add the output to the lowest priority | ||
122 | workspace_output_add_priority(ws, output); | ||
123 | |||
89 | output_add_workspace(output, ws); | 124 | output_add_workspace(output, ws); |
90 | output_sort_workspaces(output); | 125 | output_sort_workspaces(output); |
91 | 126 | ||
@@ -107,8 +142,7 @@ void workspace_destroy(struct sway_workspace *workspace) { | |||
107 | 142 | ||
108 | free(workspace->name); | 143 | free(workspace->name); |
109 | free(workspace->representation); | 144 | free(workspace->representation); |
110 | list_foreach(workspace->output_priority, free); | 145 | free_flat_list(workspace->output_priority); |
111 | list_free(workspace->output_priority); | ||
112 | list_free(workspace->floating); | 146 | list_free(workspace->floating); |
113 | list_free(workspace->tiling); | 147 | list_free(workspace->tiling); |
114 | list_free(workspace->current.floating); | 148 | list_free(workspace->current.floating); |
@@ -150,8 +184,19 @@ static bool workspace_valid_on_output(const char *output_name, | |||
150 | char identifier[128]; | 184 | char identifier[128]; |
151 | struct sway_output *output = output_by_name(output_name); | 185 | struct sway_output *output = output_by_name(output_name); |
152 | output_get_identifier(identifier, sizeof(identifier), output); | 186 | output_get_identifier(identifier, sizeof(identifier), output); |
153 | 187 | ||
154 | return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0 || strcasecmp(identifier, output_name) == 0; | 188 | if (!wsc) { |
189 | return true; | ||
190 | } | ||
191 | |||
192 | for (int i = 0; i < wsc->outputs->length; i++) { | ||
193 | if (strcmp(wsc->outputs->items[i], output_name) == 0 || | ||
194 | strcmp(wsc->outputs->items[i], identifier) == 0) { | ||
195 | return true; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | return false; | ||
155 | } | 200 | } |
156 | 201 | ||
157 | static void workspace_name_from_binding(const struct sway_binding * binding, | 202 | static void workspace_name_from_binding(const struct sway_binding * binding, |
@@ -254,10 +299,19 @@ char *workspace_next_name(const char *output_name) { | |||
254 | for (int i = 0; i < config->workspace_configs->length; ++i) { | 299 | for (int i = 0; i < config->workspace_configs->length; ++i) { |
255 | // Unlike with bindings, this does not guarantee order | 300 | // Unlike with bindings, this does not guarantee order |
256 | const struct workspace_config *wsc = config->workspace_configs->items[i]; | 301 | const struct workspace_config *wsc = config->workspace_configs->items[i]; |
257 | if (wsc->output && strcmp(wsc->output, output_name) == 0 | 302 | if (workspace_by_name(wsc->workspace)) { |
258 | && workspace_by_name(wsc->workspace) == NULL) { | 303 | continue; |
259 | free(target); | 304 | } |
260 | target = strdup(wsc->workspace); | 305 | bool found = false; |
306 | for (int j = 0; j < wsc->outputs->length; ++j) { | ||
307 | if (strcmp(wsc->outputs->items[j], output_name) == 0) { | ||
308 | found = true; | ||
309 | free(target); | ||
310 | target = strdup(wsc->workspace); | ||
311 | break; | ||
312 | } | ||
313 | } | ||
314 | if (found) { | ||
261 | break; | 315 | break; |
262 | } | 316 | } |
263 | } | 317 | } |
@@ -615,19 +669,25 @@ void workspace_insert_tiling(struct sway_workspace *workspace, | |||
615 | } | 669 | } |
616 | 670 | ||
617 | void workspace_remove_gaps(struct sway_workspace *ws) { | 671 | void workspace_remove_gaps(struct sway_workspace *ws) { |
618 | if (ws->current_gaps == 0) { | 672 | if (ws->current_gaps.top == 0 && ws->current_gaps.right == 0 && |
673 | ws->current_gaps.bottom == 0 && ws->current_gaps.left == 0) { | ||
619 | return; | 674 | return; |
620 | } | 675 | } |
621 | 676 | ||
622 | ws->width += ws->current_gaps * 2; | 677 | ws->width += ws->current_gaps.left + ws->current_gaps.right; |
623 | ws->height += ws->current_gaps * 2; | 678 | ws->height += ws->current_gaps.top + ws->current_gaps.bottom; |
624 | ws->x -= ws->current_gaps; | 679 | ws->x -= ws->current_gaps.left; |
625 | ws->y -= ws->current_gaps; | 680 | ws->y -= ws->current_gaps.top; |
626 | ws->current_gaps = 0; | 681 | |
682 | ws->current_gaps.top = 0; | ||
683 | ws->current_gaps.right = 0; | ||
684 | ws->current_gaps.bottom = 0; | ||
685 | ws->current_gaps.left = 0; | ||
627 | } | 686 | } |
628 | 687 | ||
629 | void workspace_add_gaps(struct sway_workspace *ws) { | 688 | void workspace_add_gaps(struct sway_workspace *ws) { |
630 | if (ws->current_gaps > 0) { | 689 | if (ws->current_gaps.top > 0 || ws->current_gaps.right > 0 || |
690 | ws->current_gaps.bottom > 0 || ws->current_gaps.left > 0) { | ||
631 | return; | 691 | return; |
632 | } | 692 | } |
633 | if (config->smart_gaps) { | 693 | if (config->smart_gaps) { |
@@ -643,18 +703,20 @@ void workspace_add_gaps(struct sway_workspace *ws) { | |||
643 | } | 703 | } |
644 | 704 | ||
645 | ws->current_gaps = ws->gaps_outer; | 705 | ws->current_gaps = ws->gaps_outer; |
646 | |||
647 | if (ws->layout == L_TABBED || ws->layout == L_STACKED) { | 706 | if (ws->layout == L_TABBED || ws->layout == L_STACKED) { |
648 | // We have to add inner gaps for this, because children of tabbed and | 707 | // We have to add inner gaps for this, because children of tabbed and |
649 | // stacked containers don't apply their own gaps - they assume the | 708 | // stacked containers don't apply their own gaps - they assume the |
650 | // tabbed/stacked container is using gaps. | 709 | // tabbed/stacked container is using gaps. |
651 | ws->current_gaps += ws->gaps_inner; | 710 | ws->current_gaps.top += ws->gaps_inner; |
711 | ws->current_gaps.right += ws->gaps_inner; | ||
712 | ws->current_gaps.bottom += ws->gaps_inner; | ||
713 | ws->current_gaps.left += ws->gaps_inner; | ||
652 | } | 714 | } |
653 | 715 | ||
654 | ws->x += ws->current_gaps; | 716 | ws->x += ws->current_gaps.left; |
655 | ws->y += ws->current_gaps; | 717 | ws->y += ws->current_gaps.top; |
656 | ws->width -= 2 * ws->current_gaps; | 718 | ws->width -= ws->current_gaps.left + ws->current_gaps.right; |
657 | ws->height -= 2 * ws->current_gaps; | 719 | ws->height -= ws->current_gaps.top + ws->current_gaps.bottom; |
658 | } | 720 | } |
659 | 721 | ||
660 | struct sway_container *workspace_split(struct sway_workspace *workspace, | 722 | struct sway_container *workspace_split(struct sway_workspace *workspace, |
diff --git a/swaybar/config.c b/swaybar/config.c index 98d94168..0ab346b1 100644 --- a/swaybar/config.c +++ b/swaybar/config.c | |||
@@ -84,6 +84,7 @@ void free_config(struct swaybar_config *config) { | |||
84 | free(config->mode); | 84 | free(config->mode); |
85 | free(config->hidden_state); | 85 | free(config->hidden_state); |
86 | free(config->sep_symbol); | 86 | free(config->sep_symbol); |
87 | free(config->modifier); | ||
87 | for (int i = 0; i < config->bindings->length; i++) { | 88 | for (int i = 0; i < config->bindings->length; i++) { |
88 | struct swaybar_binding *binding = config->bindings->items[i]; | 89 | struct swaybar_binding *binding = config->bindings->items[i]; |
89 | free_binding(binding); | 90 | free_binding(binding); |
diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 65d6c052..744d2785 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c | |||
@@ -183,6 +183,9 @@ void status_line_free(struct status_line *status) { | |||
183 | } | 183 | } |
184 | json_tokener_free(status->tokener); | 184 | json_tokener_free(status->tokener); |
185 | } | 185 | } |
186 | free(status->read); | ||
187 | free(status->write); | ||
188 | free((char*) status->text); | ||
186 | free(status->buffer); | 189 | free(status->buffer); |
187 | free(status); | 190 | free(status); |
188 | } | 191 | } |
diff --git a/swayidle/main.c b/swayidle/main.c index 7d0f23f4..2b185949 100644 --- a/swayidle/main.c +++ b/swayidle/main.c | |||
@@ -18,10 +18,10 @@ | |||
18 | #include "config.h" | 18 | #include "config.h" |
19 | #include "idle-client-protocol.h" | 19 | #include "idle-client-protocol.h" |
20 | #include "list.h" | 20 | #include "list.h" |
21 | #ifdef SWAY_IDLE_HAS_SYSTEMD | 21 | #if HAVE_SYSTEMD |
22 | #include <systemd/sd-bus.h> | 22 | #include <systemd/sd-bus.h> |
23 | #include <systemd/sd-login.h> | 23 | #include <systemd/sd-login.h> |
24 | #elif defined(SWAY_IDLE_HAS_ELOGIND) | 24 | #elif HAVE_ELOGIND |
25 | #include <elogind/sd-bus.h> | 25 | #include <elogind/sd-bus.h> |
26 | #include <elogind/sd-login.h> | 26 | #include <elogind/sd-login.h> |
27 | #endif | 27 | #endif |
@@ -66,7 +66,7 @@ static void cmd_exec(char *param) { | |||
66 | } | 66 | } |
67 | } | 67 | } |
68 | 68 | ||
69 | #if defined(SWAY_IDLE_HAS_SYSTEMD) || defined(SWAY_IDLE_HAS_ELOGIND) | 69 | #if HAVE_SYSTEMD || HAVE_ELOGIND |
70 | static int lock_fd = -1; | 70 | static int lock_fd = -1; |
71 | static int ongoing_fd = -1; | 71 | static int ongoing_fd = -1; |
72 | static struct sd_bus *bus = NULL; | 72 | static struct sd_bus *bus = NULL; |
@@ -414,7 +414,7 @@ int main(int argc, char *argv[]) { | |||
414 | } | 414 | } |
415 | 415 | ||
416 | bool should_run = state.timeout_cmds->length > 0; | 416 | bool should_run = state.timeout_cmds->length > 0; |
417 | #if defined(SWAY_IDLE_HAS_SYSTEMD) || defined(SWAY_IDLE_HAS_ELOGIND) | 417 | #if HAVE_SYSTEMD || HAVE_ELOGIND |
418 | if (state.lock_cmd) { | 418 | if (state.lock_cmd) { |
419 | should_run = true; | 419 | should_run = true; |
420 | setup_sleep_listener(); | 420 | setup_sleep_listener(); |
diff --git a/swayidle/meson.build b/swayidle/meson.build index 6c3ac119..79d2c5c4 100644 --- a/swayidle/meson.build +++ b/swayidle/meson.build | |||
@@ -1,18 +1,26 @@ | |||
1 | threads = dependency('threads') | 1 | threads = dependency('threads') |
2 | 2 | ||
3 | swayidle_deps = [ | ||
4 | client_protos, | ||
5 | pixman, | ||
6 | wayland_client, | ||
7 | wayland_server, | ||
8 | wlroots, | ||
9 | ] | ||
10 | |||
11 | if systemd.found() | ||
12 | swayidle_deps += systemd | ||
13 | endif | ||
14 | if elogind.found() | ||
15 | swayidle_deps += elogind | ||
16 | endif | ||
17 | |||
3 | executable( | 18 | executable( |
4 | 'swayidle', [ | 19 | 'swayidle', [ |
5 | 'main.c', | 20 | 'main.c', |
6 | ], | 21 | ], |
7 | include_directories: [sway_inc], | 22 | include_directories: [sway_inc], |
8 | dependencies: [ | 23 | dependencies: swayidle_deps, |
9 | client_protos, | ||
10 | pixman, | ||
11 | wayland_client, | ||
12 | wayland_server, | ||
13 | wlroots, | ||
14 | swayidle_deps, | ||
15 | ], | ||
16 | link_with: [lib_sway_common, lib_sway_client], | 24 | link_with: [lib_sway_common, lib_sway_client], |
17 | install_rpath : rpathdir, | 25 | install_rpath : rpathdir, |
18 | install: true | 26 | install: true |
diff --git a/swaymsg/main.c b/swaymsg/main.c index 663518f6..243b5fdc 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c | |||
@@ -111,7 +111,7 @@ static const char *pretty_type_name(const char *name) { | |||
111 | } | 111 | } |
112 | 112 | ||
113 | static void pretty_print_input(json_object *i) { | 113 | static void pretty_print_input(json_object *i) { |
114 | json_object *id, *name, *type, *product, *vendor; | 114 | json_object *id, *name, *type, *product, *vendor, *kbdlayout; |
115 | json_object_object_get_ex(i, "identifier", &id); | 115 | json_object_object_get_ex(i, "identifier", &id); |
116 | json_object_object_get_ex(i, "name", &name); | 116 | json_object_object_get_ex(i, "name", &name); |
117 | json_object_object_get_ex(i, "type", &type); | 117 | json_object_object_get_ex(i, "type", &type); |
@@ -123,7 +123,7 @@ static void pretty_print_input(json_object *i) { | |||
123 | " Type: %s\n" | 123 | " Type: %s\n" |
124 | " Identifier: %s\n" | 124 | " Identifier: %s\n" |
125 | " Product ID: %d\n" | 125 | " Product ID: %d\n" |
126 | " Vendor ID: %d\n\n"; | 126 | " Vendor ID: %d\n"; |
127 | 127 | ||
128 | 128 | ||
129 | printf(fmt, json_object_get_string(name), | 129 | printf(fmt, json_object_get_string(name), |
@@ -131,6 +131,13 @@ static void pretty_print_input(json_object *i) { | |||
131 | json_object_get_string(id), | 131 | json_object_get_string(id), |
132 | json_object_get_int(product), | 132 | json_object_get_int(product), |
133 | json_object_get_int(vendor)); | 133 | json_object_get_int(vendor)); |
134 | |||
135 | if (json_object_object_get_ex(i, "xkb_active_layout_name", &kbdlayout)) { | ||
136 | printf(" Active Keyboard Layout: %s\n", | ||
137 | json_object_get_string(kbdlayout)); | ||
138 | } | ||
139 | |||
140 | printf("\n"); | ||
134 | } | 141 | } |
135 | 142 | ||
136 | static void pretty_print_seat(json_object *i) { | 143 | static void pretty_print_seat(json_object *i) { |
diff --git a/swaynag/swaynag.c b/swaynag/swaynag.c index fa6bbe05..06185f20 100644 --- a/swaynag/swaynag.c +++ b/swaynag/swaynag.c | |||
@@ -412,6 +412,7 @@ void swaynag_destroy(struct swaynag *swaynag) { | |||
412 | free(button); | 412 | free(button); |
413 | } | 413 | } |
414 | list_free(swaynag->buttons); | 414 | list_free(swaynag->buttons); |
415 | free(swaynag->details.button_details); | ||
415 | free(swaynag->details.message); | 416 | free(swaynag->details.message); |
416 | free(swaynag->details.button_up.text); | 417 | free(swaynag->details.button_up.text); |
417 | free(swaynag->details.button_down.text); | 418 | free(swaynag->details.button_down.text); |