Merge lp:~vanvugt/compiz/fix-980663-1041066 into lp:compiz/0.9.8

Proposed by Daniel van Vugt
Status: Merged
Approved by: Daniel van Vugt
Approved revision: 3346
Merged at revision: 3338
Proposed branch: lp:~vanvugt/compiz/fix-980663-1041066
Merge into: lp:compiz/0.9.8
Diff against target: 371 lines (+266/-18)
7 files modified
plugins/opengl/CMakeLists.txt (+4/-1)
plugins/opengl/src/fsregion/CMakeLists.txt (+7/-0)
plugins/opengl/src/fsregion/fsregion.cpp (+54/-0)
plugins/opengl/src/fsregion/fsregion.h (+55/-0)
plugins/opengl/src/fsregion/tests/CMakeLists.txt (+10/-0)
plugins/opengl/src/fsregion/tests/test-fsregion.cpp (+121/-0)
plugins/opengl/src/paint.cpp (+15/-17)
To merge this branch: bzr merge lp:~vanvugt/compiz/fix-980663-1041066
Reviewer Review Type Date Requested Status
Sam Spilsbury Approve
Compiz Maintainers Pending
Review via email: mp+122650@code.launchpad.net

This proposal supersedes a proposal from 2012-09-04.

Commit message

Make "Unredirect Fullscreen Windows" more reliable. This fixes the problem
with unredirection failing to engage at all (LP: #1041066) when
gtk-window-decorator creates offscreen windows that are stacked on top.
This also fixes the problem with unredirect hiding all windows,
because it thinks the desktop window should be stacked on top (LP: #980663).

Unfortunately, both issues are so tightly coupled that they can only really
be fixed and tested together.

Description of the change

Make "Unredirect Fullscreen Windows" more reliable. This fixes the problem
with unredirection failing to engage at all (LP: #1041066) when
gtk-window-decorator creates offscreen windows that are stacked on top.
This also fixes the problem with unredirect hiding all windows,
because it thinks the desktop window should be stacked on top (LP: #980663).

Unfortunately, both issues are so tightly coupled that they can only really
be fixed and tested together.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Seems to work perfectly. But on hold until I figure out if automated testing is possible for this right now, without making the code totally unmaintainable...

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal
Download full text (4.7 KiB)

115 +/*
116 + * Why mock locally? Because...
117 + * 1. Code is cleaner without typecasts, so we need to ensure that
118 + * Output::Window is-a CompWindow when not mocking.
119 + * 2. No polymorphism is required = fewer classes, less code, easier to follow.
120 + */
121 +#ifdef OUTPUTWINDOW
122 +class MockCompWindow
123 +{
124 +public:
125 + MockCompWindow (unsigned int type, int x, int y, int width, int height) :
126 + flags (type), reg (x, y, width, height) {}
127 + unsigned int type () const { return flags; }
128 + const CompRegion &region () const { return reg; }
129 +
130 +private:
131 + unsigned int flags;
132 + CompRegion reg;
133 +};
134 +#else
135 +#define OUTPUTWINDOW CompWindow
136 +#endif

Yeah, I disagree with this :)

1. It relies on a define for the code to compile the right way
   a. (Unity has code that does this and its not nice to work with)
2. Ifdefs make the code harder to follow in general. The code is doing two different things depending on how it was compiled. This could introduce subtle gotchas.
3. This code is relying on an implicit interface (eg, what the caller is doing with CompWindow). This means that
   when it breaks, it will be non-obvious as to why (eg, instead of being told that MockCompWindow does not
   implement the interface, you get a normal compile error saying that certain functions don't exist on this object
   that #defines itself into existence at compile time).
4. The Window definition conflicts with the Xlib one.

If you don't want to use an interface class (this is a point I agree on), here are some alternatives:

 a. Output::occlude is only really interested in three things from CompWindow, firstly whether or not it can take focus (I will deal with this later), and secondly a means to get a CompositeWindow and thirdly its covering region. You can do something like this:

 typedef enum _FocusableState
 {
     CanTakeFocus = 0,
     NoFocusAllowed = 1
 } FocusableState;

 //
 Output::occlude (FocusableState focusState,
                  CompRegion const & reg,
                  Window win) // Using Window in terms of its XLib meaning here ...
 {
57 +
58 + if (!fullscreen &&
              focusState == CanTakeFocus && // Skip desktop etc
60 + reg == untouched)
61 + {
62 + fullscreen = win;
63 + }
64 + untouched -= reg;
 }

Window
Output::fullscreenWindow ()
{
    return Window;
}

// not under test
FocusableState
compiz::opengl::WindowTypeToFocusableState (CompWindow *window)
{
    if (window->type () & NO_FOCUS_MASK)
        return NoFocusAllowed;

    return CanTakeFocus;
}

Use the code like this:

FocusableState focusState = WindowTypeToFocusableState (window);
output.occlude (focusState, window->id (), window->region ());

Window fullscreenWindow = output.fullscreenWindow ();
CompWindow *fullscreenCompWindow = screen->findWindow (fullscreenWindow);
CompositeWindow *compositeFullscreenWindow = CompositeWindow::get (fullscreenCompWindow);

compositeFullscreenWindow->unredirect ();

I personally don't like using the Xlib Window handle as a means to identify windows within compiz, and would personally prefer that compiz::opengl::Output used an interface like RedirectedWindow (with metho...

Read more...

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

Actually, I thought of all of that already and disagree with almost all of it :)

I'll try to find a nicer way to hide and clean up the mocking. However changing a class' public interface is usually a mistake. Test cases can change how you do your implementation, but should never change the interfaces.

I'm not using compiz_discover_tests because I hate the fact that it necessitates excessively deep directories (plugins/NAME/src/LIBNAME/src/stuff.cpp). Also, what does compiz_discover_tests give me if I need to create more files, directories and complexity to use it?

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

Also, test-output is in a namespace already by virtue of its directory:
build/plugins/opengl/src/tests/test-output

However I will rename it internally at least so you can tell what and where it is just from the CTest output.

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

Clean-ups all round.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal
Download full text (3.2 KiB)

"Actually, I thought of all of that already and disagree with almost all of it :)"

Could you elaborate? I didn't say that you needed to change any public interfaces.

This is still very confusing:

380 +#ifdef MOCK_COMPWINDOW
381 + typedef Stackable Window;
382 +#else
383 + typedef CompWindow Window;
384 +#endif

The code is compiled twice, and you have an abstract base class in one version and a concrete class in another. What this essentially is, is a template implemented in terms of #define.

If you're going to create an abstract base class, why not just go all the way and make PrivateGLWindow inherit Stackable, put a redirect method in Stackable and make it call through to PrivateGLWindow? That way you don't need to rely on a define, and you only need to compile this code once.

96 +include_directories(${GTEST_INCLUDE_DIRS} ..)
97 +add_definitions(-DMOCK_COMPWINDOW)
98 +set(exe "compiz_opengl_test_windowstack")
99 +add_executable(${exe} test-windowstack.cpp ../windowstack.cpp)
100 +target_link_libraries(${exe} compiz_core ${GTEST_BOTH_LIBRARIES})
101 +add_test(OpenGLWindowStackTests ${exe})

"I'm not using compiz_discover_tests because I hate the fact that it necessitates excessively deep directories (plugins/NAME/src/LIBNAME/src/stuff.cpp). Also, what does compiz_discover_tests give me if I need to create more files, directories and complexity to use it?"

It doesn't necessitate that at all. The tests are only organized that way because this is the way I happened to organize them. (Also, when in doubt, its a good idea to be consistent rather than go against the grain - I'm happy to change the organization if we can agree on a better way).

Here's the syntax for compiz_discover_tests.

compiz_discover_tests (test_executable COVERAGE library_that_the_test_uses_1 library_2 ...)

The coverage argument is optional, but does require that the tested code goes into a separate library (which you should do anyways because currently the code is compiled twice, which is the exact problem that unity has which I am trying to avoid).

I strongly recommend using this function. It has the following purposes:

1. It adds every individual test to the CTest manifest, meaning that you always have a perfectly clean environment on setup and teardown (defend against subtle bugs where tests are stateful and rely on each other when they shouldn't).
2. You have per-test resolution when something fails from "make test"
3. Its the best way to get your code added to the coverage report, so that you can see if your tests are actually excersizing the code all round. (You can add to the coverage report yourself, however that's several hundred lines of CMake code).

Another good reason:
4. If someone else adds a test using compiz_discover_tests there is a race in CMake where the CTestFile for this test will be clobbered.

"WindowStack" also feels weird. Its not a window stack - its a class that accumulates uncovered screen regions to determine which windows are not occluded. Also "stackable" in the namespace compiz::opengl feels weird too. Its not a "stackable", in compiz terms "stackable" means something more like a window that sits in a stack and can be re-arranged. I...

Read more...

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

I apologize if I seem ... opinionated, I'm just trying to distill what the intention is and the best way of effecting that intention

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

Looking much better without the #define.

I think that Output can take the X11 definition of a "Window" (eg, typedef unsigned int Window) rather than using void *, it means the same thing in both instances and makes the code slightly more clear as to what is being used to identify the window. There's no need to link to xlib for this, all there is a header dependency on <X11/Xlib.h>

Now that Output is taking references to the data that it needs to use to identify which window is on top, there's not much need for MockCompWindow anymore. The boolean parameter in Output can be changed to an enum, eg

typedef enum _FocusAllowedState
{
    NoFocusAllowed,
    FocusAllowed
}

Output::occlude (FocusAllowed, region, window) is more expressive than Output::occlude (true, region, window).

Finally, it would be good if output.cpp was a static library that was linked into opengl. I've tried to avoid setting the trend of compiling any source file more than once in the tree (like Unity does), and would like to keep the source tree this way.

compiz_discover_tests(${exe})

If you are using another static library, you can create coverage targets as so

compiz_discover_tests(${exe} COVERAGE compiz_opengl_output_occlusion_detection)

That will ensure that you can get coverage reports from "make coverage"

The preferred method of addressing source files in a cmake tree is this:

${CMAKE_CURRENT_SOURCE_DIR}/../file.cpp not ../file.cpp

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

If possible by the way, see if you can find a better name for "Output". I still think there's some confusion between "Output" and "CompOutput" - the responsibility of this class seems to be finding a fullscreen window to unredirect based on which windows are not occluded.

I did mention it before, but I find that difficulty in finding a name for a class might indicate that its doing too many unrelated things. In this case, the class is checking for a window to unredirect and then offering a way to get the result. Perhaps it would be better if it stored an interface by which the window could be unredirected and then provided a method to call into the class to unredirect the saved fullscreen window. That way the class could be called "UnoccludedWindowUnredirector". Yes I know you don't like -er, but this is still a noun.

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

Lots of clean-ups and renaming.

I disagree with the bi-state enumeration and think a boolean is clearer in cases like this where you can use it.

I disagree with the suggested approach to coverage where you have to put code in a static library to get coverage data. Getting coverage information should be transparently possible for all test cases. I'm surprised it's not done that way already, but we can improve that later. See also bug 1045665.

And I disagree with putting a single, single-use class in a separate library just to avoid recompiling it in the test cases. Clarity and a simpler source tree is more important.

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

> Lots of clean-ups and renaming.
>
> I disagree with the bi-state enumeration and think a boolean is clearer in
> cases like this where you can use it.

How is:

isCoveredBy (region, true);

Any more clear than

isCoveredBy (region, FullscreenWindow); or isCoveredBy (region, NormalWindow);

Read it aloud.

"is covered by region true" vs "is covered by region, a FullscreenWindow" "is covered by region, a NormalWindow".

Not blocking on this, but please consider it.

>
> I disagree with the suggested approach to coverage where you have to put code
> in a static library to get coverage data. Getting coverage information should
> be transparently possible for all test cases. I'm surprised it's not done that
> way already, but we can improve that later. See also bug 1045665.

Right, the /current/ coverage system doesn't support this case. In fact, if you pass it the testcase as the coverage target, you should be able to get a coverage report on that file though:

>
> And I disagree with putting a single, single-use class in a separate library
> just to avoid recompiling it in the test cases. Clarity and a simpler source
> tree is more important.

add_library (compiz_opengl_fullscreen_region fullscreenregion.cpp)
target_link_libraries (compiz_opengl_fullscreen_region compiz_region)

...

compiz_plugin (opengl ... LIBRARIES compiz_opengl_fullscreen_region ...)

The source tree doesn't exactly have to be reorganized to make it work.

We aren't using autotools - any buildsystem that requires you to compile a file twice is a travesty and I won't allow this trend to be set in compiz. Unity does exactly this and it annoys me greatly - it takes at least fifteen minutes longer than it should to compile because nobody took the time to ensure that files were only compiled once.

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

I don't care any more. I'm willing to compromise any which way to get this merged. A week on a fix that took me 10 minutes is crazy...

WIP again.

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

All looking good now.

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-compiz-core/109/console reported an error when processing this lp:~vanvugt/compiz/fix-980663-1041066 branch.
Not merging it.

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

So I can't believe this, but the automerge still has -DCOMPIZ_BUILD_TESTING=OFF. You'll need to do this:

if (COMPIZ_BUILD_TESTING)
add_subdirectory (tests)
endif (COMPIZ_BUILD_TESTING)

I note that we should probably develop a cmake file with macros for this stuff.

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

Once that's fixed, just approve the branch again (though the chances are it won't merge anyways as jenkins is out of space)

3346. By Daniel van Vugt

Building of tests is conditional, apparently. This fixes a Jenkins failure.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/opengl/CMakeLists.txt'
2--- plugins/opengl/CMakeLists.txt 2012-08-29 08:41:58 +0000
3+++ plugins/opengl/CMakeLists.txt 2012-09-05 03:21:22 +0000
4@@ -3,9 +3,12 @@
5 include (CompizPlugin)
6
7 set (INTERNAL_LIBRARIES
8- compiz_opengl_double_buffer)
9+ compiz_opengl_double_buffer
10+ compiz_opengl_fsregion
11+)
12
13 add_subdirectory (src/doublebuffer)
14+add_subdirectory (src/fsregion)
15
16 if (USE_GLES)
17 compiz_plugin(opengl PLUGINDEPS composite CFLAGSADD "-DUSE_GLES -std=c++0x" LIBRARIES ${OPENGLES2_LIBRARIES} ${INTERNAL_LIBRARIES} dl INCDIRS ${OPENGLES2_INCLUDE_DIR})
18
19=== added directory 'plugins/opengl/src/fsregion'
20=== added file 'plugins/opengl/src/fsregion/CMakeLists.txt'
21--- plugins/opengl/src/fsregion/CMakeLists.txt 1970-01-01 00:00:00 +0000
22+++ plugins/opengl/src/fsregion/CMakeLists.txt 2012-09-05 03:21:22 +0000
23@@ -0,0 +1,7 @@
24+if (COMPIZ_BUILD_TESTING)
25+add_subdirectory (tests)
26+endif ()
27+
28+add_library (compiz_opengl_fsregion STATIC fsregion.cpp)
29+target_link_libraries (compiz_opengl_fsregion compiz_core)
30+
31
32=== added file 'plugins/opengl/src/fsregion/fsregion.cpp'
33--- plugins/opengl/src/fsregion/fsregion.cpp 1970-01-01 00:00:00 +0000
34+++ plugins/opengl/src/fsregion/fsregion.cpp 2012-09-05 03:21:22 +0000
35@@ -0,0 +1,54 @@
36+/*
37+ * Compiz opengl plugin, FullscreenRegion class
38+ *
39+ * Copyright (c) 2012 Canonical Ltd.
40+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
41+ *
42+ * Permission is hereby granted, free of charge, to any person obtaining a
43+ * copy of this software and associated documentation files (the "Software"),
44+ * to deal in the Software without restriction, including without limitation
45+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
46+ * and/or sell copies of the Software, and to permit persons to whom the
47+ * Software is furnished to do so, subject to the following conditions:
48+ *
49+ * The above copyright notice and this permission notice shall be included in
50+ * all copies or substantial portions of the Software.
51+ *
52+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
57+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
58+ * DEALINGS IN THE SOFTWARE.
59+ */
60+
61+#include "fsregion.h"
62+
63+namespace compiz {
64+namespace opengl {
65+
66+FullscreenRegion::FullscreenRegion (const CompRect &rect) :
67+ covered (false),
68+ untouched (rect)
69+{
70+}
71+
72+bool
73+FullscreenRegion::isCoveredBy (const CompRegion &region, WinType type)
74+{
75+ bool fullscreen = false;
76+
77+ if (!covered && type == Normal && region == untouched)
78+ {
79+ covered = true;
80+ fullscreen = true;
81+ }
82+
83+ untouched -= region;
84+
85+ return fullscreen;
86+}
87+
88+} // namespace opengl
89+} // namespace compiz
90
91=== added file 'plugins/opengl/src/fsregion/fsregion.h'
92--- plugins/opengl/src/fsregion/fsregion.h 1970-01-01 00:00:00 +0000
93+++ plugins/opengl/src/fsregion/fsregion.h 2012-09-05 03:21:22 +0000
94@@ -0,0 +1,55 @@
95+/*
96+ * Compiz opengl plugin, FullscreenRegion class
97+ *
98+ * Copyright (c) 2012 Canonical Ltd.
99+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
100+ *
101+ * Permission is hereby granted, free of charge, to any person obtaining a
102+ * copy of this software and associated documentation files (the "Software"),
103+ * to deal in the Software without restriction, including without limitation
104+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
105+ * and/or sell copies of the Software, and to permit persons to whom the
106+ * Software is furnished to do so, subject to the following conditions:
107+ *
108+ * The above copyright notice and this permission notice shall be included in
109+ * all copies or substantial portions of the Software.
110+ *
111+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
112+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
113+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
114+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
115+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
116+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
117+ * DEALINGS IN THE SOFTWARE.
118+ */
119+
120+#ifndef __COMPIZ_OPENGL_FSREGION_H
121+#define __COMPIZ_OPENGL_FSREGION_H
122+#include "core/rect.h"
123+#include "core/region.h"
124+
125+namespace compiz {
126+namespace opengl {
127+
128+class FullscreenRegion
129+{
130+public:
131+ typedef enum
132+ {
133+ Normal,
134+ Desktop
135+ } WinType;
136+
137+ FullscreenRegion (const CompRect &rect);
138+
139+ // isCoveredBy is called for windows from TOP to BOTTOM
140+ bool isCoveredBy (const CompRegion &region, WinType type = Normal);
141+
142+private:
143+ bool covered;
144+ CompRegion untouched;
145+};
146+
147+} // namespace opengl
148+} // namespace compiz
149+#endif
150
151=== added directory 'plugins/opengl/src/fsregion/tests'
152=== added file 'plugins/opengl/src/fsregion/tests/CMakeLists.txt'
153--- plugins/opengl/src/fsregion/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
154+++ plugins/opengl/src/fsregion/tests/CMakeLists.txt 2012-09-05 03:21:22 +0000
155@@ -0,0 +1,10 @@
156+include_directories (${GTEST_INCLUDE_DIRS} ..)
157+set (exe "compiz_opengl_test_fsregion")
158+add_executable (${exe} test-fsregion.cpp)
159+target_link_libraries (${exe}
160+ compiz_opengl_fsregion
161+ compiz_core
162+ ${GTEST_BOTH_LIBRARIES}
163+)
164+compiz_discover_tests(${exe} COVERAGE compiz_opengl_fsregion)
165+
166
167=== added file 'plugins/opengl/src/fsregion/tests/test-fsregion.cpp'
168--- plugins/opengl/src/fsregion/tests/test-fsregion.cpp 1970-01-01 00:00:00 +0000
169+++ plugins/opengl/src/fsregion/tests/test-fsregion.cpp 2012-09-05 03:21:22 +0000
170@@ -0,0 +1,121 @@
171+/*
172+ * Compiz opengl plugin, FullscreenRegion class
173+ *
174+ * Copyright (c) 2012 Canonical Ltd.
175+ * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
176+ *
177+ * Permission is hereby granted, free of charge, to any person obtaining a
178+ * copy of this software and associated documentation files (the "Software"),
179+ * to deal in the Software without restriction, including without limitation
180+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
181+ * and/or sell copies of the Software, and to permit persons to whom the
182+ * Software is furnished to do so, subject to the following conditions:
183+ *
184+ * The above copyright notice and this permission notice shall be included in
185+ * all copies or substantial portions of the Software.
186+ *
187+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
188+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
189+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
190+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
192+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
193+ * DEALINGS IN THE SOFTWARE.
194+ */
195+
196+#include "gtest/gtest.h"
197+#include "fsregion.h"
198+
199+using namespace compiz::opengl;
200+
201+TEST (OpenGLFullscreenRegion, NoWindows)
202+{
203+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
204+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768),
205+ FullscreenRegion::Desktop));
206+}
207+
208+TEST (OpenGLFullscreenRegion, OneFullscreen)
209+{
210+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
211+ EXPECT_TRUE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
212+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768),
213+ FullscreenRegion::Desktop));
214+}
215+
216+TEST (OpenGLFullscreenRegion, FullscreenNoDesktop)
217+{
218+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
219+ EXPECT_TRUE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
220+}
221+
222+TEST (OpenGLFullscreenRegion, NormalWindows)
223+{
224+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
225+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (10, 10, 40, 30)));
226+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (20, 20, 50, 20)));
227+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768),
228+ FullscreenRegion::Desktop));
229+}
230+
231+TEST (OpenGLFullscreenRegion, TwoFullscreen)
232+{
233+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
234+ EXPECT_TRUE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
235+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (10, 10, 40, 30)));
236+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (20, 20, 50, 20)));
237+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
238+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768),
239+ FullscreenRegion::Desktop));
240+}
241+
242+TEST (OpenGLFullscreenRegion, Offscreen)
243+{
244+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
245+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (-100, -100, 1, 1)));
246+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (2000, 2000, 123, 456)));
247+ EXPECT_TRUE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
248+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (10, 10, 40, 30)));
249+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (20, 20, 50, 20)));
250+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
251+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768),
252+ FullscreenRegion::Desktop));
253+}
254+
255+TEST (OpenGLFullscreenRegion, CancelFullscreen1)
256+{
257+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
258+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (500, 500, 345, 234)));
259+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
260+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (10, 10, 40, 30)));
261+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (20, 20, 50, 20)));
262+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
263+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768),
264+ FullscreenRegion::Desktop));
265+}
266+
267+TEST (OpenGLFullscreenRegion, CancelFullscreen2)
268+{
269+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
270+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (-100, -100, 1, 1)));
271+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (2000, 2000, 123, 456)));
272+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (500, 500, 345, 234)));
273+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
274+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (10, 10, 40, 30)));
275+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (20, 20, 50, 20)));
276+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
277+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768),
278+ FullscreenRegion::Desktop));
279+}
280+
281+TEST (OpenGLFullscreenRegion, Overflow)
282+{
283+ FullscreenRegion monitor (CompRect (0, 0, 1024, 768));
284+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (10, 10, 40, 30)));
285+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (-10, -10, 1044, 788)));
286+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768)));
287+ EXPECT_FALSE (monitor.isCoveredBy (CompRegion (0, 0, 1024, 768),
288+ FullscreenRegion::Desktop));
289+}
290+
291+
292
293=== modified file 'plugins/opengl/src/paint.cpp'
294--- plugins/opengl/src/paint.cpp 2012-08-30 09:05:04 +0000
295+++ plugins/opengl/src/paint.cpp 2012-09-05 03:21:22 +0000
296@@ -38,9 +38,12 @@
297 #include <opengl/opengl.h>
298
299 #include "privates.h"
300+#include "fsregion/fsregion.h"
301
302 #define DEG2RAD (M_PI / 180.0f)
303
304+using namespace compiz::opengl;
305+
306 GLScreenPaintAttrib defaultScreenPaintAttrib = {
307 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -DEFAULT_Z_CAMERA
308 };
309@@ -241,7 +244,7 @@
310 CompRegion tmpRegion (region);
311 CompWindow *w;
312 GLWindow *gw;
313- int count, windowMask, odMask;
314+ int windowMask, odMask;
315 CompWindow *fullscreenWindow = NULL;
316 bool status, unredirectFS;
317 bool withOffset = false;
318@@ -257,12 +260,10 @@
319 if (mask & PAINT_SCREEN_TRANSFORMED_MASK)
320 {
321 windowMask = PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
322- count = 1;
323 }
324 else
325 {
326 windowMask = 0;
327- count = 0;
328 }
329
330 /*
331@@ -274,6 +275,8 @@
332
333 if (!(mask & PAINT_SCREEN_NO_OCCLUSION_DETECTION_MASK))
334 {
335+ FullscreenRegion fs (*output);
336+
337 /* detect occlusions */
338 for (rit = pl.rbegin (); rit != pl.rend (); ++rit)
339 {
340@@ -336,23 +339,18 @@
341 tmpRegion -= w->region ();
342
343 /* unredirect top most fullscreen windows. */
344- if (count == 0 && unredirectFS)
345+ FullscreenRegion::WinType type =
346+ w->type () & CompWindowTypeDesktopMask ?
347+ FullscreenRegion::Desktop :
348+ FullscreenRegion::Normal;
349+
350+ if (unredirectFS &&
351+ !(mask & PAINT_SCREEN_TRANSFORMED_MASK) &&
352+ fs.isCoveredBy (w->region (), type))
353 {
354- if (w->region () == screen->region () &&
355- tmpRegion.isEmpty ())
356- {
357- fullscreenWindow = w;
358- }
359- else
360- {
361- foreach (CompOutput &o, screen->outputDevs ())
362- if (w->region () == CompRegion (o))
363- fullscreenWindow = w;
364- }
365+ fullscreenWindow = w;
366 }
367 }
368-
369- count++;
370 }
371 }
372

Subscribers

People subscribed via source and target branches