diff options
-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/desktop/xwayland.c | 83 | ||||
-rw-r--r-- | sway/input/seat.c | 3 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/server.c | 18 |
7 files changed, 116 insertions, 26 deletions
diff --git a/include/sway/server.h b/include/sway/server.h index 65d96e7a..96cad69d 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -11,7 +11,7 @@ | |||
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> | 14 | #include "sway/xwayland.h" |
15 | 15 | ||
16 | struct sway_server { | 16 | struct sway_server { |
17 | struct wl_display *wl_display; | 17 | struct wl_display *wl_display; |
@@ -37,12 +37,9 @@ struct sway_server { | |||
37 | struct wlr_xdg_shell *xdg_shell; | 37 | struct wlr_xdg_shell *xdg_shell; |
38 | struct wl_listener xdg_shell_surface; | 38 | struct wl_listener xdg_shell_surface; |
39 | 39 | ||
40 | struct wlr_xwayland *xwayland; | 40 | struct sway_xwayland xwayland; |
41 | struct wlr_xcursor_manager *xcursor_manager; | ||
42 | struct wl_listener xwayland_surface; | 41 | struct wl_listener xwayland_surface; |
43 | 42 | struct wl_listener xwayland_ready; | |
44 | struct wlr_wl_shell *wl_shell; | ||
45 | struct wl_listener wl_shell_surface; | ||
46 | }; | 43 | }; |
47 | 44 | ||
48 | struct sway_server server; | 45 | struct sway_server server; |
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/desktop/xwayland.c b/sway/desktop/xwayland.c index 6447b711..2c3848cd 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -15,6 +15,14 @@ | |||
15 | #include "sway/tree/layout.h" | 15 | #include "sway/tree/layout.h" |
16 | #include "sway/tree/view.h" | 16 | #include "sway/tree/view.h" |
17 | 17 | ||
18 | static const char *atom_map[ATOM_LAST] = { | ||
19 | "_NET_WM_WINDOW_TYPE_DIALOG", | ||
20 | "_NET_WM_WINDOW_TYPE_UTILITY", | ||
21 | "_NET_WM_WINDOW_TYPE_TOOLBAR", | ||
22 | "_NET_WM_WINDOW_TYPE_SPLASH", | ||
23 | "_NET_WM_STATE_MODAL", | ||
24 | }; | ||
25 | |||
18 | static void unmanaged_handle_request_configure(struct wl_listener *listener, | 26 | static void unmanaged_handle_request_configure(struct wl_listener *listener, |
19 | void *data) { | 27 | void *data) { |
20 | struct sway_xwayland_unmanaged *surface = | 28 | struct sway_xwayland_unmanaged *surface = |
@@ -61,7 +69,8 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) { | |||
61 | 69 | ||
62 | if (!wlr_xwayland_surface_is_unmanaged(xsurface)) { | 70 | if (!wlr_xwayland_surface_is_unmanaged(xsurface)) { |
63 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 71 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
64 | struct wlr_xwayland *xwayland = seat->input->server->xwayland; | 72 | struct wlr_xwayland *xwayland = |
73 | seat->input->server->xwayland.wlr_xwayland; | ||
65 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); | 74 | wlr_xwayland_set_seat(xwayland, seat->wlr_seat); |
66 | seat_set_focus_surface(seat, xsurface->surface); | 75 | seat_set_focus_surface(seat, xsurface->surface); |
67 | } | 76 | } |
@@ -199,15 +208,32 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { | |||
199 | } | 208 | } |
200 | 209 | ||
201 | static bool wants_floating(struct sway_view *view) { | 210 | static bool wants_floating(struct sway_view *view) { |
202 | // TODO: | 211 | if (xwayland_view_from_view(view) == NULL) { |
203 | // We want to return true if the window type contains any of these: | 212 | return false; |
204 | // NET_WM_WINDOW_TYPE_DIALOG | 213 | } |
205 | // NET_WM_WINDOW_TYPE_UTILITY | 214 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; |
206 | // NET_WM_WINDOW_TYPE_TOOLBAR | 215 | struct sway_xwayland *xwayland = &server.xwayland; |
207 | // NET_WM_WINDOW_TYPE_SPLASH | 216 | |
208 | // | 217 | // TODO: return true if the NET_WM_STATE is MODAL |
209 | // We also want to return true if the NET_WM_STATE is MODAL. | 218 | |
210 | // wlroots doesn't appear to provide all this information at the moment. | 219 | for (size_t i = 0; i < surface->window_type_len; ++i) { |
220 | xcb_atom_t type = surface->window_type[i]; | ||
221 | if (type == xwayland->atoms[NET_WM_WINDOW_TYPE_DIALOG] || | ||
222 | type == xwayland->atoms[NET_WM_WINDOW_TYPE_UTILITY] || | ||
223 | type == xwayland->atoms[NET_WM_WINDOW_TYPE_TOOLBAR] || | ||
224 | type == xwayland->atoms[NET_WM_WINDOW_TYPE_SPLASH]) { | ||
225 | return true; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | struct wlr_xwayland_surface_size_hints *size_hints = surface->size_hints; | ||
230 | if (size_hints != NULL && | ||
231 | size_hints->min_width != 0 && size_hints->min_height != 0 && | ||
232 | size_hints->max_width == size_hints->min_width && | ||
233 | size_hints->max_height == size_hints->min_height) { | ||
234 | return true; | ||
235 | } | ||
236 | |||
211 | return false; | 237 | return false; |
212 | } | 238 | } |
213 | 239 | ||
@@ -411,3 +437,40 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
411 | wl_signal_add(&xsurface->events.map, &xwayland_view->map); | 437 | wl_signal_add(&xsurface->events.map, &xwayland_view->map); |
412 | xwayland_view->map.notify = handle_map; | 438 | xwayland_view->map.notify = handle_map; |
413 | } | 439 | } |
440 | |||
441 | void handle_xwayland_ready(struct wl_listener *listener, void *data) { | ||
442 | struct sway_server *server = | ||
443 | wl_container_of(listener, server, xwayland_ready); | ||
444 | struct sway_xwayland *xwayland = &server->xwayland; | ||
445 | |||
446 | xcb_connection_t *xcb_conn = xcb_connect(NULL, NULL); | ||
447 | int err = xcb_connection_has_error(xcb_conn); | ||
448 | if (err) { | ||
449 | wlr_log(L_ERROR, "XCB connect failed: %d", err); | ||
450 | return; | ||
451 | } | ||
452 | |||
453 | xcb_intern_atom_cookie_t cookies[ATOM_LAST]; | ||
454 | for (size_t i = 0; i < ATOM_LAST; i++) { | ||
455 | cookies[i] = | ||
456 | xcb_intern_atom(xcb_conn, 0, strlen(atom_map[i]), atom_map[i]); | ||
457 | } | ||
458 | for (size_t i = 0; i < ATOM_LAST; i++) { | ||
459 | xcb_generic_error_t *error = NULL; | ||
460 | xcb_intern_atom_reply_t *reply = | ||
461 | xcb_intern_atom_reply(xcb_conn, cookies[i], &error); | ||
462 | if (reply != NULL && error == NULL) { | ||
463 | xwayland->atoms[i] = reply->atom; | ||
464 | } | ||
465 | free(reply); | ||
466 | |||
467 | if (error != NULL) { | ||
468 | wlr_log(L_ERROR, "could not resolve atom %s, X11 error code %d", | ||
469 | atom_map[i], error->error_code); | ||
470 | free(error); | ||
471 | break; | ||
472 | } | ||
473 | } | ||
474 | |||
475 | xcb_disconnect(xcb_conn); | ||
476 | } | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c index 1ea36466..1c2434b0 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 0da67ed7..2cf90b11 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -152,6 +152,7 @@ sway_deps = [ | |||
152 | server_protos, | 152 | server_protos, |
153 | wayland_server, | 153 | wayland_server, |
154 | wlroots, | 154 | wlroots, |
155 | xcb, | ||
155 | xkbcommon, | 156 | xkbcommon, |
156 | ] | 157 | ] |
157 | 158 | ||
diff --git a/sway/server.c b/sway/server.c index 824b1d8e..878b530d 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -18,12 +18,11 @@ | |||
18 | #include <wlr/types/wlr_xdg_output.h> | 18 | #include <wlr/types/wlr_xdg_output.h> |
19 | #include <wlr/util/log.h> | 19 | #include <wlr/util/log.h> |
20 | // TODO WLR: make Xwayland optional | 20 | // TODO WLR: make Xwayland optional |
21 | #include <wlr/xwayland.h> | ||
22 | #include "sway/config.h" | 21 | #include "sway/config.h" |
23 | #include "sway/input/input-manager.h" | 22 | #include "sway/input/input-manager.h" |
24 | #include "sway/server.h" | 23 | #include "sway/server.h" |
25 | #include "sway/tree/layout.h" | 24 | #include "sway/tree/layout.h" |
26 | 25 | #include "sway/xwayland.h" | |
27 | 26 | ||
28 | bool server_init(struct sway_server *server) { | 27 | bool server_init(struct sway_server *server) { |
29 | wlr_log(L_DEBUG, "Initializing Wayland server"); | 28 | wlr_log(L_DEBUG, "Initializing Wayland server"); |
@@ -72,20 +71,23 @@ bool server_init(struct sway_server *server) { | |||
72 | server->xdg_shell_surface.notify = handle_xdg_shell_surface; | 71 | server->xdg_shell_surface.notify = handle_xdg_shell_surface; |
73 | 72 | ||
74 | // TODO make xwayland optional | 73 | // TODO make xwayland optional |
75 | server->xwayland = | 74 | server->xwayland.wlr_xwayland = |
76 | wlr_xwayland_create(server->wl_display, server->compositor, true); | 75 | wlr_xwayland_create(server->wl_display, server->compositor, true); |
77 | wl_signal_add(&server->xwayland->events.new_surface, | 76 | wl_signal_add(&server->xwayland.wlr_xwayland->events.new_surface, |
78 | &server->xwayland_surface); | 77 | &server->xwayland_surface); |
79 | server->xwayland_surface.notify = handle_xwayland_surface; | 78 | server->xwayland_surface.notify = handle_xwayland_surface; |
79 | wl_signal_add(&server->xwayland.wlr_xwayland->events.ready, | ||
80 | &server->xwayland_ready); | ||
81 | server->xwayland_ready.notify = handle_xwayland_ready; | ||
80 | 82 | ||
81 | // TODO: configurable cursor theme and size | 83 | // TODO: configurable cursor theme and size |
82 | server->xcursor_manager = wlr_xcursor_manager_create(NULL, 24); | 84 | server->xwayland.xcursor_manager = wlr_xcursor_manager_create(NULL, 24); |
83 | wlr_xcursor_manager_load(server->xcursor_manager, 1); | 85 | wlr_xcursor_manager_load(server->xwayland.xcursor_manager, 1); |
84 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( | 86 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( |
85 | server->xcursor_manager, "left_ptr", 1); | 87 | server->xwayland.xcursor_manager, "left_ptr", 1); |
86 | if (xcursor != NULL) { | 88 | if (xcursor != NULL) { |
87 | struct wlr_xcursor_image *image = xcursor->images[0]; | 89 | struct wlr_xcursor_image *image = xcursor->images[0]; |
88 | wlr_xwayland_set_cursor(server->xwayland, image->buffer, | 90 | wlr_xwayland_set_cursor(server->xwayland.wlr_xwayland, image->buffer, |
89 | image->width * 4, image->width, image->height, image->hotspot_x, | 91 | image->width * 4, image->width, image->height, image->hotspot_x, |
90 | image->hotspot_y); | 92 | image->hotspot_y); |
91 | } | 93 | } |