diff options
-rw-r--r-- | common/stringop.c | 14 | ||||
-rw-r--r-- | include/stringop.h | 2 | ||||
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/config.h | 11 | ||||
-rw-r--r-- | include/sway/criteria.h | 2 | ||||
-rw-r--r-- | include/sway/tree/view.h | 6 | ||||
-rw-r--r-- | include/sway/xwayland.h | 1 | ||||
-rw-r--r-- | meson.build | 12 | ||||
-rw-r--r-- | meson_options.txt | 11 | ||||
-rw-r--r-- | sway/commands.c | 3 | ||||
-rw-r--r-- | sway/commands/bind.c | 2 | ||||
-rw-r--r-- | sway/commands/border.c | 6 | ||||
-rw-r--r-- | sway/commands/focus_on_window_activation.c | 25 | ||||
-rw-r--r-- | sway/config/output.c | 4 | ||||
-rw-r--r-- | sway/criteria.c | 45 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 3 | ||||
-rw-r--r-- | sway/desktop/output.c | 6 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 23 | ||||
-rw-r--r-- | sway/input/seat.c | 4 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/server.c | 2 | ||||
-rw-r--r-- | sway/tree/view.c | 23 |
22 files changed, 173 insertions, 34 deletions
diff --git a/common/stringop.c b/common/stringop.c index d9ae9925..d2c91c24 100644 --- a/common/stringop.c +++ b/common/stringop.c | |||
@@ -401,3 +401,17 @@ char *argsep(char **stringp, const char *delim) { | |||
401 | found: | 401 | found: |
402 | return start; | 402 | return start; |
403 | } | 403 | } |
404 | |||
405 | const char *strcasestr(const char *haystack, const char *needle) { | ||
406 | size_t needle_len = strlen(needle); | ||
407 | const char *pos = haystack; | ||
408 | const char *end = pos + strlen(haystack) - needle_len; | ||
409 | |||
410 | while (pos <= end) { | ||
411 | if (strncasecmp(pos, needle, needle_len) == 0) { | ||
412 | return pos; | ||
413 | } | ||
414 | ++pos; | ||
415 | } | ||
416 | return NULL; | ||
417 | } | ||
diff --git a/include/stringop.h b/include/stringop.h index e7f58011..01bbdaa9 100644 --- a/include/stringop.h +++ b/include/stringop.h | |||
@@ -46,4 +46,6 @@ char *cmdsep(char **stringp, const char *delim); | |||
46 | // Split string into 2 by delim, handle quotes | 46 | // Split string into 2 by delim, handle quotes |
47 | char *argsep(char **stringp, const char *delim); | 47 | char *argsep(char **stringp, const char *delim); |
48 | 48 | ||
49 | const char *strcasestr(const char *haystack, const char *needle); | ||
50 | |||
49 | #endif | 51 | #endif |
diff --git a/include/sway/commands.h b/include/sway/commands.h index 8e91c158..b0b5ed0f 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -117,6 +117,7 @@ sway_cmd cmd_floating_modifier; | |||
117 | sway_cmd cmd_floating_scroll; | 117 | sway_cmd cmd_floating_scroll; |
118 | sway_cmd cmd_focus; | 118 | sway_cmd cmd_focus; |
119 | sway_cmd cmd_focus_follows_mouse; | 119 | sway_cmd cmd_focus_follows_mouse; |
120 | sway_cmd cmd_focus_on_window_activation; | ||
120 | sway_cmd cmd_focus_wrapping; | 121 | sway_cmd cmd_focus_wrapping; |
121 | sway_cmd cmd_font; | 122 | sway_cmd cmd_font; |
122 | sway_cmd cmd_for_window; | 123 | sway_cmd cmd_for_window; |
diff --git a/include/sway/config.h b/include/sway/config.h index 18d10faa..4ee8c3c2 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -58,6 +58,16 @@ struct sway_mouse_binding { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | /** | 60 | /** |
61 | * Focus on window activation. | ||
62 | */ | ||
63 | enum sway_fowa { | ||
64 | FOWA_SMART, | ||
65 | FOWA_URGENT, | ||
66 | FOWA_FOCUS, | ||
67 | FOWA_NONE, | ||
68 | }; | ||
69 | |||
70 | /** | ||
61 | * A "mode" of keybindings created via the `mode` command. | 71 | * A "mode" of keybindings created via the `mode` command. |
62 | */ | 72 | */ |
63 | struct sway_mode { | 73 | struct sway_mode { |
@@ -340,6 +350,7 @@ struct sway_config { | |||
340 | size_t font_height; | 350 | size_t font_height; |
341 | bool pango_markup; | 351 | bool pango_markup; |
342 | size_t urgent_timeout; | 352 | size_t urgent_timeout; |
353 | enum sway_fowa focus_on_window_activation; | ||
343 | 354 | ||
344 | // Flags | 355 | // Flags |
345 | bool focus_follows_mouse; | 356 | bool focus_follows_mouse; |
diff --git a/include/sway/criteria.h b/include/sway/criteria.h index 7a1e547b..af12ffd7 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h | |||
@@ -31,7 +31,7 @@ struct criteria { | |||
31 | uint32_t id; // X11 window ID | 31 | uint32_t id; // X11 window ID |
32 | #endif | 32 | #endif |
33 | pcre *window_role; | 33 | pcre *window_role; |
34 | uint32_t window_type; | 34 | enum atom_name window_type; |
35 | bool floating; | 35 | bool floating; |
36 | bool tiling; | 36 | bool tiling; |
37 | char urgent; // 'l' for latest or 'o' for oldest | 37 | char urgent; // 'l' for latest or 'o' for oldest |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index f73ce571..382ab6b9 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -167,6 +167,7 @@ struct sway_xwayland_view { | |||
167 | struct wl_listener request_maximize; | 167 | struct wl_listener request_maximize; |
168 | struct wl_listener request_configure; | 168 | struct wl_listener request_configure; |
169 | struct wl_listener request_fullscreen; | 169 | struct wl_listener request_fullscreen; |
170 | struct wl_listener request_activate; | ||
170 | struct wl_listener set_title; | 171 | struct wl_listener set_title; |
171 | struct wl_listener set_class; | 172 | struct wl_listener set_class; |
172 | struct wl_listener set_window_type; | 173 | struct wl_listener set_window_type; |
@@ -259,6 +260,11 @@ void view_autoconfigure(struct sway_view *view); | |||
259 | 260 | ||
260 | void view_set_activated(struct sway_view *view, bool activated); | 261 | void view_set_activated(struct sway_view *view, bool activated); |
261 | 262 | ||
263 | /** | ||
264 | * Called when the view requests to be focused. | ||
265 | */ | ||
266 | void view_request_activate(struct sway_view *view); | ||
267 | |||
262 | void view_set_tiled(struct sway_view *view, bool tiled); | 268 | void view_set_tiled(struct sway_view *view, bool tiled); |
263 | 269 | ||
264 | void view_close(struct sway_view *view); | 270 | void view_close(struct sway_view *view); |
diff --git a/include/sway/xwayland.h b/include/sway/xwayland.h index 78d1053b..121edad3 100644 --- a/include/sway/xwayland.h +++ b/include/sway/xwayland.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <xcb/xproto.h> | 5 | #include <xcb/xproto.h> |
6 | 6 | ||
7 | enum atom_name { | 7 | enum atom_name { |
8 | NET_WM_WINDOW_TYPE_NORMAL, | ||
8 | NET_WM_WINDOW_TYPE_DIALOG, | 9 | NET_WM_WINDOW_TYPE_DIALOG, |
9 | NET_WM_WINDOW_TYPE_UTILITY, | 10 | NET_WM_WINDOW_TYPE_UTILITY, |
10 | NET_WM_WINDOW_TYPE_TOOLBAR, | 11 | NET_WM_WINDOW_TYPE_TOOLBAR, |
diff --git a/meson.build b/meson.build index 57b024c8..253a4e96 100644 --- a/meson.build +++ b/meson.build | |||
@@ -106,7 +106,7 @@ endif | |||
106 | 106 | ||
107 | add_project_arguments('-DSYSCONFDIR="/@0@/@1@"'.format(prefix, sysconfdir), language : 'c') | 107 | add_project_arguments('-DSYSCONFDIR="/@0@/@1@"'.format(prefix, sysconfdir), language : 'c') |
108 | 108 | ||
109 | version = get_option('sway_version') | 109 | version = get_option('sway-version') |
110 | if version != '' | 110 | if version != '' |
111 | version = '"@0@"'.format(version) | 111 | version = '"@0@"'.format(version) |
112 | else | 112 | else |
@@ -120,6 +120,8 @@ else | |||
120 | endif | 120 | endif |
121 | add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') | 121 | add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') |
122 | 122 | ||
123 | add_project_arguments('-D_LD_LIBRARY_PATH="@0@"'.format(get_option('ld-library-path')), language: 'c') | ||
124 | |||
123 | sway_inc = include_directories('include') | 125 | sway_inc = include_directories('include') |
124 | 126 | ||
125 | subdir('include') | 127 | subdir('include') |
@@ -168,7 +170,7 @@ install_data( | |||
168 | install_dir: datadir + '/wayland-sessions' | 170 | install_dir: datadir + '/wayland-sessions' |
169 | ) | 171 | ) |
170 | 172 | ||
171 | if (get_option('default_wallpaper')) | 173 | if (get_option('default-wallpaper')) |
172 | wallpaper_files = files( | 174 | wallpaper_files = files( |
173 | 'assets/Sway_Wallpaper_Blue_768x1024.png', | 175 | 'assets/Sway_Wallpaper_Blue_768x1024.png', |
174 | 'assets/Sway_Wallpaper_Blue_768x1024_Portrait.png', | 176 | 'assets/Sway_Wallpaper_Blue_768x1024_Portrait.png', |
@@ -184,7 +186,7 @@ if (get_option('default_wallpaper')) | |||
184 | install_data(wallpaper_files, install_dir: wallpaper_install_dir) | 186 | install_data(wallpaper_files, install_dir: wallpaper_install_dir) |
185 | endif | 187 | endif |
186 | 188 | ||
187 | if (get_option('zsh_completions')) | 189 | if (get_option('zsh-completions')) |
188 | zsh_files = files( | 190 | zsh_files = files( |
189 | 'completions/zsh/_sway', | 191 | 'completions/zsh/_sway', |
190 | 'completions/zsh/_swaylock', | 192 | 'completions/zsh/_swaylock', |
@@ -195,7 +197,7 @@ if (get_option('zsh_completions')) | |||
195 | install_data(zsh_files, install_dir: zsh_install_dir) | 197 | install_data(zsh_files, install_dir: zsh_install_dir) |
196 | endif | 198 | endif |
197 | 199 | ||
198 | if (get_option('bash_completions')) | 200 | if (get_option('bash-completions')) |
199 | bash_files = files( | 201 | bash_files = files( |
200 | 'completions/bash/sway', | 202 | 'completions/bash/sway', |
201 | 'completions/bash/swayidle', | 203 | 'completions/bash/swayidle', |
@@ -207,7 +209,7 @@ if (get_option('bash_completions')) | |||
207 | install_data(bash_files, install_dir: bash_install_dir) | 209 | install_data(bash_files, install_dir: bash_install_dir) |
208 | endif | 210 | endif |
209 | 211 | ||
210 | if (get_option('fish_completions')) | 212 | if (get_option('fish-completions')) |
211 | fish_files = files( | 213 | fish_files = files( |
212 | 'completions/fish/sway.fish', | 214 | 'completions/fish/sway.fish', |
213 | 'completions/fish/swaylock.fish', | 215 | 'completions/fish/swaylock.fish', |
diff --git a/meson_options.txt b/meson_options.txt index 5e54607f..50d646fd 100644 --- a/meson_options.txt +++ b/meson_options.txt | |||
@@ -1,6 +1,7 @@ | |||
1 | option('sway_version', type : 'string', description: 'The version string reported in `sway --version`.') | 1 | option('sway-version', type : 'string', description: 'The version string reported in `sway --version`.') |
2 | option('default_wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.') | 2 | option('ld-library-path', type: 'string', value: '', description: 'The LD_LIBRARY_PATH environment variable.') |
3 | option('zsh_completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') | 3 | option('default-wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.') |
4 | option('bash_completions', type: 'boolean', value: true, description: 'Install bash shell completions.') | 4 | option('zsh-completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') |
5 | option('fish_completions', type: 'boolean', value: true, description: 'Install fish shell completions.') | 5 | option('bash-completions', type: 'boolean', value: true, description: 'Install bash shell completions.') |
6 | option('fish-completions', type: 'boolean', value: true, description: 'Install fish shell completions.') | ||
6 | option('enable-xwayland', type: 'boolean', value: true, description: 'Enable support for X11 applications') | 7 | option('enable-xwayland', type: 'boolean', value: true, description: 'Enable support for X11 applications') |
diff --git a/sway/commands.c b/sway/commands.c index f321a874..9e0fda55 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -106,6 +106,7 @@ static struct cmd_handler handlers[] = { | |||
106 | { "floating_modifier", cmd_floating_modifier }, | 106 | { "floating_modifier", cmd_floating_modifier }, |
107 | { "focus", cmd_focus }, | 107 | { "focus", cmd_focus }, |
108 | { "focus_follows_mouse", cmd_focus_follows_mouse }, | 108 | { "focus_follows_mouse", cmd_focus_follows_mouse }, |
109 | { "focus_on_window_activation", cmd_focus_on_window_activation }, | ||
109 | { "focus_wrapping", cmd_focus_wrapping }, | 110 | { "focus_wrapping", cmd_focus_wrapping }, |
110 | { "font", cmd_font }, | 111 | { "font", cmd_font }, |
111 | { "for_window", cmd_for_window }, | 112 | { "for_window", cmd_for_window }, |
@@ -118,6 +119,8 @@ static struct cmd_handler handlers[] = { | |||
118 | { "input", cmd_input }, | 119 | { "input", cmd_input }, |
119 | { "mode", cmd_mode }, | 120 | { "mode", cmd_mode }, |
120 | { "mouse_warping", cmd_mouse_warping }, | 121 | { "mouse_warping", cmd_mouse_warping }, |
122 | { "new_float", cmd_default_floating_border }, | ||
123 | { "new_window", cmd_default_border }, | ||
121 | { "no_focus", cmd_no_focus }, | 124 | { "no_focus", cmd_no_focus }, |
122 | { "output", cmd_output }, | 125 | { "output", cmd_output }, |
123 | { "seat", cmd_seat }, | 126 | { "seat", cmd_seat }, |
diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 8270b958..b134c92f 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c | |||
@@ -310,7 +310,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) | |||
310 | bool reload = false; | 310 | bool reload = false; |
311 | // if this is a reload command we need to make a duplicate of the | 311 | // if this is a reload command we need to make a duplicate of the |
312 | // binding since it will be gone after the reload has completed. | 312 | // binding since it will be gone after the reload has completed. |
313 | if (strcasecmp(binding->command, "reload") == 0) { | 313 | if (strcasestr(binding->command, "reload")) { |
314 | reload = true; | 314 | reload = true; |
315 | binding_copy = sway_binding_dup(binding); | 315 | binding_copy = sway_binding_dup(binding); |
316 | if (!binding_copy) { | 316 | if (!binding_copy) { |
diff --git a/sway/commands/border.c b/sway/commands/border.c index 9c19e20a..9502c877 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c | |||
@@ -27,9 +27,6 @@ struct cmd_results *cmd_border(int argc, char **argv) { | |||
27 | view->border = B_NORMAL; | 27 | view->border = B_NORMAL; |
28 | } else if (strcmp(argv[0], "pixel") == 0) { | 28 | } else if (strcmp(argv[0], "pixel") == 0) { |
29 | view->border = B_PIXEL; | 29 | view->border = B_PIXEL; |
30 | if (argc == 2) { | ||
31 | view->border_thickness = atoi(argv[1]); | ||
32 | } | ||
33 | } else if (strcmp(argv[0], "toggle") == 0) { | 30 | } else if (strcmp(argv[0], "toggle") == 0) { |
34 | view->border = (view->border + 1) % 3; | 31 | view->border = (view->border + 1) % 3; |
35 | } else { | 32 | } else { |
@@ -37,6 +34,9 @@ struct cmd_results *cmd_border(int argc, char **argv) { | |||
37 | "Expected 'border <none|normal|pixel|toggle>' " | 34 | "Expected 'border <none|normal|pixel|toggle>' " |
38 | "or 'border pixel <px>'"); | 35 | "or 'border pixel <px>'"); |
39 | } | 36 | } |
37 | if (argc == 2) { | ||
38 | view->border_thickness = atoi(argv[1]); | ||
39 | } | ||
40 | 40 | ||
41 | if (container_is_floating(view->swayc)) { | 41 | if (container_is_floating(view->swayc)) { |
42 | container_set_geometry_from_floating_view(view->swayc); | 42 | container_set_geometry_from_floating_view(view->swayc); |
diff --git a/sway/commands/focus_on_window_activation.c b/sway/commands/focus_on_window_activation.c new file mode 100644 index 00000000..1fb07918 --- /dev/null +++ b/sway/commands/focus_on_window_activation.c | |||
@@ -0,0 +1,25 @@ | |||
1 | #include "sway/commands.h" | ||
2 | |||
3 | struct cmd_results *cmd_focus_on_window_activation(int argc, char **argv) { | ||
4 | struct cmd_results *error = NULL; | ||
5 | if ((error = checkarg(argc, "focus_on_window_activation", | ||
6 | EXPECTED_EQUAL_TO, 1))) { | ||
7 | return error; | ||
8 | } | ||
9 | |||
10 | if (strcmp(argv[0], "smart") == 0) { | ||
11 | config->focus_on_window_activation = FOWA_SMART; | ||
12 | } else if (strcmp(argv[0], "urgent") == 0) { | ||
13 | config->focus_on_window_activation = FOWA_URGENT; | ||
14 | } else if (strcmp(argv[0], "focus") == 0) { | ||
15 | config->focus_on_window_activation = FOWA_FOCUS; | ||
16 | } else if (strcmp(argv[0], "none") == 0) { | ||
17 | config->focus_on_window_activation = FOWA_NONE; | ||
18 | } else { | ||
19 | return cmd_results_new(CMD_INVALID, "focus_on_window_activation", | ||
20 | "Expected " | ||
21 | "'focus_on_window_activation smart|urgent|focus|none'"); | ||
22 | } | ||
23 | |||
24 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
25 | } | ||
diff --git a/sway/config/output.c b/sway/config/output.c index 16ec9339..65f09258 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -196,6 +196,10 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
196 | wlr_log(WLR_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, | 196 | wlr_log(WLR_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, |
197 | oc->height, oc->refresh_rate); | 197 | oc->height, oc->refresh_rate); |
198 | set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); | 198 | set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); |
199 | } else if (!wl_list_empty(&wlr_output->modes)) { | ||
200 | struct wlr_output_mode *mode = | ||
201 | wl_container_of(wlr_output->modes.prev, mode, link); | ||
202 | wlr_output_set_mode(wlr_output, mode); | ||
199 | } | 203 | } |
200 | if (oc && oc->scale > 0) { | 204 | if (oc && oc->scale > 0) { |
201 | wlr_log(WLR_DEBUG, "Set %s scale to %f", oc->name, oc->scale); | 205 | wlr_log(WLR_DEBUG, "Set %s scale to %f", oc->name, oc->scale); |
diff --git a/sway/criteria.c b/sway/criteria.c index 5452c4ee..13176fa1 100644 --- a/sway/criteria.c +++ b/sway/criteria.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <stdlib.h> | 2 | #include <stdlib.h> |
3 | #include <stdio.h> | 3 | #include <stdio.h> |
4 | #include <stdbool.h> | 4 | #include <stdbool.h> |
5 | #include <strings.h> | ||
5 | #include <pcre.h> | 6 | #include <pcre.h> |
6 | #include "sway/criteria.h" | 7 | #include "sway/criteria.h" |
7 | #include "sway/tree/container.h" | 8 | #include "sway/tree/container.h" |
@@ -25,7 +26,7 @@ bool criteria_is_empty(struct criteria *criteria) { | |||
25 | && !criteria->id | 26 | && !criteria->id |
26 | #endif | 27 | #endif |
27 | && !criteria->window_role | 28 | && !criteria->window_role |
28 | && !criteria->window_type | 29 | && criteria->window_type == ATOM_LAST |
29 | && !criteria->floating | 30 | && !criteria->floating |
30 | && !criteria->tiling | 31 | && !criteria->tiling |
31 | && !criteria->urgent | 32 | && !criteria->urgent |
@@ -50,6 +51,23 @@ static int regex_cmp(const char *item, const pcre *regex) { | |||
50 | return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); | 51 | return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); |
51 | } | 52 | } |
52 | 53 | ||
54 | static bool view_has_window_type(struct sway_view *view, enum atom_name name) { | ||
55 | #ifdef HAVE_XWAYLAND | ||
56 | if (view->type != SWAY_VIEW_XWAYLAND) { | ||
57 | return false; | ||
58 | } | ||
59 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; | ||
60 | struct sway_xwayland *xwayland = &server.xwayland; | ||
61 | xcb_atom_t desired_atom = xwayland->atoms[name]; | ||
62 | for (size_t i = 0; i < surface->window_type_len; ++i) { | ||
63 | if (surface->window_type[i] == desired_atom) { | ||
64 | return true; | ||
65 | } | ||
66 | } | ||
67 | #endif | ||
68 | return false; | ||
69 | } | ||
70 | |||
53 | static int cmp_urgent(const void *_a, const void *_b) { | 71 | static int cmp_urgent(const void *_a, const void *_b) { |
54 | struct sway_view *a = *(void **)_a; | 72 | struct sway_view *a = *(void **)_a; |
55 | struct sway_view *b = *(void **)_b; | 73 | struct sway_view *b = *(void **)_b; |
@@ -144,9 +162,8 @@ static bool criteria_matches_view(struct criteria *criteria, | |||
144 | // TODO | 162 | // TODO |
145 | } | 163 | } |
146 | 164 | ||
147 | if (criteria->window_type) { | 165 | if (criteria->window_type != ATOM_LAST) { |
148 | uint32_t type = view_get_window_type(view); | 166 | if (!view_has_window_type(view, criteria->window_type)) { |
149 | if (!type || type != criteria->window_type) { | ||
150 | return false; | 167 | return false; |
151 | } | 168 | } |
152 | } | 169 | } |
@@ -254,6 +271,21 @@ static bool generate_regex(pcre **regex, char *value) { | |||
254 | return true; | 271 | return true; |
255 | } | 272 | } |
256 | 273 | ||
274 | static enum atom_name parse_window_type(const char *type) { | ||
275 | if (strcasecmp(type, "normal") == 0) { | ||
276 | return NET_WM_WINDOW_TYPE_NORMAL; | ||
277 | } else if (strcasecmp(type, "dialog") == 0) { | ||
278 | return NET_WM_WINDOW_TYPE_DIALOG; | ||
279 | } else if (strcasecmp(type, "utility") == 0) { | ||
280 | return NET_WM_WINDOW_TYPE_UTILITY; | ||
281 | } else if (strcasecmp(type, "toolbar") == 0) { | ||
282 | return NET_WM_WINDOW_TYPE_TOOLBAR; | ||
283 | } else if (strcasecmp(type, "splash") == 0) { | ||
284 | return NET_WM_WINDOW_TYPE_SPLASH; | ||
285 | } | ||
286 | return ATOM_LAST; // ie. invalid | ||
287 | } | ||
288 | |||
257 | enum criteria_token { | 289 | enum criteria_token { |
258 | T_APP_ID, | 290 | T_APP_ID, |
259 | T_CLASS, | 291 | T_CLASS, |
@@ -434,7 +466,7 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { | |||
434 | generate_regex(&criteria->window_role, effective_value); | 466 | generate_regex(&criteria->window_role, effective_value); |
435 | break; | 467 | break; |
436 | case T_WINDOW_TYPE: | 468 | case T_WINDOW_TYPE: |
437 | // TODO: This is a string but will be stored as an enum or integer | 469 | criteria->window_type = parse_window_type(effective_value); |
438 | break; | 470 | break; |
439 | #ifdef HAVE_XWAYLAND | 471 | #ifdef HAVE_XWAYLAND |
440 | case T_ID: | 472 | case T_ID: |
@@ -526,7 +558,8 @@ struct criteria *criteria_parse(char *raw, char **error_arg) { | |||
526 | } | 558 | } |
527 | ++head; | 559 | ++head; |
528 | 560 | ||
529 | struct criteria *criteria = calloc(sizeof(struct criteria), 1); | 561 | struct criteria *criteria = calloc(1, sizeof(struct criteria)); |
562 | criteria->window_type = ATOM_LAST; // default value | ||
530 | char *name = NULL, *value = NULL; | 563 | char *name = NULL, *value = NULL; |
531 | bool in_quotes = false; | 564 | bool in_quotes = false; |
532 | 565 | ||
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 1fae5db2..a4f7f928 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -176,7 +176,7 @@ void arrange_layers(struct sway_output *output) { | |||
176 | sizeof(struct wlr_box)) != 0) { | 176 | sizeof(struct wlr_box)) != 0) { |
177 | wlr_log(WLR_DEBUG, "Usable area changed, rearranging output"); | 177 | wlr_log(WLR_DEBUG, "Usable area changed, rearranging output"); |
178 | memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); | 178 | memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); |
179 | container_set_dirty(output->swayc); | 179 | arrange_output(output->swayc); |
180 | } | 180 | } |
181 | 181 | ||
182 | // Arrange non-exlusive surfaces from top->bottom | 182 | // Arrange non-exlusive surfaces from top->bottom |
@@ -247,7 +247,6 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { | |||
247 | layer_surface->surface, false); | 247 | layer_surface->surface, false); |
248 | } | 248 | } |
249 | 249 | ||
250 | arrange_windows(output->swayc); | ||
251 | transaction_commit_dirty(); | 250 | transaction_commit_dirty(); |
252 | } | 251 | } |
253 | 252 | ||
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index c228979d..c30e52a1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -559,12 +559,6 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
559 | 559 | ||
560 | wl_list_insert(&root_container.sway_root->all_outputs, &output->link); | 560 | wl_list_insert(&root_container.sway_root->all_outputs, &output->link); |
561 | 561 | ||
562 | if (!wl_list_empty(&wlr_output->modes)) { | ||
563 | struct wlr_output_mode *mode = | ||
564 | wl_container_of(wlr_output->modes.prev, mode, link); | ||
565 | wlr_output_set_mode(wlr_output, mode); | ||
566 | } | ||
567 | |||
568 | output_enable(output); | 562 | output_enable(output); |
569 | } | 563 | } |
570 | 564 | ||
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 4e401008..10faf91d 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "sway/tree/view.h" | 17 | #include "sway/tree/view.h" |
18 | 18 | ||
19 | static const char *atom_map[ATOM_LAST] = { | 19 | static const char *atom_map[ATOM_LAST] = { |
20 | "_NET_WM_WINDOW_TYPE_NORMAL", | ||
20 | "_NET_WM_WINDOW_TYPE_DIALOG", | 21 | "_NET_WM_WINDOW_TYPE_DIALOG", |
21 | "_NET_WM_WINDOW_TYPE_UTILITY", | 22 | "_NET_WM_WINDOW_TYPE_UTILITY", |
22 | "_NET_WM_WINDOW_TYPE_TOOLBAR", | 23 | "_NET_WM_WINDOW_TYPE_TOOLBAR", |
@@ -217,7 +218,9 @@ static bool wants_floating(struct sway_view *view) { | |||
217 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; | 218 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; |
218 | struct sway_xwayland *xwayland = &server.xwayland; | 219 | struct sway_xwayland *xwayland = &server.xwayland; |
219 | 220 | ||
220 | // TODO: return true if the NET_WM_STATE is MODAL | 221 | if (surface->modal) { |
222 | return true; | ||
223 | } | ||
221 | 224 | ||
222 | for (size_t i = 0; i < surface->window_type_len; ++i) { | 225 | for (size_t i = 0; i < surface->window_type_len; ++i) { |
223 | xcb_atom_t type = surface->window_type[i]; | 226 | xcb_atom_t type = surface->window_type[i]; |
@@ -334,6 +337,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
334 | wl_list_remove(&xwayland_view->request_fullscreen.link); | 337 | wl_list_remove(&xwayland_view->request_fullscreen.link); |
335 | wl_list_remove(&xwayland_view->request_move.link); | 338 | wl_list_remove(&xwayland_view->request_move.link); |
336 | wl_list_remove(&xwayland_view->request_resize.link); | 339 | wl_list_remove(&xwayland_view->request_resize.link); |
340 | wl_list_remove(&xwayland_view->request_activate.link); | ||
337 | wl_list_remove(&xwayland_view->set_title.link); | 341 | wl_list_remove(&xwayland_view->set_title.link); |
338 | wl_list_remove(&xwayland_view->set_class.link); | 342 | wl_list_remove(&xwayland_view->set_class.link); |
339 | wl_list_remove(&xwayland_view->set_window_type.link); | 343 | wl_list_remove(&xwayland_view->set_window_type.link); |
@@ -460,6 +464,19 @@ static void handle_request_resize(struct wl_listener *listener, void *data) { | |||
460 | seat_begin_resize_floating(seat, view->swayc, seat->last_button, e->edges); | 464 | seat_begin_resize_floating(seat, view->swayc, seat->last_button, e->edges); |
461 | } | 465 | } |
462 | 466 | ||
467 | static void handle_request_activate(struct wl_listener *listener, void *data) { | ||
468 | struct sway_xwayland_view *xwayland_view = | ||
469 | wl_container_of(listener, xwayland_view, request_activate); | ||
470 | struct sway_view *view = &xwayland_view->view; | ||
471 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | ||
472 | if (!xsurface->mapped) { | ||
473 | return; | ||
474 | } | ||
475 | view_request_activate(view); | ||
476 | |||
477 | transaction_commit_dirty(); | ||
478 | } | ||
479 | |||
463 | static void handle_set_title(struct wl_listener *listener, void *data) { | 480 | static void handle_set_title(struct wl_listener *listener, void *data) { |
464 | struct sway_xwayland_view *xwayland_view = | 481 | struct sway_xwayland_view *xwayland_view = |
465 | wl_container_of(listener, xwayland_view, set_title); | 482 | wl_container_of(listener, xwayland_view, set_title); |
@@ -552,6 +569,10 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
552 | &xwayland_view->request_fullscreen); | 569 | &xwayland_view->request_fullscreen); |
553 | xwayland_view->request_fullscreen.notify = handle_request_fullscreen; | 570 | xwayland_view->request_fullscreen.notify = handle_request_fullscreen; |
554 | 571 | ||
572 | wl_signal_add(&xsurface->events.request_activate, | ||
573 | &xwayland_view->request_activate); | ||
574 | xwayland_view->request_activate.notify = handle_request_activate; | ||
575 | |||
555 | wl_signal_add(&xsurface->events.request_move, | 576 | wl_signal_add(&xsurface->events.request_move, |
556 | &xwayland_view->request_move); | 577 | &xwayland_view->request_move); |
557 | xwayland_view->request_move.notify = handle_request_move; | 578 | xwayland_view->request_move.notify = handle_request_move; |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 36e1d232..4b7c7893 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -635,7 +635,7 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
635 | 635 | ||
636 | // find new output's old workspace, which might have to be removed if empty | 636 | // find new output's old workspace, which might have to be removed if empty |
637 | struct sway_container *new_output_last_ws = NULL; | 637 | struct sway_container *new_output_last_ws = NULL; |
638 | if (last_output != new_output) { | 638 | if (new_output && last_output != new_output) { |
639 | new_output_last_ws = seat_get_active_child(seat, new_output); | 639 | new_output_last_ws = seat_get_active_child(seat, new_output); |
640 | } | 640 | } |
641 | 641 | ||
@@ -779,7 +779,7 @@ void seat_set_focus_layer(struct sway_seat *seat, | |||
779 | wlr_log(WLR_DEBUG, "Returning focus to %p %s '%s'", previous, | 779 | wlr_log(WLR_DEBUG, "Returning focus to %p %s '%s'", previous, |
780 | container_type_to_str(previous->type), previous->name); | 780 | container_type_to_str(previous->type), previous->name); |
781 | // Hack to get seat to re-focus the return value of get_focus | 781 | // Hack to get seat to re-focus the return value of get_focus |
782 | seat_set_focus(seat, previous->parent); | 782 | seat_set_focus(seat, NULL); |
783 | seat_set_focus(seat, previous); | 783 | seat_set_focus(seat, previous); |
784 | } | 784 | } |
785 | return; | 785 | return; |
diff --git a/sway/meson.build b/sway/meson.build index bcb44e8b..c14e58dd 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -46,6 +46,7 @@ sway_sources = files( | |||
46 | 'commands/floating_modifier.c', | 46 | 'commands/floating_modifier.c', |
47 | 'commands/focus.c', | 47 | 'commands/focus.c', |
48 | 'commands/focus_follows_mouse.c', | 48 | 'commands/focus_follows_mouse.c', |
49 | 'commands/focus_on_window_activation.c', | ||
49 | 'commands/focus_wrapping.c', | 50 | 'commands/focus_wrapping.c', |
50 | 'commands/font.c', | 51 | 'commands/font.c', |
51 | 'commands/for_window.c', | 52 | 'commands/for_window.c', |
diff --git a/sway/server.c b/sway/server.c index 92ed5595..749365cb 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <wlr/types/wlr_gamma_control_v1.h> | 12 | #include <wlr/types/wlr_gamma_control_v1.h> |
13 | #include <wlr/types/wlr_idle.h> | 13 | #include <wlr/types/wlr_idle.h> |
14 | #include <wlr/types/wlr_layer_shell.h> | 14 | #include <wlr/types/wlr_layer_shell.h> |
15 | #include <wlr/types/wlr_linux_dmabuf_v1.h> | ||
16 | #include <wlr/types/wlr_primary_selection.h> | 15 | #include <wlr/types/wlr_primary_selection.h> |
17 | #include <wlr/types/wlr_screencopy_v1.h> | 16 | #include <wlr/types/wlr_screencopy_v1.h> |
18 | #include <wlr/types/wlr_server_decoration.h> | 17 | #include <wlr/types/wlr_server_decoration.h> |
@@ -117,7 +116,6 @@ bool server_init(struct sway_server *server) { | |||
117 | server->server_decoration.notify = handle_server_decoration; | 116 | server->server_decoration.notify = handle_server_decoration; |
118 | wl_list_init(&server->decorations); | 117 | wl_list_init(&server->decorations); |
119 | 118 | ||
120 | wlr_linux_dmabuf_v1_create(server->wl_display, renderer); | ||
121 | wlr_export_dmabuf_manager_v1_create(server->wl_display); | 119 | wlr_export_dmabuf_manager_v1_create(server->wl_display); |
122 | wlr_screencopy_manager_v1_create(server->wl_display); | 120 | wlr_screencopy_manager_v1_create(server->wl_display); |
123 | 121 | ||
diff --git a/sway/tree/view.c b/sway/tree/view.c index 1a98c5f2..6bd0ef67 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -280,6 +280,29 @@ void view_set_activated(struct sway_view *view, bool activated) { | |||
280 | } | 280 | } |
281 | } | 281 | } |
282 | 282 | ||
283 | void view_request_activate(struct sway_view *view) { | ||
284 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | ||
285 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
286 | |||
287 | switch (config->focus_on_window_activation) { | ||
288 | case FOWA_SMART: | ||
289 | if (workspace_is_visible(ws)) { | ||
290 | seat_set_focus(seat, view->swayc); | ||
291 | } else { | ||
292 | view_set_urgent(view, true); | ||
293 | } | ||
294 | break; | ||
295 | case FOWA_URGENT: | ||
296 | view_set_urgent(view, true); | ||
297 | break; | ||
298 | case FOWA_FOCUS: | ||
299 | seat_set_focus(seat, view->swayc); | ||
300 | break; | ||
301 | case FOWA_NONE: | ||
302 | break; | ||
303 | } | ||
304 | } | ||
305 | |||
283 | void view_set_tiled(struct sway_view *view, bool tiled) { | 306 | void view_set_tiled(struct sway_view *view, bool tiled) { |
284 | if (!tiled) { | 307 | if (!tiled) { |
285 | view->using_csd = true; | 308 | view->using_csd = true; |