[PATCH weston 14/16] xwayland: Fix opaque and input region settings

Tiago Vignatti tiago.vignatti at intel.com
Wed Dec 12 07:26:26 PST 2012


This patch brings back a feature we removed previously (#1 opaque region box)

Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
---
 clients/xwm.c                 |   57 ++++++++++++++++++--------------------
 protocol/xserver.xml          |   26 ++++++++++++++++++
 src/xwayland/window-manager.c |   61 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 31 deletions(-)

diff --git a/clients/xwm.c b/clients/xwm.c
index e4862b1..a6501e2 100644
--- a/clients/xwm.c
+++ b/clients/xwm.c
@@ -39,6 +39,7 @@
 struct xwm {
 	struct wl_registry *registry;
 	struct wl_display *wl_display;
+	struct wl_compositor *compositor;
 	struct wm *wm;
 	struct display *display;
 
@@ -759,16 +760,14 @@ xwm_window_draw_decoration(struct xwm_window *window)
 	int x, y, width, height;
 	const char *title;
 	uint32_t flags = 0;
+	struct wl_region *region;
 
 	if (window->frame_id == XCB_WINDOW_NONE) {
-#if 0
-		if (window->surface != NULL) {
-			window->surface->opaque_rect[0] = 0.0;
-			window->surface->opaque_rect[1] = 1.0;
-			window->surface->opaque_rect[2] = 0.0;
-			window->surface->opaque_rect[3] = 1.0;
-		}
-#endif
+		xwm_window_get_frame_size(window, &width, &height);
+		region = wl_compositor_create_region(wm->xwm->compositor);
+		wl_region_add(region, 0, 0, width, height);
+		wm_set_opaque_override(wm->xwm->wm, window->id, region);
+		wl_region_destroy(region);
 		return;
 	}
 
@@ -802,28 +801,21 @@ xwm_window_draw_decoration(struct xwm_window *window)
 	xcb_flush(window->wm->conn);
 
 	cairo_destroy(cr);
-#if 0
-	if (window->surface) {
-		pixman_region32_fini(&window->surface->pending.opaque);
-		pixman_region32_init_rect(&window->surface->pending.opaque, 0, 0,
-					  width, height);
-
-		/* 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_intersect_rect(&window->surface->pending.opaque,
-					       &window->surface->pending.opaque,
-					       x - 1, y - 1,
-					       window->width + 2,
-					       window->height + 2);
-		window->surface->geometry.dirty = 1;
-
-		pixman_region32_init_rect(&window->surface->input,
-					  t->margin, t->margin,
-					  width - 2 * t->margin,
-					  height - 2 * t->margin);
-	}
-#endif
+
+	region = wl_compositor_create_region(wm->xwm->compositor);
+
+	/* We leave an extra pixel around the X window area to make sure we
+	 * don't sample from the undefined alpha channel when filtering. */
+	wl_region_add(region, x - 1, y - 1,
+		      window->width + 2, window->height + 2);
+	wm_set_opaque_override(wm->xwm->wm, window->frame_id, region);
+	wl_region_destroy(region);
+
+	region = wl_compositor_create_region(wm->xwm->compositor);
+	wl_region_add(region, t->margin, t->margin,
+		      width - 2 * t->margin, height - 2 * t->margin);
+	wm_set_input_region(wm->xwm->wm, window->frame_id, region);
+	wl_region_destroy(region);
 }
 
 static void
@@ -1591,7 +1583,10 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
 {
 	struct xwm *xwm = data;
 
-	if (!strcmp(interface, "wm")) {
+        if (strcmp(interface, "wl_compositor") == 0) {
+		xwm->compositor = wl_registry_bind(registry, id,
+					&wl_compositor_interface, 1);
+	} else if (!strcmp(interface, "wm")) {
 		xwm->wm = wl_registry_bind(registry, id,
 					&wm_interface, 1);
 		wm_add_listener(xwm->wm, &wm_listener, xwm);
diff --git a/protocol/xserver.xml b/protocol/xserver.xml
index e4fc359..86cf162 100644
--- a/protocol/xserver.xml
+++ b/protocol/xserver.xml
@@ -97,6 +97,32 @@
       <arg name="flags" type="uint"/>
     </request>
 
+    <request name="set_opaque_override">
+      <description summary="set opaque override region">
+	Textures coming from X windows usually have their X window as RGBx,
+	i.e. 32 bit with an undefined alpha channel for the content part while
+	the decorations are rendered with a well-defined alpha channel. On
+	this case set_opaque_override is needed for marking a rectangle in a
+	texture and force the alpha = 1.0.
+
+	This is different from the wl_surface.set_opaque_region, where that
+	one is meant only as a hint for optimization while this is a necessity
+	for painting XWayland windows right. Therefore X must never use
+	wl_surface.set_opaque_region either.
+      </description>
+
+      <arg name="id" type="uint"/>
+      <arg name="region" type="object" interface="wl_region"/>
+    </request>
+
+    <request name="set_input_region">
+      <description summary="set window id input region">
+      </description>
+
+      <arg name="id" type="uint"/>
+      <arg name="region" type="object" interface="wl_region" allow-null="true"/>
+    </request>
+
     <request name="move">
       <arg name="id" type="uint"/>
     </request>
diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c
index 6d6ea8f..a57e6ea 100644
--- a/src/xwayland/window-manager.c
+++ b/src/xwayland/window-manager.c
@@ -134,6 +134,7 @@ wm_get_window(struct wl_client *client, struct wl_resource *resource,
 			return;
 		}
 		hash_table_insert(wxs->window_hash, id, w);
+		w->surface = NULL;
 		w->shsurf = NULL;
 		w->wxs = wxs;
 		w->id = id;
@@ -147,6 +148,64 @@ wm_get_window(struct wl_client *client, struct wl_resource *resource,
 }
 
 static void
+wm_get_opaque_override(struct wl_client *client, struct wl_resource *resource,
+		       uint32_t id, struct wl_resource *region_resource)
+{
+	struct weston_xserver *wxs = resource->data;
+	struct weston_region *region;
+	struct xserver_window *window;
+	struct weston_surface *surface;
+
+	if (!region_resource) {
+		weston_log("Region resource not provided\n");
+		return;
+	}
+	region = region_resource->data;
+
+	window = hash_table_lookup(wxs->window_hash, id);
+	if (!window) {
+		weston_log("Failed to lookup window %d\n", id);
+		return;
+	}
+
+	surface = (struct weston_surface *) window->surface;
+	if (!surface)
+		return;
+
+	pixman_region32_copy(&surface->pending.opaque, &region->region);
+	surface->geometry.dirty = 1;
+}
+
+static void
+wm_get_input_region(struct wl_client *client, struct wl_resource *resource,
+		    uint32_t id, struct wl_resource *region_resource)
+{
+	struct weston_xserver *wxs = resource->data;
+	struct weston_region *region;
+	struct xserver_window *window;
+	struct weston_surface *surface;
+
+	if (!region_resource) {
+		weston_log("Region resource not provided\n");
+		return;
+	}
+	region = region_resource->data;
+
+	window = hash_table_lookup(wxs->window_hash, id);
+	if (!window) {
+		weston_log("Failed to lookup window %d\n", id);
+		return;
+	}
+
+	surface = (struct weston_surface *) window->surface;
+	if (!surface)
+		return;
+
+	pixman_region32_copy(&surface->pending.input, &region->region);
+	surface->geometry.dirty = 1;
+}
+
+static void
 weston_wm_activate_client(struct wl_listener *listener, void *data)
 {
 	struct weston_surface *surface = data;
@@ -288,6 +347,8 @@ const struct wm_interface wm_implementation = {
 	wm_get_ready,
 	wm_get_map,
 	wm_get_window,
+	wm_get_opaque_override,
+	wm_get_input_region,
 	wm_get_move,
 	wm_get_resize
 };
-- 
1.7.9.5



More information about the wayland-devel mailing list