2
* Compiz XOrg GTest Decoration Acceptance Tests
4
* Copyright (C) 2013 Sam Spilsbury.
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
* Sam Spilsbury <smspillaz@gmail.com>
23
#include <gtest/gtest.h>
24
#include <gmock/gmock.h>
29
#include <boost/shared_array.hpp>
30
#include <boost/shared_ptr.hpp>
32
#include <boost/bind.hpp>
35
#include <X11/Xatom.h>
37
#include "decoration.h"
39
#include <core/point.h>
40
#include <core/size.h>
41
#include <core/rect.h>
43
#include <xorg/gtest/xorg-gtest.h>
44
#include <compiz-xorg-gtest.h>
46
#include <gtest_shared_tmpenv.h>
48
namespace xt = xorg::testing;
49
namespace ct = compiz::testing;
51
using ::testing::AtLeast;
52
using ::testing::ReturnNull;
53
using ::testing::Return;
54
using ::testing::MatcherInterface;
55
using ::testing::MatchResultListener;
56
using ::testing::Matcher;
57
using ::testing::MakeMatcher;
58
using ::testing::StrEq;
59
using ::testing::ValuesIn;
60
using ::testing::WithParamInterface;
63
using ::compiz::testing::HasGeometry;
64
using ::compiz::testing::RelativeWindowGeometry;
65
using ::compiz::testing::AbsoluteWindowGeometry;
67
class BaseDecorAcceptance :
68
public ct::AutostartCompizXorgSystemTestWithTestHelper
72
BaseDecorAcceptance ();
74
virtual void SetUp ();
75
virtual ct::CompizProcess::PluginList GetPluginList ();
82
Atom mDecorationManagerNameAtom;
83
Atom mDecorationTypeAtom;
84
Atom mDecorationTypePixmap;
85
Atom mDecorationTypeWindow;
86
Atom mDecorationInputFrameAtom;
87
Atom mDecorationOutputFrameAtom;
89
TmpEnv mDisableConfigureBufferLocksEnv;
93
int GetEventMask () const;
96
BaseDecorAcceptance::BaseDecorAcceptance () :
99
mDecorationManagerNameAtom (0),
100
mDecorationTypeAtom (0),
101
mDecorationTypePixmap (0),
102
mDecorationTypeWindow (0),
103
mDecorationInputFrameAtom (0),
104
mDecorationOutputFrameAtom (0),
105
/* Disable configure buffer locks as they cause event delivery indeterminacy
106
* that isn't useful for a testing environment */
107
mDisableConfigureBufferLocksEnv ("COMPIZ_NO_CONFIGURE_BUFFER_LOCKS", "1")
112
BaseDecorAcceptance::GetEventMask () const
114
return ct::AutostartCompizXorgSystemTestWithTestHelper::GetEventMask () |
115
SubstructureNotifyMask;
119
BaseDecorAcceptance::SetUp ()
121
ct::AutostartCompizXorgSystemTestWithTestHelper::SetUp ();
123
mUtf8StringAtom = XInternAtom (Display (),
127
ASSERT_NE (0, mUtf8StringAtom);
129
mDecorationManagerNameAtom = XInternAtom (Display (),
133
ASSERT_NE (0, mDecorationManagerNameAtom);
135
mDecorationTypePixmap = XInternAtom (Display (),
136
DECOR_TYPE_PIXMAP_ATOM_NAME,
139
ASSERT_NE (0, mDecorationTypePixmap);
141
mDecorationTypeWindow = XInternAtom (Display (),
142
DECOR_TYPE_WINDOW_ATOM_NAME,
145
ASSERT_NE (0, mDecorationTypeWindow);
147
mDecorationTypeAtom = XInternAtom (Display (),
148
DECOR_TYPE_ATOM_NAME,
151
ASSERT_NE (0, mDecorationTypeAtom);
153
mDecorationInputFrameAtom = XInternAtom (Display (),
154
DECOR_INPUT_FRAME_ATOM_NAME,
157
ASSERT_NE (0, mDecorationInputFrameAtom);
159
mDecorationOutputFrameAtom = XInternAtom (Display (),
160
DECOR_OUTPUT_FRAME_ATOM_NAME,
163
ASSERT_NE (0, mDecorationOutputFrameAtom);
165
mRootWindow = DefaultRootWindow (Display ());
167
ASSERT_NE (0, mRootWindow);
170
ct::CompizProcess::PluginList
171
BaseDecorAcceptance::GetPluginList ()
173
typedef ct::AutostartCompizXorgSystemTestWithTestHelper Base;
174
ct::CompizProcess::PluginList baseList (Base::GetPluginList ());
175
ct::CompizProcess::PluginList list;
177
list.push_back (ct::CompizProcess::Plugin ("composite",
178
ct::CompizProcess::Real));
179
list.push_back (ct::CompizProcess::Plugin ("opengl",
180
ct::CompizProcess::Real));
181
list.push_back (ct::CompizProcess::Plugin ("decor",
182
ct::CompizProcess::Real));
184
for (ct::CompizProcess::PluginList::iterator it = baseList.begin ();
185
it != baseList.end ();
187
list.push_back (*it);
199
const char *DecorationClientName = "fake";
201
const char *FailedToAcquireMessage =
202
"Could not acquire selection for an unknown reason";
203
const char *OtherDecorationManagerRunningMessage =
204
"Another decoration manager is already running";
209
unsigned long functions;
210
unsigned long decorations;
213
static const unsigned int MwmDecor = 1L << 0;
219
FakeDecorator (Display *d,
220
int supporting = WINDOW_DECORATION_TYPE_WINDOW);
223
Window currentSelectionOwner ();
224
Atom sessionOwnerAtom ();
226
Window supportingCheckWindow ();
234
Time mDecorationManagerTimestamp;
236
Atom mSessionOwnerAtom;
237
Window mSessionOwner;
239
Atom mSupportingHintAtom;
240
Atom mSupportingHintWindowAtom;
241
Window mSupportingHintWindow;
249
typedef boost::shared_ptr <FakeDecoration> Ptr;
251
FakeDecoration (unsigned int type,
253
unsigned int actions,
254
unsigned int minWidth,
255
unsigned int minHeight);
257
virtual ~FakeDecoration ();
259
virtual size_t propertyDataSize () const = 0;
260
virtual void addPropertyData (std::vector <long> &) const = 0;
262
bool match (unsigned int type,
264
unsigned int actions) const;
266
virtual CompPoint restoredFrameWindowOffset () const = 0;
267
virtual CompSize restoredDecorationBorderSize () const = 0;
268
virtual CompSize restoredDecorationInputSize () const = 0;
272
void insertBaseData (std::vector <long> &) const;
274
static const size_t BaseDataSize = 5;
278
unsigned int mActions;
280
unsigned int mMinWidth;
281
unsigned int mMinHeight;
284
class FakeWindowTypeDecoration :
285
public FakeDecoration
289
FakeWindowTypeDecoration (unsigned int type,
291
unsigned int actions,
292
unsigned int minWidth,
293
unsigned int minHeight,
294
const decor_extents_t &restored,
295
const decor_extents_t &maximized);
299
size_t propertyDataSize () const;
300
void addPropertyData (std::vector<long> &) const;
301
CompPoint restoredFrameWindowOffset () const;
302
CompSize restoredDecorationBorderSize () const;
303
CompSize restoredDecorationInputSize () const;
305
static const unsigned int WindowDecorationSize = 8;
309
decor_extents_t mRestored;
310
decor_extents_t mMaximized;
313
class FakePixmapTypeDecoration :
314
public FakeDecoration
318
typedef boost::shared_ptr <FakePixmapTypeDecoration> Ptr;
320
FakePixmapTypeDecoration (unsigned int type,
322
unsigned int actions,
323
unsigned int minWidth,
324
unsigned int minHeight,
325
const decor_extents_t &restoredBorder,
326
const decor_extents_t &restoredInput,
327
const decor_extents_t &maximizedBorder,
328
const decor_extents_t &maximizedInput,
330
~FakePixmapTypeDecoration ();
332
void changeRestoredBorder (const decor_extents_t &border);
333
void changeRestoredInput (const decor_extents_t &input);
335
CompPoint restoredFrameWindowOffset () const;
336
CompSize restoredDecorationBorderSize () const;
337
CompSize restoredDecorationInputSize () const;
341
size_t propertyDataSize () const;
342
void addPropertyData (std::vector<long> &) const;
346
decor_extents_t mRestoredBorder;
347
decor_extents_t mRestoredInput;
348
decor_extents_t mMaximizedBorder;
349
decor_extents_t mMaximizedInput;
351
decor_context_t mContext;
352
decor_quad_t mQuads[N_QUADS_MAX];
353
decor_layout_t mLayout;
354
unsigned int mNQuads;
360
class FakeDecorationList
364
FakeDecorationList () :
365
mDecorationType (WINDOW_DECORATION_TYPE_PIXMAP)
369
FakeDecorationList (unsigned int type) :
370
mDecorationType (type)
374
void AddDecoration (const FakeDecoration::Ptr &);
375
void RemoveDecoration (unsigned int type,
377
unsigned int actions);
378
void RemoveAllDecorations ();
380
void SetPropertyOnWindow (Display *dpy,
386
unsigned int mDecorationType;
387
std::vector <FakeDecoration::Ptr> decorations;
390
class AcquisitionFailed :
391
public std::exception
395
AcquisitionFailed (int status);
397
const char * what () const throw ();
410
bool Advance (Display *d, bool result)
412
return ct::AdvanceToNextEventOnSuccess (d, result);
415
class ManagerMessageMatcher :
416
public ct::ClientMessageXEventMatcher
420
ManagerMessageMatcher (Display *dpy,
423
virtual bool MatchAndExplain (const XEvent &event,
424
MatchResultListener *listener) const;
426
virtual void DescribeTo (std::ostream *os) const;
435
void FreePropertyData (unsigned char *array)
441
int SafeFetchProperty (Display *dpy,
449
unsigned long &returnNItems,
450
unsigned long &returnBytesRemaining,
451
boost::shared_ptr <unsigned char> &data)
453
unsigned char *dataLocation;
455
int status = XGetWindowProperty (dpy, w, property, offset, length, 0,
456
requestedType, &returnType,
457
&returnFormat, &returnNItems,
458
&returnBytesRemaining,
461
data.reset (dataLocation,
462
boost::bind (FreePropertyData, _1));
467
void FetchAndVerifyProperty (Display *dpy,
472
unsigned long expectedItems,
473
unsigned long expectedBytesAfter,
474
boost::shared_ptr <unsigned char> &data)
476
Atom returnedType = 0;
477
int returnedFormat = 0;
478
unsigned long returnedNItems = 0;
479
unsigned long returnedBytesRemaining = 0;
481
std::stringstream ss;
483
int status = SafeFetchProperty (dpy,
492
returnedBytesRemaining,
495
if (status != Success)
496
ss << "XGetWindowProperty failed:" << std::endl;
498
if (returnedType != expectedType)
499
ss << "Expected type of " << XGetAtomName (dpy, expectedType)
502
if (returnedFormat != expectedFormat)
503
ss << "Expected format of " << expectedFormat
504
<< " but got " << returnedFormat << std::endl;
506
if (returnedNItems != expectedItems)
507
ss << "Expected " << expectedItems << " items"
508
<< " but got " << returnedNItems << " items" << std::endl;
510
if (returnedBytesRemaining != expectedBytesAfter)
511
ss << "Expected " << expectedBytesAfter << " bytes remaining"
512
<< " but got " << returnedBytesRemaining << " bytes remaining"
515
if (!ss.str ().empty ())
516
throw std::logic_error (ss.str ());
520
ManagerMessageMatcher::ManagerMessageMatcher (Display *dpy,
522
ct::ClientMessageXEventMatcher (dpy,
526
DefaultRootWindow (dpy)),
533
ManagerMessageMatcher::MatchAndExplain (const XEvent &event,
534
MatchResultListener *listener) const
536
if (ct::ClientMessageXEventMatcher::MatchAndExplain (event, listener))
538
/* Evaluate the second field for the atom */
539
return event.xclient.data.l[1] ==
540
static_cast <long> (mManaged);
547
ManagerMessageMatcher::DescribeTo (std::ostream *os) const
549
*os << "manager of selection atom " << XGetAtomName (mDpy, mManaged);
554
namespace cdt = compiz::decor::testing;
556
cdt::FakeDecoration::FakeDecoration (unsigned int type,
558
unsigned int actions,
559
unsigned int minWidth,
560
unsigned int minHeight) :
564
mMinWidth (minWidth),
565
mMinHeight (minHeight)
569
cdt::FakeDecoration::~FakeDecoration ()
574
cdt::FakeDecoration::match (unsigned int type,
576
unsigned int actions) const
578
return type == mType &&
583
cdt::FakeWindowTypeDecoration::FakeWindowTypeDecoration (unsigned int type,
585
unsigned int actions,
586
unsigned int minWidth,
587
unsigned int minHeight,
588
const decor_extents_t &restored,
589
const decor_extents_t &maximized) :
590
FakeDecoration (type, state, actions, minWidth, minHeight),
591
mRestored (restored),
592
mMaximized (maximized)
597
cdt::FakeWindowTypeDecoration::addPropertyData (std::vector<long> &vec) const
599
long propData[PROP_HEADER_SIZE + propertyDataSize ()];
601
decor_gen_window_property (propData,
603
const_cast <decor_extents_t *> (&mRestored),
604
const_cast <decor_extents_t *> (&mMaximized),
611
for (size_t i = PROP_HEADER_SIZE;
612
i < (PROP_HEADER_SIZE + propertyDataSize ());
614
vec.push_back (propData[i]);
618
cdt::FakeWindowTypeDecoration::propertyDataSize () const
620
return WINDOW_PROP_SIZE;
624
cdt::FakeWindowTypeDecoration::restoredFrameWindowOffset () const
626
int xOffset = -mRestored.left;
627
int yOffset = -mRestored.top;
629
return CompPoint (xOffset, yOffset);
633
cdt::FakeWindowTypeDecoration::restoredDecorationBorderSize () const
635
return CompSize (mRestored.left + mRestored.right,
636
mRestored.top + mRestored.bottom);
640
cdt::FakeWindowTypeDecoration::restoredDecorationInputSize () const
642
return restoredDecorationBorderSize ();
645
cdt::FakePixmapTypeDecoration::FakePixmapTypeDecoration (unsigned int type,
647
unsigned int actions,
648
unsigned int minWidth,
649
unsigned int minHeight,
650
const decor_extents_t &restoredBorder,
651
const decor_extents_t &restoredInput,
652
const decor_extents_t &maximizedBorder,
653
const decor_extents_t &maximizedInput,
655
FakeDecoration (type, state, actions, minWidth, minHeight),
656
mRestoredBorder (restoredBorder),
657
mRestoredInput (restoredInput),
658
mMaximizedBorder (maximizedBorder),
659
mMaximizedInput (maximizedInput),
661
mPixmap (XCreatePixmap (mDpy,
662
DefaultRootWindow (mDpy),
665
DefaultDepth (mDpy, (DefaultScreen (mDpy)))))
667
/* 10x10 decoration, 0 corner space, 0 spacing, 2px each side */
668
mContext.extents.left = 2;
669
mContext.extents.right = 2;
670
mContext.extents.top = 2;
671
mContext.extents.bottom = 2;
673
mContext.left_space = 0;
674
mContext.right_space = 0;
675
mContext.top_space = 0;
676
mContext.bottom_space = 0;
677
mContext.left_corner_space = 0;
678
mContext.right_corner_space = 0;
679
mContext.top_corner_space = 0;
680
mContext.bottom_corner_space = 0;
682
decor_get_default_layout (&mContext, minWidth, minHeight, &mLayout);
683
mNQuads = decor_set_lSrStSbS_window_quads (mQuads, &mContext, &mLayout);
686
cdt::FakePixmapTypeDecoration::~FakePixmapTypeDecoration ()
688
XFreePixmap (mDpy, mPixmap);
692
cdt::FakePixmapTypeDecoration::propertyDataSize () const
694
return BASE_PROP_SIZE + (QUAD_PROP_SIZE * mNQuads);
698
cdt::FakePixmapTypeDecoration::addPropertyData (std::vector<long> &vec) const
700
long propData[PROP_HEADER_SIZE + propertyDataSize ()];
702
decor_quads_to_property (propData,
705
const_cast <decor_extents_t *> (&mRestoredInput),
706
const_cast <decor_extents_t *> (&mRestoredBorder),
707
const_cast <decor_extents_t *> (&mMaximizedInput),
708
const_cast <decor_extents_t *> (&mMaximizedBorder),
711
const_cast <decor_quad_t *> (mQuads),
717
for (size_t i = PROP_HEADER_SIZE;
718
i < (PROP_HEADER_SIZE + propertyDataSize ());
720
vec.push_back (propData[i]);
724
cdt::FakePixmapTypeDecoration::restoredFrameWindowOffset () const
726
int xOffset = mRestoredBorder.left - mRestoredInput.left;
727
int yOffset = mRestoredBorder.top - mRestoredInput.top;
729
return CompPoint (xOffset, yOffset);
733
cdt::FakePixmapTypeDecoration::restoredDecorationBorderSize () const
735
return CompSize (mRestoredBorder.left + mRestoredBorder.right,
736
mRestoredBorder.top + mRestoredBorder.bottom);
740
cdt::FakePixmapTypeDecoration::restoredDecorationInputSize () const
742
return CompSize (mRestoredInput.left + mRestoredInput.right,
743
mRestoredInput.top + mRestoredInput.bottom);
747
cdt::FakePixmapTypeDecoration::changeRestoredBorder (const decor_extents_t &b)
753
cdt::FakePixmapTypeDecoration::changeRestoredInput (const decor_extents_t &i)
759
cdt::FakeDecorationList::AddDecoration (const cdt::FakeDecoration::Ptr &decoration)
761
decorations.push_back (decoration);
766
bool MatchesTypeStateAndActions (const cdt::FakeDecoration::Ptr &decoration,
769
unsigned int actions)
771
return decoration->match (type, state, actions);
775
void cdt::FakeDecorationList::RemoveDecoration (unsigned int type,
777
unsigned int actions)
780
std::remove_if (decorations.begin (),
782
boost::bind (MatchesTypeStateAndActions,
790
void cdt::FakeDecorationList::RemoveAllDecorations ()
792
decorations.clear ();
796
cdt::FakeDecorationList::SetPropertyOnWindow (Display *dpy,
800
size_t size = PROP_HEADER_SIZE;
801
for (std::vector <FakeDecoration::Ptr>::iterator it = decorations.begin ();
802
it != decorations.end ();
804
size += (*it)->propertyDataSize ();
806
std::vector <long> data;
810
data.push_back (decor_version ());
811
data.push_back (mDecorationType);
812
data.push_back (decorations.size ());
814
for (std::vector <FakeDecoration::Ptr>::iterator it = decorations.begin ();
815
it != decorations.end ();
817
(*it)->addPropertyData (data);
819
XChangeProperty (dpy,
825
reinterpret_cast <unsigned char *> (&data[0]),
829
cdt::AcquisitionFailed::AcquisitionFailed (int status) :
835
cdt::AcquisitionFailed::what () const throw ()
839
case DECOR_ACQUIRE_STATUS_FAILED:
840
return FailedToAcquireMessage;
841
case DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING:
842
return OtherDecorationManagerRunningMessage;
844
return "Unknown status";
847
return "Unknown status";
850
cdt::FakeDecorator::FakeDecorator (Display *d,
853
mScreenNumber (DefaultScreen (d)),
854
mRootWindow (DefaultRootWindow (d)),
855
mSessionStatus (decor_acquire_dm_session (d,
859
&mDecorationManagerTimestamp)),
860
mSessionOwnerAtom (0),
862
mSupportingHintAtom (XInternAtom (d, DECOR_TYPE_ATOM_NAME, 0)),
863
mSupportingHintWindowAtom (XInternAtom (d,
864
DECOR_SUPPORTING_DM_CHECK_ATOM_NAME,
867
if (mSessionStatus != DECOR_ACQUIRE_STATUS_SUCCESS)
868
throw AcquisitionFailed (mSessionStatus);
870
std::stringstream sessionOwnerStream;
872
sessionOwnerStream << "_COMPIZ_DM_S" << mScreenNumber;
873
mSessionOwnerAtom = XInternAtom (d,
874
sessionOwnerStream.str ().c_str (),
877
mSessionOwner = XGetSelectionOwner (d, mSessionOwnerAtom);
880
throw std::runtime_error ("Expected a selection owner");
882
decor_set_dm_check_hint (d, mScreenNumber, supports);
884
boost::shared_ptr <unsigned char> data;
886
FetchAndVerifyProperty (mDpy,
888
mSupportingHintWindowAtom,
895
mSupportingHintWindow = *(reinterpret_cast <Window *> (data.get ()));
897
if (!mSupportingHintWindow)
898
throw std::runtime_error ("Failed to find supporting hint window");
903
cdt::FakeDecorator::~FakeDecorator ()
905
/* Destroy the session owner, taking the selection with it */
906
XDestroyWindow (mDpy, mSessionOwner);
907
XDestroyWindow (mDpy, mSupportingHintWindow);
911
cdt::FakeDecorator::currentSelectionOwner ()
913
return mSessionOwner;
917
cdt::FakeDecorator::sessionOwnerAtom ()
919
return mSessionOwnerAtom;
923
cdt::FakeDecorator::supportingCheckWindow ()
925
return mSupportingHintWindow;
928
TEST_F (BaseDecorAcceptance, Startup)
932
TEST_F (BaseDecorAcceptance, FakeDecoratorSessionOwnerNameSetOnSelectionOwner)
934
cdt::FakeDecorator decorator (Display ());
935
boost::shared_ptr <unsigned char> data;
937
FetchAndVerifyProperty (Display (),
938
decorator.currentSelectionOwner (),
939
mDecorationManagerNameAtom,
946
std::string name (reinterpret_cast <char *> (data.get ()));
948
EXPECT_THAT (name, StrEq (cdt::DecorationClientName));
952
TEST_F (BaseDecorAcceptance, FakeDecoratorReceiveClientMessage)
954
cdt::FakeDecorator decorator (Display ());
956
ManagerMessageMatcher matcher (Display (),
957
decorator.sessionOwnerAtom ());
959
EXPECT_TRUE (Advance (Display (),
960
ct::WaitForEventOfTypeOnWindowMatching (Display (),
968
TEST_F (BaseDecorAcceptance, DecorationSupportsWindowType)
970
cdt::FakeDecorator decorator (Display (),
971
WINDOW_DECORATION_TYPE_WINDOW);
973
boost::shared_ptr <unsigned char> data;
975
FetchAndVerifyProperty (Display (),
976
decorator.supportingCheckWindow (),
984
Atom *atoms = reinterpret_cast <Atom *> (data.get ());
985
EXPECT_EQ (atoms[0], mDecorationTypeWindow);
988
TEST_F (BaseDecorAcceptance, DecorationSupportsPixmapType)
990
cdt::FakeDecorator decorator (Display (),
991
WINDOW_DECORATION_TYPE_PIXMAP);
993
boost::shared_ptr <unsigned char> data;
995
FetchAndVerifyProperty (Display (),
996
decorator.supportingCheckWindow (),
1004
Atom *atoms = reinterpret_cast <Atom *> (data.get ());
1005
EXPECT_EQ (atoms[0], mDecorationTypePixmap);
1008
class DecorFakeDecoratorAcceptance :
1009
public BaseDecorAcceptance
1013
virtual void SetUp ();
1014
virtual void TearDown ();
1016
virtual unsigned int SupportedDecorations () const;
1017
virtual bool StartDecoratorOnSetUp () const;
1019
void SetUpDecorator ();
1021
void DisallowDecorationsOnWindow (Window window);
1022
void AllowDecorationsOnWindow (Window window);
1024
std::auto_ptr <cdt::FakeDecorator> decorator;
1026
Atom NETWMFrameExtentsAtom;
1027
Atom WindowDecorationAtom;
1028
Atom DefaultActiveDecorationAtom;
1029
Atom DefaultBareDecorationAtom;
1034
DecorFakeDecoratorAcceptance::SetUp ()
1036
BaseDecorAcceptance::SetUp ();
1038
NETWMFrameExtentsAtom = XInternAtom (Display (),
1039
"_NET_FRAME_EXTENTS",
1042
WindowDecorationAtom = XInternAtom (Display (),
1043
DECOR_WINDOW_ATOM_NAME,
1046
DefaultActiveDecorationAtom = XInternAtom (Display (),
1047
DECOR_ACTIVE_ATOM_NAME,
1050
DefaultBareDecorationAtom = XInternAtom (Display (),
1051
DECOR_BARE_ATOM_NAME,
1054
if (StartDecoratorOnSetUp ())
1059
DecorFakeDecoratorAcceptance::SetUpDecorator ()
1061
decorator.reset (new cdt::FakeDecorator (Display (),
1062
SupportedDecorations ()));
1067
void ChangeDecorationState (Display *display,
1069
unsigned int decorationFlags)
1071
Atom mwmHintsAtom = XInternAtom (display, "_MOTIF_WM_HINTS", 0);
1072
cdt::MWMHints hints;
1074
hints.flags = 1L << 1;
1075
hints.decorations = decorationFlags;
1077
XChangeProperty (display,
1083
reinterpret_cast <unsigned char *> (&hints),
1089
DecorFakeDecoratorAcceptance::DisallowDecorationsOnWindow (Window window)
1091
ChangeDecorationState (Display (), window, 0);
1095
DecorFakeDecoratorAcceptance::AllowDecorationsOnWindow (Window window)
1097
ChangeDecorationState (Display (), window, cdt::MwmDecor);
1101
DecorFakeDecoratorAcceptance::TearDown ()
1105
BaseDecorAcceptance::TearDown ();
1109
DecorFakeDecoratorAcceptance::SupportedDecorations () const
1111
return WINDOW_DECORATION_TYPE_WINDOW;
1115
DecorFakeDecoratorAcceptance::StartDecoratorOnSetUp () const
1122
void RecievePropertyNotifyEvents (Display *dpy,
1125
XWindowAttributes attrib;
1127
XGetWindowAttributes (dpy, w, &attrib);
1128
XSelectInput (dpy, w, attrib.your_event_mask | PropertyChangeMask);
1131
void WaitForPropertyNotify (Display *dpy,
1133
std::string const &prop)
1135
RecievePropertyNotifyEvents (dpy, w);
1137
ct::PropertyNotifyXEventMatcher matcher (dpy,
1140
ASSERT_TRUE (Advance (dpy,
1141
ct::WaitForEventOfTypeOnWindowMatching (dpy,
1149
void WaitForConfigureOn (Display *display,
1154
unsigned int height,
1157
/* Wait for the ConfigureNotify on the frame window
1158
* after an offset move */
1159
ct::ConfigureNotifyXEventMatcher matcher (None,
1168
ct::WaitForEventOfTypeOnWindowMatching (display,
1176
void WaitForFrameExtents (Display *dpy,
1179
RecievePropertyNotifyEvents (dpy, w);
1181
XMapRaised (dpy, w);
1183
WaitForPropertyNotify (dpy, w, "_NET_FRAME_EXTENTS");
1186
Window FindParent (Display *dpy,
1191
Window root = DefaultRootWindow (dpy);
1193
while (next != root)
1199
unsigned int nchildren;
1201
int status = XQueryTree (dpy, parent, &dummy, &next, &children, &nchildren);
1205
throw std::logic_error ("XQueryTree failed");
1211
void FreeWindowArray (Window *array)
1217
boost::shared_array <Window> FetchChildren (Display *dpy,
1224
int status = XQueryTree (dpy,
1232
throw std::logic_error ("XQueryTree failed");
1234
return boost::shared_array <Window> (children,
1235
boost::bind (FreeWindowArray, _1));
1238
class FrameExtentsMatcher :
1239
public MatcherInterface <unsigned long *>
1243
FrameExtentsMatcher (unsigned int left,
1246
unsigned int bottom);
1248
bool MatchAndExplain (unsigned long *extents,
1249
MatchResultListener *listener) const;
1251
void DescribeTo (std::ostream *os) const;
1256
unsigned int mRight;
1258
unsigned int mBottom;
1261
Matcher <unsigned long *>
1262
IsExtents (unsigned int left,
1265
unsigned int bottom)
1267
return MakeMatcher (new FrameExtentsMatcher (left, right, top, bottom));
1271
FrameExtentsMatcher::FrameExtentsMatcher (unsigned int left,
1274
unsigned int bottom) :
1283
FrameExtentsMatcher::MatchAndExplain (unsigned long *extents,
1284
MatchResultListener *listener) const
1286
return mLeft == extents[0] &&
1287
mRight == extents[1] &&
1288
mTop == extents[2] &&
1289
mBottom == extents[3];
1293
FrameExtentsMatcher::DescribeTo (std::ostream *os) const
1295
*os << "Expected frame extents of :" << std::endl
1296
<< " left: " << mLeft << std::endl
1297
<< " right: " << mRight << std::endl
1298
<< " top: " << mTop << std::endl
1299
<< " bottom: " << mBottom << std::endl;
1302
TEST_F (DecorFakeDecoratorAcceptance, WindowDefaultFallbackNoExtents)
1304
Window w = ct::CreateNormalWindow (Display ());
1305
WaitForFrameExtents (Display (), w);
1307
boost::shared_ptr <unsigned char> data;
1309
FetchAndVerifyProperty (Display (),
1311
NETWMFrameExtentsAtom,
1318
unsigned long *frameExtents =
1319
reinterpret_cast <unsigned long *> (data.get ());
1321
EXPECT_THAT (frameExtents, IsExtents (0, 0, 0, 0));
1324
class DecorWithPixmapDefaultsAcceptance :
1325
public DecorFakeDecoratorAcceptance
1329
DecorWithPixmapDefaultsAcceptance ();
1331
virtual void SetUp ();
1332
virtual void TearDown ();
1333
virtual unsigned int SupportedDecorations () const;
1341
cdt::FakeDecoration::Ptr defaultActiveDecoration ();
1343
cdt::FakeDecoration::Ptr rootActiveDecoration;
1344
cdt::FakeDecoration::Ptr rootBareDecoration;
1346
cdt::FakeDecorationList rootActiveDecorationList;
1347
cdt::FakeDecorationList rootBareDecorationList;
1349
static const unsigned int MaximizedBorderExtent = 1;
1350
static const unsigned int ActiveBorderExtent = 2;
1351
static const unsigned int ActiveInputExtent = 4;
1356
cdt::FakePixmapTypeDecoration::Ptr
1357
MakeFakePixmapTypeDecoration (unsigned int type,
1359
unsigned int actions,
1360
unsigned int minWidth,
1361
unsigned int minHeight,
1362
const decor_extents_t &restoredBorder,
1363
const decor_extents_t &restoredInput,
1364
const decor_extents_t &maximizedBorder,
1365
const decor_extents_t &maximizedInput,
1368
cdt::FakePixmapTypeDecoration *decoration =
1369
new cdt::FakePixmapTypeDecoration (type,
1380
return boost::shared_ptr <cdt::FakePixmapTypeDecoration> (decoration);
1384
DecorationExtents (unsigned int left,
1387
unsigned int bottom)
1389
decor_extents_t extents;
1391
extents.left = left;
1392
extents.right = right;
1394
extents.bottom = bottom;
1399
class ExtentsFromMatcher :
1400
public MatcherInterface <Window>
1404
ExtentsFromMatcher (Display *dpy,
1406
const decor_extents_t &extents);
1408
bool MatchAndExplain (Window window,
1409
MatchResultListener *listener) const;
1411
void DescribeTo (std::ostream *os) const;
1417
decor_extents_t mExpectedExtents;
1421
ExtendsFromWindowBy (Display *dpy,
1423
const decor_extents_t &extents)
1425
return MakeMatcher (new ExtentsFromMatcher (dpy, w, extents));
1430
operator<< (std::ostream &lhs, const decor_extents_t &extents)
1432
return lhs << "Extents: " << std::endl
1433
<< " left: " << extents.left << std::endl
1434
<< " right: " << extents.right << std::endl
1435
<< " top: " << extents.top << std::endl
1436
<< " bottom: " << extents.bottom << std::endl;
1439
ExtentsFromMatcher::ExtentsFromMatcher (Display *dpy,
1441
const decor_extents_t &extents) :
1444
mExpectedExtents (extents)
1449
ExtentsFromMatcher::MatchAndExplain (Window window,
1450
MatchResultListener *listener) const
1452
unsigned int border, depth;
1455
int compareX, compareY, matchX, matchY;
1456
unsigned int compareWidth, compareHeight, matchWidth, matchHeight;
1458
if (!XGetGeometry (mDpy, window, &root,
1459
&matchX, &matchY, &matchWidth, &matchHeight,
1461
throw std::logic_error ("XGetGeometry failed");
1463
if (!XGetGeometry (mDpy, mWindow, &root,
1464
&compareX, &compareY, &compareWidth, &compareHeight,
1466
throw std::logic_error ("XGetGeometry failed");
1468
unsigned int left = matchX - compareX;
1469
unsigned int top = matchY - compareY;
1470
unsigned int right = (matchX + matchWidth) - (compareX + compareWidth);
1471
unsigned int bottom = (matchY + matchHeight) - (compareY + compareHeight);
1473
decor_extents_t determinedExtents = DecorationExtents (left, right, top, bottom);
1475
return decor_extents_cmp (&determinedExtents, &mExpectedExtents);
1479
ExtentsFromMatcher::DescribeTo (std::ostream *os) const
1481
*os << "Extends outwards from " << std::hex << mWindow << std::dec
1482
<< " by: " << mExpectedExtents;
1485
DecorWithPixmapDefaultsAcceptance::DecorWithPixmapDefaultsAcceptance () :
1487
rootActiveDecorationList (WINDOW_DECORATION_TYPE_PIXMAP),
1488
rootBareDecorationList (WINDOW_DECORATION_TYPE_PIXMAP)
1493
DecorWithPixmapDefaultsAcceptance::SupportedDecorations () const
1495
return WINDOW_DECORATION_TYPE_PIXMAP;
1499
DecorWithPixmapDefaultsAcceptance::SetUp ()
1501
DecorFakeDecoratorAcceptance::SetUp ();
1503
mRoot = DefaultRootWindow (Display ());
1505
unsigned int ResBo = ActiveBorderExtent;
1506
unsigned int ResIn = ActiveInputExtent;
1507
unsigned int MaxEx = MaximizedBorderExtent;
1509
decor_extents_t activeBorderRestored (DecorationExtents (ResBo, ResBo, ResBo, ResBo));
1510
decor_extents_t activeBorderMaximized (DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx));
1511
decor_extents_t activeInputRestored (DecorationExtents (ResIn, ResIn, ResIn, ResIn));
1512
decor_extents_t activeInputMaximized (DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx));
1514
decor_extents_t emptyExtents (DecorationExtents (0, 0, 0, 0));
1516
rootActiveDecoration =
1517
MakeFakePixmapTypeDecoration (DECOR_WINDOW_TYPE_NORMAL,
1521
activeBorderRestored,
1522
activeInputRestored,
1523
activeBorderMaximized,
1524
activeInputMaximized,
1527
rootBareDecoration =
1528
MakeFakePixmapTypeDecoration (0, 0, 0,
1536
rootActiveDecorationList.AddDecoration (rootActiveDecoration);
1537
rootBareDecorationList.AddDecoration (rootBareDecoration);
1539
rootActiveDecorationList.SetPropertyOnWindow (Display (),
1541
DefaultActiveDecorationAtom);
1542
rootBareDecorationList.SetPropertyOnWindow (Display (),
1544
DefaultBareDecorationAtom);
1548
DecorWithPixmapDefaultsAcceptance::TearDown ()
1550
/* Remove inserted decorations */
1551
rootActiveDecorationList.RemoveAllDecorations ();
1552
rootBareDecorationList.RemoveAllDecorations ();
1554
/* This is a bit of a kludge, but we also need to reset
1555
* the two decorations manually before TearDown. We can
1556
* probably fix this later by encapsulating it all in one
1557
* class, but that's a bit of an effort */
1558
rootActiveDecoration.reset ();
1559
rootBareDecoration.reset ();
1561
DecorFakeDecoratorAcceptance::TearDown ();
1564
TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackRecieveInputFrameNotify)
1566
Window w = ct::CreateNormalWindow (Display ());
1567
RecievePropertyNotifyEvents (Display (), w);
1568
XMapRaised (Display (), w);
1570
ct::PropertyNotifyXEventMatcher matcher (Display (),
1571
DECOR_INPUT_FRAME_ATOM_NAME);
1573
EXPECT_TRUE (Advance (Display (),
1574
ct::WaitForEventOfTypeOnWindowMatching (Display (),
1582
TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackHasInputFrameInParent)
1584
Window w = ct::CreateNormalWindow (Display ());
1586
XMapRaised (Display (), w);
1587
WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
1589
Window parent = FindParent (Display (), w);
1591
unsigned int nChildren;
1592
boost::shared_array <Window> children (FetchChildren (Display (),
1596
EXPECT_EQ (2, nChildren);
1601
Window FindDecorationWindowFromChildren (Display *dpy,
1602
const boost::shared_array <Window> &c,
1603
unsigned int nChildren)
1605
for (unsigned int i = 0; i < nChildren; ++i)
1607
/* The decoration window will have no children, but
1608
* the wrapper window will have one child */
1610
boost::shared_array <Window> childChildren (FetchChildren (dpy,
1621
TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackNormalWindowExtentOnDecoration)
1623
Window w = ct::CreateNormalWindow (Display ());
1625
XMapRaised (Display (), w);
1626
WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
1628
Window parent = FindParent (Display (), w);
1630
unsigned int nChildren;
1631
boost::shared_array <Window> children (FetchChildren (Display (),
1635
ASSERT_EQ (2, nChildren);
1637
Window decorationWindow = FindDecorationWindowFromChildren (Display (),
1641
ASSERT_NE (None, decorationWindow);
1643
decor_extents_t borderExtents (DecorationExtents (ActiveBorderExtent,
1646
ActiveBorderExtent));
1647
EXPECT_THAT (decorationWindow, ExtendsFromWindowBy (Display (),
1652
TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackNormalWindowInputOnFrame)
1654
Window w = ct::CreateNormalWindow (Display ());
1656
XMapRaised (Display (), w);
1657
WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
1659
Window parent = FindParent (Display (), w);
1661
decor_extents_t inputExtents (DecorationExtents (ActiveInputExtent,
1664
ActiveInputExtent));
1665
EXPECT_THAT (parent, ExtendsFromWindowBy (Display (),
1670
/* TODO: Get bare decorations tests */
1672
/* Helper class with some useful member functions */
1673
class PixmapDecoratorAcceptance :
1674
public DecorWithPixmapDefaultsAcceptance
1678
typedef cdt::FakeDecoration::Ptr FakeDecorPtr;
1679
typedef cdt::FakePixmapTypeDecoration::Ptr FakePixDecorPtr;
1681
virtual void TearDown ();
1683
Window CreateDecoratableWindow (::Display *display);
1684
Window MapAndReparent (::Display *display,
1687
void DecorateWindow (::Display *display,
1689
const FakePixDecorPtr &decoration);
1690
void WaitForDecoration (::Display *display,
1692
const FakeDecorPtr &decoration);
1693
void WaitForDefaultDecoration (::Display *display,
1695
CompRect &testFrameDecorationGeometry,
1696
CompRect &testWindowDecorationGeometry);
1697
void WaitForDecorationUpdate (::Display *display,
1699
const FakeDecorPtr &decor);
1701
cdt::FakeDecorationList GetDecorations (Window window);
1702
Window GetParent (Window window);
1704
void ReconfigureDecoration (::Display *display,
1706
const FakePixDecorPtr &decor,
1707
cdt::FakeDecorationList &list,
1708
const decor_extents_t &border,
1709
const decor_extents_t &input);
1711
bool DestroyWindow (::Display *display,
1717
std::map <Window, cdt::FakeDecorationList> windowDecorations;
1718
std::map <Window, Window> windowParents;
1722
PixmapDecoratorAcceptance::TearDown ()
1724
windowDecorations.clear ();
1726
DecorWithPixmapDefaultsAcceptance::TearDown ();
1730
PixmapDecoratorAcceptance::CreateDecoratableWindow (::Display *display)
1732
return ct::CreateNormalWindow (display);
1736
PixmapDecoratorAcceptance::MapAndReparent (::Display *display,
1739
if (windowParents.find (window) != windowParents.end ())
1740
return windowParents[window];
1742
XSelectInput (display, window,
1743
StructureNotifyMask |
1744
PropertyChangeMask);
1745
XMapRaised (display, window);
1747
/* Wait for the window to be reparented */
1748
Advance (Display (),
1749
ct::WaitForEventOfTypeOnWindow (display,
1755
/* Select for StructureNotify on the parent and wrapper
1757
windowParents[window] = FindParent (display, window);
1760
Window wrapper = ct::GetImmediateParent (display, window, root);
1762
XSelectInput (display, windowParents[window], StructureNotifyMask);
1763
XSelectInput (display, wrapper, StructureNotifyMask);
1765
return windowParents[window];
1769
PixmapDecoratorAcceptance::DecorateWindow (::Display *display,
1771
const FakePixDecorPtr &decoration)
1773
windowDecorations[window] = cdt::FakeDecorationList (WINDOW_DECORATION_TYPE_PIXMAP);
1774
windowDecorations[window].AddDecoration (decoration);
1775
windowDecorations[window].SetPropertyOnWindow (display,
1777
WindowDecorationAtom);
1781
PixmapDecoratorAcceptance::WaitForDecoration (::Display *display,
1783
const FakeDecorPtr &decoration)
1785
WaitForDecorationUpdate (display, window, decoration);
1786
WaitForPropertyNotify (display, window, DECOR_INPUT_FRAME_ATOM_NAME);
1790
PixmapDecoratorAcceptance::WaitForDefaultDecoration (::Display *display,
1792
CompRect &decoratedWindowGeometry,
1793
CompRect &decoratedFrameGeometry)
1795
WaitForDecoration (display, window, rootActiveDecoration);
1797
/* Fetch the window's absolute geometry */
1799
unsigned int width, height, border;
1801
ct::AbsoluteWindowGeometry (display, window, x, y, width, height, border);
1803
/* Fetch frame extents */
1804
boost::shared_ptr <unsigned char> data;
1806
FetchAndVerifyProperty (Display (),
1808
NETWMFrameExtentsAtom,
1815
unsigned long *frameExtents =
1816
reinterpret_cast <unsigned long *> (data.get ());
1818
decoratedWindowGeometry.setGeometry (x, y, width, height);
1820
/* Adjust for decoration size. This is what future decorations
1821
* will add and subtract from */
1822
decoratedFrameGeometry.setGeometry (x - frameExtents[0],
1823
y - frameExtents[2],
1824
width + (frameExtents[0] + frameExtents[1]),
1825
height + (frameExtents[2] + frameExtents[3]));
1829
PixmapDecoratorAcceptance::WaitForDecorationUpdate (::Display *display,
1831
const FakeDecorPtr &decor)
1833
const CompPoint &framePos (decor->restoredFrameWindowOffset ());
1835
/* Wait for the ConfigureNotify on the frame window
1836
* after an offset move */
1837
WaitForConfigureOn (display,
1845
/* Wait for the frame extents to change */
1846
WaitForPropertyNotify (display, window, "_NET_FRAME_EXTENTS");
1850
PixmapDecoratorAcceptance::ReconfigureDecoration (::Display *display,
1852
const FakePixDecorPtr &decor,
1853
cdt::FakeDecorationList &list,
1854
const decor_extents_t &border,
1855
const decor_extents_t &input)
1857
decor->changeRestoredInput (input);
1858
decor->changeRestoredBorder (border);
1859
list.SetPropertyOnWindow (display,
1861
WindowDecorationAtom);
1863
WaitForDecorationUpdate (display, window, decor);
1867
PixmapDecoratorAcceptance::DestroyWindow (::Display *display,
1870
std::map <Window, Window>::iterator parentIterator =
1871
windowParents.find (window);
1872
std::map <Window, cdt::FakeDecorationList>::iterator decorIterator =
1873
windowDecorations.find (window);
1875
if (parentIterator != windowParents.end ())
1876
windowParents.erase (parentIterator);
1877
if (decorIterator != windowDecorations.end ())
1879
windowDecorations[window].RemoveAllDecorations ();
1880
windowDecorations.erase (decorIterator);
1883
XDestroyWindow (display, window);
1885
return parentIterator != windowParents.end () ||
1886
decorIterator != windowDecorations.end ();
1890
PixmapDecoratorAcceptance::GetParent (Window window)
1892
return windowParents[window];
1895
cdt::FakeDecorationList
1896
PixmapDecoratorAcceptance::GetDecorations (Window window)
1898
return windowDecorations[window];
1901
class PixmapInitialDecorationAcceptance :
1902
public PixmapDecoratorAcceptance
1906
virtual void SetUp ();
1907
virtual void TearDown ();
1909
virtual bool StartDecoratorOnSetUp () const;
1911
Window CreateDecoratedWindow ();
1915
cdt::FakePixmapTypeDecoration::Ptr mTestWindowDecoration;
1916
CompRect mClientGeometryOnInitialDecoration;
1917
CompRect mBorderGeometryOnInitialDecoration;
1921
PixmapInitialDecorationAcceptance::SetUp ()
1923
PixmapDecoratorAcceptance::SetUp ();
1925
unsigned int ResBo = ActiveBorderExtent + 1;
1926
unsigned int ResIn = ActiveInputExtent;
1927
unsigned int MaxEx = MaximizedBorderExtent;
1929
mTestWindowDecoration =
1930
MakeFakePixmapTypeDecoration (DECOR_WINDOW_TYPE_NORMAL,
1935
DecorationExtents (ResBo, ResBo, ResBo, ResBo),
1936
DecorationExtents (ResIn, ResIn, ResIn, ResIn),
1937
DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
1938
DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
1943
PixmapInitialDecorationAcceptance::StartDecoratorOnSetUp () const
1949
PixmapInitialDecorationAcceptance::TearDown ()
1951
mTestWindowDecoration.reset ();
1952
PixmapDecoratorAcceptance::TearDown ();
1956
PixmapInitialDecorationAcceptance::CreateDecoratedWindow ()
1958
Window testWindow = CreateDecoratableWindow (Display ());
1960
/* We need to first explicitly recieve PropertyNotify events before
1961
* core starts sending them */
1962
RecievePropertyNotifyEvents (Display (), testWindow);
1964
/* Map and reparent the window so that it gets a decoration */
1965
MapAndReparent (Display (), testWindow);
1967
/* Start the decorator */
1970
WaitForDefaultDecoration (Display (),
1972
mClientGeometryOnInitialDecoration,
1973
mBorderGeometryOnInitialDecoration);
1974
DecorateWindow (Display (), testWindow, mTestWindowDecoration);
1975
WaitForDecorationUpdate (Display (), testWindow, mTestWindowDecoration);
1981
operator<< (std::ostream &os, const CompSize &sz)
1983
return os << "Size: (width: "
1990
TEST_F (PixmapInitialDecorationAcceptance, NoSizeChangeInitially)
1992
CreateDecoratedWindow ();
1993
EXPECT_EQ (CompSize (mClientGeometryOnInitialDecoration.width (),
1994
mClientGeometryOnInitialDecoration.height ()),
1995
CompSize (ct::WINDOW_WIDTH,
1996
ct::WINDOW_HEIGHT));
1999
TEST_F (PixmapInitialDecorationAcceptance, SizeChangesApplySubsequently)
2001
Window testWindow = CreateDecoratedWindow ();
2003
/* Measuring size change from default decoration to real decoration */
2004
const CompSize &size (mTestWindowDecoration->restoredDecorationBorderSize ());
2006
EXPECT_THAT (testWindow,
2007
HasGeometry (Display (),
2008
RelativeWindowGeometry,
2011
mBorderGeometryOnInitialDecoration.width () -
2013
mBorderGeometryOnInitialDecoration.height () -
2018
class PixmapDecoratedWindowAcceptance :
2019
public PixmapDecoratorAcceptance
2023
PixmapDecoratedWindowAcceptance ();
2025
virtual void SetUp ();
2026
virtual void TearDown ();
2028
virtual bool StartDecoratorOnSetUp () const;
2032
unsigned int RealDecorationActiveBorderExtent;
2035
Window mTestWindowParent;
2037
cdt::FakePixmapTypeDecoration::Ptr mTestWindowDecoration;
2038
CompRect mClientGeometryOnInitialDecoration;
2039
CompRect mBorderGeometryOnInitialDecoration;
2042
PixmapDecoratedWindowAcceptance::PixmapDecoratedWindowAcceptance () :
2043
RealDecorationActiveBorderExtent (ActiveBorderExtent + 1)
2048
PixmapDecoratedWindowAcceptance::SetUp ()
2050
DecorWithPixmapDefaultsAcceptance::SetUp ();
2052
::Display *display = Display ();
2054
mTestWindow = CreateDecoratableWindow (display);
2055
mTestWindowParent = MapAndReparent (display, mTestWindow);
2057
/* Start the decorator */
2060
WaitForDefaultDecoration (display,
2062
mClientGeometryOnInitialDecoration,
2063
mBorderGeometryOnInitialDecoration);
2065
/* We need to change the border extent so that the window
2066
* will move from its position in the default decoration */
2067
unsigned int ResBo = RealDecorationActiveBorderExtent;
2068
unsigned int ResIn = ActiveInputExtent;
2069
unsigned int MaxEx = MaximizedBorderExtent;
2071
mTestWindowDecoration =
2072
MakeFakePixmapTypeDecoration (DECOR_WINDOW_TYPE_NORMAL,
2077
DecorationExtents (ResBo, ResBo, ResBo, ResBo),
2078
DecorationExtents (ResIn, ResIn, ResIn, ResIn),
2079
DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
2080
DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
2083
DecorateWindow (display, mTestWindow, mTestWindowDecoration);
2084
WaitForDecorationUpdate (display, mTestWindow, mTestWindowDecoration);
2088
PixmapDecoratedWindowAcceptance::TearDown ()
2090
mTestWindowDecoration.reset ();
2091
DestroyWindow (Display (), mTestWindow);
2093
PixmapDecoratorAcceptance::TearDown ();
2097
PixmapDecoratedWindowAcceptance::StartDecoratorOnSetUp () const
2104
static const unsigned int RemoveState = 0;
2105
static const unsigned int AddState = 1;
2106
static const unsigned int ToggleState = 2;
2108
void ChangeStateOfWindow (Display *dpy,
2110
const std::string &state,
2115
const long ClientTypePager = 2;
2117
event.type = ClientMessage;
2118
event.xany.window = w;
2120
event.xclient.format = 32;
2121
event.xclient.message_type = XInternAtom (dpy, "_NET_WM_STATE", 0);
2123
event.xclient.data.l[0] = mode;
2124
event.xclient.data.l[1] = XInternAtom (dpy, state.c_str (), 0);
2125
event.xclient.data.l[2] = 0;
2126
event.xclient.data.l[3] = ClientTypePager;
2129
DefaultRootWindow (dpy),
2131
SubstructureRedirectMask,
2136
boost::shared_ptr <unsigned char>
2137
FetchCardinalProperty (Display *dpy,
2139
Atom NETWMFrameExtentsAtom)
2141
boost::shared_ptr <unsigned char> data;
2143
FetchAndVerifyProperty (dpy,
2145
NETWMFrameExtentsAtom,
2156
TEST_F (PixmapDecoratedWindowAcceptance, MaximizeBorderExtentsOnMaximize)
2158
ChangeStateOfWindow (Display (),
2160
"_NET_WM_STATE_MAXIMIZED_VERT",
2163
WaitForPropertyNotify (Display (), mTestWindow, "_NET_FRAME_EXTENTS");
2165
ChangeStateOfWindow (Display (),
2167
"_NET_WM_STATE_MAXIMIZED_HORZ",
2170
WaitForPropertyNotify (Display (), mTestWindow, "_NET_FRAME_EXTENTS");
2172
boost::shared_ptr <unsigned char> data =
2173
FetchCardinalProperty (Display (),
2175
NETWMFrameExtentsAtom);
2177
unsigned long *frameExtents =
2178
reinterpret_cast <unsigned long *> (data.get ());
2180
unsigned int MaxEx = MaximizedBorderExtent;
2182
EXPECT_THAT (frameExtents, IsExtents (MaxEx, MaxEx, MaxEx, MaxEx));
2185
TEST_F (PixmapDecoratedWindowAcceptance, RestoredBorderExtentsOnVertMaximize)
2187
ChangeStateOfWindow (Display (),
2189
"_NET_WM_STATE_MAXIMIZED_VERT",
2192
WaitForPropertyNotify (Display (), mTestWindow, "_NET_FRAME_EXTENTS");
2194
boost::shared_ptr <unsigned char> data =
2195
FetchCardinalProperty (Display (),
2197
NETWMFrameExtentsAtom);
2199
unsigned long *frameExtents =
2200
reinterpret_cast <unsigned long *> (data.get ());
2202
unsigned int ActEx = RealDecorationActiveBorderExtent;
2204
EXPECT_THAT (frameExtents, IsExtents (ActEx, ActEx, ActEx, ActEx));
2207
TEST_F (PixmapDecoratedWindowAcceptance, RestoredBorderExtentsOnHorzMaximize)
2209
ChangeStateOfWindow (Display (),
2211
"_NET_WM_STATE_MAXIMIZED_HORZ",
2214
WaitForPropertyNotify (Display (), mTestWindow, "_NET_FRAME_EXTENTS");
2216
boost::shared_ptr <unsigned char> data =
2217
FetchCardinalProperty (Display (),
2219
NETWMFrameExtentsAtom);
2221
unsigned long *frameExtents =
2222
reinterpret_cast <unsigned long *> (data.get ());
2224
unsigned int ActEx = RealDecorationActiveBorderExtent;
2226
EXPECT_THAT (frameExtents, IsExtents (ActEx, ActEx, ActEx, ActEx));
2229
TEST_F (PixmapDecoratedWindowAcceptance, MaximizeFrameWindowSizeEqOutputSize)
2231
XWindowAttributes attrib;
2232
XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
2234
/* The assumption here is that there is only one output */
2236
ChangeStateOfWindow (Display (),
2238
"_NET_WM_STATE_MAXIMIZED_VERT",
2241
ChangeStateOfWindow (Display (),
2243
"_NET_WM_STATE_MAXIMIZED_HORZ",
2246
ct::ConfigureNotifyXEventMatcher matcher (None,
2252
CWX | CWY | CWWidth | CWHeight);
2254
EXPECT_TRUE (Advance (Display (),
2255
ct::WaitForEventOfTypeOnWindowMatching (Display (),
2263
TEST_F (PixmapDecoratedWindowAcceptance, VertMaximizeFrameWindowYHeight)
2265
XWindowAttributes attrib;
2266
XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
2268
ChangeStateOfWindow (Display (),
2270
"_NET_WM_STATE_MAXIMIZED_VERT",
2273
int offset = RealDecorationActiveBorderExtent - ActiveInputExtent;
2274
ct::ConfigureNotifyXEventMatcher matcher (None,
2279
attrib.height - 2 * offset,
2282
EXPECT_TRUE (Advance (Display (),
2283
ct::WaitForEventOfTypeOnWindowMatching (Display (),
2291
TEST_F (PixmapDecoratedWindowAcceptance, HorzMaximizeFrameWindowXWidth)
2293
XWindowAttributes attrib;
2294
XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
2296
ChangeStateOfWindow (Display (),
2298
"_NET_WM_STATE_MAXIMIZED_HORZ",
2301
int offset = RealDecorationActiveBorderExtent - ActiveInputExtent;
2302
ct::ConfigureNotifyXEventMatcher matcher (None,
2306
attrib.width - 2 * offset,
2310
EXPECT_TRUE (Advance (Display (),
2311
ct::WaitForEventOfTypeOnWindowMatching (Display (),
2319
TEST_F (PixmapDecoratedWindowAcceptance, VertMaximizeFrameWindowSizeSameXWidth)
2321
XWindowAttributes rootAttrib, attrib;
2322
XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &rootAttrib);
2323
XGetWindowAttributes (Display (), mTestWindowParent, &attrib);
2325
ChangeStateOfWindow (Display (),
2327
"_NET_WM_STATE_MAXIMIZED_VERT",
2330
/* Wait for the window to be maximized first */
2331
int offset = RealDecorationActiveBorderExtent - ActiveInputExtent;
2332
WaitForConfigureOn (Display (),
2337
rootAttrib.height - 2 * offset,
2340
/* Query the window geometry and ensure that the width and
2341
* height have remained the same (adding on any extended borders,
2342
* in this case 0) */
2343
EXPECT_THAT (mTestWindowParent,
2344
HasGeometry (Display (),
2345
RelativeWindowGeometry,
2353
TEST_F (PixmapDecoratedWindowAcceptance, HorzMaximizeFrameWindowSizeSameYHeight)
2355
XWindowAttributes rootAttrib, attrib;
2356
XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &rootAttrib);
2357
XGetWindowAttributes (Display (), mTestWindowParent, &attrib);
2359
ChangeStateOfWindow (Display (),
2361
"_NET_WM_STATE_MAXIMIZED_HORZ",
2364
/* Wait for the window to be maximized first */
2365
int offset = RealDecorationActiveBorderExtent - ActiveInputExtent;
2366
WaitForConfigureOn (Display (),
2370
rootAttrib.width - 2 * offset,
2374
/* Query the window geometry and ensure that the width and
2375
* height have remained the same (adding on any extended borders,
2376
* in this case 0) */
2377
EXPECT_THAT (mTestWindowParent,
2378
HasGeometry (Display (),
2379
RelativeWindowGeometry,
2387
/* Ensure that a window expands to its original size when it is
2389
TEST_F (PixmapDecoratedWindowAcceptance, UndecoratedWindowExpandToOrigSizePlusInitialBorder)
2391
DisallowDecorationsOnWindow (mTestWindow);
2393
WaitForConfigureOn (Display (),
2395
mBorderGeometryOnInitialDecoration.x (),
2396
mBorderGeometryOnInitialDecoration.y (),
2397
mBorderGeometryOnInitialDecoration.width (),
2398
mBorderGeometryOnInitialDecoration.height (),
2399
CWX | CWY | CWWidth | CWHeight);
2401
EXPECT_THAT (mTestWindow,
2402
HasGeometry (Display (),
2403
AbsoluteWindowGeometry,
2404
mBorderGeometryOnInitialDecoration.x (),
2405
mBorderGeometryOnInitialDecoration.y (),
2406
mBorderGeometryOnInitialDecoration.width (),
2407
mBorderGeometryOnInitialDecoration.height (),
2411
TEST_F (PixmapDecoratedWindowAcceptance, UndecorateStaticGravityWindow)
2415
hints.flags = PWinGravity;
2416
hints.win_gravity = StaticGravity;
2418
XSetWMNormalHints (Display (), mTestWindow, &hints);
2419
DisallowDecorationsOnWindow (mTestWindow);
2421
WaitForConfigureOn (Display (),
2423
mBorderGeometryOnInitialDecoration.x (),
2424
mBorderGeometryOnInitialDecoration.y (),
2425
mBorderGeometryOnInitialDecoration.width (),
2426
mBorderGeometryOnInitialDecoration.height (),
2427
CWX | CWY | CWWidth | CWHeight);
2429
EXPECT_THAT (mTestWindow,
2430
HasGeometry (Display (),
2431
AbsoluteWindowGeometry,
2432
mBorderGeometryOnInitialDecoration.x (),
2433
mBorderGeometryOnInitialDecoration.y (),
2434
mBorderGeometryOnInitialDecoration.width (),
2435
mBorderGeometryOnInitialDecoration.height (),
2439
class PixmapDecorationAdjustment :
2440
public PixmapDecoratedWindowAcceptance,
2441
public WithParamInterface <decor_extents_t>
2445
void MaximizeWindow (Window window);
2446
void RestoreWindow (Window window,
2449
unsigned int restoredFrameWidth,
2450
unsigned int restoredFrameHeight);
2454
PixmapDecorationAdjustment::MaximizeWindow (Window window)
2456
XWindowAttributes rootAttrib;
2457
XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &rootAttrib);
2459
ChangeStateOfWindow (Display (),
2461
"_NET_WM_STATE_MAXIMIZED_HORZ",
2464
ChangeStateOfWindow (Display (),
2466
"_NET_WM_STATE_MAXIMIZED_VERT",
2469
/* Wait for the window to be maximized first */
2470
WaitForConfigureOn (Display (),
2476
CWX | CWY | CWWidth | CWHeight);
2480
PixmapDecorationAdjustment::RestoreWindow (Window window,
2483
unsigned int restoredFrameWidth,
2484
unsigned int restoredFrameHeight)
2486
ChangeStateOfWindow (Display (),
2488
"_NET_WM_STATE_MAXIMIZED_HORZ",
2491
ChangeStateOfWindow (Display (),
2493
"_NET_WM_STATE_MAXIMIZED_VERT",
2496
/* Wait for the window to be restored first */
2497
WaitForConfigureOn (Display (),
2502
restoredFrameHeight,
2503
CWX | CWY | CWWidth | CWHeight);
2506
TEST_P (PixmapDecorationAdjustment, AdjustRestoredWindowBorderMovesClient)
2508
ReconfigureDecoration (Display (),
2510
mTestWindowDecoration,
2511
windowDecorations[mTestWindow],
2515
EXPECT_THAT (mTestWindow, HasGeometry (Display (),
2516
AbsoluteWindowGeometry,
2517
mBorderGeometryOnInitialDecoration.x () +
2519
mBorderGeometryOnInitialDecoration.y () +
2526
TEST_P (PixmapDecorationAdjustment, AdjustRestoredWindowBorderShrinkClient)
2528
ReconfigureDecoration (Display (),
2530
mTestWindowDecoration,
2531
windowDecorations[mTestWindow],
2535
EXPECT_THAT (mTestWindow, HasGeometry (Display (),
2536
AbsoluteWindowGeometry,
2539
mBorderGeometryOnInitialDecoration.width () -
2542
mBorderGeometryOnInitialDecoration.height () -
2544
GetParam ().bottom),
2548
TEST_P (PixmapDecorationAdjustment, ClientExpandsAsBorderShrinks)
2550
decor_extents_t newExtents = GetParam ();
2552
ReconfigureDecoration (Display (),
2554
mTestWindowDecoration,
2555
windowDecorations[mTestWindow],
2556
DecorationExtents (10, 10, 10, 10),
2557
DecorationExtents (10, 10, 10, 10));
2559
ReconfigureDecoration (Display (),
2561
mTestWindowDecoration,
2562
windowDecorations[mTestWindow],
2564
DecorationExtents (10, 10, 10, 10));
2566
EXPECT_THAT (mTestWindow, HasGeometry (Display (),
2567
AbsoluteWindowGeometry,
2570
mBorderGeometryOnInitialDecoration.width () -
2573
mBorderGeometryOnInitialDecoration.height () -
2579
TEST_P (PixmapDecorationAdjustment, ClientExpandsAsBorderShrinksWhilstMaximized)
2581
decor_extents_t newExtents = GetParam ();
2583
ReconfigureDecoration (Display (),
2585
mTestWindowDecoration,
2586
windowDecorations[mTestWindow],
2587
DecorationExtents (10, 10, 10, 10),
2588
DecorationExtents (10, 10, 10, 10));
2590
MaximizeWindow (mTestWindow);
2592
/* Set the property on the window, then demaximize without waiting
2593
* for a response we will continue to use the maximized window decoration */
2594
mTestWindowDecoration->changeRestoredBorder (newExtents);
2595
windowDecorations[mTestWindow].SetPropertyOnWindow (Display (),
2597
WindowDecorationAtom);
2599
const CompPoint &off (mTestWindowDecoration->restoredFrameWindowOffset ());
2600
const CompSize &size (mTestWindowDecoration->restoredDecorationInputSize ());
2602
/* As the window is shrunk to accomodate the border size, we must subtract
2603
* the border from the original window size */
2604
CompSize shrink ((newExtents.left + newExtents.right),
2605
(newExtents.top + newExtents.bottom));
2607
RestoreWindow (mTestWindow,
2608
mBorderGeometryOnInitialDecoration.x () + off.x (),
2609
mBorderGeometryOnInitialDecoration.y () + off.y (),
2610
mBorderGeometryOnInitialDecoration.width () -
2611
shrink.width () + size.width (),
2612
mBorderGeometryOnInitialDecoration.height () -
2613
shrink.height () + size.height ());
2615
/* Subtract the old offset and size and add on the new decoration geometry */
2616
EXPECT_THAT (mTestWindow, HasGeometry (Display (),
2617
AbsoluteWindowGeometry,
2618
mBorderGeometryOnInitialDecoration.x () +
2620
mBorderGeometryOnInitialDecoration.y () +
2622
mBorderGeometryOnInitialDecoration.width () -
2625
mBorderGeometryOnInitialDecoration.height () -
2627
newExtents.bottom)),
2631
TEST_P (PixmapDecorationAdjustment, ClientExpandsAsBorderShrinksWhilstUndecorated)
2633
decor_extents_t newExtents = GetParam ();
2635
ReconfigureDecoration (Display (),
2637
mTestWindowDecoration,
2638
windowDecorations[mTestWindow],
2639
DecorationExtents (10, 10, 10, 10),
2640
DecorationExtents (10, 10, 10, 10));
2642
/* When decorations are disabled on this window, the frame window
2643
* will retain the exact same size, as border == input in the previous
2644
* case. So there's no need to wait */
2645
DisallowDecorationsOnWindow (mTestWindow);
2647
/* Set the property on the window, then decorate without waiting
2648
* for a response we will continue to use the maximized window decoration */
2649
mTestWindowDecoration->changeRestoredBorder (newExtents);
2650
windowDecorations[mTestWindow].SetPropertyOnWindow (Display (),
2652
WindowDecorationAtom);
2654
AllowDecorationsOnWindow (mTestWindow);
2656
const CompPoint &off (mTestWindowDecoration->restoredFrameWindowOffset ());
2657
const CompSize &size (mTestWindowDecoration->restoredDecorationInputSize ());
2659
/* As the window is shrunk to accomadate the border size, we must subtract
2660
* the border from the original window size */
2661
CompSize shrink ((newExtents.left + newExtents.right),
2662
(newExtents.top + newExtents.bottom));
2664
WaitForConfigureOn (Display (),
2666
mBorderGeometryOnInitialDecoration.x () + off.x (),
2667
mBorderGeometryOnInitialDecoration.y () + off.y (),
2668
mBorderGeometryOnInitialDecoration.width () -
2669
shrink.width () + size.width (),
2670
mBorderGeometryOnInitialDecoration.height () -
2671
shrink.height () + size.height (),
2672
CWX | CWY | CWWidth | CWHeight);
2674
EXPECT_THAT (mTestWindow, HasGeometry (Display (),
2675
AbsoluteWindowGeometry,
2676
mBorderGeometryOnInitialDecoration.x () +
2678
mBorderGeometryOnInitialDecoration.y () +
2680
mBorderGeometryOnInitialDecoration.width () -
2683
mBorderGeometryOnInitialDecoration.height () -
2689
TEST_P (PixmapDecorationAdjustment, AdjustRestoredWindowInputNoMoveClient)
2691
decor_extents_t newExtents = GetParam ();
2693
ReconfigureDecoration (Display (),
2695
mTestWindowDecoration,
2696
windowDecorations[mTestWindow],
2697
DecorationExtents (1, 1, 1, 1),
2700
EXPECT_THAT (mTestWindow, HasGeometry (Display (),
2701
AbsoluteWindowGeometry,
2702
mBorderGeometryOnInitialDecoration.x () + 1,
2703
mBorderGeometryOnInitialDecoration.y () + 1,
2709
decor_extents_t AdjustmentExtents[] =
2711
DecorationExtents (2, 0, 0, 0),
2712
DecorationExtents (0, 2, 0, 0),
2713
DecorationExtents (0, 0, 2, 0),
2714
DecorationExtents (0, 0, 0, 2)
2717
INSTANTIATE_TEST_CASE_P (AdjustmentExtents,
2718
PixmapDecorationAdjustment,
2719
ValuesIn (AdjustmentExtents));