diff options
| author | Drew DeVault <sir@cmpwn.com> | 2017-10-05 16:27:30 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-10-05 16:27:30 -0400 | 
| commit | b2d478a4189ffd96dc6158003f5cde76b70bd368 (patch) | |
| tree | 996db63c86039c143c9eafd8666f46c3eb85e72f | |
| parent | 7d57c1463da61ff16784e6b756356720a0af185c (diff) | |
| parent | 12b9b1a4bdf00742cc510c2329c7a66c649b3ab0 (diff) | |
| download | wlroots-b2d478a4189ffd96dc6158003f5cde76b70bd368.tar.xz | |
Merge pull request #189 from emersion/xwayland-hints
xwayland: add support for window hints
| -rw-r--r-- | include/wlr/xwayland.h | 39 | ||||
| -rw-r--r-- | meson.build | 5 | ||||
| -rw-r--r-- | xwayland/meson.build | 2 | ||||
| -rw-r--r-- | xwayland/xwm.c | 117 | ||||
| -rw-r--r-- | xwayland/xwm.h | 4 | 
5 files changed, 163 insertions, 4 deletions
| diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 3525ff3b..09f9fbac 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -6,6 +6,10 @@  #include <wlr/types/wlr_compositor.h>  #include <xcb/xcb.h> +#ifdef HAS_XCB_ICCCM +	#include <xcb/xcb_icccm.h> +#endif +  struct wlr_xwm;  struct wlr_xwayland { @@ -29,6 +33,36 @@ 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_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; @@ -53,6 +87,11 @@ struct wlr_xwayland_surface {  	xcb_atom_t *protocols;  	size_t protocols_len; +	uint32_t decorations; +	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/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 39989672..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,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);  } @@ -269,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, @@ -294,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);  	} @@ -313,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, | 
