summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar sghctoma <sghctoma@gmail.com>2018-09-03 08:57:17 +0200
committerLibravatar sghctoma <sghctoma@gmail.com>2018-09-03 08:57:17 +0200
commitdf730a88919b078093dbc322926ada219a60d036 (patch)
treef2837f24092c7be5dfccdf448e47062cb5718549
parentEnable privilege dropping of FreeBSD (diff)
parentMerge pull request #2553 from emersion/disabled-no-modeset (diff)
downloadsway-df730a88919b078093dbc322926ada219a60d036.tar.gz
sway-df730a88919b078093dbc322926ada219a60d036.tar.zst
sway-df730a88919b078093dbc322926ada219a60d036.zip
Merge remote-tracking branch 'upstream/master' into fix-freebsd-build
-rw-r--r--common/stringop.c14
-rw-r--r--include/stringop.h2
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/config.h11
-rw-r--r--include/sway/criteria.h2
-rw-r--r--include/sway/tree/view.h6
-rw-r--r--include/sway/xwayland.h1
-rw-r--r--meson.build12
-rw-r--r--meson_options.txt11
-rw-r--r--sway/commands.c3
-rw-r--r--sway/commands/bind.c2
-rw-r--r--sway/commands/border.c6
-rw-r--r--sway/commands/focus_on_window_activation.c25
-rw-r--r--sway/config/output.c4
-rw-r--r--sway/criteria.c45
-rw-r--r--sway/desktop/layer_shell.c3
-rw-r--r--sway/desktop/output.c6
-rw-r--r--sway/desktop/xwayland.c23
-rw-r--r--sway/input/seat.c4
-rw-r--r--sway/meson.build1
-rw-r--r--sway/server.c2
-rw-r--r--sway/tree/view.c23
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
405const 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
47char *argsep(char **stringp, const char *delim); 47char *argsep(char **stringp, const char *delim);
48 48
49const 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;
117sway_cmd cmd_floating_scroll; 117sway_cmd cmd_floating_scroll;
118sway_cmd cmd_focus; 118sway_cmd cmd_focus;
119sway_cmd cmd_focus_follows_mouse; 119sway_cmd cmd_focus_follows_mouse;
120sway_cmd cmd_focus_on_window_activation;
120sway_cmd cmd_focus_wrapping; 121sway_cmd cmd_focus_wrapping;
121sway_cmd cmd_font; 122sway_cmd cmd_font;
122sway_cmd cmd_for_window; 123sway_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 */
63enum 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 */
63struct sway_mode { 73struct 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
260void view_set_activated(struct sway_view *view, bool activated); 261void view_set_activated(struct sway_view *view, bool activated);
261 262
263/**
264 * Called when the view requests to be focused.
265 */
266void view_request_activate(struct sway_view *view);
267
262void view_set_tiled(struct sway_view *view, bool tiled); 268void view_set_tiled(struct sway_view *view, bool tiled);
263 269
264void view_close(struct sway_view *view); 270void 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
7enum atom_name { 7enum 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
107add_project_arguments('-DSYSCONFDIR="/@0@/@1@"'.format(prefix, sysconfdir), language : 'c') 107add_project_arguments('-DSYSCONFDIR="/@0@/@1@"'.format(prefix, sysconfdir), language : 'c')
108 108
109version = get_option('sway_version') 109version = get_option('sway-version')
110if version != '' 110if version != ''
111 version = '"@0@"'.format(version) 111 version = '"@0@"'.format(version)
112else 112else
@@ -120,6 +120,8 @@ else
120endif 120endif
121add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') 121add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c')
122 122
123add_project_arguments('-D_LD_LIBRARY_PATH="@0@"'.format(get_option('ld-library-path')), language: 'c')
124
123sway_inc = include_directories('include') 125sway_inc = include_directories('include')
124 126
125subdir('include') 127subdir('include')
@@ -168,7 +170,7 @@ install_data(
168 install_dir: datadir + '/wayland-sessions' 170 install_dir: datadir + '/wayland-sessions'
169) 171)
170 172
171if (get_option('default_wallpaper')) 173if (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)
185endif 187endif
186 188
187if (get_option('zsh_completions')) 189if (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)
196endif 198endif
197 199
198if (get_option('bash_completions')) 200if (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)
208endif 210endif
209 211
210if (get_option('fish_completions')) 212if (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 @@
1option('sway_version', type : 'string', description: 'The version string reported in `sway --version`.') 1option('sway-version', type : 'string', description: 'The version string reported in `sway --version`.')
2option('default_wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.') 2option('ld-library-path', type: 'string', value: '', description: 'The LD_LIBRARY_PATH environment variable.')
3option('zsh_completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') 3option('default-wallpaper', type: 'boolean', value: true, description: 'Install the default wallpaper.')
4option('bash_completions', type: 'boolean', value: true, description: 'Install bash shell completions.') 4option('zsh-completions', type: 'boolean', value: true, description: 'Install zsh shell completions.')
5option('fish_completions', type: 'boolean', value: true, description: 'Install fish shell completions.') 5option('bash-completions', type: 'boolean', value: true, description: 'Install bash shell completions.')
6option('fish-completions', type: 'boolean', value: true, description: 'Install fish shell completions.')
6option('enable-xwayland', type: 'boolean', value: true, description: 'Enable support for X11 applications') 7option('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
3struct 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
54static 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
53static int cmp_urgent(const void *_a, const void *_b) { 71static 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
274static 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
257enum criteria_token { 289enum 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
19static const char *atom_map[ATOM_LAST] = { 19static 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
467static 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
463static void handle_set_title(struct wl_listener *listener, void *data) { 480static 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
283void 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
283void view_set_tiled(struct sway_view *view, bool tiled) { 306void 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;