~ubuntu-branches/ubuntu/trusty/compiz/trusty

« back to all changes in this revision

Viewing changes to plugins/decor/tests/acceptance/xorg-gtest/compiz_decor_acceptance_tests.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release
  • Date: 2013-08-22 06:58:07 UTC
  • mto: This revision was merged to the branch mainline in revision 3352.
  • Revision ID: package-import@ubuntu.com-20130822065807-17nlzez0d30y09so
Tags: upstream-0.9.10+13.10.20130822
ImportĀ upstreamĀ versionĀ 0.9.10+13.10.20130822

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Compiz XOrg GTest Decoration Acceptance Tests
 
3
 *
 
4
 * Copyright (C) 2013 Sam Spilsbury.
 
5
 *
 
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.
 
10
 
 
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.
 
15
 
 
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
 
19
 *
 
20
 * Authored By:
 
21
 * Sam Spilsbury <smspillaz@gmail.com>
 
22
 */
 
23
#include <gtest/gtest.h>
 
24
#include <gmock/gmock.h>
 
25
 
 
26
#include <sstream>
 
27
#include <vector>
 
28
 
 
29
#include <boost/shared_array.hpp>
 
30
#include <boost/shared_ptr.hpp>
 
31
 
 
32
#include <boost/bind.hpp>
 
33
 
 
34
#include <X11/Xlib.h>
 
35
#include <X11/Xatom.h>
 
36
 
 
37
#include "decoration.h"
 
38
 
 
39
#include <core/point.h>
 
40
#include <core/size.h>
 
41
#include <core/rect.h>
 
42
 
 
43
#include <xorg/gtest/xorg-gtest.h>
 
44
#include <compiz-xorg-gtest.h>
 
45
 
 
46
#include <gtest_shared_tmpenv.h>
 
47
 
 
48
namespace xt = xorg::testing;
 
49
namespace ct = compiz::testing;
 
50
 
 
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;
 
61
using ::testing::_;
 
62
 
 
63
using ::compiz::testing::HasGeometry;
 
64
using ::compiz::testing::RelativeWindowGeometry;
 
65
using ::compiz::testing::AbsoluteWindowGeometry;
 
66
 
 
67
class BaseDecorAcceptance :
 
68
    public ct::AutostartCompizXorgSystemTestWithTestHelper
 
69
{
 
70
    public:
 
71
 
 
72
        BaseDecorAcceptance ();
 
73
 
 
74
        virtual void SetUp ();
 
75
        virtual ct::CompizProcess::PluginList GetPluginList ();
 
76
 
 
77
    protected:
 
78
 
 
79
        Window mRootWindow;
 
80
 
 
81
        Atom   mUtf8StringAtom;
 
82
        Atom   mDecorationManagerNameAtom;
 
83
        Atom   mDecorationTypeAtom;
 
84
        Atom   mDecorationTypePixmap;
 
85
        Atom   mDecorationTypeWindow;
 
86
        Atom   mDecorationInputFrameAtom;
 
87
        Atom   mDecorationOutputFrameAtom;
 
88
 
 
89
        TmpEnv mDisableConfigureBufferLocksEnv;
 
90
 
 
91
    private:
 
92
 
 
93
        int GetEventMask () const;
 
94
};
 
95
 
 
96
BaseDecorAcceptance::BaseDecorAcceptance () :
 
97
    mRootWindow (0),
 
98
    mUtf8StringAtom (0),
 
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")
 
108
{
 
109
}
 
110
 
 
111
int
 
112
BaseDecorAcceptance::GetEventMask () const
 
113
{
 
114
    return ct::AutostartCompizXorgSystemTestWithTestHelper::GetEventMask () |
 
115
               SubstructureNotifyMask;
 
116
}
 
117
 
 
118
void
 
119
BaseDecorAcceptance::SetUp ()
 
120
{
 
121
    ct::AutostartCompizXorgSystemTestWithTestHelper::SetUp ();
 
122
 
 
123
    mUtf8StringAtom = XInternAtom (Display (),
 
124
                                  "UTF8_STRING",
 
125
                                  1);
 
126
 
 
127
    ASSERT_NE (0, mUtf8StringAtom);
 
128
 
 
129
    mDecorationManagerNameAtom = XInternAtom (Display (),
 
130
                                             "_COMPIZ_DM_NAME",
 
131
                                             0);
 
132
 
 
133
    ASSERT_NE (0, mDecorationManagerNameAtom);
 
134
 
 
135
    mDecorationTypePixmap = XInternAtom (Display (),
 
136
                                         DECOR_TYPE_PIXMAP_ATOM_NAME,
 
137
                                         0);
 
138
 
 
139
    ASSERT_NE (0, mDecorationTypePixmap);
 
140
 
 
141
    mDecorationTypeWindow = XInternAtom (Display (),
 
142
                                         DECOR_TYPE_WINDOW_ATOM_NAME,
 
143
                                         0);
 
144
 
 
145
    ASSERT_NE (0, mDecorationTypeWindow);
 
146
 
 
147
    mDecorationTypeAtom = XInternAtom (Display (),
 
148
                                       DECOR_TYPE_ATOM_NAME,
 
149
                                       0);
 
150
 
 
151
    ASSERT_NE (0, mDecorationTypeAtom);
 
152
 
 
153
    mDecorationInputFrameAtom = XInternAtom (Display (),
 
154
                                             DECOR_INPUT_FRAME_ATOM_NAME,
 
155
                                             0);
 
156
 
 
157
    ASSERT_NE (0, mDecorationInputFrameAtom);
 
158
 
 
159
    mDecorationOutputFrameAtom = XInternAtom (Display (),
 
160
                                              DECOR_OUTPUT_FRAME_ATOM_NAME,
 
161
                                              0);
 
162
 
 
163
    ASSERT_NE (0, mDecorationOutputFrameAtom);
 
164
 
 
165
    mRootWindow = DefaultRootWindow (Display ());
 
166
 
 
167
    ASSERT_NE (0, mRootWindow);
 
168
}
 
169
 
 
170
ct::CompizProcess::PluginList
 
171
BaseDecorAcceptance::GetPluginList ()
 
172
{
 
173
    typedef ct::AutostartCompizXorgSystemTestWithTestHelper Base;
 
174
    ct::CompizProcess::PluginList baseList (Base::GetPluginList ());
 
175
    ct::CompizProcess::PluginList list;
 
176
 
 
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));
 
183
 
 
184
    for (ct::CompizProcess::PluginList::iterator it = baseList.begin ();
 
185
         it != baseList.end ();
 
186
         ++it)
 
187
        list.push_back (*it);
 
188
 
 
189
    return list;
 
190
}
 
191
 
 
192
namespace compiz
 
193
{
 
194
namespace decor
 
195
{
 
196
namespace testing
 
197
{
 
198
 
 
199
const char *DecorationClientName = "fake";
 
200
 
 
201
const char *FailedToAcquireMessage =
 
202
        "Could not acquire selection for an unknown reason";
 
203
const char *OtherDecorationManagerRunningMessage =
 
204
        "Another decoration manager is already running";
 
205
 
 
206
struct MWMHints
 
207
{
 
208
    unsigned long flags;
 
209
    unsigned long functions;
 
210
    unsigned long decorations;
 
211
};
 
212
 
 
213
static const unsigned int MwmDecor = 1L << 0;
 
214
 
 
215
class FakeDecorator
 
216
{
 
217
    public:
 
218
 
 
219
        FakeDecorator (Display *d,
 
220
                       int supporting = WINDOW_DECORATION_TYPE_WINDOW);
 
221
        ~FakeDecorator ();
 
222
 
 
223
        Window currentSelectionOwner ();
 
224
        Atom   sessionOwnerAtom ();
 
225
 
 
226
        Window supportingCheckWindow ();
 
227
 
 
228
    private:
 
229
 
 
230
        Display *mDpy;
 
231
        int     mScreenNumber;
 
232
        Window  mRootWindow;
 
233
        int     mSessionStatus;
 
234
        Time    mDecorationManagerTimestamp;
 
235
 
 
236
        Atom    mSessionOwnerAtom;
 
237
        Window  mSessionOwner;
 
238
 
 
239
        Atom    mSupportingHintAtom;
 
240
        Atom    mSupportingHintWindowAtom;
 
241
        Window  mSupportingHintWindow;
 
242
 
 
243
};
 
244
 
 
245
class FakeDecoration
 
246
{
 
247
    public:
 
248
 
 
249
        typedef boost::shared_ptr <FakeDecoration> Ptr;
 
250
 
 
251
        FakeDecoration (unsigned int type,
 
252
                        unsigned int state,
 
253
                        unsigned int actions,
 
254
                        unsigned int minWidth,
 
255
                        unsigned int minHeight);
 
256
 
 
257
        virtual ~FakeDecoration ();
 
258
 
 
259
        virtual size_t propertyDataSize () const = 0;
 
260
        virtual void addPropertyData (std::vector <long> &) const = 0;
 
261
 
 
262
        bool match (unsigned int type,
 
263
                    unsigned int state,
 
264
                    unsigned int actions) const;
 
265
 
 
266
        virtual CompPoint restoredFrameWindowOffset () const = 0;
 
267
        virtual CompSize restoredDecorationBorderSize () const = 0;
 
268
        virtual CompSize restoredDecorationInputSize () const = 0;
 
269
 
 
270
    protected:
 
271
 
 
272
        void insertBaseData (std::vector <long> &) const;
 
273
 
 
274
        static const size_t BaseDataSize = 5;
 
275
 
 
276
        unsigned int mType;
 
277
        unsigned int mState;
 
278
        unsigned int mActions;
 
279
 
 
280
        unsigned int mMinWidth;
 
281
        unsigned int mMinHeight;
 
282
};
 
283
 
 
284
class FakeWindowTypeDecoration :
 
285
    public FakeDecoration
 
286
{
 
287
    public:
 
288
 
 
289
        FakeWindowTypeDecoration (unsigned int type,
 
290
                                  unsigned int state,
 
291
                                  unsigned int actions,
 
292
                                  unsigned int minWidth,
 
293
                                  unsigned int minHeight,
 
294
                                  const decor_extents_t &restored,
 
295
                                  const decor_extents_t &maximized);
 
296
 
 
297
    protected:
 
298
 
 
299
        size_t propertyDataSize () const;
 
300
        void addPropertyData (std::vector<long> &) const;
 
301
        CompPoint restoredFrameWindowOffset () const;
 
302
        CompSize restoredDecorationBorderSize () const;
 
303
        CompSize restoredDecorationInputSize () const;
 
304
 
 
305
        static const unsigned int WindowDecorationSize = 8;
 
306
 
 
307
    private:
 
308
 
 
309
        decor_extents_t mRestored;
 
310
        decor_extents_t mMaximized;
 
311
};
 
312
 
 
313
class FakePixmapTypeDecoration :
 
314
    public FakeDecoration
 
315
{
 
316
    public:
 
317
 
 
318
        typedef boost::shared_ptr <FakePixmapTypeDecoration> Ptr;
 
319
 
 
320
        FakePixmapTypeDecoration (unsigned int type,
 
321
                                  unsigned int state,
 
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,
 
329
                                  Display               *dpy);
 
330
        ~FakePixmapTypeDecoration ();
 
331
 
 
332
        void changeRestoredBorder (const decor_extents_t &border);
 
333
        void changeRestoredInput (const decor_extents_t &input);
 
334
 
 
335
        CompPoint restoredFrameWindowOffset () const;
 
336
        CompSize restoredDecorationBorderSize () const;
 
337
        CompSize restoredDecorationInputSize () const;
 
338
 
 
339
    protected:
 
340
 
 
341
        size_t propertyDataSize () const;
 
342
        void addPropertyData (std::vector<long> &) const;
 
343
 
 
344
    private:
 
345
 
 
346
        decor_extents_t mRestoredBorder;
 
347
        decor_extents_t mRestoredInput;
 
348
        decor_extents_t mMaximizedBorder;
 
349
        decor_extents_t mMaximizedInput;
 
350
 
 
351
        decor_context_t mContext;
 
352
        decor_quad_t    mQuads[N_QUADS_MAX];
 
353
        decor_layout_t  mLayout;
 
354
        unsigned int    mNQuads;
 
355
 
 
356
        Display         *mDpy;
 
357
        Pixmap          mPixmap;
 
358
};
 
359
 
 
360
class FakeDecorationList
 
361
{
 
362
    public:
 
363
 
 
364
        FakeDecorationList () :
 
365
            mDecorationType (WINDOW_DECORATION_TYPE_PIXMAP)
 
366
        {
 
367
        }
 
368
 
 
369
        FakeDecorationList (unsigned int type) :
 
370
            mDecorationType (type)
 
371
        {
 
372
        }
 
373
 
 
374
        void AddDecoration (const FakeDecoration::Ptr &);
 
375
        void RemoveDecoration (unsigned int type,
 
376
                               unsigned int state,
 
377
                               unsigned int actions);
 
378
        void RemoveAllDecorations ();
 
379
 
 
380
        void SetPropertyOnWindow (Display *dpy,
 
381
                                  Window  w,
 
382
                                  Atom    property);
 
383
 
 
384
    private:
 
385
 
 
386
        unsigned int                      mDecorationType;
 
387
        std::vector <FakeDecoration::Ptr> decorations;
 
388
};
 
389
 
 
390
class AcquisitionFailed :
 
391
    public std::exception
 
392
{
 
393
    public:
 
394
 
 
395
        AcquisitionFailed (int status);
 
396
 
 
397
        const char * what () const throw ();
 
398
 
 
399
    private:
 
400
 
 
401
        int mStatus;
 
402
};
 
403
 
 
404
}
 
405
}
 
406
}
 
407
 
 
408
namespace
 
409
{
 
410
bool Advance (Display *d, bool result)
 
411
{
 
412
    return ct::AdvanceToNextEventOnSuccess (d, result);
 
413
}
 
414
 
 
415
class ManagerMessageMatcher :
 
416
    public ct::ClientMessageXEventMatcher
 
417
{
 
418
    public:
 
419
 
 
420
        ManagerMessageMatcher (Display *dpy,
 
421
                               Atom managed);
 
422
 
 
423
        virtual bool MatchAndExplain (const XEvent &event,
 
424
                                      MatchResultListener *listener) const;
 
425
 
 
426
        virtual void DescribeTo (std::ostream *os) const;
 
427
 
 
428
    private:
 
429
 
 
430
        Display *mDpy;
 
431
        Atom    mManager;
 
432
        Atom    mManaged;
 
433
};
 
434
 
 
435
void FreePropertyData (unsigned char *array)
 
436
{
 
437
    if (array)
 
438
        XFree (array);
 
439
}
 
440
 
 
441
int SafeFetchProperty (Display       *dpy,
 
442
                       Window        w,
 
443
                       Atom          property,
 
444
                       long          offset,
 
445
                       long          length,
 
446
                       Atom          requestedType,
 
447
                       Atom          &returnType,
 
448
                       int           &returnFormat,
 
449
                       unsigned long &returnNItems,
 
450
                       unsigned long &returnBytesRemaining,
 
451
                       boost::shared_ptr <unsigned char> &data)
 
452
{
 
453
    unsigned char *dataLocation;
 
454
 
 
455
    int status = XGetWindowProperty (dpy, w, property, offset, length, 0,
 
456
                                     requestedType, &returnType,
 
457
                                     &returnFormat, &returnNItems,
 
458
                                     &returnBytesRemaining,
 
459
                                     &dataLocation);
 
460
 
 
461
    data.reset (dataLocation,
 
462
                boost::bind (FreePropertyData, _1));
 
463
 
 
464
    return status;
 
465
}
 
466
 
 
467
void FetchAndVerifyProperty (Display       *dpy,
 
468
                             Window        w,
 
469
                             Atom          property,
 
470
                             Atom          expectedType,
 
471
                             int           expectedFormat,
 
472
                             unsigned long expectedItems,
 
473
                             unsigned long expectedBytesAfter,
 
474
                             boost::shared_ptr <unsigned char> &data)
 
475
{
 
476
    Atom          returnedType = 0;
 
477
    int           returnedFormat = 0;
 
478
    unsigned long returnedNItems = 0;
 
479
    unsigned long returnedBytesRemaining = 0;
 
480
 
 
481
    std::stringstream ss;
 
482
 
 
483
    int status = SafeFetchProperty (dpy,
 
484
                                    w,
 
485
                                    property,
 
486
                                    0L,
 
487
                                    1024L,
 
488
                                    expectedType,
 
489
                                    returnedType,
 
490
                                    returnedFormat,
 
491
                                    returnedNItems,
 
492
                                    returnedBytesRemaining,
 
493
                                    data);
 
494
 
 
495
    if (status != Success)
 
496
        ss << "XGetWindowProperty failed:" << std::endl;
 
497
 
 
498
    if (returnedType != expectedType)
 
499
        ss << "Expected type of " << XGetAtomName (dpy, expectedType)
 
500
           << std::endl;
 
501
 
 
502
    if (returnedFormat != expectedFormat)
 
503
        ss << "Expected format of " << expectedFormat
 
504
           << " but got " << returnedFormat << std::endl;
 
505
 
 
506
    if (returnedNItems != expectedItems)
 
507
        ss  << "Expected " << expectedItems << " items"
 
508
            << " but got " << returnedNItems << " items" << std::endl;
 
509
 
 
510
    if (returnedBytesRemaining != expectedBytesAfter)
 
511
        ss << "Expected " << expectedBytesAfter << " bytes remaining"
 
512
           << " but got " << returnedBytesRemaining << " bytes remaining"
 
513
           << std::endl;
 
514
 
 
515
    if (!ss.str ().empty ())
 
516
        throw std::logic_error (ss.str ());
 
517
}
 
518
}
 
519
 
 
520
ManagerMessageMatcher::ManagerMessageMatcher (Display *dpy,
 
521
                                              Atom managed) :
 
522
    ct::ClientMessageXEventMatcher (dpy,
 
523
                                    XInternAtom (dpy,
 
524
                                                 "MANAGER",
 
525
                                                 1),
 
526
                                    DefaultRootWindow (dpy)),
 
527
    mDpy (dpy),
 
528
    mManaged (managed)
 
529
{
 
530
}
 
531
 
 
532
bool
 
533
ManagerMessageMatcher::MatchAndExplain (const XEvent &event,
 
534
                                        MatchResultListener *listener) const
 
535
{
 
536
    if (ct::ClientMessageXEventMatcher::MatchAndExplain (event, listener))
 
537
    {
 
538
        /* Evaluate the second field for the atom */
 
539
        return event.xclient.data.l[1] ==
 
540
            static_cast <long> (mManaged);
 
541
    }
 
542
 
 
543
    return false;
 
544
}
 
545
 
 
546
void
 
547
ManagerMessageMatcher::DescribeTo (std::ostream *os) const
 
548
{
 
549
    *os << "manager of selection atom " << XGetAtomName (mDpy, mManaged);
 
550
}
 
551
 
 
552
 
 
553
 
 
554
namespace cdt = compiz::decor::testing;
 
555
 
 
556
cdt::FakeDecoration::FakeDecoration (unsigned int type,
 
557
                                     unsigned int state,
 
558
                                     unsigned int actions,
 
559
                                     unsigned int minWidth,
 
560
                                     unsigned int minHeight) :
 
561
    mType (type),
 
562
    mState (state),
 
563
    mActions (actions),
 
564
    mMinWidth (minWidth),
 
565
    mMinHeight (minHeight)
 
566
{
 
567
}
 
568
 
 
569
cdt::FakeDecoration::~FakeDecoration ()
 
570
{
 
571
}
 
572
 
 
573
bool
 
574
cdt::FakeDecoration::match (unsigned int type,
 
575
                            unsigned int state,
 
576
                            unsigned int actions) const
 
577
{
 
578
    return type == mType &&
 
579
           state == mState &&
 
580
           actions == mActions;
 
581
}
 
582
 
 
583
cdt::FakeWindowTypeDecoration::FakeWindowTypeDecoration (unsigned int type,
 
584
                                                         unsigned int state,
 
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)
 
593
{
 
594
}
 
595
 
 
596
void
 
597
cdt::FakeWindowTypeDecoration::addPropertyData (std::vector<long> &vec) const
 
598
{
 
599
    long propData[PROP_HEADER_SIZE + propertyDataSize ()];
 
600
 
 
601
    decor_gen_window_property (propData,
 
602
                               0,
 
603
                               const_cast <decor_extents_t *> (&mRestored),
 
604
                               const_cast <decor_extents_t *> (&mMaximized),
 
605
                               mMinWidth,
 
606
                               mMinHeight,
 
607
                               mState,
 
608
                               mType,
 
609
                               mActions);
 
610
 
 
611
    for (size_t i = PROP_HEADER_SIZE;
 
612
         i < (PROP_HEADER_SIZE + propertyDataSize ());
 
613
         ++i)
 
614
        vec.push_back (propData[i]);
 
615
}
 
616
 
 
617
size_t
 
618
cdt::FakeWindowTypeDecoration::propertyDataSize () const
 
619
{
 
620
    return WINDOW_PROP_SIZE;
 
621
}
 
622
 
 
623
CompPoint
 
624
cdt::FakeWindowTypeDecoration::restoredFrameWindowOffset () const
 
625
{
 
626
    int xOffset = -mRestored.left;
 
627
    int yOffset = -mRestored.top;
 
628
 
 
629
    return CompPoint (xOffset, yOffset);
 
630
}
 
631
 
 
632
CompSize
 
633
cdt::FakeWindowTypeDecoration::restoredDecorationBorderSize () const
 
634
{
 
635
    return CompSize (mRestored.left + mRestored.right,
 
636
                     mRestored.top + mRestored.bottom);
 
637
}
 
638
 
 
639
CompSize
 
640
cdt::FakeWindowTypeDecoration::restoredDecorationInputSize () const
 
641
{
 
642
    return restoredDecorationBorderSize ();
 
643
}
 
644
 
 
645
cdt::FakePixmapTypeDecoration::FakePixmapTypeDecoration (unsigned int type,
 
646
                                                         unsigned int state,
 
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,
 
654
                                                         Display               *dpy) :
 
655
    FakeDecoration (type, state, actions, minWidth, minHeight),
 
656
    mRestoredBorder (restoredBorder),
 
657
    mRestoredInput (restoredInput),
 
658
    mMaximizedBorder (maximizedBorder),
 
659
    mMaximizedInput (maximizedInput),
 
660
    mDpy (dpy),
 
661
    mPixmap (XCreatePixmap (mDpy,
 
662
                            DefaultRootWindow (mDpy),
 
663
                            10,
 
664
                            10,
 
665
                            DefaultDepth (mDpy, (DefaultScreen (mDpy)))))
 
666
{
 
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;
 
672
 
 
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;
 
681
 
 
682
    decor_get_default_layout (&mContext, minWidth, minHeight, &mLayout);
 
683
    mNQuads = decor_set_lSrStSbS_window_quads (mQuads, &mContext, &mLayout);
 
684
}
 
685
 
 
686
cdt::FakePixmapTypeDecoration::~FakePixmapTypeDecoration ()
 
687
{
 
688
    XFreePixmap (mDpy, mPixmap);
 
689
}
 
690
 
 
691
size_t
 
692
cdt::FakePixmapTypeDecoration::propertyDataSize () const
 
693
{
 
694
    return BASE_PROP_SIZE + (QUAD_PROP_SIZE * mNQuads);
 
695
}
 
696
 
 
697
void
 
698
cdt::FakePixmapTypeDecoration::addPropertyData (std::vector<long> &vec) const
 
699
{
 
700
    long propData[PROP_HEADER_SIZE + propertyDataSize ()];
 
701
 
 
702
    decor_quads_to_property (propData,
 
703
                             0,
 
704
                             mPixmap,
 
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),
 
709
                             mMinWidth,
 
710
                             mMinHeight,
 
711
                             const_cast <decor_quad_t *> (mQuads),
 
712
                             mNQuads,
 
713
                             mType,
 
714
                             mState,
 
715
                             mActions);
 
716
 
 
717
    for (size_t i = PROP_HEADER_SIZE;
 
718
         i < (PROP_HEADER_SIZE + propertyDataSize ());
 
719
         ++i)
 
720
        vec.push_back (propData[i]);
 
721
}
 
722
 
 
723
CompPoint
 
724
cdt::FakePixmapTypeDecoration::restoredFrameWindowOffset () const
 
725
{
 
726
    int xOffset = mRestoredBorder.left - mRestoredInput.left;
 
727
    int yOffset = mRestoredBorder.top - mRestoredInput.top;
 
728
 
 
729
    return CompPoint (xOffset, yOffset);
 
730
}
 
731
 
 
732
CompSize
 
733
cdt::FakePixmapTypeDecoration::restoredDecorationBorderSize () const
 
734
{
 
735
    return CompSize (mRestoredBorder.left + mRestoredBorder.right,
 
736
                     mRestoredBorder.top + mRestoredBorder.bottom);
 
737
}
 
738
 
 
739
CompSize
 
740
cdt::FakePixmapTypeDecoration::restoredDecorationInputSize () const
 
741
{
 
742
    return CompSize (mRestoredInput.left + mRestoredInput.right,
 
743
                     mRestoredInput.top + mRestoredInput.bottom);
 
744
}
 
745
 
 
746
void
 
747
cdt::FakePixmapTypeDecoration::changeRestoredBorder (const decor_extents_t &b)
 
748
{
 
749
    mRestoredBorder = b;
 
750
}
 
751
 
 
752
void
 
753
cdt::FakePixmapTypeDecoration::changeRestoredInput (const decor_extents_t &i)
 
754
{
 
755
    mRestoredInput = i;
 
756
}
 
757
 
 
758
void
 
759
cdt::FakeDecorationList::AddDecoration (const cdt::FakeDecoration::Ptr &decoration)
 
760
{
 
761
    decorations.push_back (decoration);
 
762
}
 
763
 
 
764
namespace
 
765
{
 
766
bool MatchesTypeStateAndActions (const cdt::FakeDecoration::Ptr &decoration,
 
767
                                 unsigned int type,
 
768
                                 unsigned int state,
 
769
                                 unsigned int actions)
 
770
{
 
771
    return decoration->match (type, state, actions);
 
772
}
 
773
}
 
774
 
 
775
void cdt::FakeDecorationList::RemoveDecoration (unsigned int type,
 
776
                                                unsigned int state,
 
777
                                                unsigned int actions)
 
778
{
 
779
    decorations.erase (
 
780
        std::remove_if (decorations.begin (),
 
781
                        decorations.end (),
 
782
                        boost::bind (MatchesTypeStateAndActions,
 
783
                                     _1,
 
784
                                     type,
 
785
                                     state,
 
786
                                     actions)),
 
787
        decorations.end ());
 
788
}
 
789
 
 
790
void cdt::FakeDecorationList::RemoveAllDecorations ()
 
791
{
 
792
    decorations.clear ();
 
793
}
 
794
 
 
795
void
 
796
cdt::FakeDecorationList::SetPropertyOnWindow (Display *dpy,
 
797
                                              Window  w,
 
798
                                              Atom    property)
 
799
{
 
800
    size_t size = PROP_HEADER_SIZE;
 
801
    for (std::vector <FakeDecoration::Ptr>::iterator it = decorations.begin ();
 
802
         it != decorations.end ();
 
803
         ++it)
 
804
        size += (*it)->propertyDataSize ();
 
805
 
 
806
    std::vector <long> data;
 
807
 
 
808
    data.reserve (size);
 
809
 
 
810
    data.push_back (decor_version ());
 
811
    data.push_back (mDecorationType);
 
812
    data.push_back (decorations.size ());
 
813
 
 
814
    for (std::vector <FakeDecoration::Ptr>::iterator it = decorations.begin ();
 
815
         it != decorations.end ();
 
816
         ++it)
 
817
        (*it)->addPropertyData (data);
 
818
 
 
819
    XChangeProperty (dpy,
 
820
                     w,
 
821
                     property,
 
822
                     XA_INTEGER,
 
823
                     32,
 
824
                     PropModeReplace,
 
825
                     reinterpret_cast <unsigned char *> (&data[0]),
 
826
                     size);
 
827
}
 
828
 
 
829
cdt::AcquisitionFailed::AcquisitionFailed (int status) :
 
830
    mStatus (status)
 
831
{
 
832
}
 
833
 
 
834
const char *
 
835
cdt::AcquisitionFailed::what () const throw ()
 
836
{
 
837
    switch (mStatus)
 
838
    {
 
839
        case DECOR_ACQUIRE_STATUS_FAILED:
 
840
            return FailedToAcquireMessage;
 
841
        case DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING:
 
842
            return OtherDecorationManagerRunningMessage;
 
843
        default:
 
844
            return "Unknown status";
 
845
    }
 
846
 
 
847
    return "Unknown status";
 
848
}
 
849
 
 
850
cdt::FakeDecorator::FakeDecorator (Display *d,
 
851
                                   int     supports) :
 
852
    mDpy (d),
 
853
    mScreenNumber (DefaultScreen (d)),
 
854
    mRootWindow (DefaultRootWindow (d)),
 
855
    mSessionStatus (decor_acquire_dm_session (d,
 
856
                                              mScreenNumber,
 
857
                                              "fake",
 
858
                                              1,
 
859
                                              &mDecorationManagerTimestamp)),
 
860
    mSessionOwnerAtom (0),
 
861
    mSessionOwner (0),
 
862
    mSupportingHintAtom (XInternAtom (d, DECOR_TYPE_ATOM_NAME, 0)),
 
863
    mSupportingHintWindowAtom (XInternAtom (d,
 
864
                                            DECOR_SUPPORTING_DM_CHECK_ATOM_NAME,
 
865
                                            0))
 
866
{
 
867
    if (mSessionStatus != DECOR_ACQUIRE_STATUS_SUCCESS)
 
868
        throw AcquisitionFailed (mSessionStatus);
 
869
 
 
870
    std::stringstream sessionOwnerStream;
 
871
 
 
872
    sessionOwnerStream << "_COMPIZ_DM_S" << mScreenNumber;
 
873
    mSessionOwnerAtom = XInternAtom (d,
 
874
                                     sessionOwnerStream.str ().c_str (),
 
875
                                     1);
 
876
 
 
877
    mSessionOwner = XGetSelectionOwner (d, mSessionOwnerAtom);
 
878
 
 
879
    if (!mSessionOwner)
 
880
        throw std::runtime_error ("Expected a selection owner");
 
881
 
 
882
    decor_set_dm_check_hint (d, mScreenNumber, supports);
 
883
 
 
884
    boost::shared_ptr <unsigned char> data;
 
885
 
 
886
    FetchAndVerifyProperty (mDpy,
 
887
                            mRootWindow,
 
888
                            mSupportingHintWindowAtom,
 
889
                            XA_WINDOW,
 
890
                            32,
 
891
                            1,
 
892
                            0,
 
893
                            data);
 
894
 
 
895
    mSupportingHintWindow = *(reinterpret_cast <Window *> (data.get ()));
 
896
 
 
897
    if (!mSupportingHintWindow)
 
898
        throw std::runtime_error ("Failed to find supporting hint window");
 
899
 
 
900
 
 
901
}
 
902
 
 
903
cdt::FakeDecorator::~FakeDecorator ()
 
904
{
 
905
    /* Destroy the session owner, taking the selection with it */
 
906
    XDestroyWindow (mDpy, mSessionOwner);
 
907
    XDestroyWindow (mDpy, mSupportingHintWindow);
 
908
}
 
909
 
 
910
Window
 
911
cdt::FakeDecorator::currentSelectionOwner ()
 
912
{
 
913
    return mSessionOwner;
 
914
}
 
915
 
 
916
Atom
 
917
cdt::FakeDecorator::sessionOwnerAtom ()
 
918
{
 
919
    return mSessionOwnerAtom;
 
920
}
 
921
 
 
922
Atom
 
923
cdt::FakeDecorator::supportingCheckWindow ()
 
924
{
 
925
    return mSupportingHintWindow;
 
926
}
 
927
 
 
928
TEST_F (BaseDecorAcceptance, Startup)
 
929
{
 
930
}
 
931
 
 
932
TEST_F (BaseDecorAcceptance, FakeDecoratorSessionOwnerNameSetOnSelectionOwner)
 
933
{
 
934
    cdt::FakeDecorator decorator (Display ());
 
935
    boost::shared_ptr <unsigned char> data;
 
936
 
 
937
    FetchAndVerifyProperty (Display (),
 
938
                            decorator.currentSelectionOwner (),
 
939
                            mDecorationManagerNameAtom,
 
940
                            mUtf8StringAtom,
 
941
                            8,
 
942
                            4,
 
943
                            0,
 
944
                            data);
 
945
 
 
946
    std::string name (reinterpret_cast <char *> (data.get ()));
 
947
 
 
948
    EXPECT_THAT (name, StrEq (cdt::DecorationClientName));
 
949
 
 
950
}
 
951
 
 
952
TEST_F (BaseDecorAcceptance, FakeDecoratorReceiveClientMessage)
 
953
{
 
954
    cdt::FakeDecorator decorator (Display ());
 
955
 
 
956
    ManagerMessageMatcher matcher (Display (),
 
957
                                   decorator.sessionOwnerAtom ());
 
958
 
 
959
    EXPECT_TRUE (Advance (Display (),
 
960
                          ct::WaitForEventOfTypeOnWindowMatching (Display (),
 
961
                                                                  mRootWindow,
 
962
                                                                  ClientMessage,
 
963
                                                                  -1,
 
964
                                                                  -1,
 
965
                                                                  matcher)));
 
966
}
 
967
 
 
968
TEST_F (BaseDecorAcceptance, DecorationSupportsWindowType)
 
969
{
 
970
    cdt::FakeDecorator decorator (Display (),
 
971
                                  WINDOW_DECORATION_TYPE_WINDOW);
 
972
 
 
973
    boost::shared_ptr <unsigned char> data;
 
974
 
 
975
    FetchAndVerifyProperty (Display (),
 
976
                            decorator.supportingCheckWindow (),
 
977
                            mDecorationTypeAtom,
 
978
                            XA_ATOM,
 
979
                            32,
 
980
                            1,
 
981
                            0,
 
982
                            data);
 
983
 
 
984
    Atom *atoms = reinterpret_cast <Atom *> (data.get ());
 
985
    EXPECT_EQ (atoms[0], mDecorationTypeWindow);
 
986
}
 
987
 
 
988
TEST_F (BaseDecorAcceptance, DecorationSupportsPixmapType)
 
989
{
 
990
    cdt::FakeDecorator decorator (Display (),
 
991
                                  WINDOW_DECORATION_TYPE_PIXMAP);
 
992
 
 
993
    boost::shared_ptr <unsigned char> data;
 
994
 
 
995
    FetchAndVerifyProperty (Display (),
 
996
                            decorator.supportingCheckWindow (),
 
997
                            mDecorationTypeAtom,
 
998
                            XA_ATOM,
 
999
                            32,
 
1000
                            1,
 
1001
                            0,
 
1002
                            data);
 
1003
 
 
1004
    Atom *atoms = reinterpret_cast <Atom *> (data.get ());
 
1005
    EXPECT_EQ (atoms[0], mDecorationTypePixmap);
 
1006
}
 
1007
 
 
1008
class DecorFakeDecoratorAcceptance :
 
1009
    public BaseDecorAcceptance
 
1010
{
 
1011
    protected:
 
1012
 
 
1013
        virtual void SetUp ();
 
1014
        virtual void TearDown ();
 
1015
 
 
1016
        virtual unsigned int SupportedDecorations () const;
 
1017
        virtual bool         StartDecoratorOnSetUp () const;
 
1018
 
 
1019
        void SetUpDecorator ();
 
1020
 
 
1021
        void DisallowDecorationsOnWindow (Window window);
 
1022
        void AllowDecorationsOnWindow (Window window);
 
1023
 
 
1024
        std::auto_ptr <cdt::FakeDecorator> decorator;
 
1025
 
 
1026
        Atom NETWMFrameExtentsAtom;
 
1027
        Atom WindowDecorationAtom;
 
1028
        Atom DefaultActiveDecorationAtom;
 
1029
        Atom DefaultBareDecorationAtom;
 
1030
        Atom MWMHintsAtom;
 
1031
};
 
1032
 
 
1033
void
 
1034
DecorFakeDecoratorAcceptance::SetUp ()
 
1035
{
 
1036
    BaseDecorAcceptance::SetUp ();
 
1037
 
 
1038
    NETWMFrameExtentsAtom = XInternAtom (Display (),
 
1039
                                         "_NET_FRAME_EXTENTS",
 
1040
                                         0);
 
1041
 
 
1042
    WindowDecorationAtom = XInternAtom (Display (),
 
1043
                                        DECOR_WINDOW_ATOM_NAME,
 
1044
                                        0);
 
1045
 
 
1046
    DefaultActiveDecorationAtom = XInternAtom (Display (),
 
1047
                                               DECOR_ACTIVE_ATOM_NAME,
 
1048
                                               0);
 
1049
 
 
1050
    DefaultBareDecorationAtom = XInternAtom (Display (),
 
1051
                                             DECOR_BARE_ATOM_NAME,
 
1052
                                             0);
 
1053
 
 
1054
    if (StartDecoratorOnSetUp ())
 
1055
        SetUpDecorator ();
 
1056
}
 
1057
 
 
1058
void
 
1059
DecorFakeDecoratorAcceptance::SetUpDecorator ()
 
1060
{
 
1061
    decorator.reset (new cdt::FakeDecorator (Display (),
 
1062
                                             SupportedDecorations ()));
 
1063
}
 
1064
 
 
1065
namespace
 
1066
{
 
1067
void ChangeDecorationState (Display      *display,
 
1068
                            Window       window,
 
1069
                            unsigned int decorationFlags)
 
1070
{
 
1071
    Atom          mwmHintsAtom = XInternAtom (display, "_MOTIF_WM_HINTS", 0);
 
1072
    cdt::MWMHints hints;
 
1073
 
 
1074
    hints.flags = 1L << 1;
 
1075
    hints.decorations = decorationFlags;
 
1076
 
 
1077
    XChangeProperty (display,
 
1078
                     window,
 
1079
                     mwmHintsAtom,
 
1080
                     mwmHintsAtom,
 
1081
                     32,
 
1082
                     PropModeReplace,
 
1083
                     reinterpret_cast <unsigned char *> (&hints),
 
1084
                     3);
 
1085
}
 
1086
}
 
1087
 
 
1088
void
 
1089
DecorFakeDecoratorAcceptance::DisallowDecorationsOnWindow (Window window)
 
1090
{
 
1091
    ChangeDecorationState (Display (), window, 0);
 
1092
}
 
1093
 
 
1094
void
 
1095
DecorFakeDecoratorAcceptance::AllowDecorationsOnWindow (Window window)
 
1096
{
 
1097
    ChangeDecorationState (Display (), window, cdt::MwmDecor);
 
1098
}
 
1099
 
 
1100
void
 
1101
DecorFakeDecoratorAcceptance::TearDown ()
 
1102
{
 
1103
    decorator.reset ();
 
1104
 
 
1105
    BaseDecorAcceptance::TearDown ();
 
1106
}
 
1107
 
 
1108
unsigned int
 
1109
DecorFakeDecoratorAcceptance::SupportedDecorations () const
 
1110
{
 
1111
    return WINDOW_DECORATION_TYPE_WINDOW;
 
1112
}
 
1113
 
 
1114
bool
 
1115
DecorFakeDecoratorAcceptance::StartDecoratorOnSetUp () const
 
1116
{
 
1117
    return true;
 
1118
}
 
1119
 
 
1120
namespace
 
1121
{
 
1122
void RecievePropertyNotifyEvents (Display *dpy,
 
1123
                                  Window  w)
 
1124
{
 
1125
    XWindowAttributes attrib;
 
1126
 
 
1127
    XGetWindowAttributes (dpy, w, &attrib);
 
1128
    XSelectInput (dpy, w, attrib.your_event_mask | PropertyChangeMask);
 
1129
}
 
1130
 
 
1131
void WaitForPropertyNotify (Display           *dpy,
 
1132
                            Window            w,
 
1133
                            std::string const &prop)
 
1134
{
 
1135
    RecievePropertyNotifyEvents (dpy, w);
 
1136
 
 
1137
    ct::PropertyNotifyXEventMatcher matcher (dpy,
 
1138
                                             prop);
 
1139
 
 
1140
    ASSERT_TRUE (Advance (dpy,
 
1141
                          ct::WaitForEventOfTypeOnWindowMatching (dpy,
 
1142
                                                                  w,
 
1143
                                                                  PropertyNotify,
 
1144
                                                                  -1,
 
1145
                                                                  -1,
 
1146
                                                                  matcher)));
 
1147
}
 
1148
 
 
1149
void WaitForConfigureOn (Display      *display,
 
1150
                         Window       window,
 
1151
                         int          x,
 
1152
                         int          y,
 
1153
                         unsigned int width,
 
1154
                         unsigned int height,
 
1155
                         unsigned int mask)
 
1156
{
 
1157
    /* Wait for the ConfigureNotify on the frame window
 
1158
     * after an offset move */
 
1159
    ct::ConfigureNotifyXEventMatcher matcher (None,
 
1160
                                              0,
 
1161
                                              x,
 
1162
                                              y,
 
1163
                                              width,
 
1164
                                              height,
 
1165
                                              mask);
 
1166
 
 
1167
    Advance (display,
 
1168
             ct::WaitForEventOfTypeOnWindowMatching (display,
 
1169
                                                     window,
 
1170
                                                     ConfigureNotify,
 
1171
                                                     -1,
 
1172
                                                     -1,
 
1173
                                                     matcher));
 
1174
}
 
1175
 
 
1176
void WaitForFrameExtents (Display *dpy,
 
1177
                          Window  w)
 
1178
{
 
1179
    RecievePropertyNotifyEvents (dpy, w);
 
1180
 
 
1181
    XMapRaised (dpy, w);
 
1182
 
 
1183
    WaitForPropertyNotify (dpy, w, "_NET_FRAME_EXTENTS");
 
1184
}
 
1185
 
 
1186
Window FindParent (Display *dpy,
 
1187
                   Window  w)
 
1188
{
 
1189
    Window parent = 0;
 
1190
    Window next = w;
 
1191
    Window root = DefaultRootWindow (dpy);
 
1192
 
 
1193
    while (next != root)
 
1194
    {
 
1195
        parent = next;
 
1196
 
 
1197
        Window       dummy;
 
1198
        Window       *children;
 
1199
        unsigned int nchildren;
 
1200
 
 
1201
        int status = XQueryTree (dpy, parent, &dummy, &next, &children, &nchildren);
 
1202
        XFree (children);
 
1203
 
 
1204
        if (!status)
 
1205
            throw std::logic_error ("XQueryTree failed");
 
1206
    }
 
1207
 
 
1208
    return parent;
 
1209
}
 
1210
 
 
1211
void FreeWindowArray (Window *array)
 
1212
{
 
1213
    if (array)
 
1214
        XFree (array);
 
1215
}
 
1216
 
 
1217
boost::shared_array <Window> FetchChildren (Display      *dpy,
 
1218
                                            Window       w,
 
1219
                                            unsigned int &n)
 
1220
{
 
1221
    Window *children;
 
1222
    Window dummy;
 
1223
 
 
1224
    int status = XQueryTree (dpy,
 
1225
                             w,
 
1226
                             &dummy,
 
1227
                             &dummy,
 
1228
                             &children,
 
1229
                             &n);
 
1230
 
 
1231
    if (!status)
 
1232
        throw std::logic_error ("XQueryTree failed");
 
1233
 
 
1234
    return boost::shared_array <Window> (children,
 
1235
                                         boost::bind (FreeWindowArray, _1));
 
1236
}
 
1237
 
 
1238
class FrameExtentsMatcher :
 
1239
    public MatcherInterface <unsigned long *>
 
1240
{
 
1241
    public:
 
1242
 
 
1243
        FrameExtentsMatcher (unsigned int left,
 
1244
                             unsigned int right,
 
1245
                             unsigned int top,
 
1246
                             unsigned int bottom);
 
1247
 
 
1248
        bool MatchAndExplain (unsigned long *extents,
 
1249
                              MatchResultListener *listener) const;
 
1250
 
 
1251
        void DescribeTo (std::ostream *os) const;
 
1252
 
 
1253
    private:
 
1254
 
 
1255
        unsigned int mLeft;
 
1256
        unsigned int mRight;
 
1257
        unsigned int mTop;
 
1258
        unsigned int mBottom;
 
1259
};
 
1260
 
 
1261
Matcher <unsigned long *>
 
1262
IsExtents (unsigned int left,
 
1263
           unsigned int right,
 
1264
           unsigned int top,
 
1265
           unsigned int bottom)
 
1266
{
 
1267
    return MakeMatcher (new FrameExtentsMatcher (left, right, top, bottom));
 
1268
}
 
1269
}
 
1270
 
 
1271
FrameExtentsMatcher::FrameExtentsMatcher (unsigned int left,
 
1272
                                          unsigned int right,
 
1273
                                          unsigned int top,
 
1274
                                          unsigned int bottom) :
 
1275
    mLeft (left),
 
1276
    mRight (right),
 
1277
    mTop (top),
 
1278
    mBottom (bottom)
 
1279
{
 
1280
}
 
1281
 
 
1282
bool
 
1283
FrameExtentsMatcher::MatchAndExplain (unsigned long *extents,
 
1284
                                      MatchResultListener *listener) const
 
1285
{
 
1286
    return mLeft == extents[0] &&
 
1287
           mRight == extents[1] &&
 
1288
           mTop == extents[2] &&
 
1289
           mBottom == extents[3];
 
1290
}
 
1291
 
 
1292
void
 
1293
FrameExtentsMatcher::DescribeTo (std::ostream *os) const
 
1294
{
 
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;
 
1300
}
 
1301
 
 
1302
TEST_F (DecorFakeDecoratorAcceptance, WindowDefaultFallbackNoExtents)
 
1303
{
 
1304
    Window w = ct::CreateNormalWindow (Display ());
 
1305
    WaitForFrameExtents (Display (), w);
 
1306
 
 
1307
    boost::shared_ptr <unsigned char> data;
 
1308
 
 
1309
    FetchAndVerifyProperty (Display (),
 
1310
                            w,
 
1311
                            NETWMFrameExtentsAtom,
 
1312
                            XA_CARDINAL,
 
1313
                            32,
 
1314
                            4,
 
1315
                            0,
 
1316
                            data);
 
1317
 
 
1318
    unsigned long *frameExtents =
 
1319
        reinterpret_cast <unsigned long *> (data.get ());
 
1320
 
 
1321
    EXPECT_THAT (frameExtents, IsExtents (0, 0, 0, 0));
 
1322
}
 
1323
 
 
1324
class DecorWithPixmapDefaultsAcceptance :
 
1325
    public DecorFakeDecoratorAcceptance
 
1326
{
 
1327
    protected:
 
1328
 
 
1329
        DecorWithPixmapDefaultsAcceptance ();
 
1330
 
 
1331
        virtual void SetUp ();
 
1332
        virtual void TearDown ();
 
1333
        virtual unsigned int SupportedDecorations () const;
 
1334
 
 
1335
    private:
 
1336
 
 
1337
        Window mRoot;
 
1338
 
 
1339
    protected:
 
1340
 
 
1341
        cdt::FakeDecoration::Ptr defaultActiveDecoration ();
 
1342
 
 
1343
        cdt::FakeDecoration::Ptr rootActiveDecoration;
 
1344
        cdt::FakeDecoration::Ptr rootBareDecoration;
 
1345
 
 
1346
        cdt::FakeDecorationList rootActiveDecorationList;
 
1347
        cdt::FakeDecorationList rootBareDecorationList;
 
1348
 
 
1349
        static const unsigned int MaximizedBorderExtent = 1;
 
1350
        static const unsigned int ActiveBorderExtent = 2;
 
1351
        static const unsigned int ActiveInputExtent = 4;
 
1352
};
 
1353
 
 
1354
namespace
 
1355
{
 
1356
cdt::FakePixmapTypeDecoration::Ptr
 
1357
MakeFakePixmapTypeDecoration (unsigned int type,
 
1358
                              unsigned int state,
 
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,
 
1366
                              Display               *dpy)
 
1367
{
 
1368
    cdt::FakePixmapTypeDecoration *decoration =
 
1369
        new cdt::FakePixmapTypeDecoration (type,
 
1370
                                           state,
 
1371
                                           actions,
 
1372
                                           minWidth,
 
1373
                                           minHeight,
 
1374
                                           restoredBorder,
 
1375
                                           restoredInput,
 
1376
                                           maximizedBorder,
 
1377
                                           maximizedInput,
 
1378
                                           dpy);
 
1379
 
 
1380
    return boost::shared_ptr <cdt::FakePixmapTypeDecoration> (decoration);
 
1381
}
 
1382
 
 
1383
decor_extents_t
 
1384
DecorationExtents (unsigned int    left,
 
1385
                   unsigned int    right,
 
1386
                   unsigned int    top,
 
1387
                   unsigned int    bottom)
 
1388
{
 
1389
    decor_extents_t extents;
 
1390
 
 
1391
    extents.left = left;
 
1392
    extents.right = right;
 
1393
    extents.top = top;
 
1394
    extents.bottom = bottom;
 
1395
 
 
1396
    return extents;
 
1397
}
 
1398
 
 
1399
class ExtentsFromMatcher :
 
1400
    public MatcherInterface <Window>
 
1401
{
 
1402
    public:
 
1403
 
 
1404
        ExtentsFromMatcher (Display               *dpy,
 
1405
                            Window                w,
 
1406
                            const decor_extents_t &extents);
 
1407
 
 
1408
        bool MatchAndExplain (Window window,
 
1409
                              MatchResultListener *listener) const;
 
1410
 
 
1411
        void DescribeTo (std::ostream *os) const;
 
1412
 
 
1413
    private:
 
1414
 
 
1415
        Display         *mDpy;
 
1416
        Window          mWindow;
 
1417
        decor_extents_t mExpectedExtents;
 
1418
};
 
1419
 
 
1420
Matcher <Window>
 
1421
ExtendsFromWindowBy (Display               *dpy,
 
1422
                     Window                w,
 
1423
                     const decor_extents_t &extents)
 
1424
{
 
1425
    return MakeMatcher (new ExtentsFromMatcher (dpy, w, extents));
 
1426
}
 
1427
}
 
1428
 
 
1429
std::ostream &
 
1430
operator<< (std::ostream &lhs, const decor_extents_t &extents)
 
1431
{
 
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;
 
1437
}
 
1438
 
 
1439
ExtentsFromMatcher::ExtentsFromMatcher (Display               *dpy,
 
1440
                                        Window                w,
 
1441
                                        const decor_extents_t &extents) :
 
1442
    mDpy (dpy),
 
1443
    mWindow (w),
 
1444
    mExpectedExtents (extents)
 
1445
{
 
1446
}
 
1447
 
 
1448
bool
 
1449
ExtentsFromMatcher::MatchAndExplain (Window window,
 
1450
                                     MatchResultListener *listener) const
 
1451
{
 
1452
    unsigned int border, depth;
 
1453
    Window       root;
 
1454
 
 
1455
    int          compareX, compareY, matchX, matchY;
 
1456
    unsigned int compareWidth, compareHeight, matchWidth, matchHeight;
 
1457
 
 
1458
    if (!XGetGeometry (mDpy, window, &root,
 
1459
                       &matchX, &matchY, &matchWidth, &matchHeight,
 
1460
                       &border, &depth))
 
1461
        throw std::logic_error ("XGetGeometry failed");
 
1462
 
 
1463
    if (!XGetGeometry (mDpy, mWindow, &root,
 
1464
                       &compareX, &compareY, &compareWidth, &compareHeight,
 
1465
                       &border, &depth))
 
1466
        throw std::logic_error ("XGetGeometry failed");
 
1467
 
 
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);
 
1472
 
 
1473
    decor_extents_t determinedExtents = DecorationExtents (left, right, top, bottom);
 
1474
 
 
1475
    return decor_extents_cmp (&determinedExtents, &mExpectedExtents);
 
1476
}
 
1477
 
 
1478
void
 
1479
ExtentsFromMatcher::DescribeTo (std::ostream *os) const
 
1480
{
 
1481
    *os << "Extends outwards from " << std::hex << mWindow << std::dec
 
1482
        << " by: " << mExpectedExtents;
 
1483
}
 
1484
 
 
1485
DecorWithPixmapDefaultsAcceptance::DecorWithPixmapDefaultsAcceptance () :
 
1486
    mRoot (0),
 
1487
    rootActiveDecorationList (WINDOW_DECORATION_TYPE_PIXMAP),
 
1488
    rootBareDecorationList (WINDOW_DECORATION_TYPE_PIXMAP)
 
1489
{
 
1490
}
 
1491
 
 
1492
unsigned int
 
1493
DecorWithPixmapDefaultsAcceptance::SupportedDecorations () const
 
1494
{
 
1495
    return WINDOW_DECORATION_TYPE_PIXMAP;
 
1496
}
 
1497
 
 
1498
void
 
1499
DecorWithPixmapDefaultsAcceptance::SetUp ()
 
1500
{
 
1501
    DecorFakeDecoratorAcceptance::SetUp ();
 
1502
 
 
1503
    mRoot = DefaultRootWindow (Display ());
 
1504
 
 
1505
    unsigned int ResBo = ActiveBorderExtent;
 
1506
    unsigned int ResIn = ActiveInputExtent;
 
1507
    unsigned int MaxEx = MaximizedBorderExtent;
 
1508
 
 
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));
 
1513
 
 
1514
    decor_extents_t emptyExtents (DecorationExtents (0, 0, 0, 0));
 
1515
 
 
1516
    rootActiveDecoration =
 
1517
        MakeFakePixmapTypeDecoration (DECOR_WINDOW_TYPE_NORMAL,
 
1518
                                      0,
 
1519
                                      0,
 
1520
                                      10, 10,
 
1521
                                      activeBorderRestored,
 
1522
                                      activeInputRestored,
 
1523
                                      activeBorderMaximized,
 
1524
                                      activeInputMaximized,
 
1525
                                      Display ());
 
1526
 
 
1527
    rootBareDecoration =
 
1528
        MakeFakePixmapTypeDecoration (0, 0, 0,
 
1529
                                      1, 1,
 
1530
                                      emptyExtents,
 
1531
                                      emptyExtents,
 
1532
                                      emptyExtents,
 
1533
                                      emptyExtents,
 
1534
                                      Display ());
 
1535
 
 
1536
    rootActiveDecorationList.AddDecoration (rootActiveDecoration);
 
1537
    rootBareDecorationList.AddDecoration (rootBareDecoration);
 
1538
 
 
1539
    rootActiveDecorationList.SetPropertyOnWindow (Display (),
 
1540
                                                  mRoot,
 
1541
                                                  DefaultActiveDecorationAtom);
 
1542
    rootBareDecorationList.SetPropertyOnWindow (Display (),
 
1543
                                                mRoot,
 
1544
                                                DefaultBareDecorationAtom);
 
1545
}
 
1546
 
 
1547
void
 
1548
DecorWithPixmapDefaultsAcceptance::TearDown ()
 
1549
{
 
1550
    /* Remove inserted decorations */
 
1551
    rootActiveDecorationList.RemoveAllDecorations ();
 
1552
    rootBareDecorationList.RemoveAllDecorations ();
 
1553
 
 
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 ();
 
1560
 
 
1561
    DecorFakeDecoratorAcceptance::TearDown ();
 
1562
}
 
1563
 
 
1564
TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackRecieveInputFrameNotify)
 
1565
{
 
1566
    Window w = ct::CreateNormalWindow (Display ());
 
1567
    RecievePropertyNotifyEvents (Display (), w);
 
1568
    XMapRaised (Display (), w);
 
1569
 
 
1570
    ct::PropertyNotifyXEventMatcher matcher (Display (),
 
1571
                                             DECOR_INPUT_FRAME_ATOM_NAME);
 
1572
 
 
1573
    EXPECT_TRUE (Advance (Display (),
 
1574
                          ct::WaitForEventOfTypeOnWindowMatching (Display (),
 
1575
                                                                  w,
 
1576
                                                                  PropertyNotify,
 
1577
                                                                  -1,
 
1578
                                                                  -1,
 
1579
                                                                  matcher)));
 
1580
}
 
1581
 
 
1582
TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackHasInputFrameInParent)
 
1583
{
 
1584
    Window w = ct::CreateNormalWindow (Display ());
 
1585
 
 
1586
    XMapRaised (Display (), w);
 
1587
    WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
 
1588
 
 
1589
    Window parent = FindParent (Display (), w);
 
1590
 
 
1591
    unsigned int                 nChildren;
 
1592
    boost::shared_array <Window> children (FetchChildren (Display (),
 
1593
                                                          parent,
 
1594
                                                          nChildren));
 
1595
 
 
1596
    EXPECT_EQ (2, nChildren);
 
1597
}
 
1598
 
 
1599
namespace
 
1600
{
 
1601
Window FindDecorationWindowFromChildren (Display *dpy,
 
1602
                                         const boost::shared_array <Window> &c,
 
1603
                                         unsigned int nChildren)
 
1604
{
 
1605
    for (unsigned int i = 0; i < nChildren; ++i)
 
1606
    {
 
1607
        /* The decoration window will have no children, but
 
1608
         * the wrapper window will have one child */
 
1609
        unsigned int                 n;
 
1610
        boost::shared_array <Window> childChildren (FetchChildren (dpy,
 
1611
                                                                   c[i],
 
1612
                                                                   n));
 
1613
        if (n == 0)
 
1614
            return c[i];
 
1615
    }
 
1616
 
 
1617
    return None;
 
1618
}
 
1619
}
 
1620
 
 
1621
TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackNormalWindowExtentOnDecoration)
 
1622
{
 
1623
    Window w = ct::CreateNormalWindow (Display ());
 
1624
 
 
1625
    XMapRaised (Display (), w);
 
1626
    WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
 
1627
 
 
1628
    Window parent = FindParent (Display (), w);
 
1629
 
 
1630
    unsigned int                 nChildren;
 
1631
    boost::shared_array <Window> children (FetchChildren (Display (),
 
1632
                                                          parent,
 
1633
                                                          nChildren));
 
1634
 
 
1635
    ASSERT_EQ (2, nChildren);
 
1636
 
 
1637
    Window decorationWindow = FindDecorationWindowFromChildren (Display (),
 
1638
                                                                children,
 
1639
                                                                nChildren);
 
1640
 
 
1641
    ASSERT_NE (None, decorationWindow);
 
1642
 
 
1643
    decor_extents_t borderExtents (DecorationExtents (ActiveBorderExtent,
 
1644
                                                      ActiveBorderExtent,
 
1645
                                                      ActiveBorderExtent,
 
1646
                                                      ActiveBorderExtent));
 
1647
    EXPECT_THAT (decorationWindow, ExtendsFromWindowBy (Display (),
 
1648
                                                        w,
 
1649
                                                        borderExtents));
 
1650
}
 
1651
 
 
1652
TEST_F (DecorWithPixmapDefaultsAcceptance, FallbackNormalWindowInputOnFrame)
 
1653
{
 
1654
    Window w = ct::CreateNormalWindow (Display ());
 
1655
 
 
1656
    XMapRaised (Display (), w);
 
1657
    WaitForPropertyNotify (Display (), w, DECOR_INPUT_FRAME_ATOM_NAME);
 
1658
 
 
1659
    Window parent = FindParent (Display (), w);
 
1660
 
 
1661
    decor_extents_t inputExtents (DecorationExtents (ActiveInputExtent,
 
1662
                                                     ActiveInputExtent,
 
1663
                                                     ActiveInputExtent,
 
1664
                                                     ActiveInputExtent));
 
1665
    EXPECT_THAT (parent, ExtendsFromWindowBy (Display (),
 
1666
                                              w,
 
1667
                                              inputExtents));
 
1668
}
 
1669
 
 
1670
/* TODO: Get bare decorations tests */
 
1671
 
 
1672
/* Helper class with some useful member functions */
 
1673
class PixmapDecoratorAcceptance :
 
1674
    public DecorWithPixmapDefaultsAcceptance
 
1675
{
 
1676
    public:
 
1677
 
 
1678
        typedef cdt::FakeDecoration::Ptr FakeDecorPtr;
 
1679
        typedef cdt::FakePixmapTypeDecoration::Ptr FakePixDecorPtr;
 
1680
 
 
1681
        virtual void TearDown ();
 
1682
 
 
1683
        Window CreateDecoratableWindow (::Display *display);
 
1684
        Window MapAndReparent (::Display *display,
 
1685
                               Window window);
 
1686
 
 
1687
        void DecorateWindow (::Display                *display,
 
1688
                             Window                   window,
 
1689
                             const FakePixDecorPtr &decoration);
 
1690
        void WaitForDecoration (::Display          *display,
 
1691
                                Window             window,
 
1692
                                const FakeDecorPtr &decoration);
 
1693
        void WaitForDefaultDecoration (::Display *display,
 
1694
                                       Window    window,
 
1695
                                       CompRect  &testFrameDecorationGeometry,
 
1696
                                       CompRect  &testWindowDecorationGeometry);
 
1697
        void WaitForDecorationUpdate (::Display          *display,
 
1698
                                      Window             window,
 
1699
                                      const FakeDecorPtr &decor);
 
1700
 
 
1701
        cdt::FakeDecorationList GetDecorations (Window window);
 
1702
        Window                  GetParent (Window window);
 
1703
 
 
1704
        void ReconfigureDecoration (::Display             *display,
 
1705
                                    Window                window,
 
1706
                                    const FakePixDecorPtr &decor,
 
1707
                                    cdt::FakeDecorationList &list,
 
1708
                                    const decor_extents_t &border,
 
1709
                                    const decor_extents_t &input);
 
1710
 
 
1711
        bool DestroyWindow (::Display *display,
 
1712
                            Window    window);
 
1713
 
 
1714
 
 
1715
    protected:
 
1716
 
 
1717
        std::map <Window, cdt::FakeDecorationList> windowDecorations;
 
1718
        std::map <Window, Window> windowParents;
 
1719
};
 
1720
 
 
1721
void
 
1722
PixmapDecoratorAcceptance::TearDown ()
 
1723
{
 
1724
    windowDecorations.clear ();
 
1725
 
 
1726
    DecorWithPixmapDefaultsAcceptance::TearDown ();
 
1727
}
 
1728
 
 
1729
Window
 
1730
PixmapDecoratorAcceptance::CreateDecoratableWindow (::Display *display)
 
1731
{
 
1732
    return ct::CreateNormalWindow (display);
 
1733
}
 
1734
 
 
1735
Window
 
1736
PixmapDecoratorAcceptance::MapAndReparent (::Display *display,
 
1737
                                           Window    window)
 
1738
{
 
1739
    if (windowParents.find (window) != windowParents.end ())
 
1740
        return windowParents[window];
 
1741
 
 
1742
    XSelectInput (display, window,
 
1743
                  StructureNotifyMask |
 
1744
                  PropertyChangeMask);
 
1745
    XMapRaised (display, window);
 
1746
 
 
1747
    /* Wait for the window to be reparented */
 
1748
    Advance (Display (),
 
1749
             ct::WaitForEventOfTypeOnWindow (display,
 
1750
                                             window,
 
1751
                                             ReparentNotify,
 
1752
                                             -1,
 
1753
                                             -1));
 
1754
 
 
1755
    /* Select for StructureNotify on the parent and wrapper
 
1756
     * windows */
 
1757
    windowParents[window] = FindParent (display, window);
 
1758
 
 
1759
    Window root = 0;
 
1760
    Window wrapper = ct::GetImmediateParent (display, window, root);
 
1761
 
 
1762
    XSelectInput (display, windowParents[window], StructureNotifyMask);
 
1763
    XSelectInput (display, wrapper, StructureNotifyMask);
 
1764
 
 
1765
    return windowParents[window];
 
1766
}
 
1767
 
 
1768
void
 
1769
PixmapDecoratorAcceptance::DecorateWindow (::Display             *display,
 
1770
                                           Window                window,
 
1771
                                           const FakePixDecorPtr &decoration)
 
1772
{
 
1773
    windowDecorations[window] = cdt::FakeDecorationList (WINDOW_DECORATION_TYPE_PIXMAP);
 
1774
    windowDecorations[window].AddDecoration (decoration);
 
1775
    windowDecorations[window].SetPropertyOnWindow (display,
 
1776
                                                window,
 
1777
                                                WindowDecorationAtom);
 
1778
}
 
1779
 
 
1780
void
 
1781
PixmapDecoratorAcceptance::WaitForDecoration (::Display          *display,
 
1782
                                              Window             window,
 
1783
                                              const FakeDecorPtr &decoration)
 
1784
{
 
1785
    WaitForDecorationUpdate (display, window, decoration);
 
1786
    WaitForPropertyNotify (display, window, DECOR_INPUT_FRAME_ATOM_NAME);
 
1787
}
 
1788
 
 
1789
void
 
1790
PixmapDecoratorAcceptance::WaitForDefaultDecoration (::Display *display,
 
1791
                                                     Window    window,
 
1792
                                                     CompRect  &decoratedWindowGeometry,
 
1793
                                                     CompRect  &decoratedFrameGeometry)
 
1794
{
 
1795
    WaitForDecoration (display, window, rootActiveDecoration);
 
1796
 
 
1797
    /* Fetch the window's absolute geometry */
 
1798
    int x, y;
 
1799
    unsigned int width, height, border;
 
1800
 
 
1801
    ct::AbsoluteWindowGeometry (display, window, x, y, width, height, border);
 
1802
 
 
1803
    /* Fetch frame extents */
 
1804
    boost::shared_ptr <unsigned char> data;
 
1805
 
 
1806
    FetchAndVerifyProperty (Display (),
 
1807
                            window,
 
1808
                            NETWMFrameExtentsAtom,
 
1809
                            XA_CARDINAL,
 
1810
                            32,
 
1811
                            4,
 
1812
                            0,
 
1813
                            data);
 
1814
 
 
1815
    unsigned long *frameExtents =
 
1816
        reinterpret_cast <unsigned long *> (data.get ());
 
1817
 
 
1818
    decoratedWindowGeometry.setGeometry (x, y, width, height);
 
1819
 
 
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]));
 
1826
}
 
1827
 
 
1828
void
 
1829
PixmapDecoratorAcceptance::WaitForDecorationUpdate (::Display          *display,
 
1830
                                                    Window             window,
 
1831
                                                    const FakeDecorPtr &decor)
 
1832
{
 
1833
    const CompPoint &framePos (decor->restoredFrameWindowOffset ());
 
1834
 
 
1835
    /* Wait for the ConfigureNotify on the frame window
 
1836
     * after an offset move */
 
1837
    WaitForConfigureOn (display,
 
1838
                        GetParent (window),
 
1839
                        framePos.x (),
 
1840
                        framePos.y (),
 
1841
                        0,
 
1842
                        0,
 
1843
                        CWX | CWY);
 
1844
 
 
1845
    /* Wait for the frame extents to change */
 
1846
    WaitForPropertyNotify (display, window, "_NET_FRAME_EXTENTS");
 
1847
}
 
1848
 
 
1849
void
 
1850
PixmapDecoratorAcceptance::ReconfigureDecoration (::Display             *display,
 
1851
                                                  Window                window,
 
1852
                                                  const FakePixDecorPtr &decor,
 
1853
                                                  cdt::FakeDecorationList &list,
 
1854
                                                  const decor_extents_t &border,
 
1855
                                                  const decor_extents_t &input)
 
1856
{
 
1857
    decor->changeRestoredInput (input);
 
1858
    decor->changeRestoredBorder (border);
 
1859
    list.SetPropertyOnWindow (display,
 
1860
                              window,
 
1861
                              WindowDecorationAtom);
 
1862
 
 
1863
    WaitForDecorationUpdate (display, window, decor);
 
1864
}
 
1865
 
 
1866
bool
 
1867
PixmapDecoratorAcceptance::DestroyWindow (::Display *display,
 
1868
                                          Window    window)
 
1869
{
 
1870
    std::map <Window, Window>::iterator parentIterator =
 
1871
        windowParents.find (window);
 
1872
    std::map <Window, cdt::FakeDecorationList>::iterator decorIterator =
 
1873
        windowDecorations.find (window);
 
1874
 
 
1875
    if (parentIterator != windowParents.end ())
 
1876
        windowParents.erase (parentIterator);
 
1877
    if (decorIterator != windowDecorations.end ())
 
1878
    {
 
1879
        windowDecorations[window].RemoveAllDecorations ();
 
1880
        windowDecorations.erase (decorIterator);
 
1881
    }
 
1882
 
 
1883
    XDestroyWindow (display, window);
 
1884
 
 
1885
    return parentIterator != windowParents.end () ||
 
1886
           decorIterator != windowDecorations.end ();
 
1887
}
 
1888
 
 
1889
Window
 
1890
PixmapDecoratorAcceptance::GetParent (Window window)
 
1891
{
 
1892
    return windowParents[window];
 
1893
}
 
1894
 
 
1895
cdt::FakeDecorationList
 
1896
PixmapDecoratorAcceptance::GetDecorations (Window window)
 
1897
{
 
1898
    return windowDecorations[window];
 
1899
}
 
1900
 
 
1901
class PixmapInitialDecorationAcceptance :
 
1902
    public PixmapDecoratorAcceptance
 
1903
{
 
1904
    public:
 
1905
 
 
1906
        virtual void SetUp ();
 
1907
        virtual void TearDown ();
 
1908
 
 
1909
        virtual bool StartDecoratorOnSetUp () const;
 
1910
 
 
1911
        Window CreateDecoratedWindow ();
 
1912
 
 
1913
    protected:
 
1914
 
 
1915
        cdt::FakePixmapTypeDecoration::Ptr mTestWindowDecoration;
 
1916
        CompRect                           mClientGeometryOnInitialDecoration;
 
1917
        CompRect                           mBorderGeometryOnInitialDecoration;
 
1918
};
 
1919
 
 
1920
void
 
1921
PixmapInitialDecorationAcceptance::SetUp ()
 
1922
{
 
1923
    PixmapDecoratorAcceptance::SetUp ();
 
1924
 
 
1925
    unsigned int ResBo = ActiveBorderExtent + 1;
 
1926
    unsigned int ResIn = ActiveInputExtent;
 
1927
    unsigned int MaxEx = MaximizedBorderExtent;
 
1928
 
 
1929
    mTestWindowDecoration =
 
1930
        MakeFakePixmapTypeDecoration (DECOR_WINDOW_TYPE_NORMAL,
 
1931
                                      0,
 
1932
                                      0,
 
1933
                                      10,
 
1934
                                      10,
 
1935
                                      DecorationExtents (ResBo, ResBo, ResBo, ResBo),
 
1936
                                      DecorationExtents (ResIn, ResIn, ResIn, ResIn),
 
1937
                                      DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
 
1938
                                      DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
 
1939
                                      Display ());
 
1940
}
 
1941
 
 
1942
bool
 
1943
PixmapInitialDecorationAcceptance::StartDecoratorOnSetUp () const
 
1944
{
 
1945
    return false;
 
1946
}
 
1947
 
 
1948
void
 
1949
PixmapInitialDecorationAcceptance::TearDown ()
 
1950
{
 
1951
    mTestWindowDecoration.reset ();
 
1952
    PixmapDecoratorAcceptance::TearDown ();
 
1953
}
 
1954
 
 
1955
Window
 
1956
PixmapInitialDecorationAcceptance::CreateDecoratedWindow ()
 
1957
{
 
1958
    Window testWindow = CreateDecoratableWindow (Display ());
 
1959
 
 
1960
    /* We need to first explicitly recieve PropertyNotify events before
 
1961
     * core starts sending them */
 
1962
    RecievePropertyNotifyEvents (Display (), testWindow);
 
1963
 
 
1964
    /* Map and reparent the window so that it gets a decoration */
 
1965
    MapAndReparent (Display (), testWindow);
 
1966
 
 
1967
    /* Start the decorator */
 
1968
    SetUpDecorator ();
 
1969
 
 
1970
    WaitForDefaultDecoration (Display (),
 
1971
                              testWindow,
 
1972
                              mClientGeometryOnInitialDecoration,
 
1973
                              mBorderGeometryOnInitialDecoration);
 
1974
    DecorateWindow (Display (), testWindow, mTestWindowDecoration);
 
1975
    WaitForDecorationUpdate (Display (), testWindow, mTestWindowDecoration);
 
1976
 
 
1977
    return testWindow;
 
1978
}
 
1979
 
 
1980
std::ostream &
 
1981
operator<< (std::ostream &os, const CompSize &sz)
 
1982
{
 
1983
    return os << "Size: (width: "
 
1984
              << sz.width ()
 
1985
              << " height: "
 
1986
              << sz.height ()
 
1987
              << ")";
 
1988
}
 
1989
 
 
1990
TEST_F (PixmapInitialDecorationAcceptance, NoSizeChangeInitially)
 
1991
{
 
1992
    CreateDecoratedWindow ();
 
1993
    EXPECT_EQ (CompSize (mClientGeometryOnInitialDecoration.width (),
 
1994
                         mClientGeometryOnInitialDecoration.height ()),
 
1995
               CompSize (ct::WINDOW_WIDTH,
 
1996
                         ct::WINDOW_HEIGHT));
 
1997
}
 
1998
 
 
1999
TEST_F (PixmapInitialDecorationAcceptance, SizeChangesApplySubsequently)
 
2000
{
 
2001
    Window testWindow = CreateDecoratedWindow ();
 
2002
 
 
2003
    /* Measuring size change from default decoration to real decoration */
 
2004
    const CompSize &size (mTestWindowDecoration->restoredDecorationBorderSize ());
 
2005
 
 
2006
    EXPECT_THAT (testWindow,
 
2007
                 HasGeometry (Display (),
 
2008
                              RelativeWindowGeometry,
 
2009
                              _,
 
2010
                              _,
 
2011
                              mBorderGeometryOnInitialDecoration.width () -
 
2012
                                  size.width (),
 
2013
                              mBorderGeometryOnInitialDecoration.height () -
 
2014
                                  size.height (),
 
2015
                              _));
 
2016
}
 
2017
 
 
2018
class PixmapDecoratedWindowAcceptance :
 
2019
    public PixmapDecoratorAcceptance
 
2020
{
 
2021
    public:
 
2022
 
 
2023
        PixmapDecoratedWindowAcceptance ();
 
2024
 
 
2025
        virtual void SetUp ();
 
2026
        virtual void TearDown ();
 
2027
 
 
2028
        virtual bool StartDecoratorOnSetUp () const;
 
2029
 
 
2030
    protected:
 
2031
 
 
2032
        unsigned int RealDecorationActiveBorderExtent;
 
2033
 
 
2034
        Window mTestWindow;
 
2035
        Window mTestWindowParent;
 
2036
 
 
2037
        cdt::FakePixmapTypeDecoration::Ptr mTestWindowDecoration;
 
2038
        CompRect mClientGeometryOnInitialDecoration;
 
2039
        CompRect mBorderGeometryOnInitialDecoration;
 
2040
};
 
2041
 
 
2042
PixmapDecoratedWindowAcceptance::PixmapDecoratedWindowAcceptance () :
 
2043
    RealDecorationActiveBorderExtent (ActiveBorderExtent + 1)
 
2044
{
 
2045
}
 
2046
 
 
2047
void
 
2048
PixmapDecoratedWindowAcceptance::SetUp ()
 
2049
{
 
2050
    DecorWithPixmapDefaultsAcceptance::SetUp ();
 
2051
 
 
2052
    ::Display *display = Display ();
 
2053
 
 
2054
    mTestWindow = CreateDecoratableWindow (display);
 
2055
    mTestWindowParent = MapAndReparent (display, mTestWindow);
 
2056
 
 
2057
    /* Start the decorator */
 
2058
    SetUpDecorator ();
 
2059
 
 
2060
    WaitForDefaultDecoration (display,
 
2061
                              mTestWindow,
 
2062
                              mClientGeometryOnInitialDecoration,
 
2063
                              mBorderGeometryOnInitialDecoration);
 
2064
 
 
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;
 
2070
 
 
2071
    mTestWindowDecoration =
 
2072
        MakeFakePixmapTypeDecoration (DECOR_WINDOW_TYPE_NORMAL,
 
2073
                                      0,
 
2074
                                      0,
 
2075
                                      10,
 
2076
                                      10,
 
2077
                                      DecorationExtents (ResBo, ResBo, ResBo, ResBo),
 
2078
                                      DecorationExtents (ResIn, ResIn, ResIn, ResIn),
 
2079
                                      DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
 
2080
                                      DecorationExtents (MaxEx, MaxEx, MaxEx, MaxEx),
 
2081
                                      Display ());
 
2082
 
 
2083
    DecorateWindow (display, mTestWindow, mTestWindowDecoration);
 
2084
    WaitForDecorationUpdate (display, mTestWindow, mTestWindowDecoration);
 
2085
}
 
2086
 
 
2087
void
 
2088
PixmapDecoratedWindowAcceptance::TearDown ()
 
2089
{
 
2090
    mTestWindowDecoration.reset ();
 
2091
    DestroyWindow (Display (), mTestWindow);
 
2092
 
 
2093
    PixmapDecoratorAcceptance::TearDown ();
 
2094
}
 
2095
 
 
2096
bool
 
2097
PixmapDecoratedWindowAcceptance::StartDecoratorOnSetUp () const
 
2098
{
 
2099
    return false;
 
2100
}
 
2101
 
 
2102
namespace
 
2103
{
 
2104
static const unsigned int RemoveState = 0;
 
2105
static const unsigned int AddState = 1;
 
2106
static const unsigned int ToggleState = 2;
 
2107
 
 
2108
void ChangeStateOfWindow (Display           *dpy,
 
2109
                          unsigned int      mode,
 
2110
                          const std::string &state,
 
2111
                          Window            w)
 
2112
{
 
2113
    XEvent event;
 
2114
 
 
2115
    const long ClientTypePager = 2;
 
2116
 
 
2117
    event.type = ClientMessage;
 
2118
    event.xany.window = w;
 
2119
 
 
2120
    event.xclient.format = 32;
 
2121
    event.xclient.message_type = XInternAtom (dpy, "_NET_WM_STATE", 0);
 
2122
 
 
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;
 
2127
 
 
2128
    XSendEvent (dpy,
 
2129
                DefaultRootWindow (dpy),
 
2130
                1,
 
2131
                SubstructureRedirectMask,
 
2132
                &event);
 
2133
    XSync (dpy, 0);
 
2134
}
 
2135
 
 
2136
boost::shared_ptr <unsigned char>
 
2137
FetchCardinalProperty (Display *dpy,
 
2138
                       Window  w,
 
2139
                       Atom    NETWMFrameExtentsAtom)
 
2140
{
 
2141
    boost::shared_ptr <unsigned char> data;
 
2142
 
 
2143
    FetchAndVerifyProperty (dpy,
 
2144
                            w,
 
2145
                            NETWMFrameExtentsAtom,
 
2146
                            XA_CARDINAL,
 
2147
                            32,
 
2148
                            4,
 
2149
                            0,
 
2150
                            data);
 
2151
 
 
2152
    return data;
 
2153
}
 
2154
}
 
2155
 
 
2156
TEST_F (PixmapDecoratedWindowAcceptance, MaximizeBorderExtentsOnMaximize)
 
2157
{
 
2158
    ChangeStateOfWindow (Display (),
 
2159
                         AddState,
 
2160
                         "_NET_WM_STATE_MAXIMIZED_VERT",
 
2161
                         mTestWindow);
 
2162
                         
 
2163
    WaitForPropertyNotify (Display (), mTestWindow, "_NET_FRAME_EXTENTS");
 
2164
 
 
2165
    ChangeStateOfWindow (Display (),
 
2166
                         AddState,
 
2167
                         "_NET_WM_STATE_MAXIMIZED_HORZ",
 
2168
                         mTestWindow);
 
2169
 
 
2170
    WaitForPropertyNotify (Display (), mTestWindow, "_NET_FRAME_EXTENTS");
 
2171
 
 
2172
    boost::shared_ptr <unsigned char> data =
 
2173
        FetchCardinalProperty (Display (),
 
2174
                               mTestWindow,
 
2175
                               NETWMFrameExtentsAtom);
 
2176
 
 
2177
    unsigned long *frameExtents =
 
2178
        reinterpret_cast <unsigned long *> (data.get ());
 
2179
 
 
2180
    unsigned int MaxEx = MaximizedBorderExtent;
 
2181
 
 
2182
    EXPECT_THAT (frameExtents, IsExtents (MaxEx, MaxEx, MaxEx, MaxEx));
 
2183
}
 
2184
 
 
2185
TEST_F (PixmapDecoratedWindowAcceptance, RestoredBorderExtentsOnVertMaximize)
 
2186
{
 
2187
    ChangeStateOfWindow (Display (),
 
2188
                         AddState,
 
2189
                         "_NET_WM_STATE_MAXIMIZED_VERT",
 
2190
                         mTestWindow);
 
2191
 
 
2192
    WaitForPropertyNotify (Display (), mTestWindow, "_NET_FRAME_EXTENTS");
 
2193
 
 
2194
    boost::shared_ptr <unsigned char> data =
 
2195
        FetchCardinalProperty (Display (),
 
2196
                               mTestWindow,
 
2197
                               NETWMFrameExtentsAtom);
 
2198
 
 
2199
    unsigned long *frameExtents =
 
2200
        reinterpret_cast <unsigned long *> (data.get ());
 
2201
 
 
2202
    unsigned int ActEx = RealDecorationActiveBorderExtent;
 
2203
 
 
2204
    EXPECT_THAT (frameExtents, IsExtents (ActEx, ActEx, ActEx, ActEx));
 
2205
}
 
2206
 
 
2207
TEST_F (PixmapDecoratedWindowAcceptance, RestoredBorderExtentsOnHorzMaximize)
 
2208
{
 
2209
    ChangeStateOfWindow (Display (),
 
2210
                         AddState,
 
2211
                         "_NET_WM_STATE_MAXIMIZED_HORZ",
 
2212
                         mTestWindow);
 
2213
 
 
2214
    WaitForPropertyNotify (Display (), mTestWindow, "_NET_FRAME_EXTENTS");
 
2215
 
 
2216
    boost::shared_ptr <unsigned char> data =
 
2217
        FetchCardinalProperty (Display (),
 
2218
                               mTestWindow,
 
2219
                               NETWMFrameExtentsAtom);
 
2220
 
 
2221
    unsigned long *frameExtents =
 
2222
        reinterpret_cast <unsigned long *> (data.get ());
 
2223
 
 
2224
    unsigned int ActEx = RealDecorationActiveBorderExtent;
 
2225
    
 
2226
    EXPECT_THAT (frameExtents, IsExtents (ActEx, ActEx, ActEx, ActEx));
 
2227
}
 
2228
 
 
2229
TEST_F (PixmapDecoratedWindowAcceptance, MaximizeFrameWindowSizeEqOutputSize)
 
2230
{
 
2231
    XWindowAttributes attrib;
 
2232
    XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
 
2233
 
 
2234
    /* The assumption here is that there is only one output */
 
2235
 
 
2236
    ChangeStateOfWindow (Display (),
 
2237
                         AddState,
 
2238
                         "_NET_WM_STATE_MAXIMIZED_VERT",
 
2239
                         mTestWindow);
 
2240
 
 
2241
    ChangeStateOfWindow (Display (),
 
2242
                         AddState,
 
2243
                         "_NET_WM_STATE_MAXIMIZED_HORZ",
 
2244
                         mTestWindow);
 
2245
 
 
2246
    ct::ConfigureNotifyXEventMatcher matcher (None,
 
2247
                                              0,
 
2248
                                              0,
 
2249
                                              0,
 
2250
                                              attrib.width,
 
2251
                                              attrib.height,
 
2252
                                              CWX | CWY | CWWidth | CWHeight);
 
2253
 
 
2254
    EXPECT_TRUE (Advance (Display (),
 
2255
                          ct::WaitForEventOfTypeOnWindowMatching (Display (),
 
2256
                                                                  mTestWindowParent,
 
2257
                                                                  ConfigureNotify,
 
2258
                                                                  -1,
 
2259
                                                                  -1,
 
2260
                                                                  matcher)));
 
2261
}
 
2262
 
 
2263
TEST_F (PixmapDecoratedWindowAcceptance, VertMaximizeFrameWindowYHeight)
 
2264
{
 
2265
    XWindowAttributes attrib;
 
2266
    XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
 
2267
 
 
2268
    ChangeStateOfWindow (Display (),
 
2269
                         AddState,
 
2270
                         "_NET_WM_STATE_MAXIMIZED_VERT",
 
2271
                         mTestWindow);
 
2272
 
 
2273
    int offset = RealDecorationActiveBorderExtent - ActiveInputExtent;
 
2274
    ct::ConfigureNotifyXEventMatcher matcher (None,
 
2275
                                              0,
 
2276
                                              0,
 
2277
                                              offset,
 
2278
                                              0,
 
2279
                                              attrib.height - 2 * offset,
 
2280
                                              CWY | CWHeight);
 
2281
 
 
2282
    EXPECT_TRUE (Advance (Display (),
 
2283
                          ct::WaitForEventOfTypeOnWindowMatching (Display (),
 
2284
                                                                  mTestWindowParent,
 
2285
                                                                  ConfigureNotify,
 
2286
                                                                  -1,
 
2287
                                                                  -1,
 
2288
                                                                  matcher)));
 
2289
}
 
2290
 
 
2291
TEST_F (PixmapDecoratedWindowAcceptance, HorzMaximizeFrameWindowXWidth)
 
2292
{
 
2293
    XWindowAttributes attrib;
 
2294
    XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &attrib);
 
2295
 
 
2296
    ChangeStateOfWindow (Display (),
 
2297
                         AddState,
 
2298
                         "_NET_WM_STATE_MAXIMIZED_HORZ",
 
2299
                         mTestWindow);
 
2300
 
 
2301
    int offset = RealDecorationActiveBorderExtent - ActiveInputExtent;
 
2302
    ct::ConfigureNotifyXEventMatcher matcher (None,
 
2303
                                              0,
 
2304
                                              offset,
 
2305
                                              0,
 
2306
                                              attrib.width - 2 * offset,
 
2307
                                              0,
 
2308
                                              CWX | CWWidth);
 
2309
 
 
2310
    EXPECT_TRUE (Advance (Display (),
 
2311
                          ct::WaitForEventOfTypeOnWindowMatching (Display (),
 
2312
                                                                  mTestWindowParent,
 
2313
                                                                  ConfigureNotify,
 
2314
                                                                  -1,
 
2315
                                                                  -1,
 
2316
                                                                  matcher)));
 
2317
}
 
2318
 
 
2319
TEST_F (PixmapDecoratedWindowAcceptance, VertMaximizeFrameWindowSizeSameXWidth)
 
2320
{
 
2321
    XWindowAttributes rootAttrib, attrib;
 
2322
    XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &rootAttrib);
 
2323
    XGetWindowAttributes (Display (), mTestWindowParent, &attrib);
 
2324
 
 
2325
    ChangeStateOfWindow (Display (),
 
2326
                         AddState,
 
2327
                         "_NET_WM_STATE_MAXIMIZED_VERT",
 
2328
                         mTestWindow);
 
2329
 
 
2330
    /* Wait for the window to be maximized first */
 
2331
    int offset = RealDecorationActiveBorderExtent - ActiveInputExtent;
 
2332
    WaitForConfigureOn (Display (),
 
2333
                        mTestWindowParent,
 
2334
                        0,
 
2335
                        offset,
 
2336
                        0,
 
2337
                        rootAttrib.height - 2 * offset,
 
2338
                        CWY | CWHeight);
 
2339
 
 
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,
 
2346
                              attrib.x,
 
2347
                              _,
 
2348
                              attrib.width,
 
2349
                              _,
 
2350
                              _));
 
2351
}
 
2352
 
 
2353
TEST_F (PixmapDecoratedWindowAcceptance, HorzMaximizeFrameWindowSizeSameYHeight)
 
2354
{
 
2355
    XWindowAttributes rootAttrib, attrib;
 
2356
    XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &rootAttrib);
 
2357
    XGetWindowAttributes (Display (), mTestWindowParent, &attrib);
 
2358
 
 
2359
    ChangeStateOfWindow (Display (),
 
2360
                         AddState,
 
2361
                         "_NET_WM_STATE_MAXIMIZED_HORZ",
 
2362
                         mTestWindow);
 
2363
 
 
2364
    /* Wait for the window to be maximized first */
 
2365
    int offset = RealDecorationActiveBorderExtent - ActiveInputExtent;
 
2366
    WaitForConfigureOn (Display (),
 
2367
                        mTestWindowParent,
 
2368
                        offset,
 
2369
                        0,
 
2370
                        rootAttrib.width - 2 * offset,
 
2371
                        0,
 
2372
                        CWX | CWWidth);
 
2373
 
 
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,
 
2380
                              _,
 
2381
                              attrib.y,
 
2382
                              _,
 
2383
                              attrib.height,
 
2384
                              _));
 
2385
}
 
2386
 
 
2387
/* Ensure that a window expands to its original size when it is
 
2388
 * undecorated */
 
2389
TEST_F (PixmapDecoratedWindowAcceptance, UndecoratedWindowExpandToOrigSizePlusInitialBorder)
 
2390
{
 
2391
    DisallowDecorationsOnWindow (mTestWindow);
 
2392
 
 
2393
    WaitForConfigureOn (Display (),
 
2394
                        mTestWindowParent,
 
2395
                        mBorderGeometryOnInitialDecoration.x (),
 
2396
                        mBorderGeometryOnInitialDecoration.y (),
 
2397
                        mBorderGeometryOnInitialDecoration.width (),
 
2398
                        mBorderGeometryOnInitialDecoration.height (),
 
2399
                        CWX | CWY | CWWidth | CWHeight);
 
2400
 
 
2401
    EXPECT_THAT (mTestWindow,
 
2402
                 HasGeometry (Display (),
 
2403
                              AbsoluteWindowGeometry,
 
2404
                              mBorderGeometryOnInitialDecoration.x (),
 
2405
                              mBorderGeometryOnInitialDecoration.y (),
 
2406
                              mBorderGeometryOnInitialDecoration.width (),
 
2407
                              mBorderGeometryOnInitialDecoration.height (),
 
2408
                              _));
 
2409
}
 
2410
 
 
2411
TEST_F (PixmapDecoratedWindowAcceptance, UndecorateStaticGravityWindow)
 
2412
{
 
2413
    XSizeHints hints;
 
2414
 
 
2415
    hints.flags = PWinGravity;
 
2416
    hints.win_gravity = StaticGravity;
 
2417
 
 
2418
    XSetWMNormalHints (Display (), mTestWindow, &hints);
 
2419
    DisallowDecorationsOnWindow (mTestWindow);
 
2420
 
 
2421
    WaitForConfigureOn (Display (),
 
2422
                        mTestWindowParent,
 
2423
                        mBorderGeometryOnInitialDecoration.x (),
 
2424
                        mBorderGeometryOnInitialDecoration.y (),
 
2425
                        mBorderGeometryOnInitialDecoration.width (),
 
2426
                        mBorderGeometryOnInitialDecoration.height (),
 
2427
                        CWX | CWY | CWWidth | CWHeight);
 
2428
 
 
2429
    EXPECT_THAT (mTestWindow,
 
2430
                 HasGeometry (Display (),
 
2431
                              AbsoluteWindowGeometry,
 
2432
                              mBorderGeometryOnInitialDecoration.x (),
 
2433
                              mBorderGeometryOnInitialDecoration.y (),
 
2434
                              mBorderGeometryOnInitialDecoration.width (),
 
2435
                              mBorderGeometryOnInitialDecoration.height (),
 
2436
                              _));
 
2437
}
 
2438
 
 
2439
class PixmapDecorationAdjustment :
 
2440
    public PixmapDecoratedWindowAcceptance,
 
2441
    public WithParamInterface <decor_extents_t>
 
2442
{
 
2443
    public:
 
2444
 
 
2445
        void MaximizeWindow (Window window);
 
2446
        void RestoreWindow (Window       window,
 
2447
                            int          restoredFrameX,
 
2448
                            int          restoredFrameY,
 
2449
                            unsigned int restoredFrameWidth,
 
2450
                            unsigned int restoredFrameHeight);
 
2451
};
 
2452
 
 
2453
void
 
2454
PixmapDecorationAdjustment::MaximizeWindow (Window window)
 
2455
{
 
2456
    XWindowAttributes rootAttrib;
 
2457
    XGetWindowAttributes (Display (), DefaultRootWindow (Display ()), &rootAttrib);
 
2458
 
 
2459
    ChangeStateOfWindow (Display (),
 
2460
                         AddState,
 
2461
                         "_NET_WM_STATE_MAXIMIZED_HORZ",
 
2462
                         window);
 
2463
 
 
2464
    ChangeStateOfWindow (Display (),
 
2465
                         AddState,
 
2466
                         "_NET_WM_STATE_MAXIMIZED_VERT",
 
2467
                         window);
 
2468
 
 
2469
    /* Wait for the window to be maximized first */
 
2470
    WaitForConfigureOn (Display (),
 
2471
                        mTestWindowParent,
 
2472
                        0,
 
2473
                        0,
 
2474
                        rootAttrib.width,
 
2475
                        rootAttrib.height,
 
2476
                        CWX | CWY | CWWidth | CWHeight);
 
2477
}
 
2478
 
 
2479
void
 
2480
PixmapDecorationAdjustment::RestoreWindow (Window       window,
 
2481
                                           int          restoredFrameX,
 
2482
                                           int          restoredFrameY,
 
2483
                                           unsigned int restoredFrameWidth,
 
2484
                                           unsigned int restoredFrameHeight)
 
2485
{
 
2486
    ChangeStateOfWindow (Display (),
 
2487
                         RemoveState,
 
2488
                         "_NET_WM_STATE_MAXIMIZED_HORZ",
 
2489
                         window);
 
2490
 
 
2491
    ChangeStateOfWindow (Display (),
 
2492
                         RemoveState,
 
2493
                         "_NET_WM_STATE_MAXIMIZED_VERT",
 
2494
                         window);
 
2495
 
 
2496
    /* Wait for the window to be restored first */
 
2497
    WaitForConfigureOn (Display (),
 
2498
                        mTestWindowParent,
 
2499
                        restoredFrameX,
 
2500
                        restoredFrameY,
 
2501
                        restoredFrameWidth,
 
2502
                        restoredFrameHeight,
 
2503
                        CWX | CWY | CWWidth | CWHeight);
 
2504
}
 
2505
 
 
2506
TEST_P (PixmapDecorationAdjustment, AdjustRestoredWindowBorderMovesClient)
 
2507
{
 
2508
    ReconfigureDecoration (Display (),
 
2509
                           mTestWindow,
 
2510
                           mTestWindowDecoration,
 
2511
                           windowDecorations[mTestWindow],
 
2512
                           GetParam (),
 
2513
                           GetParam ());
 
2514
 
 
2515
    EXPECT_THAT (mTestWindow, HasGeometry (Display (),
 
2516
                                           AbsoluteWindowGeometry,
 
2517
                                           mBorderGeometryOnInitialDecoration.x () +
 
2518
                                               GetParam ().left,
 
2519
                                           mBorderGeometryOnInitialDecoration.y () +
 
2520
                                               GetParam ().top,
 
2521
                                           _,
 
2522
                                           _,
 
2523
                                           _));
 
2524
}
 
2525
 
 
2526
TEST_P (PixmapDecorationAdjustment, AdjustRestoredWindowBorderShrinkClient)
 
2527
{
 
2528
    ReconfigureDecoration (Display (),
 
2529
                           mTestWindow,
 
2530
                           mTestWindowDecoration,
 
2531
                           windowDecorations[mTestWindow],
 
2532
                           GetParam (),
 
2533
                           GetParam ());
 
2534
 
 
2535
    EXPECT_THAT (mTestWindow, HasGeometry (Display (),
 
2536
                                           AbsoluteWindowGeometry,
 
2537
                                           _,
 
2538
                                           _,
 
2539
                                           mBorderGeometryOnInitialDecoration.width () -
 
2540
                                               (GetParam ().left +
 
2541
                                                GetParam ().right),
 
2542
                                           mBorderGeometryOnInitialDecoration.height () -
 
2543
                                               (GetParam ().top +
 
2544
                                                GetParam ().bottom),
 
2545
                                           _));
 
2546
}
 
2547
 
 
2548
TEST_P (PixmapDecorationAdjustment, ClientExpandsAsBorderShrinks)
 
2549
{
 
2550
    decor_extents_t newExtents = GetParam ();
 
2551
 
 
2552
    ReconfigureDecoration (Display (),
 
2553
                           mTestWindow,
 
2554
                           mTestWindowDecoration,
 
2555
                           windowDecorations[mTestWindow],
 
2556
                           DecorationExtents (10, 10, 10, 10),
 
2557
                           DecorationExtents (10, 10, 10, 10));
 
2558
 
 
2559
    ReconfigureDecoration (Display (),
 
2560
                           mTestWindow,
 
2561
                           mTestWindowDecoration,
 
2562
                           windowDecorations[mTestWindow],
 
2563
                           newExtents,
 
2564
                           DecorationExtents (10, 10, 10, 10));
 
2565
 
 
2566
    EXPECT_THAT (mTestWindow, HasGeometry (Display (),
 
2567
                                           AbsoluteWindowGeometry,
 
2568
                                           _,
 
2569
                                           _,
 
2570
                                           mBorderGeometryOnInitialDecoration.width () -
 
2571
                                               (newExtents.left +
 
2572
                                                newExtents.right),
 
2573
                                           mBorderGeometryOnInitialDecoration.height () -
 
2574
                                               (newExtents.top +
 
2575
                                                newExtents.bottom),
 
2576
                                           _));
 
2577
}
 
2578
 
 
2579
TEST_P (PixmapDecorationAdjustment, ClientExpandsAsBorderShrinksWhilstMaximized)
 
2580
{
 
2581
    decor_extents_t newExtents = GetParam ();
 
2582
 
 
2583
    ReconfigureDecoration (Display (),
 
2584
                           mTestWindow,
 
2585
                           mTestWindowDecoration,
 
2586
                           windowDecorations[mTestWindow],
 
2587
                           DecorationExtents (10, 10, 10, 10),
 
2588
                           DecorationExtents (10, 10, 10, 10));
 
2589
 
 
2590
    MaximizeWindow (mTestWindow);
 
2591
 
 
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 (),
 
2596
                                                        mTestWindow,
 
2597
                                                        WindowDecorationAtom);
 
2598
 
 
2599
    const CompPoint &off (mTestWindowDecoration->restoredFrameWindowOffset ());
 
2600
    const CompSize &size (mTestWindowDecoration->restoredDecorationInputSize ());
 
2601
 
 
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));
 
2606
 
 
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 ());
 
2614
 
 
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 () +
 
2619
                                               newExtents.left,
 
2620
                                           mBorderGeometryOnInitialDecoration.y () +
 
2621
                                               newExtents.top,
 
2622
                                           mBorderGeometryOnInitialDecoration.width () -
 
2623
                                               ((newExtents.left +
 
2624
                                                 newExtents.right)),
 
2625
                                           mBorderGeometryOnInitialDecoration.height () -
 
2626
                                               ((newExtents.top +
 
2627
                                                 newExtents.bottom)),
 
2628
                                           _));
 
2629
}
 
2630
 
 
2631
TEST_P (PixmapDecorationAdjustment, ClientExpandsAsBorderShrinksWhilstUndecorated)
 
2632
{
 
2633
    decor_extents_t newExtents = GetParam ();
 
2634
 
 
2635
    ReconfigureDecoration (Display (),
 
2636
                           mTestWindow,
 
2637
                           mTestWindowDecoration,
 
2638
                           windowDecorations[mTestWindow],
 
2639
                           DecorationExtents (10, 10, 10, 10),
 
2640
                           DecorationExtents (10, 10, 10, 10));
 
2641
 
 
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);
 
2646
 
 
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 (),
 
2651
                                                        mTestWindow,
 
2652
                                                        WindowDecorationAtom);
 
2653
 
 
2654
    AllowDecorationsOnWindow (mTestWindow);
 
2655
 
 
2656
    const CompPoint &off (mTestWindowDecoration->restoredFrameWindowOffset ());
 
2657
    const CompSize  &size (mTestWindowDecoration->restoredDecorationInputSize ());
 
2658
 
 
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));
 
2663
 
 
2664
    WaitForConfigureOn (Display (),
 
2665
                        mTestWindowParent,
 
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);
 
2673
 
 
2674
    EXPECT_THAT (mTestWindow, HasGeometry (Display (),
 
2675
                                           AbsoluteWindowGeometry,
 
2676
                                           mBorderGeometryOnInitialDecoration.x () +
 
2677
                                               newExtents.left,
 
2678
                                           mBorderGeometryOnInitialDecoration.y () +
 
2679
                                               newExtents.top,
 
2680
                                           mBorderGeometryOnInitialDecoration.width () -
 
2681
                                               (newExtents.left +
 
2682
                                                newExtents.right),
 
2683
                                           mBorderGeometryOnInitialDecoration.height () -
 
2684
                                               (newExtents.top +
 
2685
                                                newExtents.bottom),
 
2686
                                           _));
 
2687
}
 
2688
 
 
2689
TEST_P (PixmapDecorationAdjustment, AdjustRestoredWindowInputNoMoveClient)
 
2690
{
 
2691
    decor_extents_t newExtents = GetParam ();
 
2692
 
 
2693
    ReconfigureDecoration (Display (),
 
2694
                           mTestWindow,
 
2695
                           mTestWindowDecoration,
 
2696
                           windowDecorations[mTestWindow],
 
2697
                           DecorationExtents (1, 1, 1, 1),
 
2698
                           newExtents);
 
2699
 
 
2700
    EXPECT_THAT (mTestWindow, HasGeometry (Display (),
 
2701
                                           AbsoluteWindowGeometry,
 
2702
                                           mBorderGeometryOnInitialDecoration.x () + 1,
 
2703
                                           mBorderGeometryOnInitialDecoration.y () + 1,
 
2704
                                           _,
 
2705
                                           _,
 
2706
                                           _));
 
2707
}
 
2708
 
 
2709
decor_extents_t AdjustmentExtents[] =
 
2710
{
 
2711
    DecorationExtents (2, 0, 0, 0),
 
2712
    DecorationExtents (0, 2, 0, 0),
 
2713
    DecorationExtents (0, 0, 2, 0),
 
2714
    DecorationExtents (0, 0, 0, 2)
 
2715
};
 
2716
 
 
2717
INSTANTIATE_TEST_CASE_P (AdjustmentExtents,
 
2718
                         PixmapDecorationAdjustment,
 
2719
                         ValuesIn (AdjustmentExtents));