Sophie

Sophie

distrib > Mageia > 5 > x86_64 > by-pkgid > b05df564e3ca4b477ee8582adf1c552c > files > 2

compiz-0.9.10.0-13.mga5.src.rpm

Committer: Tarmac
Author(s): Chris Townsend
Date: 2013-09-09 13:05:20 UTC
mfrom: (3786.1.1 compiz-0.9.10)
Revision ID: tarmac-20130909130520-tb8f2jwfrbe5rco1

Work done by Sam Spilsbury:
Ensure that the frame region is always set as soon as the window is decorated.
Further ensure that the window decoration isn't needlessly reset if the window already had one.
Refactored XShape usage into a common function.
Added tests to verify the behaviour of shape set on initially creating a decorated window and also upon changing the input frame window shape. Fixes: https://bugs.launchpad.net/bugs/1158267.

=== modified file 'plugins/decor/src/decor.cpp'
--- a/plugins/decor/src/decor.cpp	2013-07-19 15:49:47 +0000
+++ b/plugins/decor/src/decor.cpp	2013-09-06 14:17:55 +0000
@@ -44,6 +44,34 @@
 
 namespace cwe = compiz::window::extents;
 
+namespace
+{
+void updateRegionWithShapeRectangles (Display    *dpy,
+				      Window     w,
+				      CompRegion &region)
+{
+    int n = 0;
+    int order = 0;
+    XRectangle *shapeRects = NULL;
+
+    shapeRects =
+	XShapeGetRectangles (dpy,
+	    w, ShapeInput,
+	    &n, &order);
+    if (!shapeRects)
+	return;
+
+    for (int i = 0; i < n; i++)
+	region +=
+	    CompRegion (shapeRects[i].x,
+			shapeRects[i].y,
+			shapeRects[i].width,
+			shapeRects[i].height);
+
+    XFree (shapeRects);
+}
+}
+
 MatchedDecorClipGroup::MatchedDecorClipGroup (const CompMatch &match) :
     mMatch (match)
 {
@@ -1590,13 +1618,6 @@
         lastMaximizedStateDecorated == decorMaximizeState)
 	return false;
 
-    /* Destroy the old WindowDecoration */
-    if (old)
-    {
-	WindowDecoration::destroy (wd);
-	wd = NULL;
-    }
-
     /* If a decoration was found for this window, create
      * a new WindowDecoration for it and set the frame
      * extents accordingly. We should also move the
@@ -1622,6 +1643,8 @@
 	if (decorate ||
 	    shadowOnly)
 	{
+	    if (wd)
+		WindowDecoration::destroy (wd);
 	    wd = WindowDecoration::create (decoration);
 	    if (!wd)
 	    {
@@ -1649,7 +1672,12 @@
     else
     {
 	CompWindowExtents emptyExtents;
-	wd = NULL;
+
+	if (wd)
+	{
+	    WindowDecoration::destroy (wd);
+	    wd = NULL;
+	}
 
 	/* _NET_FRAME_EXTENTS should be updated before the frame
 	 * atom is */
@@ -1903,6 +1931,13 @@
 				 ShapeSet, YXBanded);
 
 	frameRegion = CompRegion ();
+
+	/* Immediately query shape rectangles so that we can
+	 * report them if core asks for them */
+	updateRegionWithShapeRectangles (screen->dpy (),
+					 inputFrame,
+					 frameRegion);
+	window->updateFrameRegion ();
     }
 
     XUngrabServer (screen->dpy ());
@@ -2045,6 +2080,13 @@
 				 ShapeSet, YXBanded);
 
 	frameRegion = CompRegion ();
+
+	/* Immediately query shape rectangles so that we can
+	 * report them if core asks for them */
+	updateRegionWithShapeRectangles (screen->dpy (),
+					 outputFrame,
+					 frameRegion);
+	window->updateFrameRegion ();
     }
 
     XUngrabServer (screen->dpy ());
@@ -2168,6 +2210,7 @@
 DecorWindow::updateFrameRegion (CompRegion &region)
 {
     window->updateFrameRegion (region);
+
     if (wd)
     {
 	if (!frameRegion.isEmpty ())
@@ -2180,10 +2223,6 @@
 	    region += frameRegion.translated (x - wd->decor->input.left,
 					      y - wd->decor->input.top);
 	}
-	else
-	{
-	    region += infiniteRegion;
-	}
     }
 
     updateReg = true;
@@ -2602,54 +2641,24 @@
 			if (dw->inputFrame ==
 			    ((XShapeEvent *) event)->window)
 			{
-			    XRectangle *shapeRects = 0;
-			    int order, n;
-
 			    dw->frameRegion = CompRegion ();
 
-			    shapeRects =
-				XShapeGetRectangles (screen->dpy (),
-				    dw->inputFrame, ShapeInput,
-				    &n, &order);
-			    if (!shapeRects || !n)
-				break;
-
-			    for (int i = 0; i < n; i++)
-				dw->frameRegion +=
-				    CompRegion (shapeRects[i].x,
-					        shapeRects[i].y,
-						shapeRects[i].width,
-						shapeRects[i].height);
+			    updateRegionWithShapeRectangles (screen->dpy (),
+							     dw->inputFrame,
+							     dw->frameRegion);
 
 			    w->updateFrameRegion ();
-
-			    XFree (shapeRects);
 			}
 			else if (dw->outputFrame ==
 			         ((XShapeEvent *) event)->window)
 			{
-			    XRectangle *shapeRects = 0;
-			    int order, n;
-
 			    dw->frameRegion = CompRegion ();
 
-			    shapeRects =
-				XShapeGetRectangles (screen->dpy (),
-				    dw->outputFrame, ShapeBounding,
-				    &n, &order);
-			    if (!n || !shapeRects)
-				break;
-
-			    for (int i = 0; i < n; i++)
-				dw->frameRegion +=
-				    CompRegion (shapeRects[i].x,
-					        shapeRects[i].y,
-						shapeRects[i].width,
-						shapeRects[i].height);
+			    updateRegionWithShapeRectangles (screen->dpy (),
+							     dw->outputFrame,
+							     dw->frameRegion);
 
 			    w->updateFrameRegion ();
-
-			    XFree (shapeRects);
 			}
 		    }
 		}

=== modified file 'plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt'
--- a/plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt	2013-07-15 20:11:19 +0000
+++ b/plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt	2013-09-06 14:17:55 +0000
@@ -1,6 +1,8 @@
 include (FindPkgConfig)
 
-if (BUILD_XORG_GTEST)
+pkg_check_modules (X11_XI x11 xi xext)
+
+if (BUILD_XORG_GTEST AND X11_XI_FOUND)
 
     include_directories (${compiz_SOURCE_DIR}/tests/shared
                          ${COMPIZ_XORG_SYSTEM_TEST_INCLUDE_DIR}
@@ -35,5 +37,5 @@
     # Disabled until the tests can be run without opengl
     #compiz_discover_tests (compiz_test_decor_acceptance WITH_XORG_GTEST)
 
-endif (BUILD_XORG_GTEST)
+endif (BUILD_XORG_GTEST AND X11_XI_FOUND)
 

=== modified file 'plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp'
--- a/plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp	2013-07-19 19:17:31 +0000
+++ b/plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp	2013-09-06 14:17:55 +0000
@@ -33,6 +33,7 @@
 
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
 
 #include "decoration.h"
 
@@ -48,7 +49,10 @@
 namespace xt = xorg::testing;
 namespace ct = compiz::testing;
 
+using ::testing::AllOf;
 using ::testing::AtLeast;
+using ::testing::Eq;
+using ::testing::Field;
 using ::testing::ReturnNull;
 using ::testing::Return;
 using ::testing::MatcherInterface;
@@ -1208,6 +1212,17 @@
     return parent;
 }
 
+bool WaitForReparent (::Display *dpy,
+		      Window  w)
+{
+    return Advance (dpy,
+		    ct::WaitForEventOfTypeOnWindow (dpy,
+						    w,
+						    ReparentNotify,
+						    -1,
+						    -1));
+}
+
 void FreeWindowArray (Window *array)
 {
     if (array)
@@ -1667,6 +1682,188 @@
 					      inputExtents));
 }
 
+class DecorPixmapShapeSetAcceptance :
+    public DecorWithPixmapDefaultsAcceptance
+{
+    public:
+
+	virtual void SetUp ();
+
+    protected:
+
+	int shapeEvent;
+	int shapeError;
+
+	int shapeMajor;
+	int shapeMinor;
+};
+
+void
+DecorPixmapShapeSetAcceptance::SetUp ()
+{
+    DecorWithPixmapDefaultsAcceptance::SetUp ();
+
+    if (!XShapeQueryVersion (Display (), &shapeMajor, &shapeMinor))
+	throw std::runtime_error ("Unable to query shape extension version");
+
+    if (!XShapeQueryExtension (Display (), &shapeEvent, &shapeError))
+	throw std::runtime_error ("Unable to initialize shape extension");
+}
+
+std::ostream &
+operator<< (std::ostream &os, const XRectangle &r)
+{
+    os << "XRectangle: "
+       << " x: " << r.x
+       << " y: " << r.y
+       << " width: " << r.width
+       << " height: " << r.height;
+
+    return os;
+}
+
+namespace
+{
+void FreeXRectangleArray (XRectangle *array)
+{
+    XFree (array);
+}
+
+boost::shared_array <XRectangle>
+ShapeRectangles (::Display    *dpy,
+		 Window       w,
+		 int          &n,
+		 int          &order)
+{
+    XRectangle *rects = XShapeGetRectangles(dpy,
+					    w,
+					    ShapeInput,
+					    &n,
+					    &order);
+
+    return boost::shared_array <XRectangle> (rects,
+					     boost::bind (FreeXRectangleArray,
+							  _1));
+}
+}
+
+TEST_F (DecorPixmapShapeSetAcceptance, FrameWindowHasInitialFullShape)
+{
+    Window w = ct::CreateNormalWindow (Display ());
+
+    RecievePropertyNotifyEvents (Display (), w);
+    XMapRaised (Display (), w);
+    WaitForPropertyNotify (Display (), w, "_NET_FRAME_EXTENTS");
+
+    Window parent = FindParent (Display (), w);
+
+    int x, y;
+    unsigned int width, height, border;
+
+    ct::AbsoluteWindowGeometry (Display (),
+				parent,
+				x,
+				y,
+				width,
+				height,
+				border);
+
+    int n, order;
+    boost::shared_array <XRectangle> rects (ShapeRectangles (Display (),
+							     parent,
+							     n,
+							     order));
+
+    ASSERT_THAT (n, Eq (1));
+    EXPECT_THAT (rects[0],
+		 AllOf (Field (&XRectangle::x, Eq (0)),
+			Field (&XRectangle::y, Eq (0)),
+			Field (&XRectangle::width, Eq (width)),
+			Field (&XRectangle::height, Eq (height))));
+}
+
+TEST_F (DecorPixmapShapeSetAcceptance, FrameWindowShapeIsUpdated)
+{
+    Window w = ct::CreateNormalWindow (Display ());
+
+    RecievePropertyNotifyEvents (Display (), w);
+    XMapRaised (Display (), w);
+    WaitForReparent (Display (), w);
+    WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
+
+    Window parent = FindParent (Display (), w);
+
+    int clientX, clientY;
+    unsigned int clientWidth, clientHeight, border;
+
+    ct::AbsoluteWindowGeometry (Display (),
+				w,
+				clientX,
+				clientY,
+				clientWidth,
+				clientHeight,
+				border);
+
+    /* Get the input frame remove its input shape completely */
+    boost::shared_ptr <unsigned char> inputFramePropertyData;
+    FetchAndVerifyProperty (Display (),
+			    w,
+			    mDecorationInputFrameAtom,
+			    XA_WINDOW,
+			    32,
+			    1,
+			    0L,
+			    inputFramePropertyData);
+
+    Window inputFrame = *(reinterpret_cast <Window *> (inputFramePropertyData.get ()));
+
+    /* Sync first, and then combine rectangles on the input frame */
+    XSync (Display (), false);
+    XShapeSelectInput (Display (), parent, ShapeNotifyMask);
+    XShapeCombineRectangles (Display (),
+			     inputFrame,
+			     ShapeInput,
+			     0,
+			     0,
+			     NULL,
+			     0,
+			     ShapeSet,
+			     0);
+
+    clientX += ActiveBorderExtent;
+    clientY += ActiveBorderExtent;
+
+    /* Wait for a shape event on the frame window */
+    ct::ShapeNotifyXEventMatcher matcher (ShapeInput,
+					  clientX,
+					  clientY,
+					  clientWidth,
+					  clientHeight,
+					  1);
+    Advance (Display (),
+	     ct::WaitForEventOfTypeOnWindowMatching (Display (),
+						     parent,
+						     shapeEvent + ShapeNotify,
+						     -1,
+						     0,
+						     matcher));
+
+    /* Grab the shape rectangles of the parent, they should
+     * be equal to the client window size */
+    int n, order;
+    boost::shared_array <XRectangle> rects (ShapeRectangles (Display (),
+							     parent,
+							     n,
+							     order));
+
+    ASSERT_THAT (n, Eq (1));
+    EXPECT_THAT (rects[0],
+		 AllOf (Field (&XRectangle::x, Eq (clientX)),
+			Field (&XRectangle::y, Eq (clientY)),
+			Field (&XRectangle::width, Eq (clientWidth)),
+			Field (&XRectangle::height, Eq (clientHeight))));
+}
+
 /* TODO: Get bare decorations tests */
 
 /* Helper class with some useful member functions */
@@ -1745,12 +1942,7 @@
     XMapRaised (display, window);
 
     /* Wait for the window to be reparented */
-    Advance (Display (),
-	     ct::WaitForEventOfTypeOnWindow (display,
-					     window,
-					     ReparentNotify,
-					     -1,
-					     -1));
+    WaitForReparent (display, window);
 
     /* Select for StructureNotify on the parent and wrapper
      * windows */