From 0c22ad09a7f4673b533c70f5a9a6bfcb523eba3a Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 2 Oct 2017 17:34:55 +0200 Subject: [PATCH 1/8] xwayland: request hints --- xwayland/xwm.c | 27 +++++++++++++++++++++++++++ xwayland/xwm.h | 3 +++ 2 files changed, 30 insertions(+) diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 39989672..7030442b 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -12,6 +12,9 @@ const char *atom_map[ATOM_LAST] = { "WL_SURFACE_ID", "WM_DELETE_WINDOW", "WM_PROTOCOLS", + "WM_NORMAL_HINTS", + "WM_SIZE_HINTS", + "_MOTIF_WM_HINTS", "UTF8_STRING", "WM_S0", "_NET_SUPPORTED", @@ -269,6 +272,24 @@ static void read_surface_protocols(struct wlr_xwm *xwm, wlr_log(L_DEBUG, "WM_PROTOCOLS (%zu)", atoms_len); } +static void read_surface_normal_hints(struct wlr_xwm *xwm, + struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { + if (reply->type != xwm->atoms[WM_SIZE_HINTS]) { + return; + } + + // TODO: xcb_icccm_get_wm_size_hints_from_reply + // See https://github.com/i3/i3/blob/55bc6741796e8b179b6111a721a3e9631934bb86/src/handlers.c#L994 + + wlr_log(L_DEBUG, "WM_NORMAL_HINTS (%d)", reply->value_len); +} + +static void read_surface_motif_hints(struct wlr_xwm *xwm, + struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { + // TODO + wlr_log(L_DEBUG, "MOTIF_WM_HINTS (%d)", reply->value_len); +} + static void read_surface_property(struct wlr_xwm *xwm, struct wlr_xwayland_surface *surface, xcb_atom_t property) { xcb_get_property_cookie_t cookie = xcb_get_property(xwm->xcb_conn, 0, @@ -294,6 +315,10 @@ static void read_surface_property(struct wlr_xwm *xwm, read_surface_protocols(xwm, surface, reply); } else if (property == xwm->atoms[NET_WM_STATE]) { read_surface_state(xwm, surface, reply); + } else if (property == xwm->atoms[WM_NORMAL_HINTS]) { + read_surface_normal_hints(xwm, surface, reply); + } else if (property == xwm->atoms[MOTIF_WM_HINTS]) { + read_surface_motif_hints(xwm, surface, reply); } else { wlr_log(L_DEBUG, "unhandled x11 property %u", property); } @@ -313,6 +338,8 @@ static void map_shell_surface(struct wlr_xwm *xwm, XCB_ATOM_WM_NAME, XCB_ATOM_WM_TRANSIENT_FOR, xwm->atoms[WM_PROTOCOLS], + xwm->atoms[WM_NORMAL_HINTS], + xwm->atoms[MOTIF_WM_HINTS], xwm->atoms[NET_WM_STATE], xwm->atoms[NET_WM_WINDOW_TYPE], xwm->atoms[NET_WM_NAME], diff --git a/xwayland/xwm.h b/xwayland/xwm.h index d1998e48..48504602 100644 --- a/xwayland/xwm.h +++ b/xwayland/xwm.h @@ -49,6 +49,9 @@ enum atom_name { WL_SURFACE_ID, WM_DELETE_WINDOW, WM_PROTOCOLS, + WM_NORMAL_HINTS, + WM_SIZE_HINTS, + MOTIF_WM_HINTS, UTF8_STRING, WM_S0, NET_SUPPORTED, From ef5914bdb61e788cf3b62378c4e7a14d8bf0430f Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Oct 2017 11:47:58 +0200 Subject: [PATCH 2/8] xwayland: add wlr_xwayland_surface->motif_hints --- include/wlr/xwayland.h | 2 ++ xwayland/xwm.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 3525ff3b..dc9798b2 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -53,6 +53,8 @@ struct wlr_xwayland_surface { xcb_atom_t *protocols; size_t protocols_len; + uint32_t motif_hints[5]; + struct { struct wl_signal destroy; diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 7030442b..f97f0a8e 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -286,7 +286,13 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, static void read_surface_motif_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { - // TODO + if (reply->value_len < 5) { + return; + } + + uint32_t *motif_hints = xcb_get_property_value(reply); + memcpy(surface->motif_hints, motif_hints, sizeof(surface->motif_hints)); + wlr_log(L_DEBUG, "MOTIF_WM_HINTS (%d)", reply->value_len); } From ed9796ec683b64655c60b09f0c9969263f4394d6 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Oct 2017 12:32:12 +0200 Subject: [PATCH 3/8] xwayland: parse normal hints --- include/wlr/xwayland.h | 7 +++++++ meson.build | 5 +++++ xwayland/meson.build | 2 +- xwayland/xwm.c | 14 ++++++++++++-- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index dc9798b2..181259fa 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -6,6 +6,10 @@ #include #include +#ifdef HAS_XCB_ICCCM + #include +#endif + struct wlr_xwm; struct wlr_xwayland { @@ -54,6 +58,9 @@ struct wlr_xwayland_surface { size_t protocols_len; uint32_t motif_hints[5]; + #ifdef HAS_XCB_ICCCM + xcb_size_hints_t size_hints; + #endif struct { struct wl_signal destroy; diff --git a/meson.build b/meson.build index 520eceb9..57c26b0f 100644 --- a/meson.build +++ b/meson.build @@ -45,12 +45,17 @@ udev = dependency('libudev') pixman = dependency('pixman-1') xcb = dependency('xcb') xcb_composite = dependency('xcb-composite') +xcb_icccm = dependency('xcb-icccm', required: false) x11_xcb = dependency('x11-xcb') libcap = dependency('libcap', required: false) systemd = dependency('libsystemd', required: false) elogind = dependency('libelogind', required: false) math = cc.find_library('m', required: false) +if xcb_icccm.found() + add_project_arguments('-DHAS_XCB_ICCCM', language: 'c') +endif + if libcap.found() and get_option('enable_libcap') add_project_arguments('-DHAS_LIBCAP', language: 'c') endif diff --git a/xwayland/meson.build b/xwayland/meson.build index 9797a1a1..d989f6dd 100644 --- a/xwayland/meson.build +++ b/xwayland/meson.build @@ -6,5 +6,5 @@ lib_wlr_xwayland = static_library( 'xwm.c', ), include_directories: wlr_inc, - dependencies: [wayland_server, xcb, xcb_composite, pixman], + dependencies: [wayland_server, xcb, xcb_composite, xcb_icccm, pixman], ) diff --git a/xwayland/xwm.c b/xwayland/xwm.c index f97f0a8e..afd4ef29 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -8,6 +8,10 @@ #include "wlr/xwayland.h" #include "xwm.h" +#ifdef HAS_XCB_ICCCM + #include +#endif + const char *atom_map[ATOM_LAST] = { "WL_SURFACE_ID", "WM_DELETE_WINDOW", @@ -272,17 +276,23 @@ static void read_surface_protocols(struct wlr_xwm *xwm, wlr_log(L_DEBUG, "WM_PROTOCOLS (%zu)", atoms_len); } +#ifdef HAS_XCB_ICCCM static void read_surface_normal_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { if (reply->type != xwm->atoms[WM_SIZE_HINTS]) { return; } - // TODO: xcb_icccm_get_wm_size_hints_from_reply - // See https://github.com/i3/i3/blob/55bc6741796e8b179b6111a721a3e9631934bb86/src/handlers.c#L994 + xcb_icccm_get_wm_size_hints_from_reply(&surface->size_hints, reply); wlr_log(L_DEBUG, "WM_NORMAL_HINTS (%d)", reply->value_len); } +#else +static void read_surface_normal_hints(struct wlr_xwm *xwm, + struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { + // Do nothing +} +#endif static void read_surface_motif_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { From ca68ef37f056562206b0c4b0442cbfedc8a5e5f3 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Oct 2017 15:42:16 +0200 Subject: [PATCH 4/8] Add padding if xcb_icccm is not available --- include/wlr/xwayland.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 181259fa..3cbaee59 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -60,6 +60,8 @@ struct wlr_xwayland_surface { uint32_t motif_hints[5]; #ifdef HAS_XCB_ICCCM xcb_size_hints_t size_hints; + #else + char size_hints_padding[72]; #endif struct { From 267f24753f010e6ac7e49f7bfb27a9c85f40b62d Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Oct 2017 16:24:45 +0200 Subject: [PATCH 5/8] Add support for WM_HINTS --- include/wlr/xwayland.h | 2 ++ xwayland/xwm.c | 26 +++++++++++++++++++++++++- xwayland/xwm.h | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 3cbaee59..73df1ea9 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -59,8 +59,10 @@ struct wlr_xwayland_surface { uint32_t motif_hints[5]; #ifdef HAS_XCB_ICCCM + xcb_icccm_wm_hints_t hints; xcb_size_hints_t size_hints; #else + char hints_padding[36]; char size_hints_padding[72]; #endif diff --git a/xwayland/xwm.c b/xwayland/xwm.c index afd4ef29..bc930140 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -15,6 +15,7 @@ const char *atom_map[ATOM_LAST] = { "WL_SURFACE_ID", "WM_DELETE_WINDOW", + "WM_HINTS", "WM_PROTOCOLS", "WM_NORMAL_HINTS", "WM_SIZE_HINTS", @@ -276,10 +277,30 @@ static void read_surface_protocols(struct wlr_xwm *xwm, wlr_log(L_DEBUG, "WM_PROTOCOLS (%zu)", atoms_len); } +#ifdef HAS_XCB_ICCCM +static void read_surface_hints(struct wlr_xwm *xwm, + struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { + // According to the docs, reply->type == xwm->atoms[WM_HINTS] + // In practice, reply->type == XCB_ATOM_ATOM + if (reply->value_len == 0) { + return; + } + + xcb_icccm_get_wm_hints_from_reply(&surface->hints, reply); + + wlr_log(L_DEBUG, "WM_HINTS (%d)", reply->value_len); +} +#else +static void read_surface_hints(struct wlr_xwm *xwm, + struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { + // Do nothing +} +#endif + #ifdef HAS_XCB_ICCCM static void read_surface_normal_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { - if (reply->type != xwm->atoms[WM_SIZE_HINTS]) { + if (reply->type != xwm->atoms[WM_SIZE_HINTS] || reply->value_len == 0) { return; } @@ -331,6 +352,8 @@ static void read_surface_property(struct wlr_xwm *xwm, read_surface_protocols(xwm, surface, reply); } else if (property == xwm->atoms[NET_WM_STATE]) { read_surface_state(xwm, surface, reply); + } else if (property == xwm->atoms[WM_HINTS]) { + read_surface_hints(xwm, surface, reply); } else if (property == xwm->atoms[WM_NORMAL_HINTS]) { read_surface_normal_hints(xwm, surface, reply); } else if (property == xwm->atoms[MOTIF_WM_HINTS]) { @@ -354,6 +377,7 @@ static void map_shell_surface(struct wlr_xwm *xwm, XCB_ATOM_WM_NAME, XCB_ATOM_WM_TRANSIENT_FOR, xwm->atoms[WM_PROTOCOLS], + xwm->atoms[WM_HINTS], xwm->atoms[WM_NORMAL_HINTS], xwm->atoms[MOTIF_WM_HINTS], xwm->atoms[NET_WM_STATE], diff --git a/xwayland/xwm.h b/xwayland/xwm.h index 48504602..be710a1b 100644 --- a/xwayland/xwm.h +++ b/xwayland/xwm.h @@ -49,6 +49,7 @@ enum atom_name { WL_SURFACE_ID, WM_DELETE_WINDOW, WM_PROTOCOLS, + WM_HINTS, WM_NORMAL_HINTS, WM_SIZE_HINTS, MOTIF_WM_HINTS, From fc61e827953479037bd3408a2ff14fa894bcfde1 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Oct 2017 16:32:05 +0200 Subject: [PATCH 6/8] Use pointers for xwayland hints and size_hints --- include/wlr/xwayland.h | 8 ++++---- xwayland/xwm.c | 22 +++++++++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 73df1ea9..05453c21 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -59,11 +59,11 @@ struct wlr_xwayland_surface { uint32_t motif_hints[5]; #ifdef HAS_XCB_ICCCM - xcb_icccm_wm_hints_t hints; - xcb_size_hints_t size_hints; + xcb_icccm_wm_hints_t *hints; + xcb_size_hints_t *size_hints; #else - char hints_padding[36]; - char size_hints_padding[72]; + void *hints; + void *size_hints; #endif struct { diff --git a/xwayland/xwm.c b/xwayland/xwm.c index bc930140..2ac24260 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -89,12 +89,14 @@ static void wlr_xwayland_surface_destroy(struct wlr_xwayland_surface *surface) { for (size_t i = 0; i < surface->state->length; i++) { free(surface->state->items[i]); } + free(surface->title); + free(surface->class); + free(surface->instance); list_free(surface->state); free(surface->window_type); free(surface->protocols); - free(surface->class); - free(surface->instance); - free(surface->title); + free(surface->hints); + free(surface->size_hints); free(surface); } @@ -286,7 +288,12 @@ static void read_surface_hints(struct wlr_xwm *xwm, return; } - xcb_icccm_get_wm_hints_from_reply(&surface->hints, reply); + free(surface->hints); + surface->hints = calloc(1, sizeof(xcb_icccm_wm_hints_t)); + if (surface->hints == NULL) { + return; + } + xcb_icccm_get_wm_hints_from_reply(surface->hints, reply); wlr_log(L_DEBUG, "WM_HINTS (%d)", reply->value_len); } @@ -304,7 +311,12 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, return; } - xcb_icccm_get_wm_size_hints_from_reply(&surface->size_hints, reply); + free(surface->size_hints); + surface->size_hints = calloc(1, sizeof(xcb_size_hints_t)); + if (surface->size_hints == NULL) { + return; + } + xcb_icccm_get_wm_size_hints_from_reply(surface->size_hints, reply); wlr_log(L_DEBUG, "WM_NORMAL_HINTS (%d)", reply->value_len); } From 454a6a902b7e78576fa77e77395cbd26901b18e2 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Oct 2017 16:49:47 +0200 Subject: [PATCH 7/8] Parse _MOTIF_HINTS --- include/wlr/xwayland.h | 9 ++++++++- xwayland/xwm.c | 25 ++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 05453c21..1f2d7acb 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -33,6 +33,12 @@ struct wlr_xwayland { void *data; }; +enum wlr_xwayland_surface_decorations { + WLR_XWAYLAND_SURFACE_DECORATIONS_ALL = 0, + WLR_XWAYLAND_SURFACE_DECORATIONS_NO_BORDER = 1, + WLR_XWAYLAND_SURFACE_DECORATIONS_NO_TITLE = 2, +}; + struct wlr_xwayland_surface { xcb_window_t window_id; uint32_t surface_id; @@ -57,7 +63,8 @@ struct wlr_xwayland_surface { xcb_atom_t *protocols; size_t protocols_len; - uint32_t motif_hints[5]; + uint32_t decorations; + #ifdef HAS_XCB_ICCCM xcb_icccm_wm_hints_t *hints; xcb_size_hints_t *size_hints; diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 2ac24260..120c1ae8 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -327,6 +327,16 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, } #endif + +#define MWM_HINTS_FLAGS_FIELD 0 +#define MWM_HINTS_DECORATIONS_FIELD 2 + +#define MWM_HINTS_DECORATIONS (1 << 1) + +#define MWM_DECOR_ALL (1 << 0) +#define MWM_DECOR_BORDER (1 << 1) +#define MWM_DECOR_TITLE (1 << 3) + static void read_surface_motif_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *surface, xcb_get_property_reply_t *reply) { if (reply->value_len < 5) { @@ -334,7 +344,20 @@ static void read_surface_motif_hints(struct wlr_xwm *xwm, } uint32_t *motif_hints = xcb_get_property_value(reply); - memcpy(surface->motif_hints, motif_hints, sizeof(surface->motif_hints)); + if (motif_hints[MWM_HINTS_FLAGS_FIELD] & MWM_HINTS_DECORATIONS) { + surface->decorations = WLR_XWAYLAND_SURFACE_DECORATIONS_ALL; + uint32_t decorations = motif_hints[MWM_HINTS_DECORATIONS_FIELD]; + if ((decorations & MWM_DECOR_ALL) == 0) { + if ((decorations & MWM_DECOR_BORDER) == 0) { + surface->decorations |= + WLR_XWAYLAND_SURFACE_DECORATIONS_NO_BORDER; + } + if ((decorations & MWM_DECOR_TITLE) == 0) { + surface->decorations |= + WLR_XWAYLAND_SURFACE_DECORATIONS_NO_TITLE; + } + } + } wlr_log(L_DEBUG, "MOTIF_WM_HINTS (%d)", reply->value_len); } From 12b9b1a4bdf00742cc510c2329c7a66c649b3ab0 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Oct 2017 22:23:37 +0200 Subject: [PATCH 8/8] Copy xcb_icccm structs into wlroots --- include/wlr/xwayland.h | 35 +++++++++++++++++++++++++++-------- xwayland/xwm.c | 17 +++++++++++++---- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 1f2d7acb..09f9fbac 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -39,6 +39,30 @@ enum wlr_xwayland_surface_decorations { WLR_XWAYLAND_SURFACE_DECORATIONS_NO_TITLE = 2, }; +struct wlr_xwayland_surface_hints { + uint32_t flags; + uint32_t input; + int32_t initial_state; + xcb_pixmap_t icon_pixmap; + xcb_window_t icon_window; + int32_t icon_x, icon_y; + xcb_pixmap_t icon_mask; + xcb_window_t window_group; +}; + +struct wlr_xwayland_surface_size_hints { + uint32_t flags; + int32_t x, y; + int32_t width, height; + int32_t min_width, min_height; + int32_t max_width, max_height; + int32_t width_inc, height_inc; + int32_t base_width, base_height; + int32_t min_aspect_num, min_aspect_den; + int32_t max_aspect_num, max_aspect_den; + uint32_t win_gravity; +}; + struct wlr_xwayland_surface { xcb_window_t window_id; uint32_t surface_id; @@ -64,14 +88,9 @@ struct wlr_xwayland_surface { size_t protocols_len; uint32_t decorations; - - #ifdef HAS_XCB_ICCCM - xcb_icccm_wm_hints_t *hints; - xcb_size_hints_t *size_hints; - #else - void *hints; - void *size_hints; - #endif + struct wlr_xwayland_surface_hints *hints; + uint32_t hints_urgency; + struct wlr_xwayland_surface_size_hints *size_hints; struct { struct wl_signal destroy; diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 120c1ae8..a4091d1f 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -288,12 +288,16 @@ static void read_surface_hints(struct wlr_xwm *xwm, return; } + xcb_icccm_wm_hints_t hints; + xcb_icccm_get_wm_hints_from_reply(&hints, reply); + free(surface->hints); - surface->hints = calloc(1, sizeof(xcb_icccm_wm_hints_t)); + surface->hints = calloc(1, sizeof(struct wlr_xwayland_surface_hints)); if (surface->hints == NULL) { return; } - xcb_icccm_get_wm_hints_from_reply(surface->hints, reply); + memcpy(surface->hints, &hints, sizeof(struct wlr_xwayland_surface_hints)); + surface->hints_urgency = xcb_icccm_wm_hints_get_urgency(&hints); wlr_log(L_DEBUG, "WM_HINTS (%d)", reply->value_len); } @@ -311,12 +315,17 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, return; } + xcb_size_hints_t size_hints; + xcb_icccm_get_wm_size_hints_from_reply(&size_hints, reply); + free(surface->size_hints); - surface->size_hints = calloc(1, sizeof(xcb_size_hints_t)); + surface->size_hints = + calloc(1, sizeof(struct wlr_xwayland_surface_size_hints)); if (surface->size_hints == NULL) { return; } - xcb_icccm_get_wm_size_hints_from_reply(surface->size_hints, reply); + memcpy(surface->size_hints, &size_hints, + sizeof(struct wlr_xwayland_surface_size_hints)); wlr_log(L_DEBUG, "WM_NORMAL_HINTS (%d)", reply->value_len); }