diff options
Diffstat (limited to 'xwayland')
-rw-r--r-- | xwayland/meson.build | 2 | ||||
-rw-r--r-- | xwayland/xwayland.c | 4 | ||||
-rw-r--r-- | xwayland/xwm.c | 115 | ||||
-rw-r--r-- | xwayland/xwm.h | 4 |
4 files changed, 124 insertions, 1 deletions
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/xwayland.c b/xwayland/xwayland.c index d3bb41a0..2bec1b63 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -215,6 +215,10 @@ static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland, wlr_xwayland_finish(wlr_xwayland); return false; } + + // unset $DISPLAY while XWayland starts + unsetenv("DISPLAY"); + wlr_xwayland->wl_fd[0] = -1; /* not ours anymore */ wlr_xwayland->destroy_listener.notify = xwayland_destroy_event; diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 2038ff0f..a4091d1f 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -8,10 +8,18 @@ #include "wlr/xwayland.h" #include "xwm.h" +#ifdef HAS_XCB_ICCCM + #include <xcb/xcb_icccm.h> +#endif + const char *atom_map[ATOM_LAST] = { "WL_SURFACE_ID", "WM_DELETE_WINDOW", + "WM_HINTS", "WM_PROTOCOLS", + "WM_NORMAL_HINTS", + "WM_SIZE_HINTS", + "_MOTIF_WM_HINTS", "UTF8_STRING", "WM_S0", "_NET_SUPPORTED", @@ -81,8 +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->hints); + free(surface->size_hints); free(surface); } @@ -265,6 +279,98 @@ 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_wm_hints_t hints; + xcb_icccm_get_wm_hints_from_reply(&hints, reply); + + free(surface->hints); + surface->hints = calloc(1, sizeof(struct wlr_xwayland_surface_hints)); + if (surface->hints == NULL) { + return; + } + 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); +} +#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] || reply->value_len == 0) { + 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(struct wlr_xwayland_surface_size_hints)); + if (surface->size_hints == NULL) { + return; + } + memcpy(surface->size_hints, &size_hints, + sizeof(struct wlr_xwayland_surface_size_hints)); + + 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 + + +#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) { + return; + } + + uint32_t *motif_hints = xcb_get_property_value(reply); + 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); +} + 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, @@ -290,6 +396,12 @@ 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]) { + read_surface_motif_hints(xwm, surface, reply); } else { wlr_log(L_DEBUG, "unhandled x11 property %u", property); } @@ -309,6 +421,9 @@ 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], xwm->atoms[NET_WM_WINDOW_TYPE], xwm->atoms[NET_WM_NAME], diff --git a/xwayland/xwm.h b/xwayland/xwm.h index d1998e48..be710a1b 100644 --- a/xwayland/xwm.h +++ b/xwayland/xwm.h @@ -49,6 +49,10 @@ enum atom_name { WL_SURFACE_ID, WM_DELETE_WINDOW, WM_PROTOCOLS, + WM_HINTS, + WM_NORMAL_HINTS, + WM_SIZE_HINTS, + MOTIF_WM_HINTS, UTF8_STRING, WM_S0, NET_SUPPORTED, |