Merge lp:~smspillaz/unity/unity.less-paint-insanity into lp:unity

Proposed by Sam Spilsbury
Status: Work in progress
Proposed branch: lp:~smspillaz/unity/unity.less-paint-insanity
Merge into: lp:unity
Diff against target: 1599 lines (+765/-158)
21 files modified
plugins/unityshell/src/ScreenEffectFramebufferObject.cpp (+0/-2)
plugins/unityshell/src/compizminimizedwindowhandler.h (+2/-0)
plugins/unityshell/src/comptransientfor.cpp (+3/-0)
plugins/unityshell/src/comptransientfor.h (+3/-0)
plugins/unityshell/src/inputremover.cpp (+3/-0)
plugins/unityshell/src/inputremover.h (+2/-0)
plugins/unityshell/src/minimizedwindowhandler.cpp (+3/-0)
plugins/unityshell/src/minimizedwindowhandler.h (+3/-0)
plugins/unityshell/src/transientfor.cpp (+4/-0)
plugins/unityshell/src/transientfor.h (+3/-0)
plugins/unityshell/src/unityshell.cpp (+175/-119)
plugins/unityshell/src/unityshell.h (+36/-14)
tests/CMakeLists.txt (+2/-0)
tests/test-input-remover/test-input-remover.cpp (+2/-0)
tests/test-minimize-window-handler/test-minimize-handler.cpp (+2/-0)
tests/test_shell_paint_schedule.cpp (+271/-0)
tests/test_showdesktop_handler.cpp (+30/-23)
tests/x11-window-read-transients.cpp (+2/-0)
unity-shared/CMakeLists.txt (+1/-0)
unity-shared/ShellPaintSchedule.cpp (+93/-0)
unity-shared/ShellPaintSchedule.h (+125/-0)
To merge this branch: bzr merge lp:~smspillaz/unity/unity.less-paint-insanity
Reviewer Review Type Date Requested Status
Sam Spilsbury (community) Abstain
jenkins (community) continuous-integration Approve
Tim Penhey Pending
Daniel van Vugt Pending
Jason Smith Pending
Marco Trevisan (Treviño) Pending
Review via email: mp+112045@code.launchpad.net

This proposal supersedes a proposal from 2012-06-24.

Description of the change

== Problem ==

The old implementation of ensuring that unity gets painted in the right place and the nux base windows aren't painted was to hook getWindowPaintList and remove nux windows from the list every single time compiz draws a frame.

That resulted in lots of list copying.

In addition, every time we painted a window, we needed to check if it was actually above a nux window by scanning the paint list down, and the complexity of that grew by o(logN) for every new window added.

== Solution ==

Just hook glPaint, skip the wrap chain to core (eg every single plugin skipped) and tell core not to do anything with the window by returning false

== Errata ==

I have no idea why there is a bunch of logic about whether or not to paint the panel in glDraw (that was moved to glPaint). Someone enlighten me?

Blocked by: https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1012956/+merge/110268

== Test ==

Unit tests included, code refactored to get under test

To post a comment you must log in.
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Bump?

I'd like to see this go in, because it should reduce lots of list copying within unity and also lots of unecessary list traversal, which should represent a nice speed boost. In addition, its far simpler in its implementation and far less bug prone.

I'm sure testing is probably an issue. I'll have another quick look at the code and see if I can think of a way to get it under test.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Works for me. Though there are some indentation/tab mismatches around line 107. Looks like your tabs are not 8 characters wide like they should be?

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

indentation fixed ... will add tests when I have time.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Manual testing -> Works well.

This branch also appears to solve the problem of my missing panel shadow when running dev builds of Unity. But that's just a bonus.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Whoops. It turns out this branch is tricking the decor plugin into painting (proper) shadows for the panel and launcher. It looks awesome so I hope we can keep it. But it's probably a mistake.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> Whoops. It turns out this branch is tricking the decor plugin into painting
> (proper) shadows for the panel and launcher. It looks awesome so I hope we can
> keep it. But it's probably a mistake.

It probably is, thanks for catching that.

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Back, with tests.

The decor plugin is going to try and draw shadows now on the launcher and panel. That's a bug in the decor plugin. See https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1012956/+merge/110268

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Hmm, I was happy with the old proposal. It was so nice and simple. Now I'm seeing lots more green than red, which is not ideal.

I think the implementation is too abstract for its own good. Words like "Requestor", "Interface", "BindingQuery" and "dispatch" confuse what was once simpler code, making maintenance more difficult. Rewriting code to produce something that's harder to understand is much worse than no test cases.

Maybe another day I'll feel more optimistic and test and review it again properly.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

The code is abstract so we can get it under test. More classes with single responsibilities is not a bad thing.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

It shouldn't be a choice between readability and testability. It is possible to write readable code that is testable too.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

The code is readable.

The whole point of coding to interfaces is so that you can clearly label the intent of each particular process that is going on.

For example, I know just from looking at the class names that:

The paint dispatch is responsible for queuing paint requests to the painter
The painter queries whether an fbo was bound to perform a particular operation
Paint Requestors fufill the role of requesting a repaint

That's so much more clear than the voodoocode of how it used to work with stuff like

421 - if (uScreen->doShellRepaint && !uScreen->forcePaintOnTop ())
... PaintDisplay ()

In UnityWindow::glDraw and in UnityWindow::glPaintOutput

If another person comes along and reads that, they now need to figure out what forcePaintOnTop represents, where doShellRepaint is set and unset, why the code is there twice in two different "paint" functions. They also need to figure out where allowWindowPaint is set, why it is set, what it represents, etc.

In addition, there are no tests that the maintainer can go to to see how all the bits fit together. And there is no way for the maintainer to know if they've broken that code.

More Diff Size != Less Maintainability.

Revision history for this message
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal

Sam,

This code isn't really that readable. The code it is replacing
wasn't really readable either to anyone who doesn't deeply
understand the internals of the compiz drawing machinary.

I do agree that "more diff size != less maintainability", however
in this case, the class names and method names do not express
intent. I am not able to clearly follow what is supposed to be
happening here.

As an example, we have "FBOBindingQueryInterface", which has a
single pure virtual function called "WasBound". However this
method reflects the internal state of some object. It does not
describe the intent, or why a bound FBO is an important thing.

There is no documentation in the header files for any of these
classes compounding their confusion.

I'd suggest that we put all the methods and headers here into a
nested namespace inside unity, as it is directly related to
compiz painting. So unity::compiz or unity::plugin. Givin there
is a ::compiz namespace, it probably makes sense to have it in
namespace unity::plugin.

The constants inside ShellPaintRequestorInterface should really
be an enum. Also it isn't specified that the paint requestors
are supposed to be masks, or that the values will be used as
masks. Also, if we have a nested namespace with an enum, the
enum could be moved outside the class itself.

The fact that I had to do many searchs in the diff to work out
who called what with which parameters is an indicator of how hard
this code is to follow.

On matters of style, this code should follow the unity style
guidelines, not compiz, so * and & next to type not variable
names, no spaces before ().

Also unity has a strong preference for sigc::slot definitions for
functions, not boost::functions.

The fundamental objection I have to this is that the new code and
interfaces don't sufficiently describe the intent, but instead
leak implementation details into the class and method names.

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

(cant reply inline)

On "not being able to follow what is happening here" : can you clarify?

On FBOBindingQueryInterface: I will see if this can be removed ... I think it may not be necessary

On namespaces: ack

On enums: I will change the constants to enums if they can be used as masks

On searching the diff: please clarify

On leaking implementation: please clarify (Apart from the fbo query, which I agree is an ugly leak)

Sent from Samsung Mobile

 Tim Penhey <email address hidden> wrote:

Review: Needs Fixing

Sam,

This code isn't really that readable.  The code it is replacing
wasn't really readable either to anyone who doesn't deeply
understand the internals of the compiz drawing machinary.

I do agree that "more diff size != less maintainability", however
in this case, the class names and method names do not express
intent.  I am not able to clearly follow what is supposed to be
happening here.

As an example, we have "FBOBindingQueryInterface", which has a
single pure virtual function called "WasBound".  However this
method reflects the internal state of some object.  It does not
describe the intent, or why a bound FBO is an important thing.

There is no documentation in the header files for any of these
classes compounding their confusion.

I'd suggest that we put all the methods and headers here into a
nested namespace inside unity, as it is directly related to
compiz painting.  So unity::compiz or unity::plugin.  Givin there
is a ::compiz namespace, it probably makes sense to have it in
namespace unity::plugin.

The constants inside ShellPaintRequestorInterface should really
be an enum.  Also it isn't specified that the paint requestors
are supposed to be masks, or that the values will be used as
masks.  Also, if we have a nested namespace with an enum, the
enum could be moved outside the class itself.

The fact that I had to do many searchs in the diff to work out
who called what with which parameters is an indicator of how hard
this code is to follow.

On matters of style, this code should follow the unity style
guidelines, not compiz, so * and & next to type not variable
names, no spaces before ().

Also unity has a strong preference for sigc::slot definitions for
functions, not boost::functions.

The fundamental objection I have to this is that the new code and
interfaces don't sufficiently describe the intent, but instead
leak implementation details into the class and method names.

--
https://code.launchpad.net/~smspillaz/unity/unity.less-paint-insanity/+merge/110267
You are the owner of lp:~smspillaz/unity/unity.less-paint-insanity.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Leaving this open for now so I can get some more suggestions as to the desired design before I go back in and refactor it.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Nuked FBOBindingQueryInterface, changed the masks to enum and moved stuff into unity::compiz. Unfortunately that caused ambiguity in namespace lookup so I moved the other stuff in compiz to unity::compiz

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

I'm resubmitting this so that it goes to the top again.

I expect this to be marked needs fixing again, but I need some more detailed feedback as to where the design can be improved. I won't merge this fix in without tests.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

As per my previous comments, I think there are a few poor naming decisions here. That coupled with the increase in complexity makes the code much less maintainable than it already is. Despite the test cases.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> As per my previous comments, I think there are a few poor naming decisions
> here. That coupled with the increase in complexity makes the code much less
> maintainable than it already is. Despite the test cases.

Thanks Daniel, but I need more detailed feedback than that. Preferably some concrete ideas on how I can make the existing code better while still keeping the tests.

Revision history for this message
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:2404
http://s-jenkins:8080/job/unity-ci/3/

review: Disapprove (continuous-integration)
Revision history for this message
Martin Mrazik (mrazik) wrote : Posted in a previous version of this proposal

The failure above is because of this:
[...]
/home/ubuntu/jenkins/workspace/unity-ci/distribution/precise/flavor/amd64/pbuilder_setup/work/trunk/plugins/unityshell/src/unityshell.cpp: In member function ‘bool unity::UnityScreen::WasBound()’:
/home/ubuntu/jenkins/workspace/unity-ci/distribution/precise/flavor/amd64/pbuilder_setup/work/trunk/plugins/unityshell/src/unityshell.cpp:741:16: error: ‘class unity::ScreenEffectFramebufferObject’ has no member named ‘NewContentsValid’
/home/ubuntu/jenkins/workspace/unity-ci/distribution/precise/flavor/amd64/pbuilder_setup/work/trunk/plugins/unityshell/src/unityshell.cpp:745:1: error: control reaches end of non-void function [-Werror=return-type]
cc1plus: all warnings being treated as errors

It this a problem on jenkins side (build dependencies not 100% up to date)?

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> The failure above is because of this:
> [...]
> /home/ubuntu/jenkins/workspace/unity-ci/distribution/precise/flavor/amd64/pbui
> lder_setup/work/trunk/plugins/unityshell/src/unityshell.cpp: In member
> function ‘bool unity::UnityScreen::WasBound()’:
> /home/ubuntu/jenkins/workspace/unity-ci/distribution/precise/flavor/amd64/pbui
> lder_setup/work/trunk/plugins/unityshell/src/unityshell.cpp:741:16: error:
> ‘class unity::ScreenEffectFramebufferObject’ has no member named
> ‘NewContentsValid’
> /home/ubuntu/jenkins/workspace/unity-ci/distribution/precise/flavor/amd64/pbui
> lder_setup/work/trunk/plugins/unityshell/src/unityshell.cpp:745:1: error:
> control reaches end of non-void function [-Werror=return-type]
> cc1plus: all warnings being treated as errors
>
> It this a problem on jenkins side (build dependencies not 100% up to date)?

Likely not, probably a typo somewhere. Fixing.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

BTW, Jenkins should put "needs fixing" rather than "disapprove". Disapprove means that you disagree with the whole concept, if it fails CI, it just needs work.

Revision history for this message
Martin Mrazik (mrazik) wrote : Posted in a previous version of this proposal

> BTW, Jenkins should put "needs fixing" rather than "disapprove". Disapprove
> means that you disagree with the whole concept, if it fails CI, it just needs
> work.

Good point. I'll fix it.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

(Resubmitting again for some detailed feedback after fixing the CI quirk)

Revision history for this message
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:2405
http://s-jenkins:8080/job/unity-ci/19/

review: Approve (continuous-integration)
Revision history for this message
jenkins (martin-mrazik+qa) wrote :

PASSED: Continuous integration, rev:2405
http://s-jenkins:8080/job/unity-ci/20/

review: Approve (continuous-integration)
Revision history for this message
Sam Spilsbury (smspillaz) :
review: Abstain
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

I am marking this Work in Progress for now.

Now that regionalDamage is merged in, there are going to be quite massive conflicts, all of which need to be cleaned up. Because regionalDamage has to use the same technique this branch is using, this branch will be re-purposed towards getting all of the paint optimization and stack placement code under test, since it is now going to be incredibly easy to break.

Unmerged revisions

2405. By Sam Spilsbury

Remove unused method and rename methods to make more sense

2404. By Sam Spilsbury

Merge lp:unity

2403. By Sam Spilsbury

Basic documentation, not really a substitute for better code ...

2402. By Sam Spilsbury

Nuke FBOBindingQueryInterface

2401. By Sam Spilsbury

unsigned int -> enum && move namespace compiz {} to namespace unity::compiz

2400. By Sam Spilsbury

Change namespace to unity::compiz

2399. By Sam Spilsbury

Merge lp:unity

2398. By Sam Spilsbury

Merge lp:unity

2397. By Sam Spilsbury

Test prohibited paint requestor retreival

2396. By Sam Spilsbury

Tests for RepaintPending value

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/ScreenEffectFramebufferObject.cpp'
2--- plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 2012-05-28 03:19:35 +0000
3+++ plugins/unityshell/src/ScreenEffectFramebufferObject.cpp 2012-06-26 09:53:58 +0000
4@@ -76,7 +76,6 @@
5 mScreenSize = screenSize;
6 }
7
8-
9 void unity::ScreenEffectFramebufferObject::unbind ()
10 {
11 if (!mBoundCnt)
12@@ -212,7 +211,6 @@
13 mBoundCnt++;
14 }
15
16-
17 unity::ScreenEffectFramebufferObject::ScreenEffectFramebufferObject (GLXGetProcAddressProc p, const nux::Geometry &geom)
18 : getProcAddressGLX (p)
19 , mFboStatus (false)
20
21=== modified file 'plugins/unityshell/src/compizminimizedwindowhandler.h'
22--- plugins/unityshell/src/compizminimizedwindowhandler.h 2012-05-31 09:28:02 +0000
23+++ plugins/unityshell/src/compizminimizedwindowhandler.h 2012-06-26 09:53:58 +0000
24@@ -29,6 +29,7 @@
25 #include <memory>
26
27 // Will be merged back into compiz
28+namespace unity {
29 namespace compiz {
30
31 class PrivateCompizMinimizedWindowHandler
32@@ -357,5 +358,6 @@
33 Window::get (w)->window->minimize();
34 }
35 }
36+}
37
38 #endif
39
40=== modified file 'plugins/unityshell/src/comptransientfor.cpp'
41--- plugins/unityshell/src/comptransientfor.cpp 2012-03-14 06:24:18 +0000
42+++ plugins/unityshell/src/comptransientfor.cpp 2012-06-26 09:53:58 +0000
43@@ -21,6 +21,8 @@
44
45 #include "comptransientfor.h"
46
47+namespace unity
48+{
49 namespace compiz
50 {
51 class PrivateCompTransientForReader
52@@ -84,3 +86,4 @@
53
54 return false;
55 }
56+}
57
58=== modified file 'plugins/unityshell/src/comptransientfor.h'
59--- plugins/unityshell/src/comptransientfor.h 2012-05-31 09:28:02 +0000
60+++ plugins/unityshell/src/comptransientfor.h 2012-06-26 09:53:58 +0000
61@@ -28,6 +28,8 @@
62 #include "transientfor.h"
63
64 // Will be merged back into compiz
65+namespace unity
66+{
67 namespace compiz
68 {
69 class PrivateCompTransientForReader;
70@@ -51,5 +53,6 @@
71 PrivateCompTransientForReader *priv;
72 };
73 }
74+}
75
76 #endif
77
78=== modified file 'plugins/unityshell/src/inputremover.cpp'
79--- plugins/unityshell/src/inputremover.cpp 2012-03-24 02:57:48 +0000
80+++ plugins/unityshell/src/inputremover.cpp 2012-06-26 09:53:58 +0000
81@@ -24,6 +24,8 @@
82 #include <cstdio>
83 #include <cstring>
84
85+namespace unity {
86+
87 compiz::WindowInputRemoverInterface::~WindowInputRemoverInterface ()
88 {
89 }
90@@ -348,3 +350,4 @@
91
92 return true;
93 }
94+}
95
96=== modified file 'plugins/unityshell/src/inputremover.h'
97--- plugins/unityshell/src/inputremover.h 2012-04-23 12:25:44 +0000
98+++ plugins/unityshell/src/inputremover.h 2012-06-26 09:53:58 +0000
99@@ -28,6 +28,7 @@
100 #include <X11/extensions/shape.h>
101
102 // Will be merged back into compiz
103+namespace unity {
104 namespace compiz {
105
106 class WindowInputRemoverInterface
107@@ -127,5 +128,6 @@
108 };
109
110 }
111+}
112
113 #endif
114
115=== modified file 'plugins/unityshell/src/minimizedwindowhandler.cpp'
116--- plugins/unityshell/src/minimizedwindowhandler.cpp 2012-04-23 12:25:44 +0000
117+++ plugins/unityshell/src/minimizedwindowhandler.cpp 2012-06-26 09:53:58 +0000
118@@ -23,6 +23,8 @@
119 #include "inputremover.h"
120 #include <cstring>
121
122+namespace unity
123+{
124 namespace compiz
125 {
126 class PrivateMinimizedWindowHandler
127@@ -273,3 +275,4 @@
128 {
129 delete priv;
130 }
131+}
132
133=== modified file 'plugins/unityshell/src/minimizedwindowhandler.h'
134--- plugins/unityshell/src/minimizedwindowhandler.h 2012-04-18 09:19:44 +0000
135+++ plugins/unityshell/src/minimizedwindowhandler.h 2012-06-26 09:53:58 +0000
136@@ -30,6 +30,8 @@
137 #include <boost/bind.hpp>
138
139 // Will be merged back into compiz
140+namespace unity
141+{
142 namespace compiz
143 {
144 class PrivateMinimizedWindowHandler;
145@@ -58,5 +60,6 @@
146 PrivateMinimizedWindowHandler *priv;
147 };
148 }
149+}
150
151 #endif
152
153=== modified file 'plugins/unityshell/src/transientfor.cpp'
154--- plugins/unityshell/src/transientfor.cpp 2012-03-14 06:24:18 +0000
155+++ plugins/unityshell/src/transientfor.cpp 2012-06-26 09:53:58 +0000
156@@ -21,6 +21,9 @@
157
158 #include "transientfor.h"
159
160+namespace unity
161+{
162+
163 Atom compiz::X11TransientForReader::wmTransientFor = None;
164 Atom compiz::X11TransientForReader::wmClientLeader = None;
165
166@@ -216,3 +219,4 @@
167 {
168 delete priv;
169 }
170+}
171
172=== modified file 'plugins/unityshell/src/transientfor.h'
173--- plugins/unityshell/src/transientfor.h 2012-05-31 09:28:02 +0000
174+++ plugins/unityshell/src/transientfor.h 2012-06-26 09:53:58 +0000
175@@ -29,6 +29,8 @@
176 #include <string>
177
178 // Will be merged back into compiz
179+namespace unity
180+{
181 namespace compiz
182 {
183 class PrivateX11TransientForReader;
184@@ -57,5 +59,6 @@
185 PrivateX11TransientForReader *priv;
186 };
187 }
188+}
189
190 #endif
191
192=== modified file 'plugins/unityshell/src/unityshell.cpp'
193--- plugins/unityshell/src/unityshell.cpp 2012-06-25 21:37:57 +0000
194+++ plugins/unityshell/src/unityshell.cpp 2012-06-26 09:53:58 +0000
195@@ -110,6 +110,8 @@
196 , screen(screen)
197 , cScreen(CompositeScreen::get(screen))
198 , gScreen(GLScreen::get(screen))
199+ , paint_dispatch_ (this,
200+ boost::bind (&UnityScreen::GetProhibitedPaintMasks, this))
201 , debugger_(this)
202 , enable_shortcut_overlay_(true)
203 , gesture_engine_(screen)
204@@ -117,8 +119,6 @@
205 , _in_paint(false)
206 , super_keypressed_(false)
207 , newFocusedWindow(nullptr)
208- , doShellRepaint(false)
209- , allowWindowPaint(false)
210 , damaged(false)
211 , _key_nav_mode_requested(false)
212 , _last_output(nullptr)
213@@ -263,8 +263,8 @@
214 if (GL::fbo)
215 {
216 nux::Geometry geometry (0, 0, screen->width (), screen->height ());
217- uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
218- uScreen->_fbo->onScreenSizeChanged (geometry);
219+ uScreen->fbo_ = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
220+ uScreen->fbo_->onScreenSizeChanged (geometry);
221 }
222 #endif
223
224@@ -740,16 +740,41 @@
225 panel_texture_has_changed_ = true;
226 }
227
228-#ifdef USE_MODERN_COMPIZ_GL
229-void UnityScreen::paintDisplay()
230-#else
231-void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask)
232+compiz::ShellPaintRequestorInterface::PaintRequestorType
233+UnityScreen::GetPaintRequestorType ()
234+{
235+ return compiz::ShellPaintRequestorInterface::PaintRequestorType::Screen;
236+}
237+
238+bool UnityScreen::PaintBackingFBO (CompOutput *output)
239+{
240+#ifndef USE_MODERN_COMPIZ_GL
241+ bool was_bound = fbo_->bound ();
242+ if (was_bound)
243+ {
244+ fbo_->unbind ();
245+ GLMatrix sTransform;
246+ sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
247+ glPushMatrix ();
248+ glLoadMatrixf (sTransform.getMatrix ());
249+ fbo_->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
250+ glPopMatrix ();
251+ }
252+
253+ return was_bound;
254 #endif
255+ return false;
256+}
257+
258+void UnityScreen::PaintDisplay ()
259 {
260 CompOutput *output = _last_output;
261
262 #ifndef USE_MODERN_COMPIZ_GL
263- bool was_bound = _fbo->bound ();
264+ bool was_bound = PaintBackingFBO (output);
265+#else
266+ bool was_bound = true;
267+#endif
268
269 if (nux::GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath())
270 {
271@@ -785,28 +810,18 @@
272 }
273 }
274
275- _fbo->unbind ();
276-
277 /* Draw the bit of the relevant framebuffer for each output */
278
279- if (was_bound)
280- {
281- GLMatrix sTransform;
282- sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
283- glPushMatrix ();
284- glLoadMatrixf (sTransform.getMatrix ());
285- _fbo->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
286- glPopMatrix ();
287- }
288+ GLuint fbo_texture_name = 0;
289+#ifndef USE_MODERN_COMPIZ_GL
290+ fbo_texture_name = fbo_->texture();
291+#else
292+ fbo_texture_name = gScreen->fbo ()->tex ()->name ();
293+#endif
294
295 nux::ObjectPtr<nux::IOpenGLBaseTexture> device_texture =
296- nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(),
297+ nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(fbo_texture_name,
298 screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8);
299-#else
300- nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
301- nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(gScreen->fbo ()->tex ()->name (),
302- output->width(), output->height(), 1, nux::BITFMT_R8G8B8A8);
303-#endif
304
305 nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
306
307@@ -829,7 +844,7 @@
308
309 for (Window tray_xid : panel_controller_->GetTrayXids())
310 {
311- if (tray_xid && !allowWindowPaint)
312+ if (tray_xid && (no_paint_allowed_mask_ == ShellPaintRequestorInterface::PaintRequestorType::Window))
313 {
314 CompWindow *tray = screen->findWindow (tray_xid);
315
316@@ -907,15 +922,53 @@
317 }
318 }
319
320- doShellRepaint = false;
321 damaged = false;
322 }
323
324-bool UnityScreen::forcePaintOnTop ()
325-{
326- return !allowWindowPaint ||
327- ((switcher_controller_->Visible() || launcher_controller_->IsOverlayOpen())
328- && !fullscreen_windows_.empty () && (!(screen->grabbed () && !screen->otherGrabExist (NULL))));
329+compiz::ShellPaintRequestorInterface::PaintRequestorType UnityScreen::GetProhibitedPaintMasks()
330+{
331+ bool unity_force_overlay = switcher_controller_->Visible() || launcher_controller_->IsOverlayOpen();
332+ bool no_screen_grabs = !(screen->grabbed () && !screen->otherGrabExist (NULL));
333+ bool fullscreen_windows = !fullscreen_windows_.empty ();
334+
335+ compiz::ShellPaintRequestorInterface::PaintRequestorType pmask = no_paint_allowed_mask_;
336+
337+ if (unity_force_overlay &&
338+ fullscreen_windows &&
339+ no_screen_grabs)
340+ pmask = compiz::ShellPaintRequestorInterface::PaintRequestorType::Window;
341+
342+ return pmask;
343+}
344+
345+bool UnityScreen::RequestShellRepaint (compiz::ShellPaintRequestorInterface *r)
346+{
347+ return paint_dispatch_.RequestShellRepaint (r);
348+}
349+
350+bool UnityScreen::EnforcePaintByRequestor (compiz::ShellPaintRequestorInterface *r)
351+{
352+ return paint_dispatch_.EnforcePaintByRequestor (r);
353+}
354+
355+void UnityScreen::AllowPaintByAnyRequestor ()
356+{
357+ paint_dispatch_.AllowPaintByAnyRequestor ();
358+}
359+
360+compiz::ShellPaintRequestorInterface::PaintRequestorType UnityScreen::ProhibitedPaintRequestors()
361+{
362+ return paint_dispatch_.ProhibitedPaintRequestors ();
363+}
364+
365+void UnityScreen::RequireShellRepaint ()
366+{
367+ paint_dispatch_.RequireShellRepaint ();
368+}
369+
370+bool UnityScreen::RepaintPending ()
371+{
372+ return paint_dispatch_.RepaintPending ();
373 }
374
375 void UnityWindow::paintThumbnail (nux::Geometry const& bounding, float alpha)
376@@ -1210,8 +1263,9 @@
377 {
378 bool ret;
379
380- doShellRepaint = true;
381- allowWindowPaint = true;
382+ AllowPaintByAnyRequestor ();
383+ RequireShellRepaint ();
384+ no_paint_allowed_mask_ = compiz::ShellPaintRequestorInterface::PaintRequestorType::Nil;
385 _last_output = output;
386 paint_panel_ = false;
387
388@@ -1226,16 +1280,13 @@
389 * attempts to bind it will only increment
390 * its bind reference so make sure that
391 * you always unbind as much as you bind */
392- _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
393+ fbo_->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
394 #endif
395
396 /* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
397 ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
398
399-#ifndef USE_MODERN_COMPIZ_GL
400- if (doShellRepaint)
401- paintDisplay(region, transform, mask);
402-#endif
403+ RequestShellRepaint (this);
404
405 return ret;
406 }
407@@ -1247,7 +1298,7 @@
408 {
409 bool useFbo = false;
410
411- if (doShellRepaint)
412+ if (RepaintPending ())
413 {
414 oldFbo = fbo->bind ();
415 useFbo = fbo->checkStatus () && fbo->tex ();
416@@ -1256,7 +1307,7 @@
417 ::GLFramebufferObject::rebind (oldFbo);
418 return;
419 }
420- paintDisplay();
421+ RequestShellRepaint (this);
422 ::GLFramebufferObject::rebind (oldFbo);
423 }
424
425@@ -1273,7 +1324,7 @@
426 CompOutput* output,
427 unsigned int mask)
428 {
429- allowWindowPaint = false;
430+ no_paint_allowed_mask_ = compiz::ShellPaintRequestorInterface::PaintRequestorType::Window;
431 gScreen->glPaintTransformedOutput(attrib, transform, region, output, mask);
432
433 }
434@@ -2132,31 +2183,6 @@
435 return "Unity";
436 }
437
438-bool isNuxWindow (CompWindow* value)
439-{
440- std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
441- auto id = value->id();
442-
443- // iterate loop by hand rather than use std::find as this is considerably faster
444- // we care about performance here becuase of the high frequency in which this function is
445- // called (nearly every frame)
446- unsigned int size = xwns.size();
447- for (unsigned int i = 0; i < size; ++i)
448- {
449- if (xwns[i] == id)
450- return true;
451- }
452- return false;
453-}
454-
455-const CompWindowList& UnityScreen::getWindowPaintList()
456-{
457- CompWindowList& pl = _withRemovedNuxWindows = cScreen->getWindowPaintList();
458- pl.remove_if(isNuxWindow);
459-
460- return pl;
461-}
462-
463 void UnityScreen::RaiseInputWindows()
464 {
465 std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
466@@ -2169,13 +2195,11 @@
467 }
468 }
469
470-/* detect occlusions
471- *
472- * core passes down the PAINT_WINDOW_OCCLUSION_DETECTION
473- * mask when it is doing occlusion detection, so use that
474- * order to fill our occlusion buffer which we'll flip
475- * to nux later
476- */
477+/* we want to paint underneath other windows here,
478+ * so we need to find if this window is actually
479+ * stacked on top of one of the nux input windows
480+ * and if so paint nux and stop us from painting
481+ * other windows or on top of the whole screen */
482 bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib,
483 const GLMatrix& matrix,
484 const CompRegion& region,
485@@ -2195,7 +2219,7 @@
486
487 std::vector<Window> const& tray_xids = uScreen->panel_controller_->GetTrayXids();
488 if (std::find(tray_xids.begin(), tray_xids.end(), window->id()) != tray_xids.end() &&
489- !uScreen->allowWindowPaint)
490+ (uScreen->ProhibitedPaintRequestors () == compiz::ShellPaintRequestorInterface::PaintRequestorType::Window))
491 {
492 if (!uScreen->painting_tray_)
493 {
494@@ -2204,26 +2228,7 @@
495 }
496 }
497
498- return gWindow->glPaint(wAttrib, matrix, region, mask);
499-}
500-
501-/* handle window painting in an opengl context
502- *
503- * we want to paint underneath other windows here,
504- * so we need to find if this window is actually
505- * stacked on top of one of the nux input windows
506- * and if so paint nux and stop us from painting
507- * other windows or on top of the whole screen */
508-bool UnityWindow::glDraw(const GLMatrix& matrix,
509-#ifndef USE_MODERN_COMPIZ_GL
510- GLFragment::Attrib& attrib,
511-#else
512- const GLWindowPaintAttrib& attrib,
513-#endif
514- const CompRegion& region,
515- unsigned int mask)
516-{
517- if (uScreen->doShellRepaint && !uScreen->paint_panel_ && window->type() == CompWindowTypeNormalMask)
518+ if (uScreen->RepaintPending () && !uScreen->paint_panel_ && window->type() == CompWindowTypeNormalMask)
519 {
520 guint32 id = window->id();
521 bool maximized = WindowManager::Default()->IsWindowMaximized(id);
522@@ -2239,29 +2244,63 @@
523 }
524 }
525
526- if (uScreen->doShellRepaint && !uScreen->forcePaintOnTop ())
527+ if (IsNuxWindow ())
528 {
529- std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
530- unsigned int size = xwns.size();
531-
532- for (CompWindow* w = window; w && uScreen->doShellRepaint; w = w->prev)
533- {
534- auto id = w->id();
535-
536- for (unsigned int i = 0; i < size; ++i)
537- {
538- if (xwns[i] == id)
539- {
540-#ifdef USE_MODERN_COMPIZ_GL
541- uScreen->paintDisplay();
542+ /* Windows are painted in top-to-bottom order
543+ * with occlusion detection on, so we can
544+ * find out the top most nux window and paint
545+ * there */
546+ if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
547+ {
548+ GLWindowPaintAttrib noAlphaAttrib;
549+
550+ noAlphaAttrib.opacity = OPAQUE;
551+ noAlphaAttrib.brightness = BRIGHT;
552+ noAlphaAttrib.saturation = COLOR;
553+
554+ bool status = gWindow->glPaint (noAlphaAttrib,
555+ matrix,
556+ region,
557+ PAINT_WINDOW_OCCLUSION_DETECTION_MASK);
558+
559+ if (status)
560+ uScreen->EnforcePaintByRequestor (this);
561+
562+ /* We don't want core to take this window
563+ * into account when doing occlusion detection
564+ * however */
565+ return false;
566+ }
567+ /* Don't care about "fake" paints */
568+ else if (mask & PAINT_WINDOW_NO_CORE_INSTANCE_MASK)
569+ {
570+ return false;
571+ }
572+ else
573+ {
574+ uScreen->RequestShellRepaint (this);
575+
576+ /* Don't paint nux windows on the real paint pass */
577+ return false;
578+ }
579+ }
580+
581+ return gWindow->glPaint(wAttrib, matrix, region, mask);
582+}
583+
584+/* handle window painting in an opengl context
585+ */
586+bool UnityWindow::glDraw(const GLMatrix& matrix,
587+#ifndef USE_MODERN_COMPIZ_GL
588+ GLFragment::Attrib& attrib,
589 #else
590- uScreen->paintDisplay(region, matrix, mask);
591+ const GLWindowPaintAttrib& attrib,
592 #endif
593- break;
594- }
595- }
596- }
597- }
598+ const CompRegion& region,
599+ unsigned int mask)
600+{
601+ if (IsNuxWindow ())
602+ return false;
603
604 if (window->type() == CompWindowTypeDesktopMask)
605 uScreen->setPanelShadowMatrix(matrix);
606@@ -2280,7 +2319,6 @@
607 uScreen->paintPanelShadow(matrix);
608 }
609
610-
611 return ret;
612 }
613
614@@ -2755,8 +2793,8 @@
615 #ifndef USE_MODERN_COMPIZ_GL
616 if (GL::fbo)
617 {
618- uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
619- uScreen->_fbo->onScreenSizeChanged (geometry);
620+ uScreen->fbo_ = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
621+ uScreen->fbo_->onScreenSizeChanged (geometry);
622 }
623 #endif
624
625@@ -2922,6 +2960,18 @@
626 hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Resize window."), shortcut::COMPIZ_MOUSE_OPTION, "resize", "initiate_button"));
627 }
628
629+bool
630+UnityWindow::IsNuxWindow ()
631+{
632+ return is_nux_window_;
633+}
634+
635+compiz::ShellPaintRequestorInterface::PaintRequestorType
636+UnityWindow::GetPaintRequestorType ()
637+{
638+ return compiz::ShellPaintRequestorInterface::PaintRequestorType::Window;
639+}
640+
641 /* Window init */
642 UnityWindow::UnityWindow(CompWindow* window)
643 : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window)
644@@ -2930,10 +2980,16 @@
645 , gWindow(GLWindow::get(window))
646 , mMinimizeHandler()
647 , mShowdesktopHandler(nullptr)
648+ , is_nux_window_ (false)
649 {
650 WindowInterface::setHandler(window);
651 GLWindowInterface::setHandler(gWindow);
652
653+ std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
654+ for (unsigned int i = 0; i < xwns.size(); i++)
655+ if (xwns[i] == window->id ())
656+ is_nux_window_ = true;
657+
658 if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&
659 window->mapNum ())
660 {
661
662=== modified file 'plugins/unityshell/src/unityshell.h'
663--- plugins/unityshell/src/unityshell.h 2012-06-23 01:54:48 +0000
664+++ plugins/unityshell/src/unityshell.h 2012-06-26 09:53:58 +0000
665@@ -52,6 +52,7 @@
666 #include "UBusWrapper.h"
667 #include "UnityshellPrivate.h"
668 #include "UnityShowdesktopHandler.h"
669+#include "ShellPaintSchedule.h"
670 #ifndef USE_MODERN_COMPIZ_GL
671 #include "ScreenEffectFramebufferObject.h"
672 #endif
673@@ -68,6 +69,9 @@
674
675 /* base screen class */
676 class UnityScreen :
677+ public compiz::ShellPaintDispatchInterface,
678+ public compiz::ShellPaintRequestorInterface,
679+ public compiz::ShellPaintInterface,
680 public unity::debug::Introspectable,
681 public sigc::trackable,
682 public ScreenInterface,
683@@ -92,11 +96,8 @@
684 void nuxEpilogue();
685
686 /* nux draw wrapper */
687-#ifdef USE_MODERN_COMPIZ_GL
688- void paintDisplay();
689-#else
690- void paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask);
691-#endif
692+ bool PaintBackingFBO (CompOutput *output);
693+ void PaintDisplay ();
694 void paintPanelShadow(const GLMatrix& matrix);
695 void setPanelShadowMatrix(const GLMatrix& matrix);
696
697@@ -133,9 +134,6 @@
698 CompOutput*,
699 unsigned int);
700
701- /* Pop our InputOutput windows from the paint list */
702- const CompWindowList& getWindowPaintList();
703-
704 /* handle X11 events */
705 void handleEvent(XEvent*);
706
707@@ -189,8 +187,6 @@
708 void NeedsRelayout();
709 void ScheduleRelayout(guint timeout);
710
711- bool forcePaintOnTop ();
712-
713 protected:
714 std::string GetName() const;
715 void AddProperties(GVariantBuilder* builder);
716@@ -237,6 +233,18 @@
717
718 void OnPanelStyleChanged();
719
720+ compiz::ShellPaintRequestorInterface::PaintRequestorType GetPaintRequestorType ();
721+ compiz::ShellPaintRequestorInterface::PaintRequestorType GetProhibitedPaintMasks ();
722+
723+ bool RequestShellRepaint (compiz::ShellPaintRequestorInterface *);
724+ bool EnforcePaintByRequestor (compiz::ShellPaintRequestorInterface *);
725+ void AllowPaintByAnyRequestor ();
726+ ShellPaintRequestorInterface::PaintRequestorType ProhibitedPaintRequestors ();
727+ void RequireShellRepaint ();
728+ bool RepaintPending ();
729+
730+ compiz::ShellPaintDispatch paint_dispatch_;
731+
732 Settings dash_settings_;
733 dash::Style dash_style_;
734 panel::Style panel_style_;
735@@ -276,12 +284,9 @@
736 GLTexture::List _shadow_texture;
737
738 /* handle paint order */
739- bool doShellRepaint;
740- bool allowWindowPaint;
741 bool damaged;
742 bool _key_nav_mode_requested;
743 CompOutput* _last_output;
744- CompWindowList _withRemovedNuxWindows;
745
746 nux::Property<nux::Geometry> primary_monitor_;
747
748@@ -290,7 +295,7 @@
749 #ifdef USE_MODERN_COMPIZ_GL
750 ::GLFramebufferObject *oldFbo;
751 #else
752- ScreenEffectFramebufferObject::Ptr _fbo;
753+ ScreenEffectFramebufferObject::Ptr fbo_;
754 GLuint _active_fbo;
755 #endif
756
757@@ -317,15 +322,27 @@
758
759 UBusManager ubus_manager_;
760 glib::SourceManager sources_;
761+ compiz::ShellPaintRequestorInterface::PaintRequestorType no_paint_allowed_mask_;
762
763 friend class UnityWindow;
764 };
765
766+class NuxBridgeWindowInterface
767+{
768+public:
769+
770+ virtual ~NuxBridgeWindowInterface () {};
771+
772+ virtual bool IsNuxWindow () = 0;
773+};
774+
775 class UnityWindow :
776 public WindowInterface,
777 public GLWindowInterface,
778 public ShowdesktopHandlerWindowInterface,
779 public compiz::WindowInputRemoverLockAcquireInterface,
780+ public NuxBridgeWindowInterface,
781+ public compiz::ShellPaintRequestorInterface,
782 public BaseSwitchWindow,
783 public PluginClassHandler <UnityWindow, CompWindow>
784 {
785@@ -423,7 +440,12 @@
786
787 compiz::WindowInputRemoverLock::Ptr GetInputRemover ();
788
789+ bool IsNuxWindow ();
790+ compiz::ShellPaintRequestorInterface::PaintRequestorType GetPaintRequestorType ();
791+
792 compiz::WindowInputRemoverLock::Weak input_remover_;
793+
794+ bool is_nux_window_;
795 glib::Source::UniquePtr focus_desktop_timeout_;
796 };
797
798
799=== modified file 'tests/CMakeLists.txt'
800--- tests/CMakeLists.txt 2012-06-20 12:35:22 +0000
801+++ tests/CMakeLists.txt 2012-06-26 09:53:58 +0000
802@@ -150,6 +150,7 @@
803 test_unityshell_private.cpp
804 test_showdesktop_handler.cpp
805 test_hud_private.cpp
806+ test_shell_paint_schedule.cpp
807 ${CMAKE_SOURCE_DIR}/launcher/AbstractLauncherIcon.cpp
808 ${CMAKE_SOURCE_DIR}/unity-shared/Animator.cpp
809 ${UNITY_SRC}/DebugDBusInterface.cpp
810@@ -162,6 +163,7 @@
811 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp
812 ${CMAKE_SOURCE_DIR}/shortcuts/ShortcutModel.cpp
813 ${CMAKE_SOURCE_DIR}/shortcuts/ShortcutHintPrivate.cpp
814+ ${CMAKE_SOURCE_DIR}/unity-shared/ShellPaintSchedule.cpp
815 ${CMAKE_SOURCE_DIR}/unity-shared/Introspectable.cpp
816 ${CMAKE_SOURCE_DIR}/unity-shared/TextureCache.cpp
817 ${CMAKE_SOURCE_DIR}/unity-shared/Timer.cpp
818
819=== modified file 'tests/test-input-remover/test-input-remover.cpp'
820--- tests/test-input-remover/test-input-remover.cpp 2011-09-13 12:52:31 +0000
821+++ tests/test-input-remover/test-input-remover.cpp 2012-06-26 09:53:58 +0000
822@@ -27,6 +27,8 @@
823 #include <unistd.h>
824 #include <sstream>
825
826+using namespace unity;
827+
828 void usage ()
829 {
830 std::cout << "test-input-remover [WINDOW] [TIME]" << std::endl;
831
832=== modified file 'tests/test-minimize-window-handler/test-minimize-handler.cpp'
833--- tests/test-minimize-window-handler/test-minimize-handler.cpp 2012-04-18 09:19:44 +0000
834+++ tests/test-minimize-window-handler/test-minimize-handler.cpp 2012-06-26 09:53:58 +0000
835@@ -34,6 +34,8 @@
836
837 #include <x11-window-read-transients.h>
838
839+using namespace unity;
840+
841 class X11WindowFakeMinimizable :
842 public X11WindowReadTransients,
843 public compiz::WindowInputRemoverLockAcquireInterface
844
845=== added file 'tests/test_shell_paint_schedule.cpp'
846--- tests/test_shell_paint_schedule.cpp 1970-01-01 00:00:00 +0000
847+++ tests/test_shell_paint_schedule.cpp 2012-06-26 09:53:58 +0000
848@@ -0,0 +1,271 @@
849+/*
850+ * Copyright 2012 Canonical Ltd.
851+ *
852+ * This program is free software: you can redistribute it and/or modify it
853+ * under the terms of the GNU General Public License version 3, as published
854+ * by the Free Software Foundation.
855+ *
856+ * This program is distributed in the hope that it will be useful, but
857+ * WITHOUT ANY WARRANTY; without even the implied warranties of
858+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
859+ * PURPOSE. See the GNU General Public License for more details.
860+ *
861+ * You should have received a copy of the GNU General Public License
862+ * version 3 along with this program. If not, see
863+ * <http://www.gnu.org/licenses/>
864+ *
865+ * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
866+ *
867+ */
868+
869+#include <gtest/gtest.h>
870+#include <gmock/gmock.h>
871+
872+using ::testing::StrictMock;
873+using ::testing::_;
874+using ::testing::AtLeast;
875+using ::testing::Return;
876+
877+#include "ShellPaintSchedule.h"
878+
879+using namespace unity::compiz;
880+
881+class MockShellPaintRequestor :
882+ public ShellPaintRequestorInterface
883+{
884+public:
885+
886+ MOCK_METHOD0 (GetPaintRequestorType, PaintRequestorType ());
887+
888+ MockShellPaintRequestor ()
889+ {
890+ ON_CALL (*this, GetPaintRequestorType ()).WillByDefault (Return (ShellPaintRequestorInterface::PaintRequestorType::Nil));
891+ }
892+
893+};
894+
895+class MockShellPaint :
896+ public ShellPaintInterface
897+{
898+public:
899+
900+ MOCK_METHOD0 (PaintDisplay, void ());
901+};
902+
903+class MockShellPaintDispatch
904+{
905+public:
906+
907+ MOCK_METHOD1 (Paint, bool (ShellPaintRequestorInterface *));
908+ MOCK_METHOD1 (EnforceRequestor, void (ShellPaintRequestorInterface *));
909+ MOCK_METHOD0 (ClearRequestorEnforcement, void ());
910+ MOCK_METHOD0 (ProhibitedPaintRequestors, ShellPaintRequestorInterface::PaintRequestorType ());
911+ MOCK_METHOD0 (RequireShellRepaint, void ());
912+ MOCK_METHOD0 (RepaintPending, bool ());
913+};
914+
915+class TestShellPaintSchedule :
916+ public ::testing::Test
917+{
918+};
919+
920+TEST(TestShellPaintSchedule, NoPaintWhereNotRequired)
921+{
922+ StrictMock <MockShellPaint> p;
923+ MockShellPaintRequestor r;
924+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Nil; } );
925+
926+ ShellPaintDispatch dispatch (&p, f);
927+
928+ dispatch.RequestShellRepaint (&r);
929+}
930+
931+TEST(TestShellPaintSchedule, PaintWhereRequired)
932+{
933+ StrictMock <MockShellPaint> p;
934+ MockShellPaintRequestor r;
935+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Nil; } );
936+
937+ ShellPaintDispatch dispatch (&p, f);
938+
939+ dispatch.RequireShellRepaint ();
940+
941+ EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
942+ EXPECT_CALL (p, PaintDisplay ());
943+
944+ dispatch.RequestShellRepaint (&r);
945+}
946+
947+TEST(TestShellPaintSchedule, NoPaintTwice)
948+{
949+ StrictMock <MockShellPaint> p;
950+ MockShellPaintRequestor r;
951+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Nil; } );
952+
953+ ShellPaintDispatch dispatch (&p, f);
954+
955+ dispatch.RequireShellRepaint ();
956+
957+ EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
958+ EXPECT_CALL (p, PaintDisplay ());
959+
960+ dispatch.RequestShellRepaint (&r);
961+ dispatch.RequestShellRepaint (&r);
962+}
963+
964+TEST(TestShellPaintSchedule, NoWindowPaintButScreenPaint)
965+{
966+ StrictMock <MockShellPaint> p;
967+ MockShellPaintRequestor r;
968+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Window; } );
969+
970+ ShellPaintDispatch dispatch (&p, f);
971+
972+ dispatch.RequireShellRepaint ();
973+
974+ EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
975+
976+ dispatch.RequestShellRepaint (&r);
977+
978+ EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Screen));
979+ EXPECT_CALL (p, PaintDisplay ());
980+
981+ dispatch.RequestShellRepaint (&r);
982+}
983+
984+TEST(TestShellPaintSchedule, NoScreenPaintButWindowPaint)
985+{
986+ StrictMock <MockShellPaint> p;
987+ MockShellPaintRequestor r;
988+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Screen; } );
989+
990+ ShellPaintDispatch dispatch (&p, f);
991+
992+ dispatch.RequireShellRepaint ();
993+
994+ EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Screen));
995+
996+ dispatch.RequestShellRepaint (&r);
997+
998+ EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
999+ EXPECT_CALL (p, PaintDisplay ());
1000+
1001+ dispatch.RequestShellRepaint (&r);
1002+}
1003+
1004+TEST(TestShellPaintSchedule, TopRequestorOnlyPaints)
1005+{
1006+ StrictMock <MockShellPaint> p;
1007+ MockShellPaintRequestor r_w1, r_w2;
1008+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Nil; } );
1009+
1010+ ShellPaintDispatch dispatch (&p, f);
1011+
1012+ dispatch.RequireShellRepaint ();
1013+
1014+ dispatch.AllowPaintByAnyRequestor ();
1015+ dispatch.EnforcePaintByRequestor (&r_w2);
1016+
1017+ EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1018+ EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1019+
1020+ dispatch.RequestShellRepaint (&r_w1);
1021+
1022+ EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1023+ EXPECT_CALL (p, PaintDisplay ());
1024+
1025+ dispatch.RequestShellRepaint (&r_w2);
1026+}
1027+
1028+TEST(TestShellPaintSchedule, SuperveningRequestorOfOtherTypePaints)
1029+{
1030+ StrictMock <MockShellPaint> p;
1031+ MockShellPaintRequestor r_w1, r_w2, r_s1;
1032+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Nil; } );
1033+
1034+ ShellPaintDispatch dispatch (&p, f);
1035+
1036+ dispatch.RequireShellRepaint ();
1037+
1038+ dispatch.AllowPaintByAnyRequestor ();
1039+ dispatch.EnforcePaintByRequestor (&r_w2);
1040+
1041+ EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1042+ EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1043+
1044+ dispatch.RequestShellRepaint (&r_w1);
1045+
1046+ EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1047+ EXPECT_CALL (r_s1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::PaintRequestorType::Screen));
1048+
1049+ EXPECT_CALL (p, PaintDisplay ());
1050+
1051+ dispatch.RequestShellRepaint (&r_s1);
1052+
1053+ EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1054+
1055+ dispatch.RequestShellRepaint (&r_w2);
1056+}
1057+
1058+TEST(TestShellPaintSchedule, DoubleEnforcementHasNoEffect)
1059+{
1060+ StrictMock <MockShellPaint> p;
1061+ MockShellPaintRequestor r_w1, r_w2;
1062+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Nil; } );
1063+
1064+ ShellPaintDispatch dispatch (&p, f);
1065+
1066+ dispatch.RequireShellRepaint ();
1067+
1068+ dispatch.AllowPaintByAnyRequestor ();
1069+ dispatch.EnforcePaintByRequestor (&r_w2);
1070+ dispatch.EnforcePaintByRequestor (&r_w1);
1071+
1072+ EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1073+ EXPECT_CALL (r_w1, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1074+
1075+ dispatch.RequestShellRepaint (&r_w1);
1076+
1077+ EXPECT_CALL (r_w2, GetPaintRequestorType ()).WillRepeatedly (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1078+ EXPECT_CALL (p, PaintDisplay ());
1079+
1080+ dispatch.RequestShellRepaint (&r_w2);
1081+}
1082+
1083+TEST(TestShellPaintSchedule, GetPendingRepaint)
1084+{
1085+ StrictMock <MockShellPaint> p;
1086+ MockShellPaintRequestor r;
1087+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([]() -> ShellPaintRequestorInterface::PaintRequestorType { return ShellPaintRequestorInterface::PaintRequestorType::Nil; } );
1088+
1089+ ShellPaintDispatch dispatch (&p, f);
1090+
1091+ EXPECT_FALSE (dispatch.RepaintPending ());
1092+
1093+ dispatch.RequireShellRepaint ();
1094+
1095+ EXPECT_TRUE (dispatch.RepaintPending ());
1096+
1097+ EXPECT_CALL (r, GetPaintRequestorType ()).WillOnce (Return (ShellPaintRequestorInterface::PaintRequestorType::Window));
1098+ EXPECT_CALL (p, PaintDisplay ());
1099+
1100+ dispatch.RequestShellRepaint (&r);
1101+
1102+ EXPECT_FALSE (dispatch.RepaintPending ());
1103+}
1104+
1105+TEST(TestShellPaintSchedule, GetProhibitedPaintMasks)
1106+{
1107+ StrictMock <MockShellPaint> p;
1108+ MockShellPaintRequestor r;
1109+ ShellPaintRequestorInterface::PaintRequestorType prohibited_paint_mask = ShellPaintRequestorInterface::PaintRequestorType::Nil;
1110+ ShellPaintDispatch::GetProhibitedPaintMasksFunc f ([&]() -> ShellPaintRequestorInterface::PaintRequestorType { return prohibited_paint_mask; } );
1111+
1112+ ShellPaintDispatch dispatch (&p, f);
1113+
1114+ EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ());
1115+ prohibited_paint_mask = ShellPaintRequestorInterface::PaintRequestorType::Window;
1116+ EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ());
1117+ prohibited_paint_mask = ShellPaintRequestorInterface::PaintRequestorType::Screen;
1118+ EXPECT_EQ (prohibited_paint_mask, dispatch.ProhibitedPaintRequestors ());
1119+}
1120
1121=== modified file 'tests/test_showdesktop_handler.cpp'
1122--- tests/test_showdesktop_handler.cpp 2012-04-18 09:30:53 +0000
1123+++ tests/test_showdesktop_handler.cpp 2012-06-26 09:53:58 +0000
1124@@ -4,12 +4,14 @@
1125 #include <gmock/gmock.h>
1126 #include <UnityShowdesktopHandler.h>
1127
1128-using namespace unity;
1129 using ::testing::_;
1130 using ::testing::Return;
1131 using ::testing::Invoke;
1132 using ::testing::InSequence;
1133
1134+namespace unity
1135+{
1136+
1137 compiz::WindowInputRemoverInterface::~WindowInputRemoverInterface () {}
1138
1139 class MockWindowInputRemover :
1140@@ -96,11 +98,16 @@
1141 MOCK_METHOD0 (DoDeleteHandler, void ());
1142 };
1143
1144+}
1145+
1146+using namespace unity;
1147+using namespace unity::compiz;
1148+
1149 TEST_F(UnityShowdesktopHandlerTest, TestNoORWindowsSD)
1150 {
1151 MockUnityShowdesktopHandlerWindow mMockWindow;
1152
1153- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1154+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1155
1156 EXPECT_CALL (mMockWindow, IsOverrideRedirect ()).WillOnce (Return (true));
1157 EXPECT_FALSE (ShowdesktopHandler::ShouldHide (&mMockWindow));
1158@@ -110,7 +117,7 @@
1159 {
1160 MockUnityShowdesktopHandlerWindow mMockWindow;
1161
1162- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1163+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1164
1165 EXPECT_CALL (mMockWindow, IsOverrideRedirect ());
1166 EXPECT_CALL (mMockWindow, IsManaged ()).WillOnce (Return (false));
1167@@ -121,7 +128,7 @@
1168 {
1169 MockUnityShowdesktopHandlerWindow mMockWindow;
1170
1171- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1172+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1173
1174 EXPECT_CALL (mMockWindow, IsOverrideRedirect ());
1175 EXPECT_CALL (mMockWindow, IsManaged ());
1176@@ -133,7 +140,7 @@
1177 {
1178 MockUnityShowdesktopHandlerWindow mMockWindow;
1179
1180- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1181+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1182
1183 EXPECT_CALL (mMockWindow, IsOverrideRedirect ());
1184 EXPECT_CALL (mMockWindow, IsManaged ());
1185@@ -146,7 +153,7 @@
1186 {
1187 MockUnityShowdesktopHandlerWindow mMockWindow;
1188
1189- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1190+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1191
1192 EXPECT_CALL (mMockWindow, IsOverrideRedirect ());
1193 EXPECT_CALL (mMockWindow, IsManaged ());
1194@@ -160,7 +167,7 @@
1195 {
1196 MockUnityShowdesktopHandlerWindow mMockWindow;
1197
1198- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1199+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1200
1201 EXPECT_CALL (mMockWindow, IsOverrideRedirect ());
1202 EXPECT_CALL (mMockWindow, IsManaged ());
1203@@ -177,7 +184,7 @@
1204 {
1205 MockUnityShowdesktopHandlerWindow mMockWindow;
1206
1207- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1208+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1209
1210 EXPECT_CALL (mMockWindow, IsOverrideRedirect ());
1211 EXPECT_CALL (mMockWindow, IsManaged ());
1212@@ -193,7 +200,7 @@
1213 {
1214 MockUnityShowdesktopHandlerWindow mMockWindow;
1215
1216- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1217+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1218
1219 EXPECT_CALL (mMockWindow, IsOverrideRedirect ());
1220 EXPECT_CALL (mMockWindow, IsManaged ());
1221@@ -211,7 +218,7 @@
1222 {
1223 MockUnityShowdesktopHandlerWindow mMockWindow;
1224
1225- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1226+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1227
1228 EXPECT_CALL (mMockWindow, IsOverrideRedirect ());
1229 EXPECT_CALL (mMockWindow, IsManaged ());
1230@@ -226,7 +233,7 @@
1231 }
1232
1233 class MockWindowInputRemoverTestFadeOut :
1234- public compiz::WindowInputRemoverInterface
1235+ public WindowInputRemoverInterface
1236 {
1237 public:
1238
1239@@ -252,7 +259,7 @@
1240
1241 EXPECT_CALL (mMockWindow, GetInputRemover ()).WillOnce (Invoke (UnityShowdesktopHandlerTest::getLock <MockWindowInputRemoverTestFadeOut>));
1242
1243- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1244+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1245
1246 EXPECT_CALL (mMockWindow, IsHidden ());
1247 EXPECT_CALL (mMockWindow, DoHide ());
1248@@ -264,7 +271,7 @@
1249 }
1250
1251 class MockWindowInputRemoverTestFadeOutAlready :
1252- public compiz::WindowInputRemoverInterface
1253+ public WindowInputRemoverInterface
1254 {
1255 public:
1256
1257@@ -284,7 +291,7 @@
1258 {
1259 MockUnityShowdesktopHandlerWindow mMockWindow;
1260
1261- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1262+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1263
1264 EXPECT_CALL (mMockWindow, IsHidden ()).WillOnce (Return (true));
1265
1266@@ -298,7 +305,7 @@
1267 MockUnityShowdesktopHandlerWindow mMockWindow;
1268
1269 EXPECT_CALL (mMockWindow, GetInputRemover ()).WillOnce (Invoke (UnityShowdesktopHandlerTest::getLock <MockWindowInputRemoverTestFadeOut>));
1270- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1271+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1272
1273 EXPECT_CALL (mMockWindow, IsHidden ());
1274 EXPECT_CALL (mMockWindow, DoHide ());
1275@@ -314,7 +321,7 @@
1276 {
1277 MockUnityShowdesktopHandlerWindow mMockWindow;
1278
1279- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1280+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1281
1282 mMockHandler.FadeIn ();
1283
1284@@ -322,7 +329,7 @@
1285 }
1286
1287 class MockWindowInputRemoverTestFadeOutFadeIn :
1288- public compiz::WindowInputRemoverInterface
1289+ public WindowInputRemoverInterface
1290 {
1291 public:
1292
1293@@ -347,7 +354,7 @@
1294 MockUnityShowdesktopHandlerWindow mMockWindow;
1295
1296 EXPECT_CALL (mMockWindow, GetInputRemover ()).WillOnce (Invoke (UnityShowdesktopHandlerTest::getLock <MockWindowInputRemoverTestFadeOutFadeIn>));
1297- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1298+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1299
1300 EXPECT_CALL (mMockWindow, IsHidden ());
1301 EXPECT_CALL (mMockWindow, DoHide ());
1302@@ -368,7 +375,7 @@
1303 MockUnityShowdesktopHandlerWindow mMockWindow;
1304
1305 EXPECT_CALL (mMockWindow, GetInputRemover ()).WillOnce (Invoke (UnityShowdesktopHandlerTest::getLock <MockWindowInputRemoverTestFadeOutFadeIn>));
1306- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1307+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1308
1309 EXPECT_CALL (mMockWindow, IsHidden ());
1310 EXPECT_CALL (mMockWindow, DoHide ());
1311@@ -409,7 +416,7 @@
1312 MockUnityShowdesktopHandlerWindow mMockWindow;
1313
1314 EXPECT_CALL (mMockWindow, GetInputRemover ()).WillOnce (Invoke (UnityShowdesktopHandlerTest::getLock <MockWindowInputRemoverTestFadeOutFadeIn>));
1315- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1316+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1317
1318 EXPECT_CALL (mMockWindow, IsHidden ());
1319 EXPECT_CALL (mMockWindow, DoHide ());
1320@@ -465,7 +472,7 @@
1321 MockUnityShowdesktopHandlerWindow mMockWindow;
1322
1323 EXPECT_CALL (mMockWindow, GetInputRemover ()).WillOnce (Invoke (UnityShowdesktopHandlerTest::getLock <MockWindowInputRemoverTestFadeOutFadeIn>));
1324- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1325+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1326
1327 EXPECT_CALL (mMockWindow, IsHidden ());
1328 EXPECT_CALL (mMockWindow, DoHide ());
1329@@ -491,7 +498,7 @@
1330 }
1331
1332 class MockWindowInputRemoverTestFadeOutFadeInWithShapeEvent :
1333- public compiz::WindowInputRemoverInterface
1334+ public WindowInputRemoverInterface
1335 {
1336 public:
1337
1338@@ -520,7 +527,7 @@
1339 MockUnityShowdesktopHandlerWindow mMockWindow;
1340
1341 EXPECT_CALL (mMockWindow, GetInputRemover ()).WillOnce (Invoke (UnityShowdesktopHandlerTest::getLock <MockWindowInputRemoverTestFadeOutFadeInWithShapeEvent>));
1342- ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1343+ ShowdesktopHandler mMockHandler (static_cast <ShowdesktopHandlerWindowInterface *> (&mMockWindow), static_cast <WindowInputRemoverLockAcquireInterface *> (&mMockWindow));
1344
1345 EXPECT_CALL (mMockWindow, IsHidden ());
1346 EXPECT_CALL (mMockWindow, DoHide ());
1347
1348=== modified file 'tests/x11-window-read-transients.cpp'
1349--- tests/x11-window-read-transients.cpp 2011-08-24 16:46:09 +0000
1350+++ tests/x11-window-read-transients.cpp 2012-06-26 09:53:58 +0000
1351@@ -25,6 +25,8 @@
1352 #define _GNU_SOURCE
1353 #endif
1354
1355+using namespace unity;
1356+
1357 X11WindowReadTransients::X11WindowReadTransients (Display *d, Window w) :
1358 X11Window::X11Window (d, w)
1359 {
1360
1361=== modified file 'unity-shared/CMakeLists.txt'
1362--- unity-shared/CMakeLists.txt 2012-05-22 10:15:47 +0000
1363+++ unity-shared/CMakeLists.txt 2012-06-26 09:53:58 +0000
1364@@ -47,6 +47,7 @@
1365 PanelStyle.cpp
1366 SearchBar.cpp
1367 SearchBarSpinner.cpp
1368+ ShellPaintSchedule.cpp
1369 StaticCairoText.cpp
1370 TextureCache.cpp
1371 Timer.cpp
1372
1373=== added file 'unity-shared/ShellPaintSchedule.cpp'
1374--- unity-shared/ShellPaintSchedule.cpp 1970-01-01 00:00:00 +0000
1375+++ unity-shared/ShellPaintSchedule.cpp 2012-06-26 09:53:58 +0000
1376@@ -0,0 +1,93 @@
1377+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1378+/*
1379+ * Copyright (C) 2012 Canonical Ltd
1380+ *
1381+ * This program is free software: you can redistribute it and/or modify
1382+ * it under the terms of the GNU General Public License version 3 as
1383+ * published by the Free Software Foundation.
1384+ *
1385+ * This program is distributed in the hope that it will be useful,
1386+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1387+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1388+ * GNU General Public License for more details.
1389+ *
1390+ * You should have received a copy of the GNU General Public License
1391+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1392+ *
1393+ * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
1394+ */
1395+
1396+#include "ShellPaintSchedule.h"
1397+
1398+namespace unity
1399+{
1400+namespace compiz
1401+{
1402+
1403+ShellPaintDispatch::ShellPaintDispatch (ShellPaintInterface *paint_interface,
1404+ const GetProhibitedPaintMasksFunc &prohibited_func) :
1405+ shell_repaint_required_ (false),
1406+ top_requestor_ (nullptr),
1407+ prohibited_paint_masks_func_ (prohibited_func),
1408+ paint_interface_ (paint_interface)
1409+{
1410+}
1411+
1412+bool
1413+ShellPaintDispatch::RequestShellRepaint (ShellPaintRequestorInterface *requestor)
1414+{
1415+ if (!shell_repaint_required_)
1416+ return false;
1417+
1418+ if (prohibited_paint_masks_func_ () == requestor->GetPaintRequestorType ())
1419+ return false;
1420+
1421+ if (top_requestor_)
1422+ if ((top_requestor_->GetPaintRequestorType () ==
1423+ requestor->GetPaintRequestorType ()) && top_requestor_ != requestor)
1424+ return false;
1425+
1426+ paint_interface_->PaintDisplay ();
1427+
1428+ shell_repaint_required_ = false;
1429+
1430+ return true;
1431+}
1432+
1433+bool
1434+ShellPaintDispatch::EnforcePaintByRequestor (ShellPaintRequestorInterface *requestor)
1435+{
1436+ if (top_requestor_)
1437+ return false;
1438+
1439+ top_requestor_ = requestor;
1440+
1441+ return true;
1442+}
1443+
1444+void
1445+ShellPaintDispatch::AllowPaintByAnyRequestor ()
1446+{
1447+ top_requestor_ = nullptr;
1448+}
1449+
1450+ShellPaintRequestorInterface::PaintRequestorType
1451+ShellPaintDispatch::ProhibitedPaintRequestors ()
1452+{
1453+ return prohibited_paint_masks_func_ ();
1454+}
1455+
1456+void
1457+ShellPaintDispatch::RequireShellRepaint ()
1458+{
1459+ shell_repaint_required_ = true;
1460+}
1461+
1462+bool
1463+ShellPaintDispatch::RepaintPending ()
1464+{
1465+ return shell_repaint_required_;
1466+}
1467+
1468+}
1469+}
1470
1471=== added file 'unity-shared/ShellPaintSchedule.h'
1472--- unity-shared/ShellPaintSchedule.h 1970-01-01 00:00:00 +0000
1473+++ unity-shared/ShellPaintSchedule.h 2012-06-26 09:53:58 +0000
1474@@ -0,0 +1,125 @@
1475+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1476+/*
1477+ * Copyright (C) 2012 Canonical Ltd
1478+ *
1479+ * This program is free software: you can redistribute it and/or modify
1480+ * it under the terms of the GNU General Public License version 3 as
1481+ * published by the Free Software Foundation.
1482+ *
1483+ * This program is distributed in the hope that it will be useful,
1484+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1485+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1486+ * GNU General Public License for more details.
1487+ *
1488+ * You should have received a copy of the GNU General Public License
1489+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1490+ *
1491+ * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
1492+ */
1493+
1494+#ifndef UNITY_PAINT_SCHEDULE_H
1495+#define UNITY_PAINT_SCHEDULE_H
1496+
1497+#include <boost/bind.hpp>
1498+#include <boost/function.hpp>
1499+
1500+namespace unity
1501+{
1502+namespace compiz
1503+{
1504+
1505+/*
1506+ * Implementors of ShellPaintRequestorInterface are able
1507+ * to request a repaint of the unity shell by calling
1508+ * Paint () in ShellPaintDispatchInterface. Requestors
1509+ * must identify themselves to an implementor of
1510+ * ShellPaintDispatchInterface such that ShellPaintDispatch
1511+ * interface can decide whether to allow a redraw
1512+ */
1513+class ShellPaintRequestorInterface
1514+{
1515+public:
1516+
1517+ enum class PaintRequestorType
1518+ {
1519+ Nil = 0,
1520+ Window = (1 << 0),
1521+ Screen = (1 << 1)
1522+ };
1523+
1524+ virtual ~ShellPaintRequestorInterface () {}
1525+
1526+ virtual PaintRequestorType GetPaintRequestorType () = 0;
1527+};
1528+
1529+/*
1530+ * Implementors of ShellPaintInterface are capable
1531+ * of repainting the shell */
1532+class ShellPaintInterface
1533+{
1534+public:
1535+
1536+ virtual ~ShellPaintInterface () {};
1537+
1538+ virtual void PaintDisplay () = 0;
1539+};
1540+
1541+/*
1542+ * Implementors of ShellPaintDispatchInterface
1543+ * manage when the shell is allowed to be repainted
1544+ * by examining what is requesting the repaint of
1545+ * the shell and determining whether or not a
1546+ * repaint is required
1547+ */
1548+class ShellPaintDispatchInterface
1549+{
1550+public:
1551+
1552+ virtual ~ShellPaintDispatchInterface () {}
1553+
1554+ virtual bool RequestShellRepaint (ShellPaintRequestorInterface *) = 0;
1555+ virtual bool EnforcePaintByRequestor (ShellPaintRequestorInterface *) = 0;
1556+ virtual void AllowPaintByAnyRequestor () = 0;
1557+ virtual ShellPaintRequestorInterface::PaintRequestorType ProhibitedPaintRequestors () = 0;
1558+ virtual void RequireShellRepaint () = 0;
1559+ virtual bool RepaintPending () = 0;
1560+
1561+};
1562+
1563+/*
1564+ * ShellPaintDispatch is the canonical implementor
1565+ * of ShellPaintDispatchInterface and manages when
1566+ * the shell is allowed to be repainted depending
1567+ * on what ShellPaintRequestorInterface is requesting
1568+ * the repaint
1569+ */
1570+class ShellPaintDispatch :
1571+ public ShellPaintDispatchInterface
1572+{
1573+public:
1574+
1575+ typedef boost::function <ShellPaintRequestorInterface::PaintRequestorType ()> GetProhibitedPaintMasksFunc;
1576+
1577+ ShellPaintDispatch (ShellPaintInterface * paint_interface,
1578+ const GetProhibitedPaintMasksFunc &func);
1579+
1580+ bool RequestShellRepaint (ShellPaintRequestorInterface *);
1581+ bool EnforcePaintByRequestor (ShellPaintRequestorInterface *);
1582+ void AllowPaintByAnyRequestor ();
1583+ ShellPaintRequestorInterface::PaintRequestorType ProhibitedPaintRequestors();
1584+ void RequireShellRepaint ();
1585+ bool RepaintPending ();
1586+
1587+
1588+protected:
1589+
1590+ bool shell_repaint_required_;
1591+ ShellPaintRequestorInterface *top_requestor_;
1592+ GetProhibitedPaintMasksFunc prohibited_paint_masks_func_;
1593+ ShellPaintInterface *paint_interface_;
1594+};
1595+
1596+}
1597+}
1598+
1599+#endif