diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-06-29 20:04:24 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-06-29 20:04:24 +1000 |
commit | a2fbb20a616444213ff3967b33eed7f4561e3978 (patch) | |
tree | 276a133eb78d6e0655bc164693650454d43a22ca | |
parent | Add comment about usage to arrange_windows declaration (diff) | |
parent | Merge pull request #2172 from apreiml/fix-keybinding-modifier-handling (diff) | |
download | sway-a2fbb20a616444213ff3967b33eed7f4561e3978.tar.gz sway-a2fbb20a616444213ff3967b33eed7f4561e3978.tar.zst sway-a2fbb20a616444213ff3967b33eed7f4561e3978.zip |
Merge remote-tracking branch 'upstream/master' into atomic
-rw-r--r-- | include/sway/output.h | 4 | ||||
-rw-r--r-- | include/sway/server.h | 9 | ||||
-rw-r--r-- | include/sway/xwayland.h | 25 | ||||
-rw-r--r-- | meson.build | 3 | ||||
-rw-r--r-- | sway/commands/input.c | 2 | ||||
-rw-r--r-- | sway/commands/output/background.c | 56 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 9 | ||||
-rw-r--r-- | sway/desktop/output.c | 3 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 9 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 10 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 94 | ||||
-rw-r--r-- | sway/input/cursor.c | 9 | ||||
-rw-r--r-- | sway/input/keyboard.c | 10 | ||||
-rw-r--r-- | sway/input/seat.c | 3 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/server.c | 18 |
16 files changed, 192 insertions, 73 deletions
diff --git a/include/sway/output.h b/include/sway/output.h index e6ca0d02..19fc5e99 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -32,6 +32,10 @@ struct sway_output { | |||
32 | struct wl_list link; | 32 | struct wl_list link; |
33 | 33 | ||
34 | pid_t bg_pid; | 34 | pid_t bg_pid; |
35 | |||
36 | struct { | ||
37 | struct wl_signal destroy; | ||
38 | } events; | ||
35 | }; | 39 | }; |
36 | 40 | ||
37 | void output_damage_whole(struct sway_output *output); | 41 | void output_damage_whole(struct sway_output *output); |
diff --git a/include/sway/server.h b/include/sway/server.h index 0efc6baa..1e1aa3cc 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -11,8 +11,8 @@ | |||
11 | #include <wlr/types/wlr_xdg_shell.h> | 11 | #include <wlr/types/wlr_xdg_shell.h> |
12 | #include <wlr/render/wlr_renderer.h> | 12 | #include <wlr/render/wlr_renderer.h> |
13 | // TODO WLR: make Xwayland optional | 13 | // TODO WLR: make Xwayland optional |
14 | #include <wlr/xwayland.h> | ||
15 | #include "list.h" | 14 | #include "list.h" |
15 | #include "sway/xwayland.h" | ||
16 | 16 | ||
17 | struct sway_server { | 17 | struct sway_server { |
18 | struct wl_display *wl_display; | 18 | struct wl_display *wl_display; |
@@ -38,12 +38,9 @@ struct sway_server { | |||
38 | struct wlr_xdg_shell *xdg_shell; | 38 | struct wlr_xdg_shell *xdg_shell; |
39 | struct wl_listener xdg_shell_surface; | 39 | struct wl_listener xdg_shell_surface; |
40 | 40 | ||
41 | struct wlr_xwayland *xwayland; | 41 | struct sway_xwayland xwayland; |
42 | struct wlr_xcursor_manager *xcursor_manager; | ||
43 | struct wl_listener xwayland_surface; | 42 | struct wl_listener xwayland_surface; |
44 | 43 | struct wl_listener xwayland_ready; | |
45 | struct wlr_wl_shell *wl_shell; | ||
46 | struct wl_listener wl_shell_surface; | ||
47 | 44 | ||
48 | bool debug_txn_timings; | 45 | bool debug_txn_timings; |
49 | 46 | ||
diff --git a/include/sway/xwayland.h b/include/sway/xwayland.h new file mode 100644 index 00000000..78d1053b --- /dev/null +++ b/include/sway/xwayland.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef SWAY_XWAYLAND_H | ||
2 | #define SWAY_XWAYLAND_H | ||
3 | |||
4 | #include <wlr/xwayland.h> | ||
5 | #include <xcb/xproto.h> | ||
6 | |||
7 | enum atom_name { | ||
8 | NET_WM_WINDOW_TYPE_DIALOG, | ||
9 | NET_WM_WINDOW_TYPE_UTILITY, | ||
10 | NET_WM_WINDOW_TYPE_TOOLBAR, | ||
11 | NET_WM_WINDOW_TYPE_SPLASH, | ||
12 | NET_WM_STATE_MODAL, | ||
13 | ATOM_LAST, | ||
14 | }; | ||
15 | |||
16 | struct sway_xwayland { | ||
17 | struct wlr_xwayland *wlr_xwayland; | ||
18 | struct wlr_xcursor_manager *xcursor_manager; | ||
19 | |||
20 | xcb_atom_t atoms[ATOM_LAST]; | ||
21 | }; | ||
22 | |||
23 | void handle_xwayland_ready(struct wl_listener *listener, void *data); | ||
24 | |||
25 | #endif | ||
diff --git a/meson.build b/meson.build index d4ee1a11..1d40581a 100644 --- a/meson.build +++ b/meson.build | |||
@@ -43,7 +43,8 @@ systemd = dependency('libsystemd', required: false) | |||
43 | elogind = dependency('libelogind', required: false) | 43 | elogind = dependency('libelogind', required: false) |
44 | math = cc.find_library('m') | 44 | math = cc.find_library('m') |
45 | rt = cc.find_library('rt') | 45 | rt = cc.find_library('rt') |
46 | git = find_program('git', required: false) | 46 | xcb = dependency('xcb') |
47 | git = find_program('git', required: false) | ||
47 | 48 | ||
48 | conf_data = configuration_data() | 49 | conf_data = configuration_data() |
49 | 50 | ||
diff --git a/sway/commands/input.c b/sway/commands/input.c index 22a0bb7c..678c57c4 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c | |||
@@ -31,7 +31,7 @@ static struct cmd_handler input_handlers[] = { | |||
31 | 31 | ||
32 | struct cmd_results *cmd_input(int argc, char **argv) { | 32 | struct cmd_results *cmd_input(int argc, char **argv) { |
33 | struct cmd_results *error = NULL; | 33 | struct cmd_results *error = NULL; |
34 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 1))) { | 34 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { |
35 | return error; | 35 | return error; |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c index 82bccf68..55cbdff0 100644 --- a/sway/commands/output/background.c +++ b/sway/commands/output/background.c | |||
@@ -62,46 +62,56 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { | |||
62 | wordexp_t p; | 62 | wordexp_t p; |
63 | char *src = join_args(argv, j); | 63 | char *src = join_args(argv, j); |
64 | if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { | 64 | if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { |
65 | return cmd_results_new(CMD_INVALID, "output", | 65 | struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID, "output", |
66 | "Invalid syntax (%s).", src); | 66 | "Invalid syntax (%s)", src); |
67 | free(src); | ||
68 | wordfree(&p); | ||
69 | return cmd_res; | ||
67 | } | 70 | } |
68 | free(src); | 71 | free(src); |
69 | src = p.we_wordv[0]; | 72 | src = strdup(p.we_wordv[0]); |
73 | wordfree(&p); | ||
74 | if (!src) { | ||
75 | wlr_log(L_ERROR, "Failed to duplicate string"); | ||
76 | return cmd_results_new(CMD_FAILURE, "output", | ||
77 | "Unable to allocate resource"); | ||
78 | } | ||
79 | |||
70 | if (config->reading && *src != '/') { | 80 | if (config->reading && *src != '/') { |
81 | // src file is inside configuration dir | ||
82 | |||
71 | char *conf = strdup(config->current_config); | 83 | char *conf = strdup(config->current_config); |
72 | if (conf) { | 84 | if(!conf) { |
73 | char *conf_path = dirname(conf); | 85 | wlr_log(L_ERROR, "Failed to duplicate string"); |
74 | src = malloc(strlen(conf_path) + strlen(src) + 2); | 86 | return cmd_results_new(CMD_FAILURE, "output", |
75 | if (!src) { | ||
76 | free(conf); | ||
77 | wordfree(&p); | ||
78 | wlr_log(L_ERROR, | ||
79 | "Unable to allocate resource: Not enough memory"); | ||
80 | return cmd_results_new(CMD_FAILURE, "output", | ||
81 | "Unable to allocate resources"); | 87 | "Unable to allocate resources"); |
82 | } | 88 | } |
83 | sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); | 89 | |
90 | char *conf_path = dirname(conf); | ||
91 | char *rel_path = src; | ||
92 | src = malloc(strlen(conf_path) + strlen(src) + 2); | ||
93 | if (!src) { | ||
94 | free(rel_path); | ||
84 | free(conf); | 95 | free(conf); |
85 | } else { | 96 | wlr_log(L_ERROR, "Unable to allocate memory"); |
86 | wlr_log(L_ERROR, "Unable to allocate background source"); | 97 | return cmd_results_new(CMD_FAILURE, "output", |
98 | "Unable to allocate resources"); | ||
87 | } | 99 | } |
100 | |||
101 | sprintf(src, "%s/%s", conf_path, rel_path); | ||
102 | free(rel_path); | ||
103 | free(conf); | ||
88 | } | 104 | } |
89 | 105 | ||
90 | if (access(src, F_OK) == -1) { | 106 | if (access(src, F_OK) == -1) { |
91 | struct cmd_results *cmd_res = cmd_results_new(CMD_FAILURE, "output", | 107 | struct cmd_results *cmd_res = cmd_results_new(CMD_FAILURE, "output", |
92 | "Unable to access background file '%s': %s", src, strerror(errno)); | 108 | "Unable to access background file '%s': %s", src, strerror(errno)); |
93 | free(src); | 109 | free(src); |
94 | wordfree(&p); | ||
95 | return cmd_res; | 110 | return cmd_res; |
96 | } | 111 | } |
97 | 112 | ||
98 | output->background = strdup(src); | 113 | output->background = src; |
99 | output->background_option = strdup(mode); | 114 | output->background_option = strdup(mode); |
100 | if (src != p.we_wordv[0]) { | ||
101 | free(src); | ||
102 | } | ||
103 | wordfree(&p); | ||
104 | |||
105 | argc -= j + 1; argv += j + 1; | 115 | argc -= j + 1; argv += j + 1; |
106 | } | 116 | } |
107 | 117 | ||
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index fe5fc316..ff37bbf1 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c | |||
@@ -219,6 +219,8 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { | |||
219 | struct sway_layer_surface *sway_layer = | 219 | struct sway_layer_surface *sway_layer = |
220 | wl_container_of(listener, sway_layer, output_destroy); | 220 | wl_container_of(listener, sway_layer, output_destroy); |
221 | wl_list_remove(&sway_layer->output_destroy.link); | 221 | wl_list_remove(&sway_layer->output_destroy.link); |
222 | wl_list_remove(&sway_layer->link); | ||
223 | wl_list_init(&sway_layer->link); | ||
222 | sway_layer->layer_surface->output = NULL; | 224 | sway_layer->layer_surface->output = NULL; |
223 | wlr_layer_surface_close(sway_layer->layer_surface); | 225 | wlr_layer_surface_close(sway_layer->layer_surface); |
224 | } | 226 | } |
@@ -350,10 +352,6 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
350 | wl_signal_add(&layer_surface->surface->events.commit, | 352 | wl_signal_add(&layer_surface->surface->events.commit, |
351 | &sway_layer->surface_commit); | 353 | &sway_layer->surface_commit); |
352 | 354 | ||
353 | sway_layer->output_destroy.notify = handle_output_destroy; | ||
354 | wl_signal_add(&layer_surface->output->events.destroy, | ||
355 | &sway_layer->output_destroy); | ||
356 | |||
357 | sway_layer->destroy.notify = handle_destroy; | 355 | sway_layer->destroy.notify = handle_destroy; |
358 | wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); | 356 | wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); |
359 | sway_layer->map.notify = handle_map; | 357 | sway_layer->map.notify = handle_map; |
@@ -366,6 +364,9 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | |||
366 | layer_surface->data = sway_layer; | 364 | layer_surface->data = sway_layer; |
367 | 365 | ||
368 | struct sway_output *output = layer_surface->output->data; | 366 | struct sway_output *output = layer_surface->output->data; |
367 | sway_layer->output_destroy.notify = handle_output_destroy; | ||
368 | wl_signal_add(&output->events.destroy, &sway_layer->output_destroy); | ||
369 | |||
369 | wl_list_insert(&output->layers[layer_surface->layer], &sway_layer->link); | 370 | wl_list_insert(&output->layers[layer_surface->layer], &sway_layer->link); |
370 | 371 | ||
371 | // Temporarily set the layer's current state to client_pending | 372 | // Temporarily set the layer's current state to client_pending |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 34fefaa9..69d0bdd4 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -1263,6 +1263,8 @@ static void damage_handle_destroy(struct wl_listener *listener, void *data) { | |||
1263 | 1263 | ||
1264 | static void handle_destroy(struct wl_listener *listener, void *data) { | 1264 | static void handle_destroy(struct wl_listener *listener, void *data) { |
1265 | struct sway_output *output = wl_container_of(listener, output, destroy); | 1265 | struct sway_output *output = wl_container_of(listener, output, destroy); |
1266 | wl_signal_emit(&output->events.destroy, output); | ||
1267 | |||
1266 | if (output->swayc) { | 1268 | if (output->swayc) { |
1267 | container_destroy(output->swayc); | 1269 | container_destroy(output->swayc); |
1268 | } | 1270 | } |
@@ -1343,6 +1345,7 @@ void output_enable(struct sway_output *output) { | |||
1343 | for (size_t i = 0; i < len; ++i) { | 1345 | for (size_t i = 0; i < len; ++i) { |
1344 | wl_list_init(&output->layers[i]); | 1346 | wl_list_init(&output->layers[i]); |
1345 | } | 1347 | } |
1348 | wl_signal_init(&output->events.destroy); | ||
1346 | 1349 | ||
1347 | input_manager_configure_xcursor(input_manager); | 1350 | input_manager_configure_xcursor(input_manager); |
1348 | 1351 | ||
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index b076d772..0f45399d 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -117,11 +117,12 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { | |||
117 | } | 117 | } |
118 | 118 | ||
119 | static bool wants_floating(struct sway_view *view) { | 119 | static bool wants_floating(struct sway_view *view) { |
120 | struct wlr_xdg_toplevel_state *state = | 120 | struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_surface->toplevel; |
121 | &view->wlr_xdg_surface->toplevel->current; | 121 | struct wlr_xdg_toplevel_state *state = &toplevel->current; |
122 | return state->min_width != 0 && state->min_height != 0 | 122 | return (state->min_width != 0 && state->min_height != 0 |
123 | && state->min_width == state->max_width | 123 | && state->min_width == state->max_width |
124 | && state->min_height == state->max_height; | 124 | && state->min_height == state->max_height) |
125 | || toplevel->parent; | ||
125 | } | 126 | } |
126 | 127 | ||
127 | static void for_each_surface(struct sway_view *view, | 128 | static void for_each_surface(struct sway_view *view, |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 7320e629..b296f1a8 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -117,11 +117,13 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { | |||
117 | } | 117 | } |
118 | 118 | ||
119 | static bool wants_floating(struct sway_view *view) { | 119 | static bool wants_floating(struct sway_view *view) { |
120 | struct wlr_xdg_toplevel_v6_state *state = | 120 | struct wlr_xdg_toplevel_v6 *toplevel = |
121 | &view->wlr_xdg_surface_v6->toplevel->current; | 121 | view->wlr_xdg_surface_v6->toplevel; |
122 | return state->min_width != 0 && state->min_height != 0 | 122 | struct wlr_xdg_toplevel_v6_state *state = &toplevel->current; |
123 | return (state->min_width != 0 && state->min_height != 0 | ||
123 | && state->min_width == state->max_width | 124 | && state->min_width == state->max_width |
124 | && state->min_height == state->max_height; | 125 | && state->min_height == state->max_height) |
126 | || toplevel->parent; | ||
125 | } | 127 | } |
126 | 128 | ||
127 | static void for_each_surface(struct sway_view *view, | 129 | static void for_each_surface(struct sway_view *view, |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 854da006..023fb2a7 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -17,6 +17,14 @@ | |||
17 | #include "sway/tree/layout.h" | 17 | #include "sway/tree/layout.h" |
18 | #include "sway/tree/view.h" | 18 | #include "sway/tree/view.h" |
19 | 19 | ||
20 | static const char *atom_map[ATOM_LAST] = { | ||
21 | "_NET_WM_WINDOW_TYPE_DIALOG", | ||
22 | "_NET_WM_WINDOW_TYPE_UTILITY", | ||
23 | "_NET_WM_WINDOW_TYPE_TOOLBAR", | ||
24 | "_NET_WM_WINDOW_TYPE_SPLASH", | ||
25 | "_NET_WM_STATE_MODAL", | ||
26 | }; | ||
27 | |||
20 | static void unmanaged_handle_request_configure(struct wl_listener *listener, | 28 | static void unmanaged_handle_request_configure(struct wl_listener *listener, |
21 | void *data) { | 29 | void *data) { |
22 | struct sway_xwayland_unmanaged *surface = | 30 | struct sway_xwayland_unmanaged *surface = |
@@ -63,7 +71,8 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) { | |||
63 | 71 | ||
64 | if (!wlr_xwayland_surface_is_unmanaged(xsurface)) { | 72 | if (!wlr_xwayland_surface_is_unmanaged(xsurface)) { |
65 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 73 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
66 | struct wlr_xwayland *xwayland = seat->input->server->xwayland; | 74 | struct wlr_xwayland *xwayland = |
75 | seat->input->server->xwayland.wlr_xwayland; | ||
67 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 76 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
68 | seat_set_focus_surface(seat, xsurface->surface); | 77 | seat_set_focus_surface(seat, xsurface->surface); |
69 | } | 78 | } |
@@ -200,15 +209,32 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { | |||
200 | } | 209 | } |
201 | 210 | ||
202 | static bool wants_floating(struct sway_view *view) { | 211 | static bool wants_floating(struct sway_view *view) { |
203 | // TODO: | 212 | if (xwayland_view_from_view(view) == NULL) { |
204 | // We want to return true if the window type contains any of these: | 213 | return false; |
205 | // NET_WM_WINDOW_TYPE_DIALOG | 214 | } |
206 | // NET_WM_WINDOW_TYPE_UTILITY | 215 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; |
207 | // NET_WM_WINDOW_TYPE_TOOLBAR | 216 | struct sway_xwayland *xwayland = &server.xwayland; |
208 | // NET_WM_WINDOW_TYPE_SPLASH | 217 | |
209 | // | 218 | // TODO: return true if the NET_WM_STATE is MODAL |
210 | // We also want to return true if the NET_WM_STATE is MODAL. | 219 | |
211 | // wlroots doesn't appear to provide all this information at the moment. | 220 | for (size_t i = 0; i < surface->window_type_len; ++i) { |
221 | xcb_atom_t type = surface->window_type[i]; | ||
222 | if (type == xwayland->atoms[NET_WM_WINDOW_TYPE_DIALOG] || | ||
223 | type == xwayland->atoms[NET_WM_WINDOW_TYPE_UTILITY] || | ||
224 | type == xwayland->atoms[NET_WM_WINDOW_TYPE_TOOLBAR] || | ||
225 | type == xwayland->atoms[NET_WM_WINDOW_TYPE_SPLASH]) { | ||
226 | return true; | ||
227 | } | ||
228 | } | ||
229 | |||
230 | struct wlr_xwayland_surface_size_hints *size_hints = surface->size_hints; | ||
231 | if (size_hints != NULL && | ||
232 | size_hints->min_width != 0 && size_hints->min_height != 0 && | ||
233 | size_hints->max_width == size_hints->min_width && | ||
234 | size_hints->max_height == size_hints->min_height) { | ||
235 | return true; | ||
236 | } | ||
237 | |||
212 | return false; | 238 | return false; |
213 | } | 239 | } |
214 | 240 | ||
@@ -324,9 +350,14 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { | |||
324 | ev->width, ev->height); | 350 | ev->width, ev->height); |
325 | return; | 351 | return; |
326 | } | 352 | } |
327 | // TODO: Let floating views do whatever | 353 | if (container_is_floating(view->swayc)) { |
328 | configure(view, view->swayc->current.view_x, view->swayc->current.view_y, | 354 | configure(view, view->swayc->current.view_x, |
329 | view->swayc->current.view_width, view->swayc->current.view_height); | 355 | view->swayc->current.view_y, ev->width, ev->height); |
356 | } else { | ||
357 | configure(view, view->swayc->current.view_x, | ||
358 | view->swayc->current.view_y, view->swayc->current.view_width, | ||
359 | view->swayc->current.view_height); | ||
360 | } | ||
330 | } | 361 | } |
331 | 362 | ||
332 | static void handle_request_fullscreen(struct wl_listener *listener, void *data) { | 363 | static void handle_request_fullscreen(struct wl_listener *listener, void *data) { |
@@ -431,3 +462,40 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
431 | wl_signal_add(&xsurface->events.map, &xwayland_view->map); | 462 | wl_signal_add(&xsurface->events.map, &xwayland_view->map); |
432 | xwayland_view->map.notify = handle_map; | 463 | xwayland_view->map.notify = handle_map; |
433 | } | 464 | } |
465 | |||
466 | void handle_xwayland_ready(struct wl_listener *listener, void *data) { | ||
467 | struct sway_server *server = | ||
468 | wl_container_of(listener, server, xwayland_ready); | ||
469 | struct sway_xwayland *xwayland = &server->xwayland; | ||
470 | |||
471 | xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL); | ||
472 | int err = xcb_connection_has_error(xcb_conn); | ||
473 | if (err) { | ||
474 | wlr_log(L_ERROR, "XCB connect failed: %d", err); | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | xcb_intern_atom_cookie_t cookies[ATOM_LAST]; | ||
479 | for (size_t i = 0; i < ATOM_LAST; i++) { | ||
480 | cookies[i] = | ||
481 | xcb_intern_atom(xcb_conn, 0, strlen(atom_map[i]), atom_map[i]); | ||
482 | } | ||
483 | for (size_t i = 0; i < ATOM_LAST; i++) { | ||
484 | xcb_generic_error_t *error = NULL; | ||
485 | xcb_intern_atom_reply_t *reply = | ||
486 | xcb_intern_atom_reply(xcb_conn, cookies[i], &error); | ||
487 | if (reply != NULL && error == NULL) { | ||
488 | xwayland->atoms[i] = reply->atom; | ||
489 | } | ||
490 | free(reply); | ||
491 | |||
492 | if (error != NULL) { | ||
493 | wlr_log(L_ERROR, "could not resolve atom %s, X11 error code %d", | ||
494 | atom_map[i], error->error_code); | ||
495 | free(error); | ||
496 | break; | ||
497 | } | ||
498 | } | ||
499 | |||
500 | xcb_disconnect(xcb_conn); | ||
501 | } | ||
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 37a87756..944e35aa 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -174,10 +174,13 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
174 | seat_set_focus_warp(seat, c, false); | 174 | seat_set_focus_warp(seat, c, false); |
175 | } | 175 | } |
176 | } else if (c->type == C_VIEW) { | 176 | } else if (c->type == C_VIEW) { |
177 | // Focus c if both of the following are true: | 177 | // Focus c if the following are true: |
178 | // - cursor is over a new view, i.e. entered a new window; and | 178 | // - cursor is over a new view, i.e. entered a new window; and |
179 | // - the new view is visible, i.e. not hidden in a stack or tab. | 179 | // - the new view is visible, i.e. not hidden in a stack or tab; and |
180 | if (c != prev_c && view_is_visible(c->sway_view)) { | 180 | // - the seat does not have a keyboard grab |
181 | if (!wlr_seat_keyboard_has_grab(cursor->seat->wlr_seat) && | ||
182 | c != prev_c && | ||
183 | view_is_visible(c->sway_view)) { | ||
181 | seat_set_focus_warp(seat, c, false); | 184 | seat_set_focus_warp(seat, c, false); |
182 | } else { | 185 | } else { |
183 | struct sway_container *next_focus = | 186 | struct sway_container *next_focus = |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 9e093828..ec149d06 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -64,12 +64,12 @@ static void update_shortcut_state(struct sway_shortcut_state *state, | |||
64 | bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; | 64 | bool last_key_was_a_modifier = raw_modifiers != state->last_raw_modifiers; |
65 | state->last_raw_modifiers = raw_modifiers; | 65 | state->last_raw_modifiers = raw_modifiers; |
66 | 66 | ||
67 | if (event->state == WLR_KEY_PRESSED) { | 67 | if (last_key_was_a_modifier && state->last_keycode) { |
68 | if (last_key_was_a_modifier && state->last_keycode) { | 68 | // Last pressed key before this one was a modifier |
69 | // Last pressed key before this one was a modifier | 69 | state_erase_key(state, state->last_keycode); |
70 | state_erase_key(state, state->last_keycode); | 70 | } |
71 | } | ||
72 | 71 | ||
72 | if (event->state == WLR_KEY_PRESSED) { | ||
73 | // Add current key to set; there may be duplicates | 73 | // Add current key to set; there may be duplicates |
74 | state_add_key(state, event->keycode, new_key); | 74 | state_add_key(state, event->keycode, new_key); |
75 | state->last_keycode = event->keycode; | 75 | state->last_keycode = event->keycode; |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 436d18e2..2c2087da 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -99,7 +99,8 @@ static void seat_send_focus(struct sway_container *con, | |||
99 | if (con->type == C_VIEW | 99 | if (con->type == C_VIEW |
100 | && seat_is_input_allowed(seat, con->sway_view->surface)) { | 100 | && seat_is_input_allowed(seat, con->sway_view->surface)) { |
101 | if (con->sway_view->type == SWAY_VIEW_XWAYLAND) { | 101 | if (con->sway_view->type == SWAY_VIEW_XWAYLAND) { |
102 | struct wlr_xwayland *xwayland = seat->input->server->xwayland; | 102 | struct wlr_xwayland *xwayland = |
103 | seat->input->server->xwayland.wlr_xwayland; | ||
103 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 104 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
104 | } | 105 | } |
105 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); | 106 | struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); |
diff --git a/sway/meson.build b/sway/meson.build index c461b0ff..9ff3f05f 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -153,6 +153,7 @@ sway_deps = [ | |||
153 | server_protos, | 153 | server_protos, |
154 | wayland_server, | 154 | wayland_server, |
155 | wlroots, | 155 | wlroots, |
156 | xcb, | ||
156 | xkbcommon, | 157 | xkbcommon, |
157 | ] | 158 | ] |
158 | 159 | ||
diff --git a/sway/server.c b/sway/server.c index 884d971e..f5700c09 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -19,13 +19,12 @@ | |||
19 | #include <wlr/types/wlr_xdg_output.h> | 19 | #include <wlr/types/wlr_xdg_output.h> |
20 | #include <wlr/util/log.h> | 20 | #include <wlr/util/log.h> |
21 | // TODO WLR: make Xwayland optional | 21 | // TODO WLR: make Xwayland optional |
22 | #include <wlr/xwayland.h> | ||
23 | #include "list.h" | 22 | #include "list.h" |
24 | #include "sway/config.h" | 23 | #include "sway/config.h" |
25 | #include "sway/input/input-manager.h" | 24 | #include "sway/input/input-manager.h" |
26 | #include "sway/server.h" | 25 | #include "sway/server.h" |
27 | #include "sway/tree/layout.h" | 26 | #include "sway/tree/layout.h" |
28 | 27 | #include "sway/xwayland.h" | |
29 | 28 | ||
30 | bool server_privileged_prepare(struct sway_server *server) { | 29 | bool server_privileged_prepare(struct sway_server *server) { |
31 | wlr_log(L_DEBUG, "Preparing Wayland server initialization"); | 30 | wlr_log(L_DEBUG, "Preparing Wayland server initialization"); |
@@ -79,20 +78,23 @@ bool server_init(struct sway_server *server) { | |||
79 | server->xdg_shell_surface.notify = handle_xdg_shell_surface; | 78 | server->xdg_shell_surface.notify = handle_xdg_shell_surface; |
80 | 79 | ||
81 | // TODO make xwayland optional | 80 | // TODO make xwayland optional |
82 | server->xwayland = | 81 | server->xwayland.wlr_xwayland = |
83 | wlr_xwayland_create(server->wl_display, server->compositor, true); | 82 | wlr_xwayland_create(server->wl_display, server->compositor, true); |
84 | wl_signal_add(&server->xwayland->events.new_surface, | 83 | wl_signal_add(&server->xwayland.wlr_xwayland->events.new_surface, |
85 | &server->xwayland_surface); | 84 | &server->xwayland_surface); |
86 | server->xwayland_surface.notify = handle_xwayland_surface; | 85 | server->xwayland_surface.notify = handle_xwayland_surface; |
86 | wl_signal_add(&server->xwayland.wlr_xwayland->events.ready, | ||
87 | &server->xwayland_ready); | ||
88 | server->xwayland_ready.notify = handle_xwayland_ready; | ||
87 | 89 | ||
88 | // TODO: configurable cursor theme and size | 90 | // TODO: configurable cursor theme and size |
89 | server->xcursor_manager = wlr_xcursor_manager_create(NULL, 24); | 91 | server->xwayland.xcursor_manager = wlr_xcursor_manager_create(NULL, 24); |
90 | wlr_xcursor_manager_load(server->xcursor_manager, 1); | 92 | wlr_xcursor_manager_load(server->xwayland.xcursor_manager, 1); |
91 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( | 93 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( |
92 | server->xcursor_manager, "left_ptr", 1); | 94 | server->xwayland.xcursor_manager, "left_ptr", 1); |
93 | if (xcursor != NULL) { | 95 | if (xcursor != NULL) { |
94 | struct wlr_xcursor_image *image = xcursor->images[0]; | 96 | struct wlr_xcursor_image *image = xcursor->images[0]; |
95 | wlr_xwayland_set_cursor(server->xwayland, image->buffer, | 97 | wlr_xwayland_set_cursor(server->xwayland.wlr_xwayland, image->buffer, |
96 | image->width * 4, image->width, image->height, image->hotspot_x, | 98 | image->width * 4, image->width, image->height, image->hotspot_x, |
97 | image->hotspot_y); | 99 | image->hotspot_y); |
98 | } | 100 | } |