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

Tiago Vignatti tiago.vignatti at intel.com
Wed Dec 19 11:32:24 PST 2012


This patch brings back a feature we removed previously (#1 opaque region box)
and fix the input region settings, which was broken.

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

diff --git a/clients/xwm.c b/clients/xwm.c
index a4ab816..49e992b 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 wm_xwin *wm_xwin;
 	struct display *display;
@@ -793,20 +794,18 @@ xwm_window_draw_decoration(struct xwm_window *window)
 {
 	struct xwm_wm *wm = window->wm;
 	struct theme *t = wm->theme;
+	struct wl_region *region;
 	cairo_t *cr;
 	int x, y, width, height;
 	const char *title;
 	uint32_t flags = 0;
 
 	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_xwin_set_opaque_override(window->xwin, region);
+		wl_region_destroy(region);
 		return;
 	}
 
@@ -840,28 +839,20 @@ 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_xwin_set_opaque_override(window->xwin_frame, 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_xwin_set_input_region(window->xwin_frame, region);
+	wl_region_destroy(region);
 }
 
 static void
@@ -1594,7 +1585,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 a5dbebd..05f771f 100644
--- a/protocol/xserver.xml
+++ b/protocol/xserver.xml
@@ -129,6 +129,30 @@
       <arg name="height" type="int"/>
       <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="region" type="object" interface="wl_region"/>
+    </request>
+
+    <request name="set_input_region">
+      <description summary="set window input region">
+      </description>
+
+      <arg name="region" type="object" interface="wl_region" allow-null="true"/>
+    </request>
  
     <request name="move">
     </request>
diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c
index 7fb7379..00d6175 100644
--- a/src/xwayland/window-manager.c
+++ b/src/xwayland/window-manager.c
@@ -156,6 +156,52 @@ wm_xwin_handle_set_window(struct wl_client *client,
 }
 
 static void
+wm_xwin_handle_opaque_override(struct wl_client *client,
+			       struct wl_resource *resource,
+			       struct wl_resource *region_resource)
+{
+	struct xserver_window *window = resource->data;
+	struct weston_surface *surface =
+		(struct weston_surface *) window->surface;
+	struct weston_region *region;
+
+	if (!region_resource) {
+		weston_log("Region resource not provided\n");
+		return;
+	}
+	region = region_resource->data;
+
+	if (!surface)
+		return;
+
+	pixman_region32_copy(&surface->pending.opaque, &region->region);
+	surface->geometry.dirty = 1;
+}
+
+static void
+wm_xwin_handle_input_region(struct wl_client *client,
+			    struct wl_resource *resource,
+			    struct wl_resource *region_resource)
+{
+	struct xserver_window *window = resource->data;
+	struct weston_surface *surface =
+		(struct weston_surface *) window->surface;
+	struct weston_region *region;
+
+	if (!region_resource) {
+		weston_log("Region resource not provided\n");
+		return;
+	}
+	region = region_resource->data;
+
+	if (!surface)
+		return;
+
+	pixman_region32_copy(&surface->pending.input, &region->region);
+	surface->geometry.dirty = 1;
+}
+
+static void
 wm_xwin_handle_move(struct wl_client *client, struct wl_resource *resource)
 {
 	struct xserver_window *window = resource->data;
@@ -207,6 +253,8 @@ wm_xwin_handle_destroy(struct wl_client *client, struct wl_resource *resource)
 const struct wm_xwin_interface wm_xwin_implementation = {
 	wm_xwin_handle_map,
 	wm_xwin_handle_set_window,
+	wm_xwin_handle_opaque_override,
+	wm_xwin_handle_input_region,
 	wm_xwin_handle_move,
 	wm_xwin_handle_resize,
 	wm_xwin_handle_destroy
@@ -287,6 +335,7 @@ wm_handle_create_xwindow(struct wl_client *client,
                 return;
 	}
 
+	window->surface = NULL;
 	window->shsurf = NULL;
 	window->wxs = wxs;
 	window->xid = xid;
-- 
1.7.9.5



More information about the wayland-devel mailing list