Merge lp:~compiz-team/compiz/compiz.fix_1188900 into lp:compiz/0.9.10

Proposed by Sam Spilsbury
Status: Merged
Approved by: Andrea Azzarone
Approved revision: 3742
Merged at revision: 3742
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1188900
Merge into: lp:compiz/0.9.10
Prerequisite: lp:~compiz-team/compiz/compiz.fix_1189369
Diff against target: 2107 lines (+2046/-2)
7 files modified
plugins/decor/CMakeLists.txt (+2/-0)
plugins/decor/tests/CMakeLists.txt (+1/-0)
plugins/decor/tests/acceptance/CMakeLists.txt (+1/-0)
plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt (+36/-0)
plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp (+2003/-0)
tests/xorg-gtest/CMakeLists.txt (+1/-0)
tests/xorg-gtest/include/compiz-xorg-gtest.h (+2/-2)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1188900
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Andrea Azzarone Approve
MC Return Approve
Review via email: mp+168386@code.launchpad.net

Commit message

Provide a basic decor plugin acceptance test suite.

This change provides a simple acceptance test suite for the decor plugin. It
creates a fake window decorator (cdt::FakeDecorator) and allows users to
create fake decorations (eg cdt::FakePixmapDecoration) which can be serialized
as decoration properties and set on windows under xorg-gtest. It also launches
compiz with the opengl, composite and decor plugins loaded and runs some
basic tests. Among them:

BaseDecorAcceptance.
  Startup:

    Basic canary "can we start compiz with these plugins" test

  FakeDecoratorSessionOwnerNameSetOnSelectionOwner:

    Create a fake decorator, ensure that libdecoration sets our
    session name "fake" on the selection owner

  FakeDecoratorReceiveClientMessage:

    Create fake decorator, ensure that libdecoration posts a client
    message to the root window announcing that the new decorator exists.

  DecorationSupportsWindowType:

    Create a fake decorator, announce support for the WINDOW type decorations
    and ensure that the correct atom is set on the session owner window.

  DecorationSupportsPixmapType:

    Create a fake decorator, announce support for the PIXMAP type decorations
    and ensure that the correct atom is set on the session owner window.

DecorFakeDecoratorAcceptance.
  WindowDefaultFallbackNoExtents:

    By default, newly created windows should recieve a fallback decoration
    but they should not have any frame extents.

DecorWithPixmapDefaultsAcceptance.

  These tests create a default pixmap decoration to use in the hypothetical
  situation that the window decorator hasn't yet generated a decoration
  for this window.

  FallbackRecieveInputFrameNotify:

    Verify that we get a _COMPIZ_WINDOW_DECOR_INPUT_FRAME property set on
    the client when it is created and mapped (eg, an input frame window
    was annonuced to be created)

  FallbackHasInputFrameInParent:

    Verify that a second window exists in the frame window after this
    message was recieved.

  FallbackNormalWindowExtentOnDecoration:

    Verify that _NET_FRAME_EXTENTS is set to the default window extents
    for the default decoration when the window was mapped.

  FallbackNormalWindowInputOnFrame:

    Verify that the input window matches the extents set.

PixmapDecoratedWindowAcceptance.

  These tests create a new window and an associated unique decoration for
  that window.

  MaximizeBorderExtentsOnMaximize:

    Maximize the window and ensure that the correct border extents are used.

  MaximizeBorderExtentsOnVertMaximize:

    Vertically maximize the window and ensure that the correct border extents
    are used.

  MaximizeBorderExtentsOnHorzMaximize:

    Horizontally maximize the window and ensure that the correct border
    extents are used.

  MaximizeFrameWindowSizeEqOutputSize:

    Maximie the window and ensure that the frame window exactly equals
    the output size.

  VertMaximizeFrameWindowSizeEqOutputYHeight:

    Maximize the window and ensure that the frame window's Y and Height
    values are consistent with the output size.

  HorzMaximizeFrameWindowSizeEqOutputXWidth:

    Ditto horizontal maximization.

  DISABLED_VertMaximizeFrameWindowSizeSameXWidth:

    Maximize the window vertically and ensure that the frame window's
    border-relative X position and width does not change.

    This test is disabled, as the behavior in compiz is currently broken,
    (but it means that we can fix it later and enable the test).

  DISABLED_HorzMaximizeFrameWindowSizeSameYHeight

    Maximize the window horizontally and ensure that the frame window's
    border-relative Y position and height does not change.

    This test is disabled, as the behavior in compiz is currently broken,
    (but it means that we can fix it later and enable the test).

(LP: #1188900)

Description of the change

Provide a basic decor plugin acceptance test suite.

This change provides a simple acceptance test suite for the decor plugin. It
creates a fake window decorator (cdt::FakeDecorator) and allows users to
create fake decorations (eg cdt::FakePixmapDecoration) which can be serialized
as decoration properties and set on windows under xorg-gtest. It also launches
compiz with the opengl, composite and decor plugins loaded and runs some
basic tests. Among them:

BaseDecorAcceptance.
  Startup:

    Basic canary "can we start compiz with these plugins" test

  FakeDecoratorSessionOwnerNameSetOnSelectionOwner:

    Create a fake decorator, ensure that libdecoration sets our
    session name "fake" on the selection owner

  FakeDecoratorReceiveClientMessage:

    Create fake decorator, ensure that libdecoration posts a client
    message to the root window announcing that the new decorator exists.

  DecorationSupportsWindowType:

    Create a fake decorator, announce support for the WINDOW type decorations
    and ensure that the correct atom is set on the session owner window.

  DecorationSupportsPixmapType:

    Create a fake decorator, announce support for the PIXMAP type decorations
    and ensure that the correct atom is set on the session owner window.

DecorFakeDecoratorAcceptance.
  WindowDefaultFallbackNoExtents:

    By default, newly created windows should recieve a fallback decoration
    but they should not have any frame extents.

DecorWithPixmapDefaultsAcceptance.

  These tests create a default pixmap decoration to use in the hypothetical
  situation that the window decorator hasn't yet generated a decoration
  for this window.

  FallbackRecieveInputFrameNotify:

    Verify that we get a _COMPIZ_WINDOW_DECOR_INPUT_FRAME property set on
    the client when it is created and mapped (eg, an input frame window
    was annonuced to be created)

  FallbackHasInputFrameInParent:

    Verify that a second window exists in the frame window after this
    message was recieved.

  FallbackNormalWindowExtentOnDecoration:

    Verify that _NET_FRAME_EXTENTS is set to the default window extents
    for the default decoration when the window was mapped.

  FallbackNormalWindowInputOnFrame:

    Verify that the input window matches the extents set.

PixmapDecoratedWindowAcceptance.

  These tests create a new window and an associated unique decoration for
  that window.

  MaximizeBorderExtentsOnMaximize:

    Maximize the window and ensure that the correct border extents are used.

  MaximizeBorderExtentsOnVertMaximize:

    Vertically maximize the window and ensure that the correct border extents
    are used.

  MaximizeBorderExtentsOnHorzMaximize:

    Horizontally maximize the window and ensure that the correct border
    extents are used.

  MaximizeFrameWindowSizeEqOutputSize:

    Maximie the window and ensure that the frame window exactly equals
    the output size.

  VertMaximizeFrameWindowSizeEqOutputYHeight:

    Maximize the window and ensure that the frame window's Y and Height
    values are consistent with the output size.

  HorzMaximizeFrameWindowSizeEqOutputXWidth:

    Ditto horizontal maximization.

  DISABLED_VertMaximizeFrameWindowSizeSameXWidth:

    Maximize the window vertically and ensure that the frame window's
    border-relative X position and width does not change.

    This test is disabled, as the behavior in compiz is currently broken,
    (but it means that we can fix it later and enable the test).

  DISABLED_HorzMaximizeFrameWindowSizeSameYHeight

    Maximize the window horizontally and ensure that the frame window's
    border-relative Y position and height does not change.

    This test is disabled, as the behavior in compiz is currently broken,
    (but it means that we can fix it later and enable the test).

Notes and Discussion:

 1. This does not cover all of the decor plugin's functionality. I just wanted to get at least these tests in-trunk and reviewed now that the diff is approaching 2000~ lines.

 2. compiz_decor_acceptance_tests.cpp should probably be split up into multiple files for each of the components (matchers, helper functions etc). At the moment its just all in one file until the majority of tests are implemented and we can figure out the best way to split the file up.

 3. As there isn't any way to specify multiple plugin load directories yet, these tests are not yet run by default. I'll implement that functionality later as it will take some time to do and is largely unrelated to this branch.

At the moment this means that you need to make install before running the test binary. Its found in build/plugins/decor/tests/acceptance/xorg-gtest

 4. Some tests are marked as DISABLED. That's because they test for behavior that doesn't quite work yet. Ideally, we'd fix the broken behavior and get to a point where all the tests can be re-enabled.,

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote :

A minor typo in the commit message:

Maximie the window and ensure that the frame window exactly equals
    the output size.

Redundant brackets here:

230 + for (ct::CompizProcess::PluginList::iterator it = baseList.begin ();
231 + it != baseList.end ();
232 + ++it)
233 + {
234 + list.push_back (*it);
235 + }

You could align those Atoms also with Window:

142 + Atom mUtf8StringAtom;
143 + Atom mDecorationManagerNameAtom;
144 +
145 + Window mRootWindow;

All just minor issues, so no real need to fix anything here -> so take it, or leave it ;)

+1 from me.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
MC Return (mc-return) wrote :

So I guess this is ready to go ?

review: Approve
Revision history for this message
MC Return (mc-return) wrote :

Seems not :)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Autolanding.
Approved revid is not set in launchpad. This is most likely a launchpad issue and re-approve should fix it. There is also a chance (although a very small one) this is a permission problem of the ps-jenkins bot.
http://jenkins.qa.ubuntu.com/job/compiz-autolanding/98/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/compiz-saucy-amd64-autolanding/10
    SUCCESS: http://jenkins.qa.ubuntu.com/job/compiz-saucy-armhf-autolanding/10
    SUCCESS: http://jenkins.qa.ubuntu.com/job/compiz-saucy-i386-autolanding/10

review: Needs Fixing (continuous-integration)
Revision history for this message
Andrea Azzarone (azzar1) wrote :

Ok this just adds tests. Code looks good overall. All tests pass.

[----------] Global test environment tear-down
Server terminated successfully (0). Closing log file.
[==========] 16 tests from 4 test cases ran. (5229 ms total)
[ PASSED ] 16 tests.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/decor/CMakeLists.txt'
2--- plugins/decor/CMakeLists.txt 2012-09-25 01:15:36 +0000
3+++ plugins/decor/CMakeLists.txt 2013-06-15 03:55:29 +0000
4@@ -20,3 +20,5 @@
5 endif (COMPIZ_BUILD_WITH_RPATH AND NOT COMPIZ_DISABLE_PLUGIN_DECOR)
6
7 install (PROGRAMS "src/compiz-decorator" DESTINATION ${exec_prefix})
8+
9+add_subdirectory (tests)
10
11=== added directory 'plugins/decor/tests'
12=== added file 'plugins/decor/tests/CMakeLists.txt'
13--- plugins/decor/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
14+++ plugins/decor/tests/CMakeLists.txt 2013-06-15 03:55:29 +0000
15@@ -0,0 +1,1 @@
16+add_subdirectory (acceptance)
17
18=== added directory 'plugins/decor/tests/acceptance'
19=== added file 'plugins/decor/tests/acceptance/CMakeLists.txt'
20--- plugins/decor/tests/acceptance/CMakeLists.txt 1970-01-01 00:00:00 +0000
21+++ plugins/decor/tests/acceptance/CMakeLists.txt 2013-06-15 03:55:29 +0000
22@@ -0,0 +1,1 @@
23+add_subdirectory (xorg-gtest)
24
25=== added directory 'plugins/decor/tests/acceptance/xorg-gtest'
26=== added file 'plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt'
27--- plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt 1970-01-01 00:00:00 +0000
28+++ plugins/decor/tests/acceptance/xorg-gtest/CMakeLists.txt 2013-06-15 03:55:29 +0000
29@@ -0,0 +1,36 @@
30+include (FindPkgConfig)
31+
32+if (BUILD_XORG_GTEST)
33+
34+ include_directories (${compiz_SOURCE_DIR}/tests/shared
35+ ${COMPIZ_XORG_SYSTEM_TEST_INCLUDE_DIR}
36+ ${X11_INCLUDE_DIRS}
37+ ${XORG_SERVER_INCLUDE_XORG_GTEST}
38+ ${XORG_SERVER_GTEST_SRC}
39+ ${GTEST_INCLUDE_DIRS})
40+
41+ link_directories (${X11_XI_LIBRARY_DIRS}
42+ ${COMPIZ_COMPOSITE_DAMAGETRACKING_INTEGRATION_LIBRARY_DIRS})
43+
44+ add_executable (compiz_test_decor_acceptance
45+ ${CMAKE_CURRENT_SOURCE_DIR}/compiz_decor_acceptance_tests.cpp)
46+
47+ set (COMPIZ_DECOR_ACCEPTANCE_TEST_LIBRARIES
48+ xorg_gtest_all
49+ compiz_xorg_gtest_main
50+ compiz_xorg_gtest_system_test
51+ decoration
52+ ${GMOCK_LIBRARY}
53+ ${GMOCK_MAIN_LIBRARY}
54+ ${GTEST_BOTH_LIBRARIES}
55+ ${XORG_SERVER_LIBRARIES}
56+ ${X11_XI_LIBRARIES})
57+
58+ target_link_libraries (compiz_test_decor_acceptance
59+ ${COMPIZ_DECOR_ACCEPTANCE_TEST_LIBRARIES})
60+
61+ # Not run by default yet until we're able to load plugins locally
62+ #compiz_discover_tests (compiz_test_decor_acceptance WITH_XORG_GTEST)
63+
64+endif (BUILD_XORG_GTEST)
65+
66
67=== added file 'plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp'
68--- plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp 1970-01-01 00:00:00 +0000
69+++ plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp 2013-06-15 03:55:29 +0000
70@@ -0,0 +1,2003 @@
71+/*
72+ * Compiz XOrg GTest Decoration Acceptance Tests
73+ *
74+ * Copyright (C) 2013 Sam Spilsbury.
75+ *
76+ * This library is free software; you can redistribute it and/or
77+ * modify it under the terms of the GNU Lesser General Public
78+ * License as published by the Free Software Foundation; either
79+ * version 2.1 of the License, or (at your option) any later version.
80+
81+ * This library is distributed in the hope that it will be useful,
82+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
83+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84+ * Lesser General Public License for more details.
85+
86+ * You should have received a copy of the GNU Lesser General Public
87+ * License along with this library; if not, write to the Free Software
88+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
89+ *
90+ * Authored By:
91+ * Sam Spilsbury <smspillaz@gmail.com>
92+ */
93+#include <gtest/gtest.h>
94+#include <gmock/gmock.h>
95+
96+#include <sstream>
97+#include <vector>
98+
99+#include <boost/shared_array.hpp>
100+#include <boost/shared_ptr.hpp>
101+
102+#include <boost/bind.hpp>
103+
104+#include <X11/Xlib.h>
105+#include <X11/Xatom.h>
106+
107+#include "decoration.h"
108+
109+#include <xorg/gtest/xorg-gtest.h>
110+#include <compiz-xorg-gtest.h>
111+
112+namespace xt = xorg::testing;
113+namespace ct = compiz::testing;
114+
115+using ::testing::AtLeast;
116+using ::testing::ReturnNull;
117+using ::testing::Return;
118+using ::testing::MatcherInterface;
119+using ::testing::MatchResultListener;
120+using ::testing::Matcher;
121+using ::testing::MakeMatcher;
122+using ::testing::StrEq;
123+using ::testing::_;
124+
125+class BaseDecorAcceptance :
126+ public ct::AutostartCompizXorgSystemTestWithTestHelper
127+{
128+ public:
129+
130+ BaseDecorAcceptance ();
131+
132+ virtual void SetUp ();
133+ virtual ct::CompizProcess::PluginList GetPluginList ();
134+
135+ protected:
136+
137+ Window mRootWindow;
138+
139+ Atom mUtf8StringAtom;
140+ Atom mDecorationManagerNameAtom;
141+ Atom mDecorationTypeAtom;
142+ Atom mDecorationTypePixmap;
143+ Atom mDecorationTypeWindow;
144+ Atom mDecorationInputFrameAtom;
145+ Atom mDecorationOutputFrameAtom;
146+};
147+
148+BaseDecorAcceptance::BaseDecorAcceptance () :
149+ mRootWindow (0),
150+ mUtf8StringAtom (0),
151+ mDecorationManagerNameAtom (0),
152+ mDecorationTypeAtom (0),
153+ mDecorationTypePixmap (0),
154+ mDecorationTypeWindow (0),
155+ mDecorationInputFrameAtom (0),
156+ mDecorationOutputFrameAtom (0)
157+{
158+}
159+
160+void
161+BaseDecorAcceptance::SetUp ()
162+{
163+ ct::AutostartCompizXorgSystemTestWithTestHelper::SetUp ();
164+
165+ mUtf8StringAtom = XInternAtom (Display (),
166+ "UTF8_STRING",
167+ 1);
168+
169+ ASSERT_NE (0, mUtf8StringAtom);
170+
171+ mDecorationManagerNameAtom = XInternAtom (Display (),
172+ "_COMPIZ_DM_NAME",
173+ 0);
174+
175+ ASSERT_NE (0, mDecorationManagerNameAtom);
176+
177+ mDecorationTypePixmap = XInternAtom (Display (),
178+ DECOR_TYPE_PIXMAP_ATOM_NAME,
179+ 0);
180+
181+ ASSERT_NE (0, mDecorationTypePixmap);
182+
183+ mDecorationTypeWindow = XInternAtom (Display (),
184+ DECOR_TYPE_WINDOW_ATOM_NAME,
185+ 0);
186+
187+ ASSERT_NE (0, mDecorationTypeWindow);
188+
189+ mDecorationTypeAtom = XInternAtom (Display (),
190+ DECOR_TYPE_ATOM_NAME,
191+ 0);
192+
193+ ASSERT_NE (0, mDecorationTypeAtom);
194+
195+ mDecorationInputFrameAtom = XInternAtom (Display (),
196+ DECOR_INPUT_FRAME_ATOM_NAME,
197+ 0);
198+
199+ ASSERT_NE (0, mDecorationInputFrameAtom);
200+
201+ mDecorationOutputFrameAtom = XInternAtom (Display (),
202+ DECOR_OUTPUT_FRAME_ATOM_NAME,
203+ 0);
204+
205+ ASSERT_NE (0, mDecorationOutputFrameAtom);
206+
207+ mRootWindow = DefaultRootWindow (Display ());
208+
209+ ASSERT_NE (0, mRootWindow);
210+}
211+
212+ct::CompizProcess::PluginList
213+BaseDecorAcceptance::GetPluginList ()
214+{
215+ typedef ct::AutostartCompizXorgSystemTestWithTestHelper Base;
216+ ct::CompizProcess::PluginList baseList (Base::GetPluginList ());
217+ ct::CompizProcess::PluginList list;
218+
219+ list.push_back ("composite");
220+ list.push_back ("opengl");
221+ list.push_back ("decor");
222+
223+ for (ct::CompizProcess::PluginList::iterator it = baseList.begin ();
224+ it != baseList.end ();
225+ ++it)
226+ list.push_back (*it);
227+
228+ return list;
229+}
230+
231+namespace compiz
232+{
233+namespace decor
234+{
235+namespace testing
236+{
237+
238+const char *DecorationClientName = "fake";
239+
240+const char *FailedToAcquireMessage =
241+ "Could not acquire selection for an unknown reason";
242+const char *OtherDecorationManagerRunningMessage =
243+ "Another decoration manager is already running";
244+
245+class FakeDecorator
246+{
247+ public:
248+
249+ FakeDecorator (Display *d,
250+ int supporting = WINDOW_DECORATION_TYPE_WINDOW);
251+ ~FakeDecorator ();
252+
253+ Window currentSelectionOwner ();
254+ Atom sessionOwnerAtom ();
255+
256+ Window supportingCheckWindow ();
257+
258+ private:
259+
260+ Display *mDpy;
261+ int mScreenNumber;
262+ Window mRootWindow;
263+ int mSessionStatus;
264+ Time mDecorationManagerTimestamp;
265+
266+ Atom mSessionOwnerAtom;
267+ Window mSessionOwner;
268+
269+ Atom mSupportingHintAtom;
270+ Atom mSupportingHintWindowAtom;
271+ Window mSupportingHintWindow;
272+
273+};
274+
275+class FakeDecoration
276+{
277+ public:
278+
279+ typedef boost::shared_ptr <FakeDecoration> Ptr;
280+
281+ FakeDecoration (unsigned int type,
282+ unsigned int state,
283+ unsigned int actions,
284+ unsigned int minWidth,
285+ unsigned int minHeight);
286+
287+ virtual ~FakeDecoration ();
288+
289+ virtual size_t propertyDataSize () const = 0;
290+ virtual void addPropertyData (std::vector <long> &) const = 0;
291+
292+ bool match (unsigned int type,
293+ unsigned int state,
294+ unsigned int actions) const;
295+
296+ protected:
297+
298+ void insertBaseData (std::vector <long> &) const;
299+
300+ static const size_t BaseDataSize = 5;
301+
302+ unsigned int mType;
303+ unsigned int mState;
304+ unsigned int mActions;
305+
306+ unsigned int mMinWidth;
307+ unsigned int mMinHeight;
308+};
309+
310+class FakeWindowTypeDecoration :
311+ public FakeDecoration
312+{
313+ public:
314+
315+ FakeWindowTypeDecoration (unsigned int type,
316+ unsigned int state,
317+ unsigned int actions,
318+ unsigned int minWidth,
319+ unsigned int minHeight,
320+ const decor_extents_t &restored,
321+ const decor_extents_t &maximized);
322+
323+ protected:
324+
325+ size_t propertyDataSize () const;
326+ void addPropertyData (std::vector<long> &) const;
327+
328+ static const unsigned int WindowDecorationSize = 8;
329+
330+ private:
331+
332+ decor_extents_t mRestored;
333+ decor_extents_t mMaximized;
334+};
335+
336+class FakePixmapTypeDecoration :
337+ public FakeDecoration
338+{
339+ public:
340+
341+ FakePixmapTypeDecoration (unsigned int type,
342+ unsigned int state,
343+ unsigned int actions,
344+ unsigned int minWidth,
345+ unsigned int minHeight,
346+ const decor_extents_t &restoredBorder,
347+ const decor_extents_t &restoredInput,
348+ const decor_extents_t &maximizedBorder,
349+ const decor_extents_t &maximizedInput,
350+ Display *dpy);
351+ ~FakePixmapTypeDecoration ();
352+
353+ protected:
354+
355+ size_t propertyDataSize () const;
356+ void addPropertyData (std::vector<long> &) const;
357+
358+ private:
359+
360+ decor_extents_t mRestoredBorder;
361+ decor_extents_t mRestoredInput;
362+ decor_extents_t mMaximizedBorder;
363+ decor_extents_t mMaximizedInput;
364+
365+ decor_context_t mContext;
366+ decor_quad_t mQuads[N_QUADS_MAX];
367+ decor_layout_t mLayout;
368+ unsigned int mNQuads;
369+
370+ Display *mDpy;
371+ Pixmap mPixmap;
372+};
373+
374+class FakeDecorationList
375+{
376+ public:
377+
378+ FakeDecorationList (unsigned int type) :
379+ mDecorationType (type)
380+ {
381+ }
382+
383+ void AddDecoration (const FakeDecoration::Ptr &);
384+ void RemoveDecoration (unsigned int type,
385+ unsigned int state,
386+ unsigned int actions);
387+
388+ void SetPropertyOnWindow (Display *dpy,
389+ Window w,
390+ Atom property);
391+
392+ private:
393+
394+ unsigned int mDecorationType;
395+ std::vector <FakeDecoration::Ptr> decorations;
396+};
397+
398+class AcquisitionFailed :
399+ public std::exception
400+{
401+ public:
402+
403+ AcquisitionFailed (int status);
404+
405+ const char * what () const throw ();
406+
407+ private:
408+
409+ int mStatus;
410+};
411+
412+}
413+}
414+}
415+
416+namespace
417+{
418+bool Advance (Display *d, bool result)
419+{
420+ return ct::AdvanceToNextEventOnSuccess (d, result);
421+}
422+
423+class ManagerMessageMatcher :
424+ public ct::ClientMessageXEventMatcher
425+{
426+ public:
427+
428+ ManagerMessageMatcher (Display *dpy,
429+ Atom managed);
430+
431+ virtual bool MatchAndExplain (const XEvent &event,
432+ MatchResultListener *listener) const;
433+
434+ virtual void DescribeTo (std::ostream *os) const;
435+
436+ private:
437+
438+ Display *mDpy;
439+ Atom mManager;
440+ Atom mManaged;
441+};
442+
443+void FreePropertyData (unsigned char *array)
444+{
445+ if (array)
446+ XFree (array);
447+}
448+
449+int SafeFetchProperty (Display *dpy,
450+ Window w,
451+ Atom property,
452+ long offset,
453+ long length,
454+ Atom requestedType,
455+ Atom &returnType,
456+ int &returnFormat,
457+ unsigned long &returnNItems,
458+ unsigned long &returnBytesRemaining,
459+ boost::shared_ptr <unsigned char> &data)
460+{
461+ unsigned char *dataLocation;
462+
463+ int status = XGetWindowProperty (dpy, w, property, offset, length, 0,
464+ requestedType, &returnType,
465+ &returnFormat, &returnNItems,
466+ &returnBytesRemaining,
467+ &dataLocation);
468+
469+ data.reset (dataLocation,
470+ boost::bind (FreePropertyData, _1));
471+
472+ return status;
473+}
474+
475+void FetchAndVerifyProperty (Display *dpy,
476+ Window w,
477+ Atom property,
478+ Atom expectedType,
479+ int expectedFormat,
480+ unsigned long expectedItems,
481+ unsigned long expectedBytesAfter,
482+ boost::shared_ptr <unsigned char> &data)
483+{
484+ Atom returnedType = 0;
485+ int returnedFormat = 0;
486+ unsigned long returnedNItems = 0;
487+ unsigned long returnedBytesRemaining = 0;
488+
489+ std::stringstream ss;
490+
491+ int status = SafeFetchProperty (dpy,
492+ w,
493+ property,
494+ 0L,
495+ 1024L,
496+ expectedType,
497+ returnedType,
498+ returnedFormat,
499+ returnedNItems,
500+ returnedBytesRemaining,
501+ data);
502+
503+ if (status != Success)
504+ ss << "XGetWindowProperty failed:" << std::endl;
505+
506+ if (returnedType != expectedType)
507+ ss << "Expected type of " << XGetAtomName (dpy, expectedType)
508+ << std::endl;
509+
510+ if (returnedFormat != expectedFormat)
511+ ss << "Expected format of " << expectedFormat
512+ << " but got " << returnedFormat << std::endl;
513+
514+ if (returnedNItems != expectedItems)
515+ ss << "Expected " << expectedItems << " items"
516+ << " but got " << returnedNItems << " items" << std::endl;
517+
518+ if (returnedBytesRemaining != expectedBytesAfter)
519+ ss << "Expected " << expectedBytesAfter << " bytes remaining"
520+ << " but got " << returnedBytesRemaining << " bytes remaining"
521+ << std::endl;
522+
523+ if (!ss.str ().empty ())
524+ throw std::logic_error (ss.str ());
525+}
526+}
527+
528+ManagerMessageMatcher::ManagerMessageMatcher (Display *dpy,
529+ Atom managed) :
530+ ct::ClientMessageXEventMatcher (dpy,
531+ XInternAtom (dpy,
532+ "MANAGER",
533+ 1),
534+ DefaultRootWindow (dpy)),
535+ mDpy (dpy),
536+ mManaged (managed)
537+{
538+}
539+
540+bool
541+ManagerMessageMatcher::MatchAndExplain (const XEvent &event,
542+ MatchResultListener *listener) const
543+{
544+ if (ct::ClientMessageXEventMatcher::MatchAndExplain (event, listener))
545+ {
546+ /* Evaluate the second field for the atom */
547+ return event.xclient.data.l[1] ==
548+ static_cast <long> (mManaged);
549+ }
550+
551+ return false;
552+}
553+
554+void
555+ManagerMessageMatcher::DescribeTo (std::ostream *os) const
556+{
557+ *os << "manager of selection atom " << XGetAtomName (mDpy, mManaged);
558+}
559+
560+
561+
562+namespace cdt = compiz::decor::testing;
563+
564+cdt::FakeDecoration::FakeDecoration (unsigned int type,
565+ unsigned int state,
566+ unsigned int actions,
567+ unsigned int minWidth,
568+ unsigned int minHeight) :
569+ mType (type),
570+ mState (state),
571+ mActions (actions),
572+ mMinWidth (minWidth),
573+ mMinHeight (minHeight)
574+{
575+}
576+
577+cdt::FakeDecoration::~FakeDecoration ()
578+{
579+}
580+
581+bool
582+cdt::FakeDecoration::match (unsigned int type,
583+ unsigned int state,
584+ unsigned int actions) const
585+{
586+ return type == mType &&
587+ state == mState &&
588+ actions == mActions;
589+}
590+
591+cdt::FakeWindowTypeDecoration::FakeWindowTypeDecoration (unsigned int type,
592+ unsigned int state,
593+ unsigned int actions,
594+ unsigned int minWidth,
595+ unsigned int minHeight,
596+ const decor_extents_t &restored,
597+ const decor_extents_t &maximized) :
598+ FakeDecoration (type, state, actions, minWidth, minHeight),
599+ mRestored (restored),
600+ mMaximized (maximized)
601+{
602+}
603+
604+void
605+cdt::FakeWindowTypeDecoration::addPropertyData (std::vector<long> &vec) const
606+{
607+ long propData[PROP_HEADER_SIZE + propertyDataSize ()];
608+
609+ decor_gen_window_property (propData,
610+ 0,
611+ const_cast <decor_extents_t *> (&mRestored),
612+ const_cast <decor_extents_t *> (&mMaximized),
613+ mMinWidth,
614+ mMinHeight,
615+ mState,
616+ mType,
617+ mActions);
618+
619+ for (size_t i = PROP_HEADER_SIZE;
620+ i < (PROP_HEADER_SIZE + propertyDataSize ());
621+ ++i)
622+ vec.push_back (propData[i]);
623+}
624+
625+size_t
626+cdt::FakeWindowTypeDecoration::propertyDataSize () const
627+{
628+ return WINDOW_PROP_SIZE;
629+}
630+
631+cdt::FakePixmapTypeDecoration::FakePixmapTypeDecoration (unsigned int type,
632+ unsigned int state,
633+ unsigned int actions,
634+ unsigned int minWidth,
635+ unsigned int minHeight,
636+ const decor_extents_t &restoredBorder,
637+ const decor_extents_t &restoredInput,
638+ const decor_extents_t &maximizedBorder,
639+ const decor_extents_t &maximizedInput,
640+ Display *dpy) :
641+ FakeDecoration (type, state, actions, minWidth, minHeight),
642+ mRestoredBorder (restoredBorder),
643+ mRestoredInput (restoredInput),
644+ mMaximizedBorder (maximizedBorder),
645+ mMaximizedInput (maximizedInput),
646+ mDpy (dpy),
647+ mPixmap (XCreatePixmap (mDpy,
648+ DefaultRootWindow (mDpy),
649+ 10,
650+ 10,
651+ DefaultDepth (mDpy, (DefaultScreen (mDpy)))))
652+{
653+ /* 10x10 decoration, 0 corner space, 0 spacing, 2px each side */
654+ mContext.extents.left = 2;
655+ mContext.extents.right = 2;
656+ mContext.extents.top = 2;
657+ mContext.extents.bottom = 2;
658+
659+ mContext.left_space = 0;
660+ mContext.right_space = 0;
661+ mContext.top_space = 0;
662+ mContext.bottom_space = 0;
663+ mContext.left_corner_space = 0;
664+ mContext.right_corner_space = 0;
665+ mContext.top_corner_space = 0;
666+ mContext.bottom_corner_space = 0;
667+
668+ decor_get_default_layout (&mContext, minWidth, minHeight, &mLayout);
669+ mNQuads = decor_set_lSrStSbS_window_quads (mQuads, &mContext, &mLayout);
670+}
671+
672+cdt::FakePixmapTypeDecoration::~FakePixmapTypeDecoration ()
673+{
674+ XFreePixmap (mDpy, mPixmap);
675+}
676+
677+size_t
678+cdt::FakePixmapTypeDecoration::propertyDataSize () const
679+{
680+ return BASE_PROP_SIZE + (QUAD_PROP_SIZE * mNQuads);
681+}
682+
683+void
684+cdt::FakePixmapTypeDecoration::addPropertyData (std::vector<long> &vec) const
685+{
686+ long propData[PROP_HEADER_SIZE + propertyDataSize ()];
687+
688+ decor_quads_to_property (propData,
689+ 0,
690+ mPixmap,
691+ const_cast <decor_extents_t *> (&mRestoredInput),
692+ const_cast <decor_extents_t *> (&mRestoredBorder),
693+ const_cast <decor_extents_t *> (&mMaximizedInput),
694+ const_cast <decor_extents_t *> (&mMaximizedBorder),
695+ mMinWidth,
696+ mMinHeight,
697+ const_cast <decor_quad_t *> (mQuads),
698+ mNQuads,
699+ mType,
700+ mState,
701+ mActions);
702+
703+ for (size_t i = PROP_HEADER_SIZE;
704+ i < (PROP_HEADER_SIZE + propertyDataSize ());
705+ ++i)
706+ vec.push_back (propData[i]);
707+}
708+
709+void
710+cdt::FakeDecorationList::AddDecoration (const cdt::FakeDecoration::Ptr &decoration)
711+{
712+ decorations.push_back (decoration);
713+}
714+
715+namespace
716+{
717+bool MatchesTypeStateAndActions (const cdt::FakeDecoration::Ptr &decoration,
718+ unsigned int type,
719+ unsigned int state,
720+ unsigned int actions)
721+{
722+ return decoration->match (type, state, actions);
723+}
724+}
725+
726+void cdt::FakeDecorationList::RemoveDecoration (unsigned int type,
727+ unsigned int state,
728+ unsigned int actions)
729+{
730+ decorations.erase (
731+ std::remove_if (decorations.begin (),
732+ decorations.end (),
733+ boost::bind (MatchesTypeStateAndActions,
734+ _1,
735+ type,
736+ state,
737+ actions)),
738+ decorations.end ());
739+}
740+
741+void
742+cdt::FakeDecorationList::SetPropertyOnWindow (Display *dpy,
743+ Window w,
744+ Atom property)
745+{
746+ size_t size = PROP_HEADER_SIZE;
747+ for (std::vector <FakeDecoration::Ptr>::iterator it = decorations.begin ();
748+ it != decorations.end ();
749+ ++it)
750+ size += (*it)->propertyDataSize ();
751+
752+ std::vector <long> data;
753+
754+ data.reserve (size);
755+
756+ data.push_back (decor_version ());
757+ data.push_back (mDecorationType);
758+ data.push_back (decorations.size ());
759+
760+ for (std::vector <FakeDecoration::Ptr>::iterator it = decorations.begin ();
761+ it != decorations.end ();
762+ ++it)
763+ (*it)->addPropertyData (data);
764+
765+ XChangeProperty (dpy,
766+ w,
767+ property,
768+ XA_INTEGER,
769+ 32,
770+ PropModeReplace,
771+ reinterpret_cast <unsigned char *> (&data[0]),
772+ size);
773+}
774+
775+cdt::AcquisitionFailed::AcquisitionFailed (int status) :
776+ mStatus (status)
777+{
778+}
779+
780+const char *
781+cdt::AcquisitionFailed::what () const throw ()
782+{
783+ switch (mStatus)
784+ {
785+ case DECOR_ACQUIRE_STATUS_FAILED:
786+ return FailedToAcquireMessage;
787+ case DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING:
788+ return OtherDecorationManagerRunningMessage;
789+ default:
790+ return "Unknown status";
791+ }
792+
793+ return "Unknown status";
794+}
795+
796+cdt::FakeDecorator::FakeDecorator (Display *d,
797+ int supports) :
798+ mDpy (d),
799+ mScreenNumber (DefaultScreen (d)),
800+ mRootWindow (DefaultRootWindow (d)),
801+ mSessionStatus (decor_acquire_dm_session (d,
802+ mScreenNumber,
803+ "fake",
804+ 1,
805+ &mDecorationManagerTimestamp)),
806+ mSessionOwnerAtom (0),
807+ mSessionOwner (0),
808+ mSupportingHintAtom (XInternAtom (d, DECOR_TYPE_ATOM_NAME, 0)),
809+ mSupportingHintWindowAtom (XInternAtom (d,
810+ DECOR_SUPPORTING_DM_CHECK_ATOM_NAME,
811+ 0))
812+{
813+ if (mSessionStatus != DECOR_ACQUIRE_STATUS_SUCCESS)
814+ throw AcquisitionFailed (mSessionStatus);
815+
816+ std::stringstream sessionOwnerStream;
817+
818+ sessionOwnerStream << "_COMPIZ_DM_S" << mScreenNumber;
819+ mSessionOwnerAtom = XInternAtom (d,
820+ sessionOwnerStream.str ().c_str (),
821+ 1);
822+
823+ mSessionOwner = XGetSelectionOwner (d, mSessionOwnerAtom);
824+
825+ if (!mSessionOwner)
826+ throw std::runtime_error ("Expected a selection owner");
827+
828+ decor_set_dm_check_hint (d, mScreenNumber, supports);
829+
830+ boost::shared_ptr <unsigned char> data;
831+
832+ FetchAndVerifyProperty (mDpy,
833+ mRootWindow,
834+ mSupportingHintWindowAtom,
835+ XA_WINDOW,
836+ 32,
837+ 1,
838+ 0,
839+ data);
840+
841+ mSupportingHintWindow = *(reinterpret_cast <Window *> (data.get ()));
842+
843+ if (!mSupportingHintWindow)
844+ throw std::runtime_error ("Failed to find supporting hint window");
845+
846+
847+}
848+
849+cdt::FakeDecorator::~FakeDecorator ()
850+{
851+ /* Destroy the session owner, taking the selection with it */
852+ XDestroyWindow (mDpy, mSessionOwner);
853+ XDestroyWindow (mDpy, mSupportingHintWindow);
854+}
855+
856+Window
857+cdt::FakeDecorator::currentSelectionOwner ()
858+{
859+ return mSessionOwner;
860+}
861+
862+Atom
863+cdt::FakeDecorator::sessionOwnerAtom ()
864+{
865+ return mSessionOwnerAtom;
866+}
867+
868+Atom
869+cdt::FakeDecorator::supportingCheckWindow ()
870+{
871+ return mSupportingHintWindow;
872+}
873+
874+TEST_F (BaseDecorAcceptance, Startup)
875+{
876+}
877+
878+TEST_F (BaseDecorAcceptance, FakeDecoratorSessionOwnerNameSetOnSelectionOwner)
879+{
880+ cdt::FakeDecorator decorator (Display ());
881+ boost::shared_ptr <unsigned char> data;
882+
883+ FetchAndVerifyProperty (Display (),
884+ decorator.currentSelectionOwner (),
885+ mDecorationManagerNameAtom,
886+ mUtf8StringAtom,
887+ 8,
888+ 4,
889+ 0,
890+ data);
891+
892+ std::string name (reinterpret_cast <char *> (data.get ()));
893+
894+ EXPECT_THAT (name, StrEq (cdt::DecorationClientName));
895+
896+}
897+
898+TEST_F (BaseDecorAcceptance, FakeDecoratorReceiveClientMessage)
899+{
900+ cdt::FakeDecorator decorator (Display ());
901+
902+ ManagerMessageMatcher matcher (Display (),
903+ decorator.sessionOwnerAtom ());
904+
905+ EXPECT_TRUE (Advance (Display (),
906+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
907+ mRootWindow,
908+ ClientMessage,
909+ -1,
910+ -1,
911+ matcher)));
912+}
913+
914+TEST_F (BaseDecorAcceptance, DecorationSupportsWindowType)
915+{
916+ cdt::FakeDecorator decorator (Display (),
917+ WINDOW_DECORATION_TYPE_WINDOW);
918+
919+ boost::shared_ptr <unsigned char> data;
920+
921+ FetchAndVerifyProperty (Display (),
922+ decorator.supportingCheckWindow (),
923+ mDecorationTypeAtom,
924+ XA_ATOM,
925+ 32,
926+ 1,
927+ 0,
928+ data);
929+
930+ Atom *atoms = reinterpret_cast <Atom *> (data.get ());
931+ EXPECT_EQ (atoms[0], mDecorationTypeWindow);
932+}
933+
934+TEST_F (BaseDecorAcceptance, DecorationSupportsPixmapType)
935+{
936+ cdt::FakeDecorator decorator (Display (),
937+ WINDOW_DECORATION_TYPE_PIXMAP);
938+
939+ boost::shared_ptr <unsigned char> data;
940+
941+ FetchAndVerifyProperty (Display (),
942+ decorator.supportingCheckWindow (),
943+ mDecorationTypeAtom,
944+ XA_ATOM,
945+ 32,
946+ 1,
947+ 0,
948+ data);
949+
950+ Atom *atoms = reinterpret_cast <Atom *> (data.get ());
951+ EXPECT_EQ (atoms[0], mDecorationTypePixmap);
952+}
953+
954+class DecorFakeDecoratorAcceptance :
955+ public BaseDecorAcceptance
956+{
957+ protected:
958+
959+ virtual void SetUp ();
960+ virtual void TearDown ();
961+
962+ virtual unsigned int SupportedDecorations () const;
963+ virtual bool StartDecoratorOnSetUp () const;
964+
965+ void SetUpDecorator ();
966+
967+ std::auto_ptr <cdt::FakeDecorator> decorator;
968+
969+ Atom NETWMFrameExtentsAtom;
970+ Atom WindowDecorationAtom;
971+ Atom DefaultActiveDecorationAtom;
972+ Atom DefaultBareDecorationAtom;
973+};
974+
975+void
976+DecorFakeDecoratorAcceptance::SetUp ()
977+{
978+ BaseDecorAcceptance::SetUp ();
979+
980+ NETWMFrameExtentsAtom = XInternAtom (Display (),
981+ "_NET_FRAME_EXTENTS",
982+ 0);
983+
984+ WindowDecorationAtom = XInternAtom (Display (),
985+ DECOR_WINDOW_ATOM_NAME,
986+ 0);
987+
988+ DefaultActiveDecorationAtom = XInternAtom (Display (),
989+ DECOR_ACTIVE_ATOM_NAME,
990+ 0);
991+
992+ DefaultBareDecorationAtom = XInternAtom (Display (),
993+ DECOR_BARE_ATOM_NAME,
994+ 0);
995+
996+ if (StartDecoratorOnSetUp ())
997+ SetUpDecorator ();
998+}
999+
1000+void
1001+DecorFakeDecoratorAcceptance::SetUpDecorator ()
1002+{
1003+ decorator.reset (new cdt::FakeDecorator (Display (),
1004+ SupportedDecorations ()));
1005+}
1006+
1007+void
1008+DecorFakeDecoratorAcceptance::TearDown ()
1009+{
1010+ decorator.reset ();
1011+
1012+ BaseDecorAcceptance::TearDown ();
1013+}
1014+
1015+unsigned int
1016+DecorFakeDecoratorAcceptance::SupportedDecorations () const
1017+{
1018+ return WINDOW_DECORATION_TYPE_WINDOW;
1019+}
1020+
1021+bool
1022+DecorFakeDecoratorAcceptance::StartDecoratorOnSetUp () const
1023+{
1024+ return true;
1025+}
1026+
1027+namespace
1028+{
1029+void RecievePropertyNotifyEvents (Display *dpy,
1030+ Window w)
1031+{
1032+ XWindowAttributes attrib;
1033+
1034+ XGetWindowAttributes (dpy, w, &attrib);
1035+ XSelectInput (dpy, w, attrib.your_event_mask | PropertyChangeMask);
1036+}
1037+
1038+void WaitForPropertyNotify (Display *dpy,
1039+ Window w,
1040+ std::string const &prop)
1041+{
1042+ RecievePropertyNotifyEvents (dpy, w);
1043+
1044+ ct::PropertyNotifyXEventMatcher matcher (dpy,
1045+ prop);
1046+
1047+ ASSERT_TRUE (Advance (dpy,
1048+ ct::WaitForEventOfTypeOnWindowMatching (dpy,
1049+ w,
1050+ PropertyNotify,
1051+ -1,
1052+ -1,
1053+ matcher)));
1054+}
1055+
1056+void WaitForFrameExtents (Display *dpy,
1057+ Window w)
1058+{
1059+ RecievePropertyNotifyEvents (dpy, w);
1060+
1061+ XMapRaised (dpy, w);
1062+
1063+ WaitForPropertyNotify (dpy, w, "_NET_FRAME_EXTENTS");
1064+}
1065+
1066+Window FindParent (Display *dpy,
1067+ Window w)
1068+{
1069+ Window parent = 0;
1070+ Window next = w;
1071+ Window root = DefaultRootWindow (dpy);
1072+
1073+ while (next != root)
1074+ {
1075+ parent = next;
1076+
1077+ Window dummy;
1078+ Window *children;
1079+ unsigned int nchildren;
1080+
1081+ int status = XQueryTree (dpy, parent, &dummy, &next, &children, &nchildren);
1082+ XFree (children);
1083+
1084+ if (!status)
1085+ throw std::logic_error ("XQueryTree failed");
1086+ }
1087+
1088+ return parent;
1089+}
1090+
1091+void FreeWindowArray (Window *array)
1092+{
1093+ if (array)
1094+ XFree (array);
1095+}
1096+
1097+boost::shared_array <Window> FetchChildren (Display *dpy,
1098+ Window w,
1099+ unsigned int &n)
1100+{
1101+ Window *children;
1102+ Window dummy;
1103+
1104+ int status = XQueryTree (dpy,
1105+ w,
1106+ &dummy,
1107+ &dummy,
1108+ &children,
1109+ &n);
1110+
1111+ if (!status)
1112+ throw std::logic_error ("XQueryTree failed");
1113+
1114+ return boost::shared_array <Window> (children,
1115+ boost::bind (FreeWindowArray, _1));
1116+}
1117+
1118+class FrameExtentsMatcher :
1119+ public MatcherInterface <unsigned long *>
1120+{
1121+ public:
1122+
1123+ FrameExtentsMatcher (unsigned int left,
1124+ unsigned int right,
1125+ unsigned int top,
1126+ unsigned int bottom);
1127+
1128+ bool MatchAndExplain (unsigned long *extents,
1129+ MatchResultListener *listener) const;
1130+
1131+ void DescribeTo (std::ostream *os) const;
1132+
1133+ private:
1134+
1135+ unsigned int mLeft;
1136+ unsigned int mRight;
1137+ unsigned int mTop;
1138+ unsigned int mBottom;
1139+};
1140+
1141+Matcher <unsigned long *>
1142+IsExtents (unsigned int left,
1143+ unsigned int right,
1144+ unsigned int top,
1145+ unsigned int bottom)
1146+{
1147+ return MakeMatcher (new FrameExtentsMatcher (left, right, top, bottom));
1148+}
1149+}
1150+
1151+FrameExtentsMatcher::FrameExtentsMatcher (unsigned int left,
1152+ unsigned int right,
1153+ unsigned int top,
1154+ unsigned int bottom) :
1155+ mLeft (left),
1156+ mRight (right),
1157+ mTop (top),
1158+ mBottom (bottom)
1159+{
1160+}
1161+
1162+bool
1163+FrameExtentsMatcher::MatchAndExplain (unsigned long *extents,
1164+ MatchResultListener *listener) const
1165+{
1166+ return mLeft == extents[0] &&
1167+ mRight == extents[1] &&
1168+ mTop == extents[2] &&
1169+ mBottom == extents[3];
1170+}
1171+
1172+void
1173+FrameExtentsMatcher::DescribeTo (std::ostream *os) const
1174+{
1175+ *os << "Expected frame extents of :" << std::endl
1176+ << " left: " << mLeft << std::endl
1177+ << " right: " << mRight << std::endl
1178+ << " top: " << mTop << std::endl
1179+ << " bottom: " << mBottom << std::endl;
1180+}
1181+
1182+TEST_F (DecorFakeDecoratorAcceptance, WindowDefaultFallbackNoExtents)
1183+{
1184+ Window w = ct::CreateNormalWindow (Display ());
1185+ WaitForFrameExtents (Display (), w);
1186+
1187+ boost::shared_ptr <unsigned char> data;
1188+
1189+ FetchAndVerifyProperty (Display (),
1190+ w,
1191+ NETWMFrameExtentsAtom,
1192+ XA_CARDINAL,
1193+ 32,
1194+ 4,
1195+ 0,
1196+ data);
1197+
1198+ unsigned long *frameExtents =
1199+ reinterpret_cast <unsigned long *> (data.get ());
1200+
1201+ EXPECT_THAT (frameExtents, IsExtents (0, 0, 0, 0));
1202+}
1203+
1204+class DecorWithPixmapDefaultsAcceptance :
1205+ public DecorFakeDecoratorAcceptance
1206+{
1207+ protected:
1208+
1209+ DecorWithPixmapDefaultsAcceptance ();
1210+
1211+ virtual void SetUp ();
1212+ virtual void TearDown ();
1213+ virtual unsigned int SupportedDecorations () const;
1214+
1215+ private:
1216+
1217+ Window mRoot;
1218+
1219+ protected:
1220+
1221+ cdt::FakeDecorationList rootActiveDecorationList;
1222+ cdt::FakeDecorationList rootBareDecorationList;
1223+
1224+ static const unsigned int MaximizedBorderExtent = 1;
1225+ static const unsigned int ActiveBorderExtent = 2;
1226+ static const unsigned int ActiveInputExtent = 4;
1227+};
1228+
1229+namespace
1230+{
1231+cdt::FakeDecoration::Ptr
1232+MakeFakePixmapTypeDecoration (unsigned int type,
1233+ unsigned int state,
1234+ unsigned int actions,
1235+ unsigned int minWidth,
1236+ unsigned int minHeight,
1237+ const decor_extents_t &restoredBorder,
1238+ const decor_extents_t &restoredInput,
1239+ const decor_extents_t &maximizedBorder,
1240+ const decor_extents_t &maximizedInput,
1241+ Display *dpy)
1242+{
1243+ cdt::FakeDecoration *decoration =
1244+ new cdt::FakePixmapTypeDecoration (type,
1245+ state,
1246+ actions,
1247+ minWidth,
1248+ minHeight,
1249+ restoredBorder,
1250+ restoredInput,
1251+ maximizedBorder,
1252+ maximizedInput,
1253+ dpy);
1254+
1255+ return boost::shared_ptr <cdt::FakeDecoration> (decoration);
1256+}
1257+
1258+decor_extents_t
1259+DecorationExtents (unsigned int left,
1260+ unsigned int right,
1261+ unsigned int top,
1262+ unsigned int bottom)
1263+{
1264+ decor_extents_t extents;
1265+
1266+ extents.left = left;
1267+ extents.right = right;
1268+ extents.top = top;
1269+ extents.bottom = bottom;
1270+
1271+ return extents;
1272+}
1273+
1274+class ExtentsFromMatcher :
1275+ public MatcherInterface <Window>
1276+{
1277+ public:
1278+
1279+ ExtentsFromMatcher (Display *dpy,
1280+ Window w,
1281+ const decor_extents_t &extents);
1282+
1283+ bool MatchAndExplain (Window window,
1284+ MatchResultListener *listener) const;
1285+
1286+ void DescribeTo (std::ostream *os) const;
1287+
1288+ private:
1289+
1290+ Display *mDpy;
1291+ Window mWindow;
1292+ decor_extents_t mExpectedExtents;
1293+};
1294+
1295+Matcher <Window>
1296+ExtendsFromWindowBy (Display *dpy,
1297+ Window w,
1298+ const decor_extents_t &extents)
1299+{
1300+ return MakeMatcher (new ExtentsFromMatcher (dpy, w, extents));
1301+}
1302+}
1303+
1304+std::ostream &
1305+operator<< (std::ostream &lhs, const decor_extents_t &extents)
1306+{
1307+ return lhs << "Extents: " << std::endl
1308+ << " left: " << extents.left << std::endl
1309+ << " right: " << extents.right << std::endl
1310+ << " top: " << extents.top << std::endl
1311+ << " bottom: " << extents.bottom << std::endl;
1312+}
1313+
1314+ExtentsFromMatcher::ExtentsFromMatcher (Display *dpy,
1315+ Window w,
1316+ const decor_extents_t &extents) :
1317+ mDpy (dpy),
1318+ mWindow (w),
1319+ mExpectedExtents (extents)
1320+{
1321+}
1322+
1323+bool
1324+ExtentsFromMatcher::MatchAndExplain (Window window,
1325+ MatchResultListener *listener) const
1326+{
1327+ unsigned int border, depth;
1328+ Window root;
1329+
1330+ int compareX, compareY, matchX, matchY;
1331+ unsigned int compareWidth, compareHeight, matchWidth, matchHeight;
1332+
1333+ if (!XGetGeometry (mDpy, window, &root,
1334+ &matchX, &matchY, &matchWidth, &matchHeight,
1335+ &border, &depth))
1336+ throw std::logic_error ("XGetGeometry failed");
1337+
1338+ if (!XGetGeometry (mDpy, mWindow, &root,
1339+ &compareX, &compareY, &compareWidth, &compareHeight,
1340+ &border, &depth))
1341+ throw std::logic_error ("XGetGeometry failed");
1342+
1343+ unsigned int left = matchX - compareX;
1344+ unsigned int top = matchY - compareY;
1345+ unsigned int right = (matchX + matchWidth) - (compareX + compareWidth);
1346+ unsigned int bottom = (matchY + matchHeight) - (compareY + compareHeight);
1347+
1348+ decor_extents_t determinedExtents = DecorationExtents (left, right, top, bottom);
1349+
1350+ return decor_extents_cmp (&determinedExtents, &mExpectedExtents);
1351+}
1352+
1353+void
1354+ExtentsFromMatcher::DescribeTo (std::ostream *os) const
1355+{
1356+ *os << "Extends outwards from " << std::hex << mWindow << std::dec
1357+ << " by: " << mExpectedExtents;
1358+}
1359+
1360+DecorWithPixmapDefaultsAcceptance::DecorWithPixmapDefaultsAcceptance () :
1361+ mRoot (0),
1362+ rootActiveDecorationList (WINDOW_DECORATION_TYPE_PIXMAP),
1363+ rootBareDecorationList (WINDOW_DECORATION_TYPE_PIXMAP)
1364+{
1365+}
1366+
1367+unsigned int
1368+DecorWithPixmapDefaultsAcceptance::SupportedDecorations () const
1369+{
1370+ return WINDOW_DECORATION_TYPE_PIXMAP;
1371+}
1372+
1373+void
1374+DecorWithPixmapDefaultsAcceptance::SetUp ()
1375+{
1376+ DecorFakeDecoratorAcceptance::SetUp ();
1377+
1378+ mRoot = DefaultRootWindow (Display ());
1379+
1380+ unsigned int ResBo = ActiveBorderExtent;
1381+ unsigned int ResIn = ActiveInputExtent;
1382+ unsigned int MaxEx = MaximizedBorderExtent;
1383+
1384+ decor_extents_t activeBorderRestored (DecorationExtents (ResBo, ResBo, ResBo, ResBo));
1385+ decor_extents_t activeBorderMaximized (DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx));
1386+ decor_extents_t activeInputRestored (DecorationExtents (ResIn, ResIn, ResIn, ResIn));
1387+ decor_extents_t activeInputMaximized (DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx));
1388+
1389+ decor_extents_t emptyExtents (DecorationExtents (0, 0, 0, 0));
1390+
1391+ cdt::FakeDecoration::Ptr rootActiveDecoration =
1392+ MakeFakePixmapTypeDecoration (DECOR_WINDOW_TYPE_NORMAL,
1393+ 0,
1394+ 0,
1395+ 10, 10,
1396+ activeBorderRestored,
1397+ activeInputRestored,
1398+ activeBorderMaximized,
1399+ activeInputMaximized,
1400+ Display ());
1401+
1402+ cdt::FakeDecoration::Ptr rootBareDecoration =
1403+ MakeFakePixmapTypeDecoration (0, 0, 0,
1404+ 1, 1,
1405+ emptyExtents,
1406+ emptyExtents,
1407+ emptyExtents,
1408+ emptyExtents,
1409+ Display ());
1410+
1411+ rootActiveDecorationList.AddDecoration (rootActiveDecoration);
1412+ rootBareDecorationList.AddDecoration (rootBareDecoration);
1413+
1414+ rootActiveDecorationList.SetPropertyOnWindow (Display (),
1415+ mRoot,
1416+ DefaultActiveDecorationAtom);
1417+ rootBareDecorationList.SetPropertyOnWindow (Display (),
1418+ mRoot,
1419+ DefaultBareDecorationAtom);
1420+}
1421+
1422+void
1423+DecorWithPixmapDefaultsAcceptance::TearDown ()
1424+{
1425+ /* Remove inserted decorations */
1426+ rootActiveDecorationList.RemoveDecoration (DECOR_WINDOW_TYPE_NORMAL,
1427+ 0,
1428+ 0);
1429+ rootBareDecorationList.RemoveDecoration (0, 0, 0);
1430+
1431+ DecorFakeDecoratorAcceptance::TearDown ();
1432+}
1433+
1434+TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackRecieveInputFrameNotify)
1435+{
1436+ Window w = ct::CreateNormalWindow (Display ());
1437+ RecievePropertyNotifyEvents (Display (), w);
1438+ XMapRaised (Display (), w);
1439+
1440+ ct::PropertyNotifyXEventMatcher matcher (Display (),
1441+ DECOR_INPUT_FRAME_ATOM_NAME);
1442+
1443+ EXPECT_TRUE (Advance (Display (),
1444+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
1445+ w,
1446+ PropertyNotify,
1447+ -1,
1448+ -1,
1449+ matcher)));
1450+}
1451+
1452+TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackHasInputFrameInParent)
1453+{
1454+ Window w = ct::CreateNormalWindow (Display ());
1455+
1456+ XMapRaised (Display (), w);
1457+ WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
1458+
1459+ Window parent = FindParent (Display (), w);
1460+
1461+ unsigned int nChildren;
1462+ boost::shared_array <Window> children (FetchChildren (Display (),
1463+ parent,
1464+ nChildren));
1465+
1466+ EXPECT_EQ (2, nChildren);
1467+}
1468+
1469+namespace
1470+{
1471+Window FindDecorationWindowFromChildren (Display *dpy,
1472+ const boost::shared_array <Window> &c,
1473+ unsigned int nChildren)
1474+{
1475+ for (unsigned int i = 0; i < nChildren; ++i)
1476+ {
1477+ /* The decoration window will have no children, but
1478+ * the wrapper window will have one child */
1479+ unsigned int n;
1480+ boost::shared_array <Window> childChildren (FetchChildren (dpy,
1481+ c[i],
1482+ n));
1483+ if (n == 0)
1484+ return c[i];
1485+ }
1486+
1487+ return None;
1488+}
1489+}
1490+
1491+TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackNormalWindowExtentOnDecoration)
1492+{
1493+ Window w = ct::CreateNormalWindow (Display ());
1494+
1495+ XMapRaised (Display (), w);
1496+ WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
1497+
1498+ Window parent = FindParent (Display (), w);
1499+
1500+ unsigned int nChildren;
1501+ boost::shared_array <Window> children (FetchChildren (Display (),
1502+ parent,
1503+ nChildren));
1504+
1505+ ASSERT_EQ (2, nChildren);
1506+
1507+ Window decorationWindow = FindDecorationWindowFromChildren (Display (),
1508+ children,
1509+ nChildren);
1510+
1511+ ASSERT_NE (None, decorationWindow);
1512+
1513+ decor_extents_t borderExtents (DecorationExtents (ActiveBorderExtent,
1514+ ActiveBorderExtent,
1515+ ActiveBorderExtent,
1516+ ActiveBorderExtent));
1517+ EXPECT_THAT (decorationWindow, ExtendsFromWindowBy (Display (),
1518+ w,
1519+ borderExtents));
1520+}
1521+
1522+TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackNormalWindowInputOnFrame)
1523+{
1524+ Window w = ct::CreateNormalWindow (Display ());
1525+
1526+ XMapRaised (Display (), w);
1527+ WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
1528+
1529+ Window parent = FindParent (Display (), w);
1530+
1531+ decor_extents_t inputExtents (DecorationExtents (ActiveInputExtent,
1532+ ActiveInputExtent,
1533+ ActiveInputExtent,
1534+ ActiveInputExtent));
1535+ EXPECT_THAT (parent, ExtendsFromWindowBy (Display (),
1536+ w,
1537+ inputExtents));
1538+}
1539+
1540+/* TODO: Get bare decorations tests */
1541+
1542+class PixmapDecoratedWindowAcceptance :
1543+ public DecorWithPixmapDefaultsAcceptance
1544+{
1545+ public:
1546+
1547+ PixmapDecoratedWindowAcceptance ();
1548+
1549+ virtual void SetUp ();
1550+ virtual void TearDown ();
1551+
1552+ virtual bool StartDecoratorOnSetUp () const;
1553+
1554+ protected:
1555+
1556+ Window mWindow;
1557+ Window mParent;
1558+ cdt::FakeDecorationList mDecorations;
1559+};
1560+
1561+PixmapDecoratedWindowAcceptance::PixmapDecoratedWindowAcceptance () :
1562+ mDecorations (WINDOW_DECORATION_TYPE_PIXMAP)
1563+{
1564+}
1565+
1566+void
1567+PixmapDecoratedWindowAcceptance::SetUp ()
1568+{
1569+ DecorWithPixmapDefaultsAcceptance::SetUp ();
1570+
1571+ mWindow = ct::CreateNormalWindow (Display ());
1572+ XSelectInput (Display (), mWindow,
1573+ StructureNotifyMask |
1574+ PropertyChangeMask);
1575+ XMapRaised (Display (), mWindow);
1576+
1577+ /* Wait for the window to be reparented */
1578+ Advance (Display (),
1579+ ct::WaitForEventOfTypeOnWindow (Display (),
1580+ mWindow,
1581+ ReparentNotify,
1582+ -1,
1583+ -1));
1584+
1585+ /* Select for StructureNotify events on the parent window */
1586+ mParent = FindParent (Display (), mWindow);
1587+ XSelectInput (Display (), mParent, StructureNotifyMask);
1588+
1589+ /* Start the decorator */
1590+ SetUpDecorator ();
1591+
1592+ unsigned int ResBo = ActiveBorderExtent;
1593+ unsigned int ResIn = ActiveInputExtent;
1594+ unsigned int MaxEx = MaximizedBorderExtent;
1595+
1596+ cdt::FakeDecoration::Ptr decoration =
1597+ MakeFakePixmapTypeDecoration (DECOR_WINDOW_TYPE_NORMAL,
1598+ 0,
1599+ 0,
1600+ 10,
1601+ 10,
1602+ DecorationExtents (ResBo, ResBo, ResBo, ResBo),
1603+ DecorationExtents (ResIn, ResIn, ResIn, ResIn),
1604+ DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
1605+ DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
1606+ Display ());
1607+
1608+ mDecorations.AddDecoration (decoration);
1609+ mDecorations.SetPropertyOnWindow (Display (),
1610+ mWindow,
1611+ WindowDecorationAtom);
1612+
1613+ WaitForPropertyNotify (Display (), mWindow, DECOR_INPUT_FRAME_ATOM_NAME);
1614+ WaitForPropertyNotify (Display (), mWindow, "_NET_FRAME_EXTENTS");
1615+
1616+ /* Wait for the parent window to be moved to -2, -2 */
1617+ ct::ConfigureNotifyXEventMatcher matcher (None,
1618+ 0,
1619+ ResBo - ResIn,
1620+ ResBo - ResIn,
1621+ 0,
1622+ 0,
1623+ CWX | CWY);
1624+
1625+ Advance (Display (),
1626+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
1627+ mParent,
1628+ ConfigureNotify,
1629+ -1,
1630+ -1,
1631+ matcher));
1632+}
1633+
1634+void
1635+PixmapDecoratedWindowAcceptance::TearDown ()
1636+{
1637+ mDecorations.RemoveDecoration (DECOR_WINDOW_TYPE_NORMAL, 0, 0);
1638+
1639+ XDestroyWindow (Display (), mWindow);
1640+
1641+ DecorWithPixmapDefaultsAcceptance::TearDown ();
1642+}
1643+
1644+bool
1645+PixmapDecoratedWindowAcceptance::StartDecoratorOnSetUp () const
1646+{
1647+ return false;
1648+}
1649+
1650+namespace
1651+{
1652+static const unsigned int RemoveState = 0;
1653+static const unsigned int AddState = 1;
1654+static const unsigned int ToggleState = 2;
1655+
1656+void ChangeStateOfWindow (Display *dpy,
1657+ unsigned int mode,
1658+ const std::string &state,
1659+ Window w)
1660+{
1661+ XEvent event;
1662+
1663+ const long ClientTypePager = 2;
1664+
1665+ event.type = ClientMessage;
1666+ event.xany.window = w;
1667+
1668+ event.xclient.format = 32;
1669+ event.xclient.message_type = XInternAtom (dpy, "_NET_WM_STATE", 0);
1670+
1671+ event.xclient.data.l[0] = mode;
1672+ event.xclient.data.l[1] = XInternAtom (dpy, state.c_str (), 0);
1673+ event.xclient.data.l[2] = 0;
1674+ event.xclient.data.l[3] = ClientTypePager;
1675+
1676+ XSendEvent (dpy,
1677+ DefaultRootWindow (dpy),
1678+ 1,
1679+ SubstructureRedirectMask,
1680+ &event);
1681+ XSync (dpy, 0);
1682+}
1683+
1684+boost::shared_ptr <unsigned char>
1685+FetchCardinalProperty (Display *dpy,
1686+ Window w,
1687+ Atom NETWMFrameExtentsAtom)
1688+{
1689+ boost::shared_ptr <unsigned char> data;
1690+
1691+ FetchAndVerifyProperty (dpy,
1692+ w,
1693+ NETWMFrameExtentsAtom,
1694+ XA_CARDINAL,
1695+ 32,
1696+ 4,
1697+ 0,
1698+ data);
1699+
1700+ return data;
1701+}
1702+}
1703+
1704+TEST_F (PixmapDecoratedWindowAcceptance, MaximizeBorderExtentsOnMaximize)
1705+{
1706+ ChangeStateOfWindow (Display (),
1707+ AddState,
1708+ "_NET_WM_STATE_MAXIMIZED_VERT",
1709+ mWindow);
1710+
1711+ ChangeStateOfWindow (Display (),
1712+ AddState,
1713+ "_NET_WM_STATE_MAXIMIZED_HORZ",
1714+ mWindow);
1715+
1716+ WaitForPropertyNotify (Display (), mWindow, "_NET_FRAME_EXTENTS");
1717+
1718+ boost::shared_ptr <unsigned char> data =
1719+ FetchCardinalProperty (Display (),
1720+ mWindow,
1721+ NETWMFrameExtentsAtom);
1722+
1723+ unsigned long *frameExtents =
1724+ reinterpret_cast <unsigned long *> (data.get ());
1725+
1726+ unsigned int MaxEx = MaximizedBorderExtent;
1727+
1728+ EXPECT_THAT (frameExtents, IsExtents (MaxEx, MaxEx, MaxEx, MaxEx));
1729+}
1730+
1731+TEST_F (PixmapDecoratedWindowAcceptance, MaximizeBorderExtentsOnVertMaximize)
1732+{
1733+ ChangeStateOfWindow (Display (),
1734+ AddState,
1735+ "_NET_WM_STATE_MAXIMIZED_VERT",
1736+ mWindow);
1737+
1738+ WaitForPropertyNotify (Display (), mWindow, "_NET_FRAME_EXTENTS");
1739+
1740+ boost::shared_ptr <unsigned char> data =
1741+ FetchCardinalProperty (Display (),
1742+ mWindow,
1743+ NETWMFrameExtentsAtom);
1744+
1745+ unsigned long *frameExtents =
1746+ reinterpret_cast <unsigned long *> (data.get ());
1747+
1748+ unsigned int MaxEx = MaximizedBorderExtent;
1749+
1750+ EXPECT_THAT (frameExtents, IsExtents (MaxEx, MaxEx, MaxEx, MaxEx));
1751+}
1752+
1753+TEST_F (PixmapDecoratedWindowAcceptance, MaximizeBorderExtentsOnHorzMaximize)
1754+{
1755+ ChangeStateOfWindow (Display (),
1756+ AddState,
1757+ "_NET_WM_STATE_MAXIMIZED_HORZ",
1758+ mWindow);
1759+
1760+ WaitForPropertyNotify (Display (), mWindow, "_NET_FRAME_EXTENTS");
1761+
1762+ boost::shared_ptr <unsigned char> data =
1763+ FetchCardinalProperty (Display (),
1764+ mWindow,
1765+ NETWMFrameExtentsAtom);
1766+
1767+ unsigned long *frameExtents =
1768+ reinterpret_cast <unsigned long *> (data.get ());
1769+
1770+ unsigned int MaxEx = MaximizedBorderExtent;
1771+
1772+ EXPECT_THAT (frameExtents, IsExtents (MaxEx, MaxEx, MaxEx, MaxEx));
1773+}
1774+
1775+TEST_F (PixmapDecoratedWindowAcceptance, MaximizeFrameWindowSizeEqOutputSize)
1776+{
1777+ XWindowAttributes attrib;
1778+ XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
1779+
1780+ /* The assumption here is that there is only one output */
1781+
1782+ ChangeStateOfWindow (Display (),
1783+ AddState,
1784+ "_NET_WM_STATE_MAXIMIZED_VERT",
1785+ mWindow);
1786+
1787+ ChangeStateOfWindow (Display (),
1788+ AddState,
1789+ "_NET_WM_STATE_MAXIMIZED_HORZ",
1790+ mWindow);
1791+
1792+ ct::ConfigureNotifyXEventMatcher matcher (None,
1793+ 0,
1794+ 0,
1795+ 0,
1796+ attrib.width,
1797+ attrib.height,
1798+ CWX | CWY | CWWidth | CWHeight);
1799+
1800+ EXPECT_TRUE (Advance (Display (),
1801+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
1802+ mParent,
1803+ ConfigureNotify,
1804+ -1,
1805+ -1,
1806+ matcher)));
1807+}
1808+
1809+TEST_F (PixmapDecoratedWindowAcceptance, VertMaximizeFrameWindowSizeEqOutputYHeight)
1810+{
1811+ XWindowAttributes attrib;
1812+ XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
1813+
1814+ ChangeStateOfWindow (Display (),
1815+ AddState,
1816+ "_NET_WM_STATE_MAXIMIZED_VERT",
1817+ mWindow);
1818+
1819+ ct::ConfigureNotifyXEventMatcher matcher (None,
1820+ 0,
1821+ 0,
1822+ 0,
1823+ 0,
1824+ attrib.height,
1825+ CWY | CWHeight);
1826+
1827+ EXPECT_TRUE (Advance (Display (),
1828+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
1829+ mParent,
1830+ ConfigureNotify,
1831+ -1,
1832+ -1,
1833+ matcher)));
1834+}
1835+
1836+TEST_F (PixmapDecoratedWindowAcceptance, HorzMaximizeFrameWindowSizeEqOutputXWidth)
1837+{
1838+ XWindowAttributes attrib;
1839+ XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
1840+
1841+ ChangeStateOfWindow (Display (),
1842+ AddState,
1843+ "_NET_WM_STATE_MAXIMIZED_HORZ",
1844+ mWindow);
1845+
1846+ ct::ConfigureNotifyXEventMatcher matcher (None,
1847+ 0,
1848+ 0,
1849+ 0,
1850+ attrib.width,
1851+ 0,
1852+ CWX | CWWidth);
1853+
1854+ EXPECT_TRUE (Advance (Display (),
1855+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
1856+ mParent,
1857+ ConfigureNotify,
1858+ -1,
1859+ -1,
1860+ matcher)));
1861+}
1862+
1863+namespace
1864+{
1865+class WindowGeometryMatcher :
1866+ public MatcherInterface <Window>
1867+{
1868+ public:
1869+
1870+ WindowGeometryMatcher (Display *dpy,
1871+ const Matcher <int> &x,
1872+ const Matcher <int> &y,
1873+ const Matcher <unsigned int> &width,
1874+ const Matcher <unsigned int> &height,
1875+ const Matcher <unsigned int> &border);
1876+
1877+ bool MatchAndExplain (Window x, MatchResultListener *listener) const;
1878+ void DescribeTo (std::ostream *os) const;
1879+
1880+ private:
1881+
1882+ Display *mDpy;
1883+
1884+ Matcher <int> mX;
1885+ Matcher <int> mY;
1886+ Matcher <unsigned int> mWidth;
1887+ Matcher <unsigned int> mHeight;
1888+ Matcher <unsigned int> mBorder;
1889+};
1890+
1891+Matcher <Window>
1892+WindowGeometry (Display *dpy,
1893+ const Matcher <int> &x,
1894+ const Matcher <int> &y,
1895+ const Matcher <unsigned int> &width,
1896+ const Matcher <unsigned int> &height,
1897+ const Matcher <unsigned int> &border)
1898+{
1899+ return MakeMatcher (new WindowGeometryMatcher (dpy,
1900+ x,
1901+ y,
1902+ width,
1903+ height,
1904+ border));
1905+}
1906+}
1907+
1908+WindowGeometryMatcher::WindowGeometryMatcher (Display *dpy,
1909+ const Matcher <int> &x,
1910+ const Matcher <int> &y,
1911+ const Matcher <unsigned int> &width,
1912+ const Matcher <unsigned int> &height,
1913+ const Matcher <unsigned int> &border) :
1914+ mDpy (dpy),
1915+ mX (x),
1916+ mY (y),
1917+ mWidth (width),
1918+ mHeight (height),
1919+ mBorder (border)
1920+{
1921+}
1922+
1923+bool
1924+WindowGeometryMatcher::MatchAndExplain (Window w,
1925+ MatchResultListener *listener) const
1926+{
1927+ Window root;
1928+ int x, y;
1929+ unsigned int width, height, border, depth;
1930+
1931+ if (!XGetGeometry (mDpy, w, &root, &x, &y, &width, &height, &border, &depth))
1932+ throw std::logic_error ("XGetGeometry failed");
1933+
1934+ bool match = mX.MatchAndExplain (x, listener) &&
1935+ mY.MatchAndExplain (y, listener) &&
1936+ mWidth.MatchAndExplain (width, listener) &&
1937+ mHeight.MatchAndExplain (height, listener) &&
1938+ mBorder.MatchAndExplain (border, listener);
1939+
1940+ if (!match)
1941+ {
1942+ *listener << "Geometry:"
1943+ << " x: " << x
1944+ << " y: " << y
1945+ << " width: " << width
1946+ << " height: " << height
1947+ << " border: " << border;
1948+ }
1949+
1950+ return match;
1951+}
1952+
1953+void
1954+WindowGeometryMatcher::DescribeTo (std::ostream *os) const
1955+{
1956+ *os << "Window geometry matching :";
1957+
1958+ *os << std::endl << " - ";
1959+ mX.DescribeTo (os);
1960+
1961+ *os << std::endl << " - ";
1962+ mY.DescribeTo (os);
1963+
1964+ *os << std::endl << " - ";
1965+ mWidth.DescribeTo (os);
1966+
1967+ *os << std::endl << " - ";
1968+ mHeight.DescribeTo (os);
1969+
1970+ *os << std::endl << " - ";
1971+ mBorder.DescribeTo (os);
1972+}
1973+
1974+namespace
1975+{
1976+void WindowBorderPositionAttributes (Display *dpy,
1977+ Window w,
1978+ XWindowAttributes &attrib,
1979+ unsigned int ActiveBorderExtent,
1980+ unsigned int ActiveInputExtent)
1981+{
1982+ XGetWindowAttributes (dpy, w, &attrib);
1983+
1984+ /* Remove border - input offset */
1985+ attrib.x -= (ActiveBorderExtent - ActiveInputExtent);
1986+ attrib.y -= (ActiveBorderExtent - ActiveInputExtent);
1987+ attrib.width -= (ActiveBorderExtent - ActiveInputExtent) * 2;
1988+ attrib.height -= (ActiveBorderExtent - ActiveInputExtent) * 2;
1989+}
1990+}
1991+
1992+/* DISABLED - Upon maximization, x offset is 1, width offset is 10 */
1993+TEST_F (PixmapDecoratedWindowAcceptance, DISABLED_VertMaximizeFrameWindowSizeSameXWidth)
1994+{
1995+ XWindowAttributes rootAttrib, attrib;
1996+ XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &rootAttrib);
1997+
1998+ WindowBorderPositionAttributes (Display (), mParent, attrib, ActiveBorderExtent, ActiveInputExtent);
1999+
2000+ ChangeStateOfWindow (Display (),
2001+ AddState,
2002+ "_NET_WM_STATE_MAXIMIZED_VERT",
2003+ mWindow);
2004+
2005+ /* Wait for the window to be maximized first */
2006+ ct::ConfigureNotifyXEventMatcher matcher (None,
2007+ 0,
2008+ 0,
2009+ 0,
2010+ 0,
2011+ rootAttrib.height,
2012+ CWY | CWHeight);
2013+
2014+ Advance (Display (),
2015+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
2016+ mParent,
2017+ ConfigureNotify,
2018+ -1,
2019+ -1,
2020+ matcher));
2021+
2022+ /* Query the window geometry and ensure that the width and
2023+ * height have remained the same (adding on any extended borders,
2024+ * in this case 0) */
2025+ EXPECT_THAT (mParent, WindowGeometry (Display (),
2026+ attrib.x,
2027+ _,
2028+ attrib.width,
2029+ _,
2030+ _));
2031+}
2032+
2033+/* DISABLED - Upon maximization, y offset is 1, height offset is 10 */
2034+TEST_F (PixmapDecoratedWindowAcceptance, DISABLED_HorzMaximizeFrameWindowSizeSameYHeight)
2035+{
2036+ XWindowAttributes rootAttrib, attrib;
2037+ XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &rootAttrib);
2038+
2039+ WindowBorderPositionAttributes (Display (), mParent, attrib, ActiveBorderExtent, ActiveInputExtent);
2040+
2041+ ChangeStateOfWindow (Display (),
2042+ AddState,
2043+ "_NET_WM_STATE_MAXIMIZED_HORZ",
2044+ mWindow);
2045+
2046+ /* Wait for the window to be maximized first */
2047+ ct::ConfigureNotifyXEventMatcher matcher (None,
2048+ 0,
2049+ 0,
2050+ 0,
2051+ rootAttrib.width,
2052+ 0,
2053+ CWX | CWWidth);
2054+
2055+ Advance (Display (),
2056+ ct::WaitForEventOfTypeOnWindowMatching (Display (),
2057+ mParent,
2058+ ConfigureNotify,
2059+ -1,
2060+ -1,
2061+ matcher));
2062+
2063+ /* Query the window geometry and ensure that the width and
2064+ * height have remained the same (adding on any extended borders,
2065+ * in this case 0) */
2066+ EXPECT_THAT (mParent, WindowGeometry (Display (),
2067+ _,
2068+ attrib.y,
2069+ _,
2070+ attrib.height,
2071+ _));
2072+}
2073+
2074
2075=== modified file 'tests/xorg-gtest/CMakeLists.txt'
2076--- tests/xorg-gtest/CMakeLists.txt 2013-05-10 04:16:30 +0000
2077+++ tests/xorg-gtest/CMakeLists.txt 2013-06-15 03:55:29 +0000
2078@@ -37,6 +37,7 @@
2079 ${CMAKE_CURRENT_SOURCE_DIR}/src/xorg_gtest_wrapper.cpp)
2080
2081 target_link_libraries (xorg_gtest_all
2082+ ${X11_XI_LIBRARIES}
2083 ${GTEST_BOTH_LIBRARIES}
2084 ${XORG_SERVER_GTEST_LIBRARIES})
2085
2086
2087=== modified file 'tests/xorg-gtest/include/compiz-xorg-gtest.h'
2088--- tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-03-21 18:19:04 +0000
2089+++ tests/xorg-gtest/include/compiz-xorg-gtest.h 2013-06-15 03:55:29 +0000
2090@@ -213,6 +213,8 @@
2091
2092 protected:
2093
2094+ virtual void SetUp ();
2095+
2096 Atom FetchAtom (const char *);
2097 std::vector <long> WaitForWindowCreation (Window w);
2098 bool IsOverrideRedirect (std::vector <long> &data);
2099@@ -221,8 +223,6 @@
2100
2101 private:
2102
2103- virtual void SetUp ();
2104-
2105 std::auto_ptr <PrivateAutostartCompizXorgSystemTestWithTestHelper> priv;
2106 };
2107 }

Subscribers

People subscribed via source and target branches

to all changes: