xwm: Use empty opaque region for windows with alpha
Window contents cannot be assumed to be fully opaque for windows drawn with
a RGBA visual. The optimization of setting a full opaque region is limited to
windows with a color depth != 32.
diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c
index ff2d4e6..e39ce0a 100644
--- a/src/xwayland/window-manager.c
+++ b/src/xwayland/window-manager.c
@@ -116,6 +116,7 @@
int decorate;
int override_redirect;
int fullscreen;
+ int has_alpha;
};
static struct weston_wm_window *
@@ -901,13 +902,17 @@
if (window->surface) {
pixman_region32_fini(&window->surface->pending.opaque);
- /* We leave an extra pixel around the X window area to
- * make sure we don't sample from the undefined alpha
- * channel when filtering. */
- pixman_region32_init_rect(&window->surface->pending.opaque,
- x - 1, y - 1,
- window->width + 2,
- window->height + 2);
+ if(window->has_alpha) {
+ pixman_region32_init(&window->surface->pending.opaque);
+ } else {
+ /* We leave an extra pixel around the X window area to
+ * make sure we don't sample from the undefined alpha
+ * channel when filtering. */
+ pixman_region32_init_rect(&window->surface->pending.opaque,
+ x - 1, y - 1,
+ window->width + 2,
+ window->height + 2);
+ }
weston_surface_geometry_dirty(window->surface);
}
@@ -930,8 +935,12 @@
if (window->surface != NULL) {
weston_wm_window_get_frame_size(window, &width, &height);
pixman_region32_fini(&window->surface->pending.opaque);
- pixman_region32_init_rect(&window->surface->pending.opaque, 0, 0,
- width, height);
+ if(window->has_alpha) {
+ pixman_region32_init(&window->surface->pending.opaque);
+ } else {
+ pixman_region32_init_rect(&window->surface->pending.opaque, 0, 0,
+ width, height);
+ }
weston_surface_geometry_dirty(window->surface);
}
return;
@@ -977,6 +986,8 @@
{
struct weston_wm_window *window;
uint32_t values[1];
+ xcb_get_geometry_cookie_t geometry_cookie;
+ xcb_get_geometry_reply_t *geometry_reply;
window = malloc(sizeof *window);
if (window == NULL) {
@@ -984,6 +995,8 @@
return;
}
+ geometry_cookie = xcb_get_geometry(wm->conn, id);
+
values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE;
xcb_change_window_attributes(wm->conn, id, XCB_CW_EVENT_MASK, values);
@@ -995,6 +1008,13 @@
window->width = width;
window->height = height;
+ geometry_reply = xcb_get_geometry_reply(wm->conn, geometry_cookie, NULL);
+ /* technically we should use XRender and check the visual format's
+ alpha_mask, but checking depth is simpler and works in all known cases */
+ if(geometry_reply != NULL)
+ window->has_alpha = geometry_reply->depth == 32;
+ free(geometry_reply);
+
hash_table_insert(wm->window_hash, id, window);
}