Merge lp:~3v1n0/unity/unity-decorations into lp:unity
- unity-decorations
- Merge into trunk
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Christopher Townsend | ||||||||||||
Approved revision: | no longer in the source branch. | ||||||||||||
Merged at revision: | 3632 | ||||||||||||
Proposed branch: | lp:~3v1n0/unity/unity-decorations | ||||||||||||
Merge into: | lp:unity | ||||||||||||
Diff against target: |
10234 lines (+6824/-1487) 64 files modified
CMakeLists.txt (+5/-0) config.h.cmake (+1/-0) decorations/CMakeLists.txt (+38/-0) decorations/DecoratedWindow.cpp (+654/-0) decorations/DecoratedWindow.h (+73/-0) decorations/DecorationsDataPool.cpp (+153/-0) decorations/DecorationsDataPool.h (+59/-0) decorations/DecorationsEdge.cpp (+137/-0) decorations/DecorationsEdge.h (+64/-0) decorations/DecorationsEdgeBorders.cpp (+99/-0) decorations/DecorationsEdgeBorders.h (+43/-0) decorations/DecorationsGrabEdge.cpp (+102/-0) decorations/DecorationsGrabEdge.h (+53/-0) decorations/DecorationsInputMixer.cpp (+176/-0) decorations/DecorationsInputMixer.h (+66/-0) decorations/DecorationsManager.cpp (+386/-0) decorations/DecorationsManager.h (+74/-0) decorations/DecorationsPriv.h (+165/-0) decorations/DecorationsTitle.cpp (+116/-0) decorations/DecorationsTitle.h (+61/-0) decorations/DecorationsWidgets.cpp (+493/-0) decorations/DecorationsWidgets.h (+190/-0) decorations/DecorationsWindowButton.cpp (+216/-0) decorations/DecorationsWindowButton.h (+58/-0) decorations/pch/decorations_pch.hh (+39/-0) panel/PanelMenuView.cpp (+116/-254) panel/PanelMenuView.h (+9/-14) plugins/unityshell/CMakeLists.txt (+27/-2) plugins/unityshell/src/unityshell.cpp (+291/-412) plugins/unityshell/src/unityshell.h (+29/-17) plugins/unityshell/src/unityshell_glow.cpp (+4/-9) plugins/unityshell/unityshell.xml.in (+69/-1) tests/CMakeLists.txt (+14/-9) tests/decoration_mock_item.h (+88/-0) tests/test_decorations_input_mixer.cpp (+493/-0) tests/test_decorations_widgets.cpp (+512/-0) tests/test_texture_cache.cpp (+16/-1) tests/test_unity_window_style.cpp (+3/-3) unity-shared/CMakeLists.txt (+14/-1) unity-shared/CompizUtils.cpp (+181/-0) unity-shared/CompizUtils.h (+116/-0) unity-shared/DebugDBusInterface.cpp (+6/-1) unity-shared/DecorationStyle.cpp (+640/-0) unity-shared/DecorationStyle.h (+141/-0) unity-shared/Introspectable.cpp (+4/-1) unity-shared/IntrospectionData.cpp (+21/-0) unity-shared/IntrospectionData.h (+8/-0) unity-shared/PanelStyle.cpp (+58/-259) unity-shared/PanelStyle.h (+16/-38) unity-shared/PluginAdapter.cpp (+28/-311) unity-shared/PluginAdapter.h (+0/-22) unity-shared/StandaloneDecorationStyle.cpp (+146/-0) unity-shared/StandaloneWindowManager.cpp (+15/-20) unity-shared/StandaloneWindowManager.h (+2/-3) unity-shared/TextureCache.cpp (+6/-3) unity-shared/TextureCache.h (+3/-2) unity-shared/UnityWindowStyle.cpp (+1/-1) unity-shared/UnityWindowStyle.h (+1/-1) unity-shared/WindowButtonPriv.h (+1/-0) unity-shared/WindowButtons.cpp (+69/-79) unity-shared/WindowButtons.h (+1/-0) unity-shared/WindowManager.h (+4/-5) unity-shared/XWindowManager.cpp (+146/-11) unity-shared/XWindowManager.h (+4/-7) |
||||||||||||
To merge this branch: | bzr merge lp:~3v1n0/unity/unity-decorations | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christopher Townsend | Approve | ||
Brandon Schaefer (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+202582@code.launchpad.net |
Commit message
decorations: added new unity-decorations fully gtk-css-themed inside unity
Description of the change
Added new decorations to unity, inside unity itself instead of depending on the
compiz "decor" plugin and on a decorator (gtk-window-
My mission: «Everything changes, but nothing changes»; so completely new backend,
same results.
- Support for full Gtk3 Theming (https:/
- Improved resizing speed when using "Normal Resize" in compiz
- Removed duplicated textures, IPC between compiz and the decorator
- Anti aliased corners!!
Screenshot:
- Ambiance: http://
- Radiance: http://
Things to do:
- Add right-click window menu support
- Add "force quit" dialog
Not supported:
- Window buttons positions (we want a consistent user experience in unity, that
covers both the windows and the top panel and here the window buttons are, by
design on the top left corner of a window. Always).
- Custom actions on bar clicks (maybe to be supported later)
- Different decorators, just use themes.
This branch needs has a "soft dependency" on lp:~3v1n0/ubuntu-themes/unity-decorations
(for proper theming) and on lp:~3v1n0/compiz/disable-decor-with-unity to disable
decor plugin on settings.
=================
Technical details (use a better diff visualizer for review, like bzr qdiff):
- Added DecorationsManager: that handles all the windows, creates them and
redirect to the proper target the relative events.
- DecoratedWindow: wraps a CompWindow, set the extents, generates the background
textures, the top layout and draws them on screen.
Both DecorationsManager is allocated and controlled by UnityScreen (that redirects
the events to it), while each UnityWindow controls a DecoratedWindow, and redirects
to it the relevant compiz calls.
As for the decoration widgets, since I needed a simple way to handle textures and
to create a simple layout for displaying them, depending on the window size and
positioning, I've decided to write a small "widgets library" used to paint elements
and handle input events. What I called decoration::Item is basically a simple
widget with a geometry and that can be added into a container and managed by it.
Also, I've built an "InputMixer" (event compositor) that has the role to redirect
events to the proper widget that it manages.
So, with these tools, I've built all the widgets that are in a decoration:
- A DecorationsEdge
input-only widgets that care about mouse events, draw the right mouse pointers
and allow to resize and move a window (now the GrabEdge has the same logic of
the PanelGrabArea).
- A Layout containing the window buttons and the window title.
To properly theme the decorations I've built a decoration::Style class that
defines custom gtk-css parameters for an "UnityDecoration" widget that is used
for theming the whole decorations; read the values, caches the relevant settings
and emits signals when theme or font parameters changes. panel::Style has been
rewritten to use decoration::Style as its main source.
Other aspects:
- Removed all the unneeded code for decorating, undecorating and monitoring
decorations from PluginAdapter.
- Moved some XLib-only calls from PluginAdapter to XWindowManager and optimized
GetWindowName using the new GetStringProperty.
- Removing the unneeded code from PanelMenuView that was handling the decorations
and use decoration::Style on it; also remove a lot of unneeded redraws.
- Use decoration::Style for painting fake-decorations in UnityWindow.
- Added CompizUtils to unity-shared-
and functions that are useful for other components that are handling things
with compiz (allows removing duplicated code from UnityWindow as well).
- Added decoration:
- Shadows are based on simple pixmaps that are generated through cairo just
once per session (or when the shadow settings change) and shared by all
the windows.
- Fixed linking of standalone components (and tests) against libunity-
(now the library dir is added to dpath, no need to use LD_LIBRARY_PATH any more).
- Added compiz settings to override theme shadow parameters.
- Improved fallback window buttons (now they're filled with foreground color).
- All the decoration objects support debug introspection for autopilot tests.
- Added unit tests for decoration::Item and InputMixer, more tests to come later.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3891
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Brandon Schaefer (brandontschaefer) wrote : | # |
On a side note this only causes 4 conflicts in my panel high dpi code!
Text conflict in unity-shared/
Text conflict in unity-shared/
Text conflict in unity-shared/
Text conflict in unity-shared/
4 conflicts encountered.
So it shouldn't be to bad to merge those over this. Ill get on that tomorrow after I finish going through this!
Brandon Schaefer (brandontschaefer) wrote : | # |
Ignore what I already sent you! Im at about 7-8k (The test looked good!) What I have so far:
You shouldn't need the ';' but i could be wrong
+ set(UNITY_
----
To make things a but more readable, we should split this function into 2 smaller functions that accept the frame_geo as an arguments:
+void Window:
1, + if (!frame_), should then just call CreateNewFrame(
2, + if (frame_geo_ != frame_geo), UpdateFrameGeo(
+void Window:
+{
+ auto const& input = win_->input();
+ auto const& server = win_->serverGeo
+ nux::Geometry frame_geo(0, 0, server.
+ server.
+
+ if (win_->shaded())
+ frame_geo.height = input.top + input.bottom;
+
+ if (!frame_)
+ CreateNewFrame(
+
+ if (frame_geo_ != frame_geo)
+ UpdateFrameGeo(
+}
Just makes things a bit more readable, imo.
----
An if statement is a bit more readable here.
+ return active() || parent_->scaled() ? mi->active_
+ return active() || parent_->scaled() ? manager_
----
Should be a const pointer, or rather could be a const pointer to const data:
auto const* const texture.
+ auto* texture = ShadowTexture();
+ auto* win = impl_->win_;
----
Are these just for testing? As I see a lot of friend classes...which kind of defeats the purpose of encapsulation. It'll make it hard to track down bugs when all these other classes have access to the private members.... I would much rather provide an access function to these for Read only if thats whats needed. (Vs having read/write of private members.)
+ friend class Manager;
+ friend class Window;
+ friend class Window;
+ friend struct Manager::Impl;
+ friend class Manager;
+ friend struct Window::Impl;
+ friend class InputMixer;
+ friend class Item;
+ friend class decoration:
+ friend class decoration::Window;
+ friend class decoration:
----
Why make a global read/write variable for this? This should be part of the class.
+Display* dpy = nullptr;
----
You can simply this:
+EdgeBorders:
+{
+ items_.
+
+ auto item = std::make_
+ items_[
+
+ item = std::make_
+ items_[
+
+ item = std::make_
+ items_[
+
+ item = std::make_
+ items_[
+
+ item = std::make_
+ items_[
+
+ item = std::make_
+ items_[
+
+ item = std::...
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> You shouldn't need the ';' but i could be wrong
>
> + set(UNITY_
Oh, I thought I had a linking error without it, but it seems to go...
So, I've removed it. This is with gold btw.
> To make things a but more readable, we should split this function into 2 smaller
> functions that accept the frame_geo as an arguements:
>
> +void Window:
>
> 1, + if (!frame_), should then just call CreateNewFrame(
> 2, + if (frame_geo_ != frame_geo), UpdateFrameGeo(
>
> +void Window:
> +{
> + auto const& input = win_->input();
> + auto const& server = win_->serverGeo
> + nux::Geometry frame_geo(0, 0, server.
> + server.
> +
> + if (win_->shaded())
> + frame_geo.height = input.top + input.bottom;
> +
> + if (!frame_)
> + CreateNewFrame(
> +
> + if (frame_geo_ != frame_geo)
> + UpdateFrameGeo(
> +}
>
Ok, sounds good!
I didn't that to keep the frame_geo in the same function without passing it, and
not to reclare input, in UpdateFrameGeo, but it's not really a problem.
I think you're right.
> An if statement is a bit more readable here.
> + return active() || parent_->scaled() ? mi->active_
> + return active() || parent_->scaled() ? manager_
Agreedo, it was smaller at the beginning, then it got bigger :P.
> Should be a const pointer, or rather could be a const pointer to const data:
>
> auto const* const texture.
>
> + auto* texture = ShadowTexture();
>
> + auto* win = impl_->win_;
>
> ----
It doesn't change much, but ok.
> Are these just for testing? As I see a lot of friend classes...which kind of
> defeats the purpose of encaspulation. It'll make it hard to track down bugs when
> all these other classes have access to the private members.... I would much rather
> provide an access funtion to these for Read only if thats whats needed. (Vs having
> read/write of private members.)
>
> + friend class Manager;
Unfortunately I need these to make possible to a Window to access to Impl
functions that are private, but not for manager... I mean, decoration::Manager
is strictly connected to the windows and it has to access to some methods that I
don't want to make visible to everyone... So, unfortunately here we can't use
protected in the way is in java or other languages (access to the members of the
"package"), so I need to use this way... That I don't like, but it's the only
method we have to access to private methods in very limited cases.
For sure the friendship with UnityScreen/
for testing), and I could also remove the friendship with the Impl structs, by
just adding some more "public" methods to them, so that there's no private write
access to the members... That's what already happens in fact, but if we want to
protect more I...
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3898
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3901
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3902
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Brandon Schaefer (brandontschaefer) wrote : | # |
I've been using this branch for about a week now, and its working well!
Would like at lease one more person to go through the code, as this is a larger branch!
Christopher Townsend (townsend) wrote : | # |
This works well for me too and I have nothing to add on the code itself. Well done!
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-01-03 16:26:42 +0000 |
3 | +++ CMakeLists.txt 2014-01-23 15:21:26 +0000 |
4 | @@ -157,6 +157,7 @@ |
5 | set (TESTDATADIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/data") |
6 | |
7 | find_package (PkgConfig) |
8 | +execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} gtk+-3.0 --variable prefix OUTPUT_VARIABLE GTK_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) |
9 | execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} unity --variable lensesdir OUTPUT_VARIABLE LENSES_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) |
10 | execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} indicator3-0.4 --variable indicatordir OUTPUT_VARIABLE INDICATORDIR OUTPUT_STRIP_TRAILING_WHITESPACE) |
11 | execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} indicator3-0.4 --variable iconsdir OUTPUT_VARIABLE INDICATORICONDIR OUTPUT_STRIP_TRAILING_WHITESPACE) |
12 | @@ -253,12 +254,16 @@ |
13 | |
14 | pkg_check_modules (CACHED_UNITY_DEPS REQUIRED ${UNITY_PLUGIN_DEPS}) |
15 | pkg_check_modules (CACHED_UNITY_PRIVATE_DEPS REQUIRED ${UNITY_PROTOCOL_PRIVATE_DEPS}) |
16 | +find_library (UNITY_PROTOCOL_PRIVATE_LIB unity-protocol-private ${CACHED_UNITY_PRIVATE_DEPS_LIBDIR} ${CACHED_UNITY_PRIVATE_DEPS_LIBRARY_DIRS}) |
17 | +set(UNITY_STANDALONE_LADD ${UNITY_STANDALONE_LADD} ${UNITY_PROTOCOL_PRIVATE_LIB}) |
18 | + |
19 | add_subdirectory(unity-shared) |
20 | add_subdirectory(dash) |
21 | add_subdirectory(launcher) |
22 | if (ENABLE_X_SUPPORT) |
23 | add_subdirectory(hud) |
24 | add_subdirectory(panel) |
25 | + add_subdirectory(decorations) |
26 | add_subdirectory(plugins/unityshell) |
27 | add_subdirectory(plugins/networkarearegion) |
28 | add_subdirectory(plugins/unitydialog) |
29 | |
30 | === modified file 'config.h.cmake' |
31 | --- config.h.cmake 2013-07-22 17:11:47 +0000 |
32 | +++ config.h.cmake 2014-01-23 15:21:26 +0000 |
33 | @@ -11,6 +11,7 @@ |
34 | #cmakedefine TESTDATADIR "@TESTDIRDIR@" |
35 | #cmakedefine GETTEXT_PACKAGE "@GETTEXT_PACKAGE@" |
36 | #cmakedefine LENSES_DIR "@LENSES_DIR@" |
37 | +#cmakedefine GTK_PREFIX "@GTK_PREFIX@" |
38 | #ifndef INDICATORDIR |
39 | #cmakedefine INDICATORDIR "@INDICATORDIR@" |
40 | #endif |
41 | |
42 | === added directory 'decorations' |
43 | === added file 'decorations/CMakeLists.txt' |
44 | --- decorations/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
45 | +++ decorations/CMakeLists.txt 2014-01-23 15:21:26 +0000 |
46 | @@ -0,0 +1,38 @@ |
47 | +find_package (PkgConfig) |
48 | +pkg_check_modules (COMPIZ_COMPOSITE REQUIRED "compiz-composite") |
49 | + |
50 | +set (CFLAGS |
51 | + ${COMPIZ_COMPOSITE_CFLAGS} |
52 | + ${CACHED_UNITY_DEPS_CFLAGS} |
53 | + ${CACHED_UNITY_DEPS_CFLAGS_OTHER} |
54 | + ${PIC_FLAGS} |
55 | + ) |
56 | + |
57 | +string (REPLACE ";" " " CFLAGS "${CFLAGS}") |
58 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CFLAGS}") |
59 | +include_directories (.. ../UnityCore ../unity-shared ${CMAKE_BINARY_DIR}) |
60 | + |
61 | +# This makes linker to include library dir in RUNPATH |
62 | +find_library (COMPIZ_COMPOSITE_LIB composite ${COMPIZ_COMPOSITE_LIBDIR}) |
63 | +set (LIBS ${CACHED_UNITY_DEPS_LDFLAGS} ${COMPIZ_COMPOSITE_LIB} ${COMPIZ_COMPOSITE_LDFLAGS} unity-shared-compiz) |
64 | + |
65 | +# |
66 | +# Headers & Sources |
67 | +# |
68 | +set (DECORATION_SOURCES |
69 | + DecorationsManager.cpp |
70 | + DecoratedWindow.cpp |
71 | + DecorationsWidgets.cpp |
72 | + DecorationsWindowButton.cpp |
73 | + DecorationsEdge.cpp |
74 | + DecorationsGrabEdge.cpp |
75 | + DecorationsEdgeBorders.cpp |
76 | + DecorationsTitle.cpp |
77 | + DecorationsInputMixer.cpp |
78 | + DecorationsDataPool.cpp |
79 | + ) |
80 | + |
81 | +add_library (decorations-lib STATIC ${DECORATION_SOURCES}) |
82 | +target_link_libraries (decorations-lib ${LIBS}) |
83 | +add_dependencies (decorations-lib unity-core-${UNITY_API_VERSION} unity-shared-compiz) |
84 | +add_pch(pch/decorations_pch.hh decorations-lib) |
85 | |
86 | === added file 'decorations/DecoratedWindow.cpp' |
87 | --- decorations/DecoratedWindow.cpp 1970-01-01 00:00:00 +0000 |
88 | +++ decorations/DecoratedWindow.cpp 2014-01-23 15:21:26 +0000 |
89 | @@ -0,0 +1,654 @@ |
90 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
91 | +/* |
92 | + * Copyright (C) 2013 Canonical Ltd |
93 | + * |
94 | + * This program is free software: you can redistribute it and/or modify |
95 | + * it under the terms of the GNU General Public License version 3 as |
96 | + * published by the Free Software Foundation. |
97 | + * |
98 | + * This program is distributed in the hope that it will be useful, |
99 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
100 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
101 | + * GNU General Public License for more details. |
102 | + * |
103 | + * You should have received a copy of the GNU General Public License |
104 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
105 | + * |
106 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
107 | + */ |
108 | + |
109 | +#include <NuxCore/Logger.h> |
110 | +#include "DecorationsPriv.h" |
111 | +#include "DecorationsWindowButton.h" |
112 | +#include "DecorationsEdgeBorders.h" |
113 | +#include "DecorationsGrabEdge.h" |
114 | +#include "WindowManager.h" |
115 | + |
116 | +namespace unity |
117 | +{ |
118 | +namespace decoration |
119 | +{ |
120 | +namespace |
121 | +{ |
122 | +DECLARE_LOGGER(logger, "unity.decoration.window"); |
123 | +} |
124 | + |
125 | +Window::Impl::Impl(Window* parent, CompWindow* win) |
126 | + : active(false) |
127 | + , parent_(parent) |
128 | + , win_(win) |
129 | + , cwin_(CompositeWindow::get(win_)) |
130 | + , glwin_(GLWindow::get(win_)) |
131 | + , frame_(0) |
132 | + , dirty_geo_(true) |
133 | +{ |
134 | + active.changed.connect([this] (bool active) { |
135 | + bg_textures_.clear(); |
136 | + if (top_layout_) top_layout_->focused = active; |
137 | + RedrawDecorations(); |
138 | + }); |
139 | + |
140 | + parent->title.SetGetterFunction([this] { |
141 | + if (title_) |
142 | + return title_->text(); |
143 | + |
144 | + if (last_title_.empty()) |
145 | + last_title_ = WindowManager::Default().GetWindowName(win_->id()); |
146 | + |
147 | + return last_title_; |
148 | + }); |
149 | + |
150 | + parent->title.SetSetterFunction([this] (std::string const& new_title) { |
151 | + if (!title_) |
152 | + { |
153 | + if (last_title_ != new_title) |
154 | + { |
155 | + last_title_ = new_title; |
156 | + return true; |
157 | + } |
158 | + |
159 | + return false; |
160 | + } |
161 | + |
162 | + if (new_title == title_->text()) |
163 | + return false; |
164 | + |
165 | + title_->text = new_title; |
166 | + return true; |
167 | + }); |
168 | + |
169 | + parent->scaled.changed.connect(sigc::hide(sigc::mem_fun(this, &Impl::Update))); |
170 | + |
171 | + if (win_->isViewable() || win_->shaded()) |
172 | + Update(); |
173 | +} |
174 | + |
175 | +Window::Impl::~Impl() |
176 | +{ |
177 | + Undecorate(); |
178 | +} |
179 | + |
180 | +void Window::Impl::Update() |
181 | +{ |
182 | + ShouldBeDecorated() ? Decorate() : Undecorate(); |
183 | +} |
184 | + |
185 | +void Window::Impl::Decorate() |
186 | +{ |
187 | + SetupExtents(); |
188 | + UpdateFrame(); |
189 | + SetupWindowControls(); |
190 | +} |
191 | + |
192 | +void Window::Impl::Undecorate() |
193 | +{ |
194 | + UnsetExtents(); |
195 | + UnsetFrame(); |
196 | + CleanupWindowControls(); |
197 | + bg_textures_.clear(); |
198 | +} |
199 | + |
200 | +void Window::Impl::UnsetExtents() |
201 | +{ |
202 | + if (win_->hasUnmapReference()) |
203 | + return; |
204 | + |
205 | + CompWindowExtents empty(0, 0, 0, 0); |
206 | + |
207 | + if (win_->border() != empty || win_->input() != empty) |
208 | + win_->setWindowFrameExtents(&empty, &empty); |
209 | +} |
210 | + |
211 | +void Window::Impl::SetupExtents() |
212 | +{ |
213 | + if (win_->hasUnmapReference()) |
214 | + return; |
215 | + |
216 | + auto const& sb = Style::Get()->Border(); |
217 | + CompWindowExtents border(sb.left, sb.right, sb.top, sb.bottom); |
218 | + |
219 | + auto const& ib = Style::Get()->InputBorder(); |
220 | + CompWindowExtents input(sb.left + ib.left, sb.right + ib.right, |
221 | + sb.top + ib.top, sb.bottom + ib.bottom); |
222 | + |
223 | + if (win_->border() != border || win_->input() != input) |
224 | + win_->setWindowFrameExtents(&border, &input); |
225 | +} |
226 | + |
227 | +void Window::Impl::UnsetFrame() |
228 | +{ |
229 | + if (!frame_) |
230 | + return; |
231 | + |
232 | + XDestroyWindow(screen->dpy(), frame_); |
233 | + framed.emit(false, frame_); |
234 | + frame_ = 0; |
235 | + frame_geo_.Set(0, 0, 0, 0); |
236 | +} |
237 | + |
238 | +void Window::Impl::UpdateFrame() |
239 | +{ |
240 | + auto const& input = win_->input(); |
241 | + auto const& server = win_->serverGeometry(); |
242 | + nux::Geometry frame_geo(0, 0, server.widthIncBorders() + input.left + input.right, |
243 | + server.heightIncBorders() + input.top + input.bottom); |
244 | + |
245 | + if (win_->shaded()) |
246 | + frame_geo.height = input.top + input.bottom; |
247 | + |
248 | + if (!frame_) |
249 | + CreateFrame(frame_geo); |
250 | + |
251 | + if (frame_geo_ != frame_geo) |
252 | + UpdateFrameGeo(frame_geo); |
253 | +} |
254 | + |
255 | +void Window::Impl::CreateFrame(nux::Geometry const& frame_geo) |
256 | +{ |
257 | + /* Since we're reparenting windows here, we need to grab the server |
258 | + * which sucks, but its necessary */ |
259 | + Display* dpy = screen->dpy(); |
260 | + XGrabServer(dpy); |
261 | + |
262 | + XSetWindowAttributes attr; |
263 | + attr.event_mask = StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | |
264 | + EnterWindowMask | LeaveWindowMask | PointerMotionMask; |
265 | + attr.override_redirect = True; |
266 | + |
267 | + auto parent = win_->frame(); |
268 | + frame_ = XCreateWindow(dpy, parent, frame_geo.x, frame_geo.y, |
269 | + frame_geo.width, frame_geo.height, 0, CopyFromParent, |
270 | + InputOnly, CopyFromParent, CWOverrideRedirect | CWEventMask, &attr); |
271 | + |
272 | + if (screen->XShape()) |
273 | + XShapeSelectInput(dpy, frame_, ShapeNotifyMask); |
274 | + |
275 | + XMapWindow(dpy, frame_); |
276 | + framed.emit(true, frame_); |
277 | + |
278 | + XUngrabServer(dpy); |
279 | +} |
280 | + |
281 | +void Window::Impl::UpdateFrameGeo(nux::Geometry const& frame_geo) |
282 | +{ |
283 | + auto const& input = win_->input(); |
284 | + Display* dpy = screen->dpy(); |
285 | + XMoveResizeWindow(dpy, frame_, frame_geo.x, frame_geo.y, frame_geo.width, frame_geo.height); |
286 | + XLowerWindow(dpy, frame_); |
287 | + |
288 | + int i = 0; |
289 | + XRectangle rects[4]; |
290 | + |
291 | + rects[i].x = 0; |
292 | + rects[i].y = 0; |
293 | + rects[i].width = frame_geo.width; |
294 | + rects[i].height = input.top; |
295 | + |
296 | + if (rects[i].width && rects[i].height) |
297 | + i++; |
298 | + |
299 | + rects[i].x = 0; |
300 | + rects[i].y = input.top; |
301 | + rects[i].width = input.left; |
302 | + rects[i].height = frame_geo.height - input.top - input.bottom; |
303 | + |
304 | + if (rects[i].width && rects[i].height) |
305 | + i++; |
306 | + |
307 | + rects[i].x = frame_geo.width - input.right; |
308 | + rects[i].y = input.top; |
309 | + rects[i].width = input.right; |
310 | + rects[i].height = frame_geo.height - input.top - input.bottom; |
311 | + |
312 | + if (rects[i].width && rects[i].height) |
313 | + i++; |
314 | + |
315 | + rects[i].x = 0; |
316 | + rects[i].y = frame_geo.height - input.bottom; |
317 | + rects[i].width = frame_geo.width; |
318 | + rects[i].height = input.bottom; |
319 | + |
320 | + if (rects[i].width && rects[i].height) |
321 | + i++; |
322 | + |
323 | + XShapeCombineRectangles(dpy, frame_, ShapeBounding, 0, 0, rects, i, ShapeSet, YXBanded); |
324 | + |
325 | + frame_geo_ = frame_geo; |
326 | + SyncXShapeWithFrameRegion(); |
327 | +} |
328 | + |
329 | +void Window::Impl::SyncXShapeWithFrameRegion() |
330 | +{ |
331 | + frame_region_ = CompRegion(); |
332 | + |
333 | + int n = 0; |
334 | + int order = 0; |
335 | + XRectangle *rects = nullptr; |
336 | + |
337 | + rects = XShapeGetRectangles(screen->dpy(), frame_, ShapeInput, &n, &order); |
338 | + if (!rects) |
339 | + return; |
340 | + |
341 | + for (int i = 0; i < n; ++i) |
342 | + { |
343 | + auto& rect = rects[i]; |
344 | + frame_region_ += CompRegion(rect.x, rect.y, rect.width, rect.height); |
345 | + } |
346 | + |
347 | + XFree(rects); |
348 | + |
349 | + win_->updateFrameRegion(); |
350 | +} |
351 | + |
352 | +void Window::Impl::SetupWindowControls() |
353 | +{ |
354 | + if (top_layout_) |
355 | + return; |
356 | + |
357 | + auto const& style = Style::Get(); |
358 | + theme_changed_ = style->theme.changed.connect([this] (std::string const&) { |
359 | + Undecorate(); |
360 | + Decorate(); |
361 | + }); |
362 | + |
363 | + input_mixer_ = std::make_shared<InputMixer>(); |
364 | + |
365 | + if (win_->actions() & CompWindowActionResizeMask) |
366 | + edge_borders_ = std::make_shared<EdgeBorders>(win_); |
367 | + else if (win_->actions() & CompWindowActionMoveMask) |
368 | + edge_borders_ = std::make_shared<GrabEdge>(win_); |
369 | + else |
370 | + edge_borders_.reset(); |
371 | + |
372 | + input_mixer_->PushToFront(edge_borders_); |
373 | + |
374 | + auto padding = style->Padding(Side::TOP); |
375 | + top_layout_ = std::make_shared<Layout>(); |
376 | + top_layout_->left_padding = padding.left; |
377 | + top_layout_->right_padding = padding.right; |
378 | + top_layout_->top_padding = padding.top; |
379 | + top_layout_->focused = active(); |
380 | + |
381 | + if (win_->actions() & CompWindowActionCloseMask) |
382 | + top_layout_->Append(std::make_shared<WindowButton>(win_, WindowButtonType::CLOSE)); |
383 | + |
384 | + if (win_->actions() & CompWindowActionMinimizeMask) |
385 | + top_layout_->Append(std::make_shared<WindowButton>(win_, WindowButtonType::MINIMIZE)); |
386 | + |
387 | + if (win_->actions() & (CompWindowActionMaximizeHorzMask|CompWindowActionMaximizeVertMask)) |
388 | + top_layout_->Append(std::make_shared<WindowButton>(win_, WindowButtonType::MAXIMIZE)); |
389 | + |
390 | + title_ = std::make_shared<Title>(); |
391 | + title_->text = last_title_.empty() ? WindowManager::Default().GetWindowName(win_->id()) : last_title_; |
392 | + title_->sensitive = false; |
393 | + last_title_.clear(); |
394 | + |
395 | + auto title_layout = std::make_shared<Layout>(); |
396 | + title_layout->left_padding = style->TitleIndent(); |
397 | + title_layout->Append(title_); |
398 | + top_layout_->Append(title_layout); |
399 | + |
400 | + input_mixer_->PushToFront(top_layout_); |
401 | + |
402 | + RedrawDecorations(); |
403 | +} |
404 | + |
405 | +void Window::Impl::CleanupWindowControls() |
406 | +{ |
407 | + if (title_) |
408 | + last_title_ = title_->text(); |
409 | + |
410 | + theme_changed_->disconnect(); |
411 | + title_.reset(); |
412 | + top_layout_.reset(); |
413 | + input_mixer_.reset(); |
414 | + edge_borders_.reset(); |
415 | +} |
416 | + |
417 | +bool Window::Impl::IsMaximized() const |
418 | +{ |
419 | + return (win_->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE; |
420 | +} |
421 | + |
422 | +bool Window::Impl::ShadowDecorated() const |
423 | +{ |
424 | + if (!parent_->scaled() && IsMaximized()) |
425 | + return false; |
426 | + |
427 | + if (!cu::IsWindowShadowDecorable(win_)) |
428 | + return false; |
429 | + |
430 | + return true; |
431 | +} |
432 | + |
433 | +bool Window::Impl::FullyDecorated() const |
434 | +{ |
435 | + if (!parent_->scaled() && IsMaximized()) |
436 | + return false; |
437 | + |
438 | + if (!cu::IsWindowFullyDecorable(win_)) |
439 | + return false; |
440 | + |
441 | + return true; |
442 | +} |
443 | + |
444 | +bool Window::Impl::ShouldBeDecorated() const |
445 | +{ |
446 | + return (win_->frame() || win_->hasUnmapReference()) && FullyDecorated(); |
447 | +} |
448 | + |
449 | +GLTexture* Window::Impl::ShadowTexture() const |
450 | +{ |
451 | + auto const& mi = manager_->impl_; |
452 | + if (active() || parent_->scaled()) |
453 | + return mi->active_shadow_pixmap_->texture(); |
454 | + |
455 | + return mi->inactive_shadow_pixmap_->texture(); |
456 | +} |
457 | + |
458 | +unsigned Window::Impl::ShadowRadius() const |
459 | +{ |
460 | + if (active() || parent_->scaled()) |
461 | + return manager_->active_shadow_radius(); |
462 | + |
463 | + return manager_->inactive_shadow_radius(); |
464 | +} |
465 | + |
466 | +void Window::Impl::RenderDecorationTexture(Side s, nux::Geometry const& geo) |
467 | +{ |
468 | + auto& deco_tex = bg_textures_[unsigned(s)]; |
469 | + |
470 | + if (deco_tex.quad.box.width() != geo.width || deco_tex.quad.box.height() != geo.height) |
471 | + { |
472 | + cu::CairoContext ctx(geo.width, geo.height); |
473 | + auto ws = active() ? WidgetState::NORMAL : WidgetState::BACKDROP; |
474 | + Style::Get()->DrawSide(s, ws, ctx, geo.width, geo.height); |
475 | + deco_tex.SetTexture(ctx); |
476 | + } |
477 | + |
478 | + deco_tex.SetCoords(geo.x, geo.y); |
479 | +} |
480 | + |
481 | +void Window::Impl::UpdateDecorationTextures() |
482 | +{ |
483 | + if (!FullyDecorated()) |
484 | + { |
485 | + bg_textures_.clear(); |
486 | + return; |
487 | + } |
488 | + |
489 | + auto const& geo = win_->borderRect(); |
490 | + auto const& input = win_->inputRect(); |
491 | + auto const& border = win_->border(); |
492 | + |
493 | + bg_textures_.resize(4); |
494 | + RenderDecorationTexture(Side::TOP, {geo.x(), geo.y(), geo.width(), border.top}); |
495 | + RenderDecorationTexture(Side::LEFT, {geo.x(), geo.y() + border.top, border.left, geo.height() - border.top - border.bottom}); |
496 | + RenderDecorationTexture(Side::RIGHT, {geo.x2() - border.right, geo.y() + border.top, border.right, geo.height() - border.top - border.bottom}); |
497 | + RenderDecorationTexture(Side::BOTTOM, {geo.x(), geo.y2() - border.bottom, geo.width(), border.bottom}); |
498 | + |
499 | + top_layout_->SetCoords(geo.x(), geo.y()); |
500 | + top_layout_->SetSize(geo.width(), border.top); |
501 | + |
502 | + if (edge_borders_) |
503 | + { |
504 | + edge_borders_->SetCoords(input.x(), input.y()); |
505 | + edge_borders_->SetSize(input.width(), input.height()); |
506 | + } |
507 | +} |
508 | + |
509 | +void Window::Impl::ComputeShadowQuads() |
510 | +{ |
511 | + if (!ShadowDecorated()) |
512 | + return; |
513 | + |
514 | + const auto* texture = ShadowTexture(); |
515 | + |
516 | + if (!texture || !texture->width() || !texture->height()) |
517 | + return; |
518 | + |
519 | + Quads& quads = shadow_quads_; |
520 | + auto const& tex_matrix = texture->matrix(); |
521 | + auto const& border = win_->borderRect(); |
522 | + auto const& offset = manager_->shadow_offset(); |
523 | + int texture_offset = ShadowRadius() * 2; |
524 | + |
525 | + /* Top left quad */ |
526 | + auto* quad = &quads[Quads::Pos::TOP_LEFT]; |
527 | + quad->box.setGeometry(border.x() + offset.x - texture_offset, |
528 | + border.y() + offset.y - texture_offset, |
529 | + border.width() + offset.x + texture_offset * 2 - texture->width(), |
530 | + border.height() + offset.y + texture_offset * 2 - texture->height()); |
531 | + |
532 | + quad->matrix = tex_matrix; |
533 | + quad->matrix.x0 = 0.0f - COMP_TEX_COORD_X(quad->matrix, quad->box.x1()); |
534 | + quad->matrix.y0 = 0.0f - COMP_TEX_COORD_Y(quad->matrix, quad->box.y1()); |
535 | + |
536 | + /* Top right quad */ |
537 | + quad = &quads[Quads::Pos::TOP_RIGHT]; |
538 | + quad->box.setGeometry(quads[Quads::Pos::TOP_LEFT].box.x2(), |
539 | + quads[Quads::Pos::TOP_LEFT].box.y1(), |
540 | + texture->width(), |
541 | + quads[Quads::Pos::TOP_LEFT].box.height()); |
542 | + |
543 | + quad->matrix = tex_matrix; |
544 | + quad->matrix.xx = -1.0f / texture->width(); |
545 | + quad->matrix.x0 = 1.0f - COMP_TEX_COORD_X(quad->matrix, quad->box.x1()); |
546 | + quad->matrix.y0 = 0.0f - COMP_TEX_COORD_Y(quad->matrix, quad->box.y1()); |
547 | + |
548 | + /* Bottom left */ |
549 | + quad = &quads[Quads::Pos::BOTTOM_LEFT]; |
550 | + quad->box.setGeometry(quads[Quads::Pos::TOP_LEFT].box.x1(), |
551 | + quads[Quads::Pos::TOP_LEFT].box.y2(), |
552 | + quads[Quads::Pos::TOP_LEFT].box.width(), |
553 | + texture->height()); |
554 | + |
555 | + quad->matrix = tex_matrix; |
556 | + quad->matrix.yy = -1.0f / texture->height(); |
557 | + quad->matrix.x0 = 0.0f - COMP_TEX_COORD_X(quad->matrix, quad->box.x1()); |
558 | + quad->matrix.y0 = 1.0f - COMP_TEX_COORD_Y(quad->matrix, quad->box.y1()); |
559 | + |
560 | + /* Bottom right */ |
561 | + quad = &quads[Quads::Pos::BOTTOM_RIGHT]; |
562 | + quad->box.setGeometry(quads[Quads::Pos::BOTTOM_LEFT].box.x2(), |
563 | + quads[Quads::Pos::TOP_RIGHT].box.y2(), |
564 | + texture->width(), |
565 | + texture->height()); |
566 | + |
567 | + quad->matrix = tex_matrix; |
568 | + quad->matrix.xx = -1.0f / texture->width(); |
569 | + quad->matrix.yy = -1.0f / texture->height(); |
570 | + quad->matrix.x0 = 1.0f - COMP_TEX_COORD_X(quad->matrix, quad->box.x1()); |
571 | + quad->matrix.y0 = 1.0f - COMP_TEX_COORD_Y(quad->matrix, quad->box.y1()); |
572 | + |
573 | + /* Fix the quads if the texture is actually bigger than the area */ |
574 | + if (texture->width() > border.width()) |
575 | + { |
576 | + int half = win_->x() + win_->width() / 2.0f; |
577 | + quads[Quads::Pos::TOP_LEFT].box.setRight(half); |
578 | + quads[Quads::Pos::TOP_RIGHT].box.setLeft(half); |
579 | + quads[Quads::Pos::BOTTOM_LEFT].box.setRight(half); |
580 | + quads[Quads::Pos::BOTTOM_RIGHT].box.setLeft(half); |
581 | + } |
582 | + |
583 | + if (texture->height() > border.height()) |
584 | + { |
585 | + int half = win_->y() + win_->height() / 2.0f; |
586 | + quads[Quads::Pos::TOP_LEFT].box.setBottom(half); |
587 | + quads[Quads::Pos::TOP_RIGHT].box.setBottom(half); |
588 | + quads[Quads::Pos::BOTTOM_LEFT].box.setTop(half); |
589 | + quads[Quads::Pos::BOTTOM_RIGHT].box.setTop(half); |
590 | + } |
591 | + |
592 | + CompRect shadows_rect; |
593 | + shadows_rect.setLeft(quads[Quads::Pos::TOP_LEFT].box.x1()); |
594 | + shadows_rect.setTop(quads[Quads::Pos::TOP_LEFT].box.y1()); |
595 | + shadows_rect.setRight(quads[Quads::Pos::TOP_RIGHT].box.x2()); |
596 | + shadows_rect.setBottom(quads[Quads::Pos::BOTTOM_LEFT].box.y2()); |
597 | + |
598 | + if (shadows_rect != last_shadow_rect_) |
599 | + { |
600 | + last_shadow_rect_ = shadows_rect; |
601 | + win_->updateWindowOutputExtents(); |
602 | + } |
603 | +} |
604 | + |
605 | +void Window::Impl::Draw(GLMatrix const& transformation, |
606 | + GLWindowPaintAttrib const& attrib, |
607 | + CompRegion const& region, unsigned mask) |
608 | +{ |
609 | + if (!ShadowDecorated()) |
610 | + return; |
611 | + |
612 | + auto const& clip_region = (mask & PAINT_WINDOW_TRANSFORMED_MASK) ? infiniteRegion : region; |
613 | + mask |= PAINT_WINDOW_BLEND_MASK; |
614 | + |
615 | + if (dirty_geo_) |
616 | + parent_->UpdateDecorationPosition(); |
617 | + |
618 | + glwin_->vertexBuffer()->begin(); |
619 | + |
620 | + for (unsigned i = 0; i < shadow_quads_.size(); ++i) |
621 | + { |
622 | + auto& quad = shadow_quads_[Quads::Pos(i)]; |
623 | + glwin_->glAddGeometry({quad.matrix}, CompRegion(quad.box) - win_->region(), clip_region); |
624 | + } |
625 | + |
626 | + if (glwin_->vertexBuffer()->end()) |
627 | + glwin_->glDrawTexture(ShadowTexture(), transformation, attrib, mask); |
628 | + |
629 | + for (auto const& dtex : bg_textures_) |
630 | + { |
631 | + glwin_->vertexBuffer()->begin(); |
632 | + glwin_->glAddGeometry({dtex.quad.matrix}, dtex.quad.box, clip_region); |
633 | + |
634 | + if (glwin_->vertexBuffer()->end()) |
635 | + glwin_->glDrawTexture(dtex, transformation, attrib, mask); |
636 | + } |
637 | + |
638 | + if (top_layout_) |
639 | + top_layout_->Draw(glwin_, transformation, attrib, region, mask); |
640 | +} |
641 | + |
642 | +void Window::Impl::RedrawDecorations() |
643 | +{ |
644 | + dirty_geo_ = true; |
645 | + cwin_->damageOutputExtents(); |
646 | +} |
647 | + |
648 | +// Public APIs |
649 | + |
650 | +Window::Window(CompWindow* cwin) |
651 | + : scaled(false) |
652 | + , impl_(new Impl(this, cwin)) |
653 | +{} |
654 | + |
655 | +void Window::Update() |
656 | +{ |
657 | + impl_->Update(); |
658 | +} |
659 | + |
660 | +void Window::UpdateFrameRegion(CompRegion& r) |
661 | +{ |
662 | + if (impl_->frame_region_.isEmpty()) |
663 | + return; |
664 | + |
665 | + auto const& geo = impl_->win_->geometry(); |
666 | + auto const& input = impl_->win_->input(); |
667 | + |
668 | + r += impl_->frame_region_.translated(geo.x() - input.left, geo.y() - input.top); |
669 | + UpdateDecorationPositionDelayed(); |
670 | +} |
671 | + |
672 | +void Window::UpdateOutputExtents(compiz::window::extents::Extents& output) |
673 | +{ |
674 | + const auto* win = impl_->win_; |
675 | + auto const& shadow = impl_->last_shadow_rect_; |
676 | + output.top = std::max(output.top, win->y() - shadow.y1()); |
677 | + output.left = std::max(output.left, win->x() - shadow.x1()); |
678 | + output.right = std::max(output.right, shadow.x2() - win->width() - win->x()); |
679 | + output.bottom = std::max(output.bottom, shadow.y2() - win->height() - win->y()); |
680 | +} |
681 | + |
682 | +void Window::Draw(GLMatrix const& matrix, GLWindowPaintAttrib const& attrib, |
683 | + CompRegion const& region, unsigned mask) |
684 | +{ |
685 | + impl_->Draw(matrix, attrib, region, mask); |
686 | +} |
687 | + |
688 | +void Window::Undecorate() |
689 | +{ |
690 | + impl_->Undecorate(); |
691 | +} |
692 | + |
693 | +void Window::UpdateDecorationPosition() |
694 | +{ |
695 | + impl_->ComputeShadowQuads(); |
696 | + impl_->UpdateDecorationTextures(); |
697 | + impl_->dirty_geo_ = false; |
698 | +} |
699 | + |
700 | +void Window::UpdateDecorationPositionDelayed() |
701 | +{ |
702 | + impl_->dirty_geo_ = true; |
703 | +} |
704 | + |
705 | +std::string Window::GetName() const |
706 | +{ |
707 | + return "DecoratedWindow"; |
708 | +} |
709 | + |
710 | +void Window::AddProperties(debug::IntrospectionData& data) |
711 | +{ |
712 | + data.add(impl_->win_->borderRect()) |
713 | + .add("input_geo", impl_->win_->inputRect()) |
714 | + .add("content_geo", impl_->win_->region().boundingRect()) |
715 | + .add("title", title()) |
716 | + .add("active", impl_->active()) |
717 | + .add("scaled", scaled()) |
718 | + .add("xid", impl_->win_->id()) |
719 | + .add("fully_decorable", cu::IsWindowFullyDecorable(impl_->win_)) |
720 | + .add("shadow_decorable", cu::IsWindowShadowDecorable(impl_->win_)) |
721 | + .add("shadow_decorated", impl_->ShadowDecorated()) |
722 | + .add("fully_decorated", impl_->FullyDecorated()) |
723 | + .add("should_be_decorated", impl_->ShouldBeDecorated()) |
724 | + .add("framed", (impl_->frame_ != 0)) |
725 | + .add("frame_geo", impl_->frame_geo_) |
726 | + .add("shadow_rect", impl_->last_shadow_rect_) |
727 | + .add("maximized", impl_->IsMaximized()) |
728 | + .add("v_maximized", (impl_->win_->state() & CompWindowStateMaximizedVertMask)) |
729 | + .add("h_maximized", (impl_->win_->state() & CompWindowStateMaximizedHorzMask)) |
730 | + .add("resizable", (impl_->win_->actions() & CompWindowActionResizeMask)) |
731 | + .add("movable", (impl_->win_->actions() & CompWindowActionMoveMask)) |
732 | + .add("closable", (impl_->win_->actions() & CompWindowActionCloseMask)) |
733 | + .add("minimizable", (impl_->win_->actions() & CompWindowActionMinimizeMask)) |
734 | + .add("maximizable", (impl_->win_->actions() & (CompWindowActionMaximizeHorzMask|CompWindowActionMaximizeVertMask))); |
735 | +} |
736 | + |
737 | +debug::Introspectable::IntrospectableList Window::GetIntrospectableChildren() |
738 | +{ |
739 | + return IntrospectableList({impl_->top_layout_.get(), impl_->edge_borders_.get()}); |
740 | +} |
741 | + |
742 | +} // decoration namespace |
743 | +} // unity namespace |
744 | |
745 | === added file 'decorations/DecoratedWindow.h' |
746 | --- decorations/DecoratedWindow.h 1970-01-01 00:00:00 +0000 |
747 | +++ decorations/DecoratedWindow.h 2014-01-23 15:21:26 +0000 |
748 | @@ -0,0 +1,73 @@ |
749 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
750 | +/* |
751 | + * Copyright (C) 2013 Canonical Ltd |
752 | + * |
753 | + * This program is free software: you can redistribute it and/or modify |
754 | + * it under the terms of the GNU General Public License version 3 as |
755 | + * published by the Free Software Foundation. |
756 | + * |
757 | + * This program is distributed in the hope that it will be useful, |
758 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
759 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
760 | + * GNU General Public License for more details. |
761 | + * |
762 | + * You should have received a copy of the GNU General Public License |
763 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
764 | + * |
765 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
766 | + */ |
767 | + |
768 | +#ifndef UNITY_DECORATED_WINDOW |
769 | +#define UNITY_DECORATED_WINDOW |
770 | + |
771 | +#include "Introspectable.h" |
772 | +#include <memory> |
773 | + |
774 | +class CompRegion; |
775 | +class CompWindow; |
776 | +class GLWindowPaintAttrib; |
777 | +class GLMatrix; |
778 | +namespace compiz { namespace window { namespace extents { class Extents; } } } |
779 | + |
780 | +namespace unity |
781 | +{ |
782 | +namespace decoration |
783 | +{ |
784 | +class Window : public debug::Introspectable |
785 | +{ |
786 | +public: |
787 | + typedef std::shared_ptr<Window> Ptr; |
788 | + |
789 | + Window(CompWindow*); |
790 | + virtual ~Window() = default; |
791 | + |
792 | + nux::RWProperty<std::string> title; |
793 | + nux::Property<bool> scaled; |
794 | + |
795 | + void Update(); |
796 | + void Undecorate(); |
797 | + void UpdateDecorationPosition(); |
798 | + void UpdateDecorationPositionDelayed(); |
799 | + void UpdateFrameRegion(CompRegion&); |
800 | + void UpdateOutputExtents(compiz::window::extents::Extents&); |
801 | + void Draw(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); |
802 | + |
803 | +protected: |
804 | + std::string GetName() const; |
805 | + void AddProperties(debug::IntrospectionData&); |
806 | + IntrospectableList GetIntrospectableChildren(); |
807 | + |
808 | +private: |
809 | + Window(Window const&) = delete; |
810 | + Window& operator=(Window const&) = delete; |
811 | + |
812 | + friend class Manager; |
813 | + |
814 | + struct Impl; |
815 | + std::unique_ptr<Impl> impl_; |
816 | +}; |
817 | + |
818 | +} // decoration namespace |
819 | +} // unity namespace |
820 | + |
821 | +#endif |
822 | |
823 | === added file 'decorations/DecorationsDataPool.cpp' |
824 | --- decorations/DecorationsDataPool.cpp 1970-01-01 00:00:00 +0000 |
825 | +++ decorations/DecorationsDataPool.cpp 2014-01-23 15:21:26 +0000 |
826 | @@ -0,0 +1,153 @@ |
827 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
828 | +/* |
829 | + * Copyright (C) 2013 Canonical Ltd |
830 | + * |
831 | + * This program is free software: you can redistribute it and/or modify |
832 | + * it under the terms of the GNU General Public License version 3 as |
833 | + * published by the Free Software Foundation. |
834 | + * |
835 | + * This program is distributed in the hope that it will be useful, |
836 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
837 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
838 | + * GNU General Public License for more details. |
839 | + * |
840 | + * You should have received a copy of the GNU General Public License |
841 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
842 | + * |
843 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
844 | + */ |
845 | + |
846 | +#include <NuxCore/Logger.h> |
847 | +#include <X11/cursorfont.h> |
848 | +#include <sigc++/adaptors/hide.h> |
849 | +#include "glow_texture.h" |
850 | +#include "DecorationsDataPool.h" |
851 | + |
852 | +namespace unity |
853 | +{ |
854 | +namespace decoration |
855 | +{ |
856 | +namespace |
857 | +{ |
858 | +DECLARE_LOGGER(logger, "unity.decoration.datapool"); |
859 | +const std::string PLUGIN_NAME = "unityshell"; |
860 | +const int BUTTONS_SIZE = 16; |
861 | +const int BUTTONS_PADDING = 1; |
862 | +const cu::SimpleTexture::Ptr EMPTY_BUTTON; |
863 | +Display* dpy = nullptr; |
864 | + |
865 | +unsigned EdgeTypeToCursorShape(Edge::Type type) |
866 | +{ |
867 | + switch (type) |
868 | + { |
869 | + case Edge::Type::TOP: |
870 | + return XC_top_side; |
871 | + case Edge::Type::TOP_LEFT: |
872 | + return XC_top_left_corner; |
873 | + case Edge::Type::TOP_RIGHT: |
874 | + return XC_top_right_corner; |
875 | + case Edge::Type::LEFT: |
876 | + return XC_left_side; |
877 | + case Edge::Type::RIGHT: |
878 | + return XC_right_side; |
879 | + case Edge::Type::BOTTOM: |
880 | + return XC_bottom_side; |
881 | + case Edge::Type::BOTTOM_LEFT: |
882 | + return XC_bottom_left_corner; |
883 | + case Edge::Type::BOTTOM_RIGHT: |
884 | + return XC_bottom_right_corner; |
885 | + default: |
886 | + return XC_left_ptr; |
887 | + } |
888 | +} |
889 | + |
890 | +} |
891 | + |
892 | +DataPool::DataPool() |
893 | +{ |
894 | + dpy = screen->dpy(); |
895 | + SetupCursors(); |
896 | + SetupTextures(); |
897 | + |
898 | + auto cb = sigc::hide(sigc::mem_fun(this, &DataPool::SetupTextures)); |
899 | + Style::Get()->theme.changed.connect(cb); |
900 | +} |
901 | + |
902 | +DataPool::~DataPool() |
903 | +{ |
904 | + for (auto cursor : edge_cursors_) |
905 | + XFreeCursor(dpy, cursor); |
906 | +} |
907 | + |
908 | +DataPool::Ptr const& DataPool::Get() |
909 | +{ |
910 | + static DataPool::Ptr data_pool(new DataPool()); |
911 | + return data_pool; |
912 | +} |
913 | + |
914 | +void DataPool::SetupCursors() |
915 | +{ |
916 | + for (unsigned c = 0; c < edge_cursors_.size(); ++c) |
917 | + edge_cursors_[c] = XCreateFontCursor(dpy, EdgeTypeToCursorShape(Edge::Type(c))); |
918 | +} |
919 | + |
920 | +Cursor DataPool::EdgeCursor(Edge::Type type) const |
921 | +{ |
922 | + return edge_cursors_[unsigned(type)]; |
923 | +} |
924 | + |
925 | +void DataPool::SetupTextures() |
926 | +{ |
927 | + CompSize size; |
928 | + CompString plugin_name(PLUGIN_NAME); |
929 | + auto const& style = Style::Get(); |
930 | + |
931 | + for (unsigned button = 0; button < window_buttons_.size(); ++button) |
932 | + { |
933 | + for (unsigned state = 0; state < window_buttons_[button].size(); ++state) |
934 | + { |
935 | + auto file = style->WindowButtonFile(WindowButtonType(button), WidgetState(state)); |
936 | + auto const& tex_list = GLTexture::readImageToTexture(file, plugin_name, size); |
937 | + |
938 | + if (!tex_list.empty()) |
939 | + { |
940 | + LOG_DEBUG(logger) << "Loading texture " << file; |
941 | + window_buttons_[button][state] = std::make_shared<cu::SimpleTexture>(tex_list); |
942 | + } |
943 | + else |
944 | + { |
945 | + LOG_WARN(logger) << "Impossible to load local button texture file; " |
946 | + << "falling back to cairo generated one"; |
947 | + |
948 | + cu::CairoContext ctx(BUTTONS_SIZE + BUTTONS_PADDING*2, BUTTONS_SIZE + BUTTONS_PADDING*2); |
949 | + cairo_translate(ctx, BUTTONS_PADDING, BUTTONS_PADDING); |
950 | + style->DrawWindowButton(WindowButtonType(button), WidgetState(state), ctx, BUTTONS_SIZE, BUTTONS_SIZE); |
951 | + window_buttons_[button][state] = ctx; |
952 | + } |
953 | + } |
954 | + } |
955 | + |
956 | + CompSize glow_size(texture::GLOW_SIZE, texture::GLOW_SIZE); |
957 | + glow_texture_ = std::make_shared<cu::SimpleTexture>(GLTexture::imageDataToTexture(texture::GLOW, glow_size, GL_RGBA, GL_UNSIGNED_BYTE)); |
958 | +} |
959 | + |
960 | +cu::SimpleTexture::Ptr const& DataPool::GlowTexture() const |
961 | +{ |
962 | + return glow_texture_; |
963 | +} |
964 | + |
965 | +cu::SimpleTexture::Ptr const& DataPool::ButtonTexture(WindowButtonType wbt, WidgetState ws) const |
966 | +{ |
967 | + if (wbt >= WindowButtonType::Size || ws >= WidgetState::Size) |
968 | + { |
969 | + LOG_ERROR(logger) << "It has been requested an invalid button texture " |
970 | + << "WindowButtonType: " << unsigned(wbt) << ", WidgetState: " |
971 | + << unsigned(ws); |
972 | + return EMPTY_BUTTON; |
973 | + } |
974 | + |
975 | + return window_buttons_[unsigned(wbt)][unsigned(ws)]; |
976 | +} |
977 | + |
978 | +} // decoration namespace |
979 | +} // unity namespace |
980 | |
981 | === added file 'decorations/DecorationsDataPool.h' |
982 | --- decorations/DecorationsDataPool.h 1970-01-01 00:00:00 +0000 |
983 | +++ decorations/DecorationsDataPool.h 2014-01-23 15:21:26 +0000 |
984 | @@ -0,0 +1,59 @@ |
985 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
986 | +/* |
987 | + * Copyright (C) 2013 Canonical Ltd |
988 | + * |
989 | + * This program is free software: you can redistribute it and/or modify |
990 | + * it under the terms of the GNU General Public License version 3 as |
991 | + * published by the Free Software Foundation. |
992 | + * |
993 | + * This program is distributed in the hope that it will be useful, |
994 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
995 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
996 | + * GNU General Public License for more details. |
997 | + * |
998 | + * You should have received a copy of the GNU General Public License |
999 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1000 | + * |
1001 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1002 | + */ |
1003 | + |
1004 | +#ifndef UNITY_DECORATIONS_DATA_POOL |
1005 | +#define UNITY_DECORATIONS_DATA_POOL |
1006 | + |
1007 | +#include "DecorationStyle.h" |
1008 | +#include "DecorationsEdge.h" |
1009 | + |
1010 | +namespace unity |
1011 | +{ |
1012 | +namespace decoration |
1013 | +{ |
1014 | + |
1015 | +class DataPool : public sigc::trackable |
1016 | +{ |
1017 | +public: |
1018 | + typedef std::shared_ptr<DataPool> Ptr; |
1019 | + |
1020 | + static DataPool::Ptr const& Get(); |
1021 | + virtual ~DataPool(); |
1022 | + |
1023 | + Cursor EdgeCursor(Edge::Type) const; |
1024 | + cu::SimpleTexture::Ptr const& GlowTexture() const; |
1025 | + cu::SimpleTexture::Ptr const& ButtonTexture(WindowButtonType, WidgetState) const; |
1026 | + |
1027 | +private: |
1028 | + DataPool(); |
1029 | + DataPool(DataPool const&) = delete; |
1030 | + DataPool& operator=(DataPool const&) = delete; |
1031 | + |
1032 | + void SetupCursors(); |
1033 | + void SetupTextures(); |
1034 | + |
1035 | + std::array<Cursor, size_t(Edge::Type::Size)> edge_cursors_; |
1036 | + cu::SimpleTexture::Ptr glow_texture_; |
1037 | + std::array<std::array<cu::SimpleTexture::Ptr, size_t(WidgetState::Size)>, size_t(WindowButtonType::Size)> window_buttons_; |
1038 | +}; |
1039 | + |
1040 | +} // decoration namespace |
1041 | +} // unity namespace |
1042 | + |
1043 | +#endif // UNITY_DECORATIONS_DATA_POOL |
1044 | |
1045 | === added file 'decorations/DecorationsEdge.cpp' |
1046 | --- decorations/DecorationsEdge.cpp 1970-01-01 00:00:00 +0000 |
1047 | +++ decorations/DecorationsEdge.cpp 2014-01-23 15:21:26 +0000 |
1048 | @@ -0,0 +1,137 @@ |
1049 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1050 | +/* |
1051 | + * Copyright (C) 2013 Canonical Ltd |
1052 | + * |
1053 | + * This program is free software: you can redistribute it and/or modify |
1054 | + * it under the terms of the GNU General Public License version 3 as |
1055 | + * published by the Free Software Foundation. |
1056 | + * |
1057 | + * This program is distributed in the hope that it will be useful, |
1058 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1059 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1060 | + * GNU General Public License for more details. |
1061 | + * |
1062 | + * You should have received a copy of the GNU General Public License |
1063 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1064 | + * |
1065 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1066 | + */ |
1067 | + |
1068 | +#include <core/atoms.h> |
1069 | +#include "DecorationsEdge.h" |
1070 | +#include "DecorationsDataPool.h" |
1071 | + |
1072 | +namespace unity |
1073 | +{ |
1074 | +namespace decoration |
1075 | +{ |
1076 | +namespace |
1077 | +{ |
1078 | + |
1079 | +unsigned TypeToDirection(Edge::Type type) |
1080 | +{ |
1081 | + switch (type) |
1082 | + { |
1083 | + case Edge::Type::TOP: |
1084 | + return WmMoveResizeSizeTop; |
1085 | + case Edge::Type::TOP_LEFT: |
1086 | + return WmMoveResizeSizeTopLeft; |
1087 | + case Edge::Type::TOP_RIGHT: |
1088 | + return WmMoveResizeSizeTopRight; |
1089 | + case Edge::Type::LEFT: |
1090 | + return WmMoveResizeSizeLeft; |
1091 | + case Edge::Type::RIGHT: |
1092 | + return WmMoveResizeSizeRight; |
1093 | + case Edge::Type::BOTTOM: |
1094 | + return WmMoveResizeSizeBottom; |
1095 | + case Edge::Type::BOTTOM_LEFT: |
1096 | + return WmMoveResizeSizeBottomLeft; |
1097 | + case Edge::Type::BOTTOM_RIGHT: |
1098 | + return WmMoveResizeSizeBottomRight; |
1099 | + case Edge::Type::GRAB: |
1100 | + return WmMoveResizeMove; |
1101 | + default: |
1102 | + return WmMoveResizeCancel; |
1103 | + } |
1104 | +} |
1105 | + |
1106 | +} |
1107 | + |
1108 | +Edge::Edge(CompWindow* win, Type t) |
1109 | + : win_(win) |
1110 | + , type_(t) |
1111 | +{ |
1112 | + unsigned mask = (t == Type::GRAB) ? CompWindowActionMoveMask : CompWindowActionResizeMask; |
1113 | + sensitive = (win_->actions() & mask); |
1114 | + mouse_owner.changed.connect([this] (bool over) { |
1115 | + if (over) |
1116 | + XDefineCursor(screen->dpy(), win_->frame(), DataPool::Get()->EdgeCursor(type_)); |
1117 | + else |
1118 | + XUndefineCursor(screen->dpy(), win_->frame()); |
1119 | + }); |
1120 | +} |
1121 | + |
1122 | +Edge::Type Edge::GetType() const |
1123 | +{ |
1124 | + return type_; |
1125 | +} |
1126 | + |
1127 | +void Edge::ButtonDownEvent(CompPoint const& p, unsigned button) |
1128 | +{ |
1129 | + XEvent ev; |
1130 | + auto* dpy = screen->dpy(); |
1131 | + |
1132 | + ev.xclient.type = ClientMessage; |
1133 | + ev.xclient.display = screen->dpy(); |
1134 | + |
1135 | + ev.xclient.serial = 0; |
1136 | + ev.xclient.send_event = True; |
1137 | + |
1138 | + ev.xclient.window = win_->id(); |
1139 | + ev.xclient.message_type = Atoms::wmMoveResize; |
1140 | + ev.xclient.format = 32; |
1141 | + |
1142 | + ev.xclient.data.l[0] = p.x(); |
1143 | + ev.xclient.data.l[1] = p.y(); |
1144 | + ev.xclient.data.l[2] = TypeToDirection(type_); |
1145 | + ev.xclient.data.l[3] = button; |
1146 | + ev.xclient.data.l[4] = 1; |
1147 | + |
1148 | + XUngrabPointer(dpy, screen->getCurrentTime()); |
1149 | + XUngrabKeyboard(dpy, screen->getCurrentTime()); |
1150 | + |
1151 | + auto mask = SubstructureRedirectMask | SubstructureNotifyMask; |
1152 | + XSendEvent(dpy, screen->root(), False, mask, &ev); |
1153 | + |
1154 | + XSync(dpy, False); |
1155 | +} |
1156 | + |
1157 | +std::string Edge::GetName() const |
1158 | +{ |
1159 | + switch (type_) |
1160 | + { |
1161 | + case Type::TOP: |
1162 | + return "TopEdge"; |
1163 | + case Type::TOP_LEFT: |
1164 | + return "TopLeftEdge"; |
1165 | + case Type::TOP_RIGHT: |
1166 | + return "TopRightEdge"; |
1167 | + case Type::LEFT: |
1168 | + return "LeftEdge"; |
1169 | + case Type::RIGHT: |
1170 | + return "RightEdge"; |
1171 | + case Type::BOTTOM: |
1172 | + return "BottomEdge"; |
1173 | + case Type::BOTTOM_LEFT: |
1174 | + return "BottomLeftEdge"; |
1175 | + case Type::BOTTOM_RIGHT: |
1176 | + return "BottomRightEdge"; |
1177 | + case Type::GRAB: |
1178 | + return "GrabEdge"; |
1179 | + default: |
1180 | + return "Edge"; |
1181 | + } |
1182 | +} |
1183 | + |
1184 | +} // decoration namespace |
1185 | +} // unity namespace |
1186 | |
1187 | === added file 'decorations/DecorationsEdge.h' |
1188 | --- decorations/DecorationsEdge.h 1970-01-01 00:00:00 +0000 |
1189 | +++ decorations/DecorationsEdge.h 2014-01-23 15:21:26 +0000 |
1190 | @@ -0,0 +1,64 @@ |
1191 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1192 | +/* |
1193 | + * Copyright (C) 2013 Canonical Ltd |
1194 | + * |
1195 | + * This program is free software: you can redistribute it and/or modify |
1196 | + * it under the terms of the GNU General Public License version 3 as |
1197 | + * published by the Free Software Foundation. |
1198 | + * |
1199 | + * This program is distributed in the hope that it will be useful, |
1200 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1201 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1202 | + * GNU General Public License for more details. |
1203 | + * |
1204 | + * You should have received a copy of the GNU General Public License |
1205 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1206 | + * |
1207 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1208 | + */ |
1209 | + |
1210 | +#ifndef UNITY_DECORATIONS_EDGE |
1211 | +#define UNITY_DECORATIONS_EDGE |
1212 | + |
1213 | +#include "DecorationsWidgets.h" |
1214 | + |
1215 | +namespace unity |
1216 | +{ |
1217 | +namespace decoration |
1218 | +{ |
1219 | + |
1220 | +class Edge : public SimpleItem |
1221 | +{ |
1222 | +public: |
1223 | + enum class Type |
1224 | + { |
1225 | + // The order of this enum is important to define the priority of each Edge |
1226 | + // when parsing the input events (in case two areas overlap) |
1227 | + GRAB = 0, |
1228 | + TOP_LEFT, |
1229 | + TOP_RIGHT, |
1230 | + TOP, |
1231 | + BOTTOM_LEFT, |
1232 | + BOTTOM_RIGHT, |
1233 | + BOTTOM, |
1234 | + LEFT, |
1235 | + RIGHT, |
1236 | + Size |
1237 | + }; |
1238 | + |
1239 | + Edge(CompWindow* win, Type t); |
1240 | + |
1241 | + Type GetType() const; |
1242 | + void ButtonDownEvent(CompPoint const&, unsigned button); |
1243 | + |
1244 | +protected: |
1245 | + std::string GetName() const; |
1246 | + |
1247 | + CompWindow* win_; |
1248 | + Type type_; |
1249 | +}; |
1250 | + |
1251 | +} // decoration namespace |
1252 | +} // unity namespace |
1253 | + |
1254 | +#endif // UNITY_DECORATIONS_EDGE |
1255 | |
1256 | === added file 'decorations/DecorationsEdgeBorders.cpp' |
1257 | --- decorations/DecorationsEdgeBorders.cpp 1970-01-01 00:00:00 +0000 |
1258 | +++ decorations/DecorationsEdgeBorders.cpp 2014-01-23 15:21:26 +0000 |
1259 | @@ -0,0 +1,99 @@ |
1260 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1261 | +/* |
1262 | + * Copyright (C) 2013 Canonical Ltd |
1263 | + * |
1264 | + * This program is free software: you can redistribute it and/or modify |
1265 | + * it under the terms of the GNU General Public License version 3 as |
1266 | + * published by the Free Software Foundation. |
1267 | + * |
1268 | + * This program is distributed in the hope that it will be useful, |
1269 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1270 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1271 | + * GNU General Public License for more details. |
1272 | + * |
1273 | + * You should have received a copy of the GNU General Public License |
1274 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1275 | + * |
1276 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1277 | + */ |
1278 | + |
1279 | +#include "DecorationStyle.h" |
1280 | +#include "DecorationsEdgeBorders.h" |
1281 | +#include "DecorationsEdge.h" |
1282 | +#include "DecorationsGrabEdge.h" |
1283 | + |
1284 | +namespace unity |
1285 | +{ |
1286 | +namespace decoration |
1287 | +{ |
1288 | +namespace |
1289 | +{ |
1290 | +const int MIN_CORNER_EDGE = 10; |
1291 | +} |
1292 | + |
1293 | +EdgeBorders::EdgeBorders(CompWindow* win) |
1294 | +{ |
1295 | + items_.resize(size_t(Edge::Type::Size)); |
1296 | + |
1297 | + for (unsigned i = 0; i < unsigned(Edge::Type::Size); ++i) |
1298 | + { |
1299 | + auto type = Edge::Type(i); |
1300 | + |
1301 | + if (type == Edge::Type::GRAB) |
1302 | + items_[i] = std::make_shared<GrabEdge>(win); |
1303 | + else |
1304 | + items_[i] = std::make_shared<Edge>(win, type); |
1305 | + } |
1306 | + |
1307 | + Relayout(); |
1308 | +} |
1309 | + |
1310 | +void EdgeBorders::Relayout() |
1311 | +{ |
1312 | + auto const& b = Style::Get()->Border(); |
1313 | + auto const& ib = Style::Get()->InputBorder(); |
1314 | + |
1315 | + Border edges(std::max(b.top, MIN_CORNER_EDGE) + ib.top, |
1316 | + std::max(b.left, MIN_CORNER_EDGE) + ib.left, |
1317 | + std::max(b.right, MIN_CORNER_EDGE) + ib.right, |
1318 | + std::max(b.bottom, MIN_CORNER_EDGE) + ib.bottom); |
1319 | + |
1320 | + auto item = items_[unsigned(Edge::Type::TOP)]; |
1321 | + item->SetCoords(rect_.x() + edges.left, rect_.y()); |
1322 | + item->SetSize(rect_.width() - edges.left - edges.right, edges.top - b.top); |
1323 | + |
1324 | + item = items_[unsigned(Edge::Type::TOP_LEFT)]; |
1325 | + item->SetCoords(rect_.x(), rect_.y()); |
1326 | + item->SetSize(edges.left, edges.top); |
1327 | + |
1328 | + item = items_[unsigned(Edge::Type::TOP_RIGHT)]; |
1329 | + item->SetCoords(rect_.x2() - edges.right, rect_.y()); |
1330 | + item->SetSize(edges.right, edges.top); |
1331 | + |
1332 | + item = items_[unsigned(Edge::Type::LEFT)]; |
1333 | + item->SetCoords(rect_.x(), rect_.y() + edges.top); |
1334 | + item->SetSize(edges.left, rect_.height() - edges.top - edges.bottom); |
1335 | + |
1336 | + item = items_[unsigned(Edge::Type::RIGHT)]; |
1337 | + item->SetCoords(rect_.x2() - edges.right, rect_.y() + edges.top); |
1338 | + item->SetSize(edges.right, rect_.height() - edges.top - edges.bottom); |
1339 | + |
1340 | + item = items_[unsigned(Edge::Type::BOTTOM)]; |
1341 | + item->SetCoords(rect_.x() + edges.left, rect_.y2() - edges.bottom); |
1342 | + item->SetSize(rect_.width() - edges.left - edges.right, edges.bottom); |
1343 | + |
1344 | + item = items_[unsigned(Edge::Type::BOTTOM_LEFT)]; |
1345 | + item->SetCoords(rect_.x(), rect_.y2() - edges.bottom); |
1346 | + item->SetSize(edges.left, edges.bottom); |
1347 | + |
1348 | + item = items_[unsigned(Edge::Type::BOTTOM_RIGHT)]; |
1349 | + item->SetCoords(rect_.x2() - edges.right, rect_.y2() - edges.bottom); |
1350 | + item->SetSize(edges.right, edges.bottom); |
1351 | + |
1352 | + item = items_[unsigned(Edge::Type::GRAB)]; |
1353 | + item->SetCoords(rect_.x() + ib.left, rect_.y() + ib.top); |
1354 | + item->SetSize(rect_.width() - ib.left - ib.right, b.top); |
1355 | +} |
1356 | + |
1357 | +} // decoration namespace |
1358 | +} // unity namespace |
1359 | |
1360 | === added file 'decorations/DecorationsEdgeBorders.h' |
1361 | --- decorations/DecorationsEdgeBorders.h 1970-01-01 00:00:00 +0000 |
1362 | +++ decorations/DecorationsEdgeBorders.h 2014-01-23 15:21:26 +0000 |
1363 | @@ -0,0 +1,43 @@ |
1364 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1365 | +/* |
1366 | + * Copyright (C) 2013 Canonical Ltd |
1367 | + * |
1368 | + * This program is free software: you can redistribute it and/or modify |
1369 | + * it under the terms of the GNU General Public License version 3 as |
1370 | + * published by the Free Software Foundation. |
1371 | + * |
1372 | + * This program is distributed in the hope that it will be useful, |
1373 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1374 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1375 | + * GNU General Public License for more details. |
1376 | + * |
1377 | + * You should have received a copy of the GNU General Public License |
1378 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1379 | + * |
1380 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1381 | + */ |
1382 | + |
1383 | +#ifndef UNITY_DECORATIONS_EDGES |
1384 | +#define UNITY_DECORATIONS_EDGES |
1385 | + |
1386 | +#include "DecorationsWidgets.h" |
1387 | + |
1388 | +namespace unity |
1389 | +{ |
1390 | +namespace decoration |
1391 | +{ |
1392 | + |
1393 | +class EdgeBorders : public BasicContainer |
1394 | +{ |
1395 | +public: |
1396 | + EdgeBorders(CompWindow* win); |
1397 | + void Relayout(); |
1398 | + |
1399 | +protected: |
1400 | + std::string GetName() const { return "EdgeBorders"; } |
1401 | +}; |
1402 | + |
1403 | +} // decoration namespace |
1404 | +} // unity namespace |
1405 | + |
1406 | +#endif // UNITY_DECORATIONS_EDGES |
1407 | |
1408 | === added file 'decorations/DecorationsGrabEdge.cpp' |
1409 | --- decorations/DecorationsGrabEdge.cpp 1970-01-01 00:00:00 +0000 |
1410 | +++ decorations/DecorationsGrabEdge.cpp 2014-01-23 15:21:26 +0000 |
1411 | @@ -0,0 +1,102 @@ |
1412 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1413 | +/* |
1414 | + * Copyright (C) 2013 Canonical Ltd |
1415 | + * |
1416 | + * This program is free software: you can redistribute it and/or modify |
1417 | + * it under the terms of the GNU General Public License version 3 as |
1418 | + * published by the Free Software Foundation. |
1419 | + * |
1420 | + * This program is distributed in the hope that it will be useful, |
1421 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1422 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1423 | + * GNU General Public License for more details. |
1424 | + * |
1425 | + * You should have received a copy of the GNU General Public License |
1426 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1427 | + * |
1428 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1429 | + */ |
1430 | + |
1431 | +#include "DecorationsGrabEdge.h" |
1432 | +#include "DecorationStyle.h" |
1433 | + |
1434 | +namespace unity |
1435 | +{ |
1436 | +namespace decoration |
1437 | +{ |
1438 | +namespace |
1439 | +{ |
1440 | +const int MOUSE_DOWN_TIMEOUT = 150; |
1441 | +} |
1442 | + |
1443 | +GrabEdge::GrabEdge(CompWindow* win) |
1444 | + : Edge(win, Edge::Type::GRAB) |
1445 | + , last_click_time_(0) |
1446 | + , button_down_(-1) |
1447 | +{} |
1448 | + |
1449 | +void GrabEdge::ButtonDownEvent(CompPoint const& p, unsigned button) |
1450 | +{ |
1451 | + if (button != 1) |
1452 | + return; |
1453 | + |
1454 | + if (!(win_->actions() & (CompWindowActionMaximizeHorzMask|CompWindowActionMaximizeVertMask))) |
1455 | + { |
1456 | + Edge::ButtonDownEvent(p, button); |
1457 | + return; |
1458 | + } |
1459 | + |
1460 | + auto const& style = Style::Get(); |
1461 | + unsigned max_time_delta = std::max(0, style->DoubleClickMaxTimeDelta()); |
1462 | + bool maximized = false; |
1463 | + |
1464 | + if (screen->getCurrentTime() - last_click_time_ < max_time_delta) |
1465 | + { |
1466 | + int max_distance = style->DoubleClickMaxDistance(); |
1467 | + |
1468 | + if (std::abs(p.x() - last_click_pos_.x()) < max_distance && |
1469 | + std::abs(p.y() - last_click_pos_.y()) < max_distance) |
1470 | + { |
1471 | + win_->maximize(MAXIMIZE_STATE); |
1472 | + maximized = true; |
1473 | + button_down_timer_.reset(); |
1474 | + } |
1475 | + } |
1476 | + |
1477 | + if (!maximized) |
1478 | + { |
1479 | + button_down_timer_.reset(new glib::Timeout(MOUSE_DOWN_TIMEOUT)); |
1480 | + button_down_timer_->Run([this] { |
1481 | + Edge::ButtonDownEvent(CompPoint(pointerX, pointerY), button_down_); |
1482 | + button_down_timer_.reset(); |
1483 | + return false; |
1484 | + }); |
1485 | + } |
1486 | + |
1487 | + button_down_ = button; |
1488 | + last_click_pos_ = p; |
1489 | + last_click_time_ = screen->getCurrentTime(); |
1490 | +} |
1491 | + |
1492 | +void GrabEdge::MotionEvent(CompPoint const& p) |
1493 | +{ |
1494 | + if (button_down_timer_) |
1495 | + { |
1496 | + button_down_timer_.reset(); |
1497 | + Edge::ButtonDownEvent(p, button_down_); |
1498 | + } |
1499 | +} |
1500 | + |
1501 | +void GrabEdge::ButtonUpEvent(CompPoint const&, unsigned button) |
1502 | +{ |
1503 | + button_down_timer_.reset(); |
1504 | +} |
1505 | + |
1506 | +void GrabEdge::AddProperties(debug::IntrospectionData& data) |
1507 | +{ |
1508 | + Edge::AddProperties(data); |
1509 | + data.add("button_down", button_down_); |
1510 | +} |
1511 | + |
1512 | +} // decoration namespace |
1513 | +} // unity namespace |
1514 | |
1515 | === added file 'decorations/DecorationsGrabEdge.h' |
1516 | --- decorations/DecorationsGrabEdge.h 1970-01-01 00:00:00 +0000 |
1517 | +++ decorations/DecorationsGrabEdge.h 2014-01-23 15:21:26 +0000 |
1518 | @@ -0,0 +1,53 @@ |
1519 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1520 | +/* |
1521 | + * Copyright (C) 2013 Canonical Ltd |
1522 | + * |
1523 | + * This program is free software: you can redistribute it and/or modify |
1524 | + * it under the terms of the GNU General Public License version 3 as |
1525 | + * published by the Free Software Foundation. |
1526 | + * |
1527 | + * This program is distributed in the hope that it will be useful, |
1528 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1529 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1530 | + * GNU General Public License for more details. |
1531 | + * |
1532 | + * You should have received a copy of the GNU General Public License |
1533 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1534 | + * |
1535 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1536 | + */ |
1537 | + |
1538 | +#ifndef UNITY_DECORATIONS_GRAB_EDGE |
1539 | +#define UNITY_DECORATIONS_GRAB_EDGE |
1540 | + |
1541 | +#include <UnityCore/GLibSource.h> |
1542 | +#include "DecorationsEdge.h" |
1543 | + |
1544 | +namespace unity |
1545 | +{ |
1546 | +namespace decoration |
1547 | +{ |
1548 | + |
1549 | +class GrabEdge : public Edge |
1550 | +{ |
1551 | +public: |
1552 | + GrabEdge(CompWindow* win); |
1553 | + |
1554 | + void ButtonDownEvent(CompPoint const&, unsigned button); |
1555 | + void ButtonUpEvent(CompPoint const&, unsigned button); |
1556 | + void MotionEvent(CompPoint const&); |
1557 | + |
1558 | +protected: |
1559 | + void AddProperties(debug::IntrospectionData&); |
1560 | + |
1561 | +private: |
1562 | + Time last_click_time_; |
1563 | + CompPoint last_click_pos_; |
1564 | + int button_down_; |
1565 | + glib::Source::UniquePtr button_down_timer_; |
1566 | +}; |
1567 | + |
1568 | +} // decoration namespace |
1569 | +} // unity namespace |
1570 | + |
1571 | +#endif // UNITY_DECORATIONS_GRAB_EDGE |
1572 | |
1573 | === added file 'decorations/DecorationsInputMixer.cpp' |
1574 | --- decorations/DecorationsInputMixer.cpp 1970-01-01 00:00:00 +0000 |
1575 | +++ decorations/DecorationsInputMixer.cpp 2014-01-23 15:21:26 +0000 |
1576 | @@ -0,0 +1,176 @@ |
1577 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1578 | +/* |
1579 | + * Copyright (C) 2013 Canonical Ltd |
1580 | + * |
1581 | + * This program is free software: you can redistribute it and/or modify |
1582 | + * it under the terms of the GNU General Public License version 3 as |
1583 | + * published by the Free Software Foundation. |
1584 | + * |
1585 | + * This program is distributed in the hope that it will be useful, |
1586 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1587 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1588 | + * GNU General Public License for more details. |
1589 | + * |
1590 | + * You should have received a copy of the GNU General Public License |
1591 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1592 | + * |
1593 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1594 | + */ |
1595 | + |
1596 | +#include <NuxCore/Logger.h> |
1597 | +#include "DecorationsInputMixer.h" |
1598 | + |
1599 | +namespace unity |
1600 | +{ |
1601 | +namespace decoration |
1602 | +{ |
1603 | +namespace |
1604 | +{ |
1605 | +DECLARE_LOGGER(logger, "unity.decorations.inputmixer"); |
1606 | +} |
1607 | + |
1608 | +InputMixer::InputMixer() |
1609 | + : mouse_down_(false) |
1610 | +{} |
1611 | + |
1612 | +void InputMixer::PushToFront(Item::Ptr const& item) |
1613 | +{ |
1614 | + if (!item) |
1615 | + return; |
1616 | + |
1617 | + auto it = std::find(items_.begin(), items_.end(), item); |
1618 | + if (it != items_.end()) |
1619 | + items_.erase(it); |
1620 | + |
1621 | + items_.push_front(item); |
1622 | +} |
1623 | + |
1624 | +void InputMixer::PushToBack(Item::Ptr const& item) |
1625 | +{ |
1626 | + if (!item) |
1627 | + return; |
1628 | + |
1629 | + auto it = std::find(items_.begin(), items_.end(), item); |
1630 | + if (it != items_.end()) |
1631 | + items_.erase(it); |
1632 | + |
1633 | + items_.push_back(item); |
1634 | +} |
1635 | + |
1636 | +void InputMixer::Remove(Item::Ptr const& item) |
1637 | +{ |
1638 | + if (item == last_mouse_owner_) |
1639 | + UnsetMouseOwner(); |
1640 | + |
1641 | + auto it = std::find(items_.begin(), items_.end(), item); |
1642 | + if (it != items_.end()) |
1643 | + items_.erase(it); |
1644 | +} |
1645 | + |
1646 | +Item::List const& InputMixer::Items() const |
1647 | +{ |
1648 | + return items_; |
1649 | +} |
1650 | + |
1651 | +Item::Ptr InputMixer::GetMatchingItemRecursive(Item::List const& items, CompPoint const& point) |
1652 | +{ |
1653 | + for (auto const& item : items) |
1654 | + { |
1655 | + if (item->visible() && item->Geometry().contains(point)) |
1656 | + { |
1657 | + if (!item->IsContainer()) |
1658 | + return item->sensitive() ? item : nullptr; |
1659 | + |
1660 | + auto const& container = std::static_pointer_cast<BasicContainer>(item); |
1661 | + auto const& child = GetMatchingItemRecursive(container->Items(), point); |
1662 | + |
1663 | + if (child) |
1664 | + return child; |
1665 | + } |
1666 | + } |
1667 | + |
1668 | + return nullptr; |
1669 | +} |
1670 | + |
1671 | +Item::Ptr InputMixer::GetMatchingItem(CompPoint const& point) |
1672 | +{ |
1673 | + return GetMatchingItemRecursive(items_, point); |
1674 | +} |
1675 | + |
1676 | +void InputMixer::UpdateMouseOwner(CompPoint const& point) |
1677 | +{ |
1678 | + if (Item::Ptr const& item = GetMatchingItem(point)) |
1679 | + { |
1680 | + if (item != last_mouse_owner_) |
1681 | + { |
1682 | + UnsetMouseOwner(); |
1683 | + last_mouse_owner_ = item; |
1684 | + item->mouse_owner = true; |
1685 | + } |
1686 | + } |
1687 | + else |
1688 | + { |
1689 | + UnsetMouseOwner(); |
1690 | + } |
1691 | +} |
1692 | + |
1693 | +void InputMixer::UnsetMouseOwner() |
1694 | +{ |
1695 | + if (!last_mouse_owner_) |
1696 | + return; |
1697 | + |
1698 | + last_mouse_owner_->mouse_owner = false; |
1699 | + last_mouse_owner_ = nullptr; |
1700 | +} |
1701 | + |
1702 | +Item::Ptr const& InputMixer::GetMouseOwner() const |
1703 | +{ |
1704 | + return last_mouse_owner_; |
1705 | +}; |
1706 | + |
1707 | +void InputMixer::EnterEvent(CompPoint const& point) |
1708 | +{ |
1709 | + if (!mouse_down_) |
1710 | + UpdateMouseOwner(point); |
1711 | +} |
1712 | + |
1713 | +void InputMixer::LeaveEvent(CompPoint const& point) |
1714 | +{ |
1715 | + if (!mouse_down_) |
1716 | + UnsetMouseOwner(); |
1717 | +} |
1718 | + |
1719 | +void InputMixer::MotionEvent(CompPoint const& point) |
1720 | +{ |
1721 | + if (!mouse_down_) |
1722 | + UpdateMouseOwner(point); |
1723 | + |
1724 | + if (last_mouse_owner_) |
1725 | + last_mouse_owner_->MotionEvent(point); |
1726 | +} |
1727 | + |
1728 | +void InputMixer::ButtonDownEvent(CompPoint const& point, unsigned button) |
1729 | +{ |
1730 | + mouse_down_ = true; |
1731 | + |
1732 | + if (last_mouse_owner_) |
1733 | + last_mouse_owner_->ButtonDownEvent(point, button); |
1734 | +} |
1735 | + |
1736 | +void InputMixer::ButtonUpEvent(CompPoint const& point, unsigned button) |
1737 | +{ |
1738 | + mouse_down_ = false; |
1739 | + |
1740 | + if (last_mouse_owner_) |
1741 | + { |
1742 | + // This event might cause the InputMixer to be deleted, so we protect using a weak_ptr |
1743 | + std::weak_ptr<Item> weak_last_mouse_owner(last_mouse_owner_); |
1744 | + last_mouse_owner_->ButtonUpEvent(point, button); |
1745 | + |
1746 | + if (!weak_last_mouse_owner.expired() && !last_mouse_owner_->Geometry().contains(point)) |
1747 | + UpdateMouseOwner(point); |
1748 | + } |
1749 | +} |
1750 | + |
1751 | +} // decoration namespace |
1752 | +} // unity namespace |
1753 | |
1754 | === added file 'decorations/DecorationsInputMixer.h' |
1755 | --- decorations/DecorationsInputMixer.h 1970-01-01 00:00:00 +0000 |
1756 | +++ decorations/DecorationsInputMixer.h 2014-01-23 15:21:26 +0000 |
1757 | @@ -0,0 +1,66 @@ |
1758 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1759 | +/* |
1760 | + * Copyright (C) 2013 Canonical Ltd |
1761 | + * |
1762 | + * This program is free software: you can redistribute it and/or modify |
1763 | + * it under the terms of the GNU General Public License version 3 as |
1764 | + * published by the Free Software Foundation. |
1765 | + * |
1766 | + * This program is distributed in the hope that it will be useful, |
1767 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1768 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1769 | + * GNU General Public License for more details. |
1770 | + * |
1771 | + * You should have received a copy of the GNU General Public License |
1772 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1773 | + * |
1774 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1775 | + */ |
1776 | + |
1777 | +#ifndef UNITY_DECORATION_INPUT_MIXER |
1778 | +#define UNITY_DECORATION_INPUT_MIXER |
1779 | + |
1780 | +#include "DecorationsWidgets.h" |
1781 | + |
1782 | +namespace unity |
1783 | +{ |
1784 | +namespace decoration |
1785 | +{ |
1786 | + |
1787 | +class InputMixer |
1788 | +{ |
1789 | +public: |
1790 | + typedef std::shared_ptr<InputMixer> Ptr; |
1791 | + InputMixer(); |
1792 | + |
1793 | + void PushToFront(Item::Ptr const&); |
1794 | + void PushToBack(Item::Ptr const&); |
1795 | + void Remove(Item::Ptr const&); |
1796 | + |
1797 | + Item::List const& Items() const; |
1798 | + Item::Ptr const& GetMouseOwner() const; |
1799 | + |
1800 | + void EnterEvent(CompPoint const&); |
1801 | + void MotionEvent(CompPoint const&); |
1802 | + void LeaveEvent(CompPoint const&); |
1803 | + void ButtonDownEvent(CompPoint const&, unsigned button); |
1804 | + void ButtonUpEvent(CompPoint const&, unsigned button); |
1805 | + |
1806 | +private: |
1807 | + InputMixer(InputMixer const&) = delete; |
1808 | + InputMixer& operator=(InputMixer const&) = delete; |
1809 | + |
1810 | + void UpdateMouseOwner(CompPoint const&); |
1811 | + void UnsetMouseOwner(); |
1812 | + Item::Ptr GetMatchingItem(CompPoint const&); |
1813 | + Item::Ptr GetMatchingItemRecursive(Item::List const&, CompPoint const&); |
1814 | + |
1815 | + Item::List items_; |
1816 | + Item::Ptr last_mouse_owner_; |
1817 | + bool mouse_down_; |
1818 | +}; |
1819 | + |
1820 | +} // decoration namespace |
1821 | +} // unity namespace |
1822 | + |
1823 | +#endif |
1824 | |
1825 | === added file 'decorations/DecorationsManager.cpp' |
1826 | --- decorations/DecorationsManager.cpp 1970-01-01 00:00:00 +0000 |
1827 | +++ decorations/DecorationsManager.cpp 2014-01-23 15:21:26 +0000 |
1828 | @@ -0,0 +1,386 @@ |
1829 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1830 | +/* |
1831 | + * Copyright (C) 2013 Canonical Ltd |
1832 | + * |
1833 | + * This program is free software: you can redistribute it and/or modify |
1834 | + * it under the terms of the GNU General Public License version 3 as |
1835 | + * published by the Free Software Foundation. |
1836 | + * |
1837 | + * This program is distributed in the hope that it will be useful, |
1838 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1839 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1840 | + * GNU General Public License for more details. |
1841 | + * |
1842 | + * You should have received a copy of the GNU General Public License |
1843 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1844 | + * |
1845 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1846 | + */ |
1847 | + |
1848 | +#include "DecorationsPriv.h" |
1849 | + |
1850 | +#include <core/atoms.h> |
1851 | +#include <NuxCore/Logger.h> |
1852 | +#include <NuxGraphics/CairoGraphics.h> |
1853 | +#include <X11/Xatom.h> |
1854 | +#include "WindowManager.h" |
1855 | + |
1856 | +namespace unity |
1857 | +{ |
1858 | +namespace decoration |
1859 | +{ |
1860 | +Manager* manager_ = nullptr; |
1861 | + |
1862 | +namespace |
1863 | +{ |
1864 | +DECLARE_LOGGER(logger, "unity.decoration.manager"); |
1865 | + |
1866 | +namespace atom |
1867 | +{ |
1868 | +Atom _NET_REQUEST_FRAME_EXTENTS = 0; |
1869 | +Atom _NET_WM_VISIBLE_NAME = 0; |
1870 | +} |
1871 | +} |
1872 | + |
1873 | +Manager::Impl::Impl(decoration::Manager* parent) |
1874 | + : active_window_(0) |
1875 | + , enable_add_supported_atoms_(true) |
1876 | + , data_pool_(DataPool::Get()) |
1877 | +{ |
1878 | + if (!manager_) |
1879 | + manager_ = parent; |
1880 | + |
1881 | + Display* dpy = screen->dpy(); |
1882 | + atom::_NET_REQUEST_FRAME_EXTENTS = XInternAtom(dpy, "_NET_REQUEST_FRAME_EXTENTS", False); |
1883 | + atom::_NET_WM_VISIBLE_NAME = XInternAtom(dpy, "_NET_WM_VISIBLE_NAME", False); |
1884 | + screen->updateSupportedWmHints(); |
1885 | + |
1886 | + auto rebuild_cb = sigc::mem_fun(this, &Impl::OnShadowOptionsChanged); |
1887 | + manager_->active_shadow_color.changed.connect(sigc::hide(sigc::bind(rebuild_cb, true))); |
1888 | + manager_->active_shadow_radius.changed.connect(sigc::hide(sigc::bind(rebuild_cb, true))); |
1889 | + manager_->inactive_shadow_color.changed.connect(sigc::hide(sigc::bind(rebuild_cb, false))); |
1890 | + manager_->inactive_shadow_radius.changed.connect(sigc::hide(sigc::bind(rebuild_cb, false))); |
1891 | + manager_->shadow_offset.changed.connect(sigc::hide(sigc::mem_fun(this, &Impl::UpdateWindowsExtents))); |
1892 | + |
1893 | + BuildInactiveShadowTexture(); |
1894 | + BuildActiveShadowTexture(); |
1895 | +} |
1896 | + |
1897 | +Manager::Impl::~Impl() |
1898 | +{ |
1899 | + enable_add_supported_atoms_ = false; |
1900 | + screen->updateSupportedWmHints(); |
1901 | +} |
1902 | + |
1903 | +cu::PixmapTexture::Ptr Manager::Impl::BuildShadowTexture(unsigned radius, nux::Color const& color) |
1904 | +{ |
1905 | + int tex_size = radius * 4; |
1906 | + |
1907 | + nux::CairoGraphics dummy(CAIRO_FORMAT_ARGB32, tex_size, tex_size); |
1908 | + auto* dummy_ctx = dummy.GetInternalContext(); |
1909 | + cairo_rectangle(dummy_ctx, radius*2, radius*2, tex_size, tex_size); |
1910 | + cairo_set_source_rgba(dummy_ctx, color.red, color.green, color.blue, color.alpha); |
1911 | + cairo_fill(dummy_ctx); |
1912 | + dummy.BlurSurface(radius); |
1913 | + |
1914 | + cu::CairoContext shadow_ctx(tex_size, tex_size); |
1915 | + cairo_set_source_surface(shadow_ctx, dummy.GetSurface(), 0, 0); |
1916 | + cairo_paint(shadow_ctx); |
1917 | + return shadow_ctx; |
1918 | +} |
1919 | + |
1920 | +void Manager::Impl::BuildActiveShadowTexture() |
1921 | +{ |
1922 | + active_shadow_pixmap_ = BuildShadowTexture(manager_->active_shadow_radius(), manager_->active_shadow_color()); |
1923 | +} |
1924 | + |
1925 | +void Manager::Impl::BuildInactiveShadowTexture() |
1926 | +{ |
1927 | + inactive_shadow_pixmap_ = BuildShadowTexture(manager_->inactive_shadow_radius(), manager_->inactive_shadow_color()); |
1928 | +} |
1929 | + |
1930 | +void Manager::Impl::OnShadowOptionsChanged(bool active) |
1931 | +{ |
1932 | + if (active) |
1933 | + BuildActiveShadowTexture(); |
1934 | + else |
1935 | + BuildInactiveShadowTexture(); |
1936 | + |
1937 | + UpdateWindowsExtents(); |
1938 | +} |
1939 | + |
1940 | +void Manager::Impl::UpdateWindowsExtents() |
1941 | +{ |
1942 | + for (auto const& win : windows_) |
1943 | + win.second->impl_->RedrawDecorations(); |
1944 | +} |
1945 | + |
1946 | +bool Manager::Impl::UpdateWindow(::Window xid) |
1947 | +{ |
1948 | + auto const& win = GetWindowByXid(xid); |
1949 | + |
1950 | + if (win && !win->impl_->win_->hasUnmapReference()) |
1951 | + { |
1952 | + win->Update(); |
1953 | + return true; |
1954 | + } |
1955 | + |
1956 | + return false; |
1957 | +} |
1958 | + |
1959 | +Window::Ptr Manager::Impl::GetWindowByXid(::Window xid) const |
1960 | +{ |
1961 | + for (auto const& pair : windows_) |
1962 | + { |
1963 | + if (pair.first->id() == xid) |
1964 | + return pair.second; |
1965 | + } |
1966 | + |
1967 | + return nullptr; |
1968 | +} |
1969 | + |
1970 | +Window::Ptr Manager::Impl::GetWindowByFrame(::Window xid) const |
1971 | +{ |
1972 | + auto it = framed_windows_.find(xid); |
1973 | + if (it == framed_windows_.end()) |
1974 | + return nullptr; |
1975 | + |
1976 | + return it->second.lock(); |
1977 | +} |
1978 | + |
1979 | +bool Manager::Impl::HandleEventBefore(XEvent* event) |
1980 | +{ |
1981 | + active_window_ = screen->activeWindow(); |
1982 | + switch (event->type) |
1983 | + { |
1984 | + case ClientMessage: |
1985 | + if (event->xclient.message_type == atom::_NET_REQUEST_FRAME_EXTENTS) |
1986 | + { |
1987 | + if (Window::Ptr const& win = GetWindowByXid(event->xclient.window)) |
1988 | + win->impl_->Decorate(); |
1989 | + } |
1990 | + break; |
1991 | + case MotionNotify: |
1992 | + case EnterNotify: |
1993 | + case LeaveNotify: |
1994 | + case ButtonPress: |
1995 | + case ButtonRelease: |
1996 | + if (HandleFrameEvent(event)) |
1997 | + return true; |
1998 | + break; |
1999 | + } |
2000 | + |
2001 | + return false; |
2002 | +} |
2003 | + |
2004 | +bool Manager::Impl::HandleEventAfter(XEvent* event) |
2005 | +{ |
2006 | + if (screen->activeWindow() != active_window_) |
2007 | + { |
2008 | + // Do this when _NET_ACTIVE_WINDOW changes on root! |
2009 | + auto const& old_active = GetWindowByXid(active_window_); |
2010 | + |
2011 | + if (old_active) |
2012 | + old_active->impl_->active = false; |
2013 | + |
2014 | + active_window_ = screen->activeWindow(); |
2015 | + |
2016 | + auto const& new_active = GetWindowByXid(active_window_); |
2017 | + |
2018 | + if (new_active) |
2019 | + new_active->impl_->active = true; |
2020 | + } |
2021 | + |
2022 | + switch (event->type) |
2023 | + { |
2024 | + case PropertyNotify: |
2025 | + { |
2026 | + if (event->xproperty.atom == Atoms::mwmHints) |
2027 | + { |
2028 | + if (Window::Ptr const& win = GetWindowByXid(event->xproperty.window)) |
2029 | + { |
2030 | + win->impl_->CleanupWindowControls(); |
2031 | + win->Update(); |
2032 | + } |
2033 | + } |
2034 | + else if (event->xproperty.atom == XA_WM_NAME || |
2035 | + event->xproperty.atom == Atoms::wmName || |
2036 | + event->xproperty.atom == atom::_NET_WM_VISIBLE_NAME) |
2037 | + { |
2038 | + if (Window::Ptr const& win = GetWindowByXid(event->xproperty.window)) |
2039 | + { |
2040 | + auto& wm = WindowManager::Default(); |
2041 | + win->title = wm.GetStringProperty(event->xproperty.window, event->xproperty.atom); |
2042 | + } |
2043 | + } |
2044 | + break; |
2045 | + } |
2046 | + case ConfigureNotify: |
2047 | + UpdateWindow(event->xconfigure.window); |
2048 | + break; |
2049 | + default: |
2050 | + if (screen->XShape() && event->type == screen->shapeEvent() + ShapeNotify) |
2051 | + { |
2052 | + auto window = reinterpret_cast<XShapeEvent*>(event)->window; |
2053 | + if (!UpdateWindow(window)) |
2054 | + { |
2055 | + if (Window::Ptr const& win = GetWindowByFrame(window)) |
2056 | + win->impl_->SyncXShapeWithFrameRegion(); |
2057 | + } |
2058 | + } |
2059 | + break; |
2060 | + } |
2061 | + |
2062 | + return false; |
2063 | +} |
2064 | + |
2065 | +bool Manager::Impl::HandleFrameEvent(XEvent* event) |
2066 | +{ |
2067 | + auto const& win = GetWindowByFrame(event->xany.window); |
2068 | + |
2069 | + // ButtonRelease events might happen also outside the frame window, in this |
2070 | + // case we must unset the mouse owner, wherever the event happens. |
2071 | + if (!win && event->type != ButtonRelease) |
2072 | + return false; |
2073 | + |
2074 | + auto const& input_mixer = win ? win->impl_->input_mixer_ : last_mouse_owner_.lock(); |
2075 | + |
2076 | + if (!input_mixer) |
2077 | + return false; |
2078 | + |
2079 | + switch (event->type) |
2080 | + { |
2081 | + case MotionNotify: |
2082 | + { |
2083 | + input_mixer->MotionEvent(CompPoint(event->xmotion.x_root, event->xmotion.y_root)); |
2084 | + break; |
2085 | + } |
2086 | + case EnterNotify: |
2087 | + { |
2088 | + input_mixer->EnterEvent(CompPoint(event->xcrossing.x_root, event->xcrossing.y_root)); |
2089 | + break; |
2090 | + } |
2091 | + case LeaveNotify: |
2092 | + { |
2093 | + input_mixer->LeaveEvent(CompPoint(event->xcrossing.x_root, event->xcrossing.y_root)); |
2094 | + break; |
2095 | + } |
2096 | + case ButtonPress: |
2097 | + { |
2098 | + input_mixer->ButtonDownEvent(CompPoint(event->xbutton.x_root, event->xbutton.y_root), event->xbutton.button); |
2099 | + if (input_mixer->GetMouseOwner()) |
2100 | + last_mouse_owner_ = input_mixer; |
2101 | + break; |
2102 | + } |
2103 | + case ButtonRelease: |
2104 | + { |
2105 | + input_mixer->ButtonUpEvent(CompPoint(event->xbutton.x_root, event->xbutton.y_root), event->xbutton.button); |
2106 | + last_mouse_owner_.reset(); |
2107 | + break; |
2108 | + } |
2109 | + } |
2110 | + |
2111 | + // This causes the Alt+Move not to work, we should probably return this value based on the actual handled state |
2112 | + // return true; |
2113 | + return false; |
2114 | +} |
2115 | + |
2116 | +Window::Ptr Manager::Impl::HandleWindow(CompWindow* cwin) |
2117 | +{ |
2118 | + auto win = std::make_shared<Window>(cwin); |
2119 | + auto* wimpl = win->impl_.get(); |
2120 | + |
2121 | + std::weak_ptr<decoration::Window> weak_win(win); |
2122 | + wimpl->framed.connect(sigc::bind(sigc::mem_fun(this, &Impl::OnWindowFrameChanged), weak_win)); |
2123 | + windows_[cwin] = win; |
2124 | + |
2125 | + if (wimpl->frame_) |
2126 | + framed_windows_[wimpl->frame_] = win; |
2127 | + |
2128 | + return win; |
2129 | +} |
2130 | + |
2131 | +void Manager::Impl::OnWindowFrameChanged(bool framed, ::Window frame, std::weak_ptr<decoration::Window> const& window) |
2132 | +{ |
2133 | + if (!framed || !frame) |
2134 | + framed_windows_.erase(frame); |
2135 | + else |
2136 | + framed_windows_[frame] = window; |
2137 | +} |
2138 | + |
2139 | +// Public APIs |
2140 | + |
2141 | +Manager::Manager() |
2142 | + : shadow_offset(Style::Get()->ShadowOffset()) |
2143 | + , active_shadow_color(Style::Get()->ActiveShadowColor()) |
2144 | + , active_shadow_radius(Style::Get()->ActiveShadowRadius()) |
2145 | + , inactive_shadow_color(Style::Get()->InactiveShadowColor()) |
2146 | + , inactive_shadow_radius(Style::Get()->InactiveShadowRadius()) |
2147 | + , impl_(new Impl(this)) |
2148 | +{} |
2149 | + |
2150 | +Manager::~Manager() |
2151 | +{ |
2152 | + if (manager_ == this) |
2153 | + manager_ = nullptr; |
2154 | +} |
2155 | + |
2156 | +void Manager::AddSupportedAtoms(std::vector<Atom>& atoms) const |
2157 | +{ |
2158 | + if (impl_->enable_add_supported_atoms_) |
2159 | + atoms.push_back(atom::_NET_REQUEST_FRAME_EXTENTS); |
2160 | +} |
2161 | + |
2162 | +bool Manager::HandleEventBefore(XEvent* xevent) |
2163 | +{ |
2164 | + return impl_->HandleEventBefore(xevent); |
2165 | +} |
2166 | + |
2167 | +bool Manager::HandleEventAfter(XEvent* xevent) |
2168 | +{ |
2169 | + return impl_->HandleEventAfter(xevent); |
2170 | +} |
2171 | + |
2172 | +Window::Ptr Manager::HandleWindow(CompWindow* cwin) |
2173 | +{ |
2174 | + return impl_->HandleWindow(cwin); |
2175 | +} |
2176 | + |
2177 | +void Manager::UnHandleWindow(CompWindow* cwin) |
2178 | +{ |
2179 | + impl_->windows_.erase(cwin); |
2180 | +} |
2181 | + |
2182 | +Window::Ptr Manager::GetWindowByXid(::Window xid) |
2183 | +{ |
2184 | + return impl_->GetWindowByXid(xid); |
2185 | +} |
2186 | + |
2187 | +std::string Manager::GetName() const |
2188 | +{ |
2189 | + return "DecorationsManager"; |
2190 | +} |
2191 | + |
2192 | +void Manager::AddProperties(debug::IntrospectionData& data) |
2193 | +{ |
2194 | + data.add("shadow_offset", shadow_offset()) |
2195 | + .add("active_shadow_color", active_shadow_color()) |
2196 | + .add("active_shadow_radius", active_shadow_radius()) |
2197 | + .add("inactive_shadow_color", inactive_shadow_color()) |
2198 | + .add("inactive_shadow_radius", inactive_shadow_radius()) |
2199 | + .add("active_window", impl_->active_window_); |
2200 | +} |
2201 | + |
2202 | +debug::Introspectable::IntrospectableList Manager::GetIntrospectableChildren() |
2203 | +{ |
2204 | + IntrospectableList children; |
2205 | + |
2206 | + for (auto const& win : impl_->windows_) |
2207 | + children.push_back(win.second.get()); |
2208 | + |
2209 | + return children; |
2210 | +} |
2211 | + |
2212 | + |
2213 | +} // decoration namespace |
2214 | +} // unity namespace |
2215 | |
2216 | === added file 'decorations/DecorationsManager.h' |
2217 | --- decorations/DecorationsManager.h 1970-01-01 00:00:00 +0000 |
2218 | +++ decorations/DecorationsManager.h 2014-01-23 15:21:26 +0000 |
2219 | @@ -0,0 +1,74 @@ |
2220 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
2221 | +/* |
2222 | + * Copyright (C) 2013 Canonical Ltd |
2223 | + * |
2224 | + * This program is free software: you can redistribute it and/or modify |
2225 | + * it under the terms of the GNU General Public License version 3 as |
2226 | + * published by the Free Software Foundation. |
2227 | + * |
2228 | + * This program is distributed in the hope that it will be useful, |
2229 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2230 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2231 | + * GNU General Public License for more details. |
2232 | + * |
2233 | + * You should have received a copy of the GNU General Public License |
2234 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2235 | + * |
2236 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
2237 | + */ |
2238 | + |
2239 | +#ifndef UNITY_DECORATION_MANAGER |
2240 | +#define UNITY_DECORATION_MANAGER |
2241 | + |
2242 | +#include <NuxCore/Property.h> |
2243 | +#include "DecoratedWindow.h" |
2244 | + |
2245 | +class CompWindow; |
2246 | +class CompManager; |
2247 | + |
2248 | +namespace unity |
2249 | +{ |
2250 | +namespace decoration |
2251 | +{ |
2252 | +class Manager : public debug::Introspectable |
2253 | +{ |
2254 | +public: |
2255 | + typedef std::shared_ptr<Manager> Ptr; |
2256 | + |
2257 | + Manager(); |
2258 | + virtual ~Manager(); |
2259 | + |
2260 | + nux::Property<nux::Point> shadow_offset; |
2261 | + nux::Property<nux::Color> active_shadow_color; |
2262 | + nux::Property<unsigned> active_shadow_radius; |
2263 | + nux::Property<nux::Color> inactive_shadow_color; |
2264 | + nux::Property<unsigned> inactive_shadow_radius; |
2265 | + |
2266 | + void AddSupportedAtoms(std::vector<Atom>& atoms) const; |
2267 | + bool HandleEventBefore(XEvent*); |
2268 | + bool HandleEventAfter(XEvent*); |
2269 | + |
2270 | + Window::Ptr HandleWindow(CompWindow*); |
2271 | + void UnHandleWindow(CompWindow*); |
2272 | + |
2273 | + Window::Ptr GetWindowByXid(::Window); |
2274 | + |
2275 | +protected: |
2276 | + std::string GetName() const; |
2277 | + void AddProperties(debug::IntrospectionData&); |
2278 | + IntrospectableList GetIntrospectableChildren(); |
2279 | + |
2280 | +private: |
2281 | + Manager(Manager const&) = delete; |
2282 | + Manager& operator=(Manager const&) = delete; |
2283 | + |
2284 | + friend class Window; |
2285 | + |
2286 | + struct Impl; |
2287 | + std::unique_ptr<Impl> impl_; |
2288 | +}; |
2289 | + |
2290 | +} // decoration namespace |
2291 | +} // unity namespace |
2292 | + |
2293 | +#endif |
2294 | |
2295 | === added file 'decorations/DecorationsPriv.h' |
2296 | --- decorations/DecorationsPriv.h 1970-01-01 00:00:00 +0000 |
2297 | +++ decorations/DecorationsPriv.h 2014-01-23 15:21:26 +0000 |
2298 | @@ -0,0 +1,165 @@ |
2299 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
2300 | +/* |
2301 | + * Copyright (C) 2013 Canonical Ltd |
2302 | + * |
2303 | + * This program is free software: you can redistribute it and/or modify |
2304 | + * it under the terms of the GNU General Public License version 3 as |
2305 | + * published by the Free Software Foundation. |
2306 | + * |
2307 | + * This program is distributed in the hope that it will be useful, |
2308 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2309 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2310 | + * GNU General Public License for more details. |
2311 | + * |
2312 | + * You should have received a copy of the GNU General Public License |
2313 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2314 | + * |
2315 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
2316 | + */ |
2317 | + |
2318 | +#ifndef UNITY_DECORATION_MANAGER_PRIV |
2319 | +#define UNITY_DECORATION_MANAGER_PRIV |
2320 | + |
2321 | +#include <unordered_map> |
2322 | +#include <NuxCore/NuxCore.h> |
2323 | +#include <NuxCore/Rect.h> |
2324 | +#include <UnityCore/ConnectionManager.h> |
2325 | +#include <core/core.h> |
2326 | +#include <opengl/opengl.h> |
2327 | +#include <composite/composite.h> |
2328 | +#include <X11/extensions/shape.h> |
2329 | + |
2330 | +#include "DecorationsDataPool.h" |
2331 | +#include "DecorationsManager.h" |
2332 | +#include "DecorationsTitle.h" |
2333 | +#include "DecorationsInputMixer.h" |
2334 | + |
2335 | +class CompRegion; |
2336 | + |
2337 | +namespace unity |
2338 | +{ |
2339 | +namespace decoration |
2340 | +{ |
2341 | +namespace cu = compiz_utils; |
2342 | + |
2343 | +extern Manager* manager_; |
2344 | + |
2345 | +struct Quads |
2346 | +{ |
2347 | + enum class Pos |
2348 | + { |
2349 | + TOP_LEFT = 0, |
2350 | + TOP_RIGHT, |
2351 | + BOTTOM_LEFT, |
2352 | + BOTTOM_RIGHT, |
2353 | + Size |
2354 | + }; |
2355 | + |
2356 | + cu::TextureQuad& operator[](Pos position) { return inner_vector_[unsigned(position)]; } |
2357 | + cu::TextureQuad const& operator[](Pos position) const { return inner_vector_[unsigned(position)]; } |
2358 | + std::size_t size() const { return inner_vector_.size(); } |
2359 | + |
2360 | +private: |
2361 | + std::array<cu::TextureQuad, size_t(Pos::Size)> inner_vector_; |
2362 | +}; |
2363 | + |
2364 | +struct Window::Impl |
2365 | +{ |
2366 | + Impl(decoration::Window*, CompWindow*); |
2367 | + ~Impl(); |
2368 | + |
2369 | + nux::Property<bool> active; |
2370 | + sigc::signal<void, bool, ::Window> framed; |
2371 | + |
2372 | + void Update(); |
2373 | + void Decorate(); |
2374 | + void Undecorate(); |
2375 | + bool IsMaximized() const; |
2376 | + bool FullyDecorated() const; |
2377 | + bool ShadowDecorated() const; |
2378 | + void RedrawDecorations(); |
2379 | + |
2380 | +private: |
2381 | + void UnsetExtents(); |
2382 | + void SetupExtents(); |
2383 | + void UpdateFrame(); |
2384 | + void CreateFrame(nux::Geometry const&); |
2385 | + void UpdateFrameGeo(nux::Geometry const&); |
2386 | + void UnsetFrame(); |
2387 | + void SetupWindowControls(); |
2388 | + void CleanupWindowControls(); |
2389 | + void SyncXShapeWithFrameRegion(); |
2390 | + bool ShouldBeDecorated() const; |
2391 | + GLTexture* ShadowTexture() const; |
2392 | + unsigned ShadowRadius() const; |
2393 | + |
2394 | + void ComputeShadowQuads(); |
2395 | + void UpdateDecorationTextures(); |
2396 | + void RenderDecorationTexture(Side, nux::Geometry const&); |
2397 | + void Draw(GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); |
2398 | + |
2399 | + friend class Window; |
2400 | + friend struct Manager::Impl; |
2401 | + |
2402 | + decoration::Window *parent_; |
2403 | + ::CompWindow* win_; |
2404 | + ::CompositeWindow* cwin_; |
2405 | + ::GLWindow* glwin_; |
2406 | + ::Window frame_; |
2407 | + bool dirty_geo_; |
2408 | + |
2409 | + CompRect last_shadow_rect_; |
2410 | + Quads shadow_quads_; |
2411 | + nux::Geometry frame_geo_; |
2412 | + CompRegion frame_region_; |
2413 | + connection::Wrapper theme_changed_; |
2414 | + std::string last_title_; |
2415 | + std::vector<cu::SimpleTextureQuad> bg_textures_; |
2416 | + InputMixer::Ptr input_mixer_; |
2417 | + Layout::Ptr top_layout_; |
2418 | + Title::Ptr title_; |
2419 | + Item::Ptr edge_borders_; |
2420 | +}; |
2421 | + |
2422 | +struct Manager::Impl : sigc::trackable |
2423 | +{ |
2424 | + Impl(decoration::Manager*); |
2425 | + ~Impl(); |
2426 | + |
2427 | + Window::Ptr HandleWindow(CompWindow* cwin); |
2428 | + bool HandleEventBefore(XEvent*); |
2429 | + bool HandleEventAfter(XEvent*); |
2430 | + bool HandleFrameEvent(XEvent*); |
2431 | + |
2432 | +private: |
2433 | + Window::Ptr GetWindowByXid(::Window) const; |
2434 | + Window::Ptr GetWindowByFrame(::Window) const; |
2435 | + |
2436 | + bool UpdateWindow(::Window); |
2437 | + void UpdateWindowsExtents(); |
2438 | + |
2439 | + void BuildActiveShadowTexture(); |
2440 | + void BuildInactiveShadowTexture(); |
2441 | + cu::PixmapTexture::Ptr BuildShadowTexture(unsigned radius, nux::Color const&); |
2442 | + void OnShadowOptionsChanged(bool active); |
2443 | + void OnWindowFrameChanged(bool, ::Window, std::weak_ptr<decoration::Window> const&); |
2444 | + |
2445 | + friend class Manager; |
2446 | + friend struct Window::Impl; |
2447 | + |
2448 | + ::Window active_window_; |
2449 | + bool enable_add_supported_atoms_; |
2450 | + |
2451 | + DataPool::Ptr data_pool_; |
2452 | + cu::PixmapTexture::Ptr active_shadow_pixmap_; |
2453 | + cu::PixmapTexture::Ptr inactive_shadow_pixmap_; |
2454 | + |
2455 | + std::weak_ptr<InputMixer> last_mouse_owner_; |
2456 | + std::map<CompWindow*, decoration::Window::Ptr> windows_; |
2457 | + std::unordered_map<::Window, std::weak_ptr<decoration::Window>> framed_windows_; |
2458 | +}; |
2459 | + |
2460 | +} // decoration namespace |
2461 | +} // unity namespace |
2462 | + |
2463 | +#endif |
2464 | |
2465 | === added file 'decorations/DecorationsTitle.cpp' |
2466 | --- decorations/DecorationsTitle.cpp 1970-01-01 00:00:00 +0000 |
2467 | +++ decorations/DecorationsTitle.cpp 2014-01-23 15:21:26 +0000 |
2468 | @@ -0,0 +1,116 @@ |
2469 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
2470 | +/* |
2471 | + * Copyright (C) 2013 Canonical Ltd |
2472 | + * |
2473 | + * This program is free software: you can redistribute it and/or modify |
2474 | + * it under the terms of the GNU General Public License version 3 as |
2475 | + * published by the Free Software Foundation. |
2476 | + * |
2477 | + * This program is distributed in the hope that it will be useful, |
2478 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2479 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2480 | + * GNU General Public License for more details. |
2481 | + * |
2482 | + * You should have received a copy of the GNU General Public License |
2483 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2484 | + * |
2485 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
2486 | + */ |
2487 | + |
2488 | +#include <sigc++/adaptors/hide.h> |
2489 | +#include "DecorationsTitle.h" |
2490 | +#include "DecorationStyle.h" |
2491 | + |
2492 | +namespace unity |
2493 | +{ |
2494 | +namespace decoration |
2495 | +{ |
2496 | + |
2497 | +Title::Title() |
2498 | +{ |
2499 | + text.changed.connect(sigc::mem_fun(this, &Title::OnTextChanged)); |
2500 | + focused.changed.connect(sigc::hide(sigc::mem_fun(this, &Title::RenderTexture))); |
2501 | + Style::Get()->title_font.changed.connect(sigc::mem_fun(this, &Title::OnFontChanged)); |
2502 | +} |
2503 | + |
2504 | +void Title::OnTextChanged(std::string const& new_text) |
2505 | +{ |
2506 | + bool damaged = false; |
2507 | + auto real_size = Style::Get()->TitleNaturalSize(new_text); |
2508 | + |
2509 | + if (GetNaturalWidth() > real_size.width || GetNaturalHeight() > real_size.height) |
2510 | + { |
2511 | + Damage(); |
2512 | + damaged = true; |
2513 | + } |
2514 | + |
2515 | + SetSize(real_size.width, real_size.height); |
2516 | + texture_size_ = nux::Size(); |
2517 | + |
2518 | + if (!damaged) |
2519 | + Damage(); |
2520 | +} |
2521 | + |
2522 | +void Title::OnFontChanged(std::string const&) |
2523 | +{ |
2524 | + text.changed.emit(text()); |
2525 | +} |
2526 | + |
2527 | +void Title::RenderTexture() |
2528 | +{ |
2529 | + auto state = focused() ? WidgetState::NORMAL : WidgetState::BACKDROP; |
2530 | + cu::CairoContext text_ctx(texture_size_.width, texture_size_.height); |
2531 | + Style::Get()->DrawTitle(text(), state, text_ctx, texture_size_.width, texture_size_.height); |
2532 | + SetTexture(text_ctx); |
2533 | +} |
2534 | + |
2535 | +void Title::SetX(int x) |
2536 | +{ |
2537 | + float alignment = Style::Get()->TitleAlignmentValue(); |
2538 | + |
2539 | + if (alignment > 0) |
2540 | + { |
2541 | + if (BasicContainer::Ptr const& top = GetTopParent()) |
2542 | + { |
2543 | + auto const& top_geo = top->ContentGeometry(); |
2544 | + x = std::max<int>(x, top_geo.x() + (top_geo.width() - GetNaturalWidth()) * alignment); |
2545 | + } |
2546 | + } |
2547 | + |
2548 | + TexturedItem::SetX(x); |
2549 | +} |
2550 | + |
2551 | +int Title::GetNaturalWidth() const |
2552 | +{ |
2553 | + return Item::GetNaturalWidth(); |
2554 | +} |
2555 | + |
2556 | +int Title::GetNaturalHeight() const |
2557 | +{ |
2558 | + return Item::GetNaturalHeight(); |
2559 | +} |
2560 | + |
2561 | +void Title::Draw(GLWindow* ctx, GLMatrix const& transformation, GLWindowPaintAttrib const& attrib, |
2562 | + CompRegion const& clip, unsigned mask) |
2563 | +{ |
2564 | + auto const& geo = Geometry(); |
2565 | + nux::Size tex_size(geo.width(), geo.height()); |
2566 | + |
2567 | + if (texture_size_ != tex_size) |
2568 | + { |
2569 | + texture_size_ = tex_size; |
2570 | + RenderTexture(); |
2571 | + } |
2572 | + |
2573 | + TexturedItem::Draw(ctx, transformation, attrib, clip, mask); |
2574 | +} |
2575 | + |
2576 | +void Title::AddProperties(debug::IntrospectionData& data) |
2577 | +{ |
2578 | + TexturedItem::AddProperties(data); |
2579 | + data.add("text", text()) |
2580 | + .add("texture_size", texture_size_); |
2581 | +} |
2582 | + |
2583 | +} // decoration namespace |
2584 | +} // unity namespace |
2585 | |
2586 | === added file 'decorations/DecorationsTitle.h' |
2587 | --- decorations/DecorationsTitle.h 1970-01-01 00:00:00 +0000 |
2588 | +++ decorations/DecorationsTitle.h 2014-01-23 15:21:26 +0000 |
2589 | @@ -0,0 +1,61 @@ |
2590 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
2591 | +/* |
2592 | + * Copyright (C) 2013 Canonical Ltd |
2593 | + * |
2594 | + * This program is free software: you can redistribute it and/or modify |
2595 | + * it under the terms of the GNU General Public License version 3 as |
2596 | + * published by the Free Software Foundation. |
2597 | + * |
2598 | + * This program is distributed in the hope that it will be useful, |
2599 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2600 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2601 | + * GNU General Public License for more details. |
2602 | + * |
2603 | + * You should have received a copy of the GNU General Public License |
2604 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2605 | + * |
2606 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
2607 | + */ |
2608 | + |
2609 | +#ifndef UNITY_DECORATIONS_TITLE |
2610 | +#define UNITY_DECORATIONS_TITLE |
2611 | + |
2612 | +#include "DecorationsWidgets.h" |
2613 | + |
2614 | +namespace unity |
2615 | +{ |
2616 | +namespace decoration |
2617 | +{ |
2618 | + |
2619 | +class Title : public TexturedItem |
2620 | +{ |
2621 | +public: |
2622 | + typedef std::shared_ptr<Title> Ptr; |
2623 | + |
2624 | + nux::Property<std::string> text; |
2625 | + |
2626 | + Title(); |
2627 | + |
2628 | + void SetX(int); |
2629 | + int GetNaturalWidth() const; |
2630 | + int GetNaturalHeight() const; |
2631 | + |
2632 | + void Draw(GLWindow*, GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); |
2633 | + |
2634 | +protected: |
2635 | + std::string GetName() const { return "Title"; } |
2636 | + void AddProperties(debug::IntrospectionData&); |
2637 | + |
2638 | +private: |
2639 | + void OnFontChanged(std::string const&); |
2640 | + void OnTextChanged(std::string const& new_text); |
2641 | + void RenderTexture(); |
2642 | + |
2643 | + bool render_texture_; |
2644 | + nux::Size texture_size_; |
2645 | +}; |
2646 | + |
2647 | +} // decoration namespace |
2648 | +} // unity namespace |
2649 | + |
2650 | +#endif // UNITY_DECORATIONS_TITLE |
2651 | |
2652 | === added file 'decorations/DecorationsWidgets.cpp' |
2653 | --- decorations/DecorationsWidgets.cpp 1970-01-01 00:00:00 +0000 |
2654 | +++ decorations/DecorationsWidgets.cpp 2014-01-23 15:21:26 +0000 |
2655 | @@ -0,0 +1,493 @@ |
2656 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
2657 | +/* |
2658 | + * Copyright (C) 2013 Canonical Ltd |
2659 | + * |
2660 | + * This program is free software: you can redistribute it and/or modify |
2661 | + * it under the terms of the GNU General Public License version 3 as |
2662 | + * published by the Free Software Foundation. |
2663 | + * |
2664 | + * This program is distributed in the hope that it will be useful, |
2665 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2666 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2667 | + * GNU General Public License for more details. |
2668 | + * |
2669 | + * You should have received a copy of the GNU General Public License |
2670 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2671 | + * |
2672 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
2673 | + */ |
2674 | + |
2675 | +#include <NuxCore/Logger.h> |
2676 | +#include <composite/composite.h> |
2677 | +#include <boost/range/adaptor/reversed.hpp> |
2678 | +#include "DecorationsWidgets.h" |
2679 | + |
2680 | +namespace unity |
2681 | +{ |
2682 | +namespace decoration |
2683 | +{ |
2684 | +namespace |
2685 | +{ |
2686 | +DECLARE_LOGGER(logger, "unity.decoration.widgets"); |
2687 | +CompositeScreen* cscreen_ = CompositeScreen::get(screen); |
2688 | + |
2689 | +template <typename T> constexpr T max(T a, T b) { return (a > b) ? a : b; } |
2690 | +template <typename T> constexpr T min(T a, T b) { return (a < b) ? a : b; } |
2691 | +constexpr int clamp_size(int v) { return min<int>(max(0, v), std::numeric_limits<short>::max()); } |
2692 | +} |
2693 | + |
2694 | +Item::Item() |
2695 | + : visible(true) |
2696 | + , focused(false) |
2697 | + , sensitive(true) |
2698 | + , mouse_owner(false) |
2699 | + , max_(std::numeric_limits<short>::max(), std::numeric_limits<short>::max()) |
2700 | +{ |
2701 | + auto parent_relayout_cb = sigc::mem_fun(this, &Item::RequestRelayout); |
2702 | + visible.changed.connect(sigc::hide(parent_relayout_cb)); |
2703 | + geo_parameters_changed.connect(parent_relayout_cb); |
2704 | +} |
2705 | + |
2706 | +void Item::SetSize(int width, int height) |
2707 | +{ |
2708 | + natural_.width = clamp_size(width); |
2709 | + natural_.height = clamp_size(height); |
2710 | + SetMinWidth(width); |
2711 | + SetMaxWidth(width); |
2712 | + SetMinHeight(height); |
2713 | + SetMaxHeight(height); |
2714 | +} |
2715 | + |
2716 | +void Item::SetCoords(int x, int y) |
2717 | +{ |
2718 | + auto& geo = InternalGeo(); |
2719 | + |
2720 | + if (geo.x() == x && geo.y() == y) |
2721 | + return; |
2722 | + |
2723 | + geo.setX(x); |
2724 | + geo.setY(y); |
2725 | + geo_parameters_changed.emit(); |
2726 | +} |
2727 | + |
2728 | +int Item::GetNaturalWidth() const |
2729 | +{ |
2730 | + return natural_.width; |
2731 | +} |
2732 | + |
2733 | +int Item::GetNaturalHeight() const |
2734 | +{ |
2735 | + return natural_.height; |
2736 | +} |
2737 | + |
2738 | +int Item::GetMaxWidth() const |
2739 | +{ |
2740 | + return max_.width; |
2741 | +}; |
2742 | + |
2743 | +int Item::GetMaxHeight() const |
2744 | +{ |
2745 | + return max_.height; |
2746 | +}; |
2747 | + |
2748 | +int Item::GetMinWidth() const |
2749 | +{ |
2750 | + return min_.width; |
2751 | +}; |
2752 | + |
2753 | +int Item::GetMinHeight() const |
2754 | +{ |
2755 | + return min_.height; |
2756 | +}; |
2757 | + |
2758 | +void Item::SetMaxWidth(int value) |
2759 | +{ |
2760 | + int clamped = clamp_size(value); |
2761 | + |
2762 | + if (max_.width == clamped) |
2763 | + return; |
2764 | + |
2765 | + max_.width = clamped; |
2766 | + min_.width = min(min_.width, max_.width); |
2767 | + |
2768 | + if (Geometry().width() > max_.width) |
2769 | + InternalGeo().setWidth(min(GetNaturalWidth(), max_.width)); |
2770 | + |
2771 | + geo_parameters_changed.emit(); |
2772 | +} |
2773 | + |
2774 | +void Item::SetMinWidth(int value) |
2775 | +{ |
2776 | + int clamped = clamp_size(value); |
2777 | + |
2778 | + if (min_.width == clamped) |
2779 | + return; |
2780 | + |
2781 | + min_.width = clamped; |
2782 | + max_.width = max(min_.width, max_.width); |
2783 | + |
2784 | + if (Geometry().width() < min_.width) |
2785 | + InternalGeo().setWidth(min_.width); |
2786 | + |
2787 | + geo_parameters_changed.emit(); |
2788 | +} |
2789 | + |
2790 | +void Item::SetMaxHeight(int value) |
2791 | +{ |
2792 | + int clamped = clamp_size(value); |
2793 | + |
2794 | + if (max_.height == clamped) |
2795 | + return; |
2796 | + |
2797 | + max_.height = clamped; |
2798 | + min_.height = min(min_.height, max_.height); |
2799 | + |
2800 | + if (Geometry().height() > max_.height) |
2801 | + InternalGeo().setHeight(min(GetNaturalHeight(), max_.height)); |
2802 | + |
2803 | + geo_parameters_changed.emit(); |
2804 | +} |
2805 | + |
2806 | +void Item::SetMinHeight(int value) |
2807 | +{ |
2808 | + int clamped = clamp_size(value); |
2809 | + |
2810 | + if (min_.height == clamped) |
2811 | + return; |
2812 | + |
2813 | + min_.height = clamped; |
2814 | + max_.height = max(min_.height, max_.height); |
2815 | + |
2816 | + if (Geometry().height() < min_.height) |
2817 | + InternalGeo().setHeight(min_.height); |
2818 | + |
2819 | + geo_parameters_changed.emit(); |
2820 | +} |
2821 | + |
2822 | +void Item::Damage() |
2823 | +{ |
2824 | + cscreen_->damageRegion(Geometry()); |
2825 | +} |
2826 | + |
2827 | +CompRect const& Item::Geometry() const |
2828 | +{ |
2829 | + return const_cast<Item*>(this)->InternalGeo(); |
2830 | +} |
2831 | + |
2832 | +void Item::SetParent(BasicContainer::Ptr const& parent) |
2833 | +{ |
2834 | + if (parent && !parent_.expired()) |
2835 | + { |
2836 | + LOG_ERROR(logger) << "This item has already a parent!"; |
2837 | + return; |
2838 | + } |
2839 | + |
2840 | + parent_ = parent; |
2841 | +} |
2842 | + |
2843 | +BasicContainer::Ptr Item::GetParent() const |
2844 | +{ |
2845 | + return parent_.lock(); |
2846 | +} |
2847 | + |
2848 | +BasicContainer::Ptr Item::GetTopParent() const |
2849 | +{ |
2850 | + BasicContainer::Ptr parent = GetParent(); |
2851 | + |
2852 | + while (parent) |
2853 | + { |
2854 | + if (parent->parent_.expired()) |
2855 | + return parent; |
2856 | + |
2857 | + parent = parent->GetParent(); |
2858 | + } |
2859 | + |
2860 | + return parent; |
2861 | +} |
2862 | + |
2863 | +void Item::RequestRelayout() |
2864 | +{ |
2865 | + if (BasicContainer::Ptr const& parent = parent_.lock()) |
2866 | + parent->Relayout(); |
2867 | +} |
2868 | + |
2869 | +void Item::AddProperties(debug::IntrospectionData& data) |
2870 | +{ |
2871 | + data.add(Geometry()) |
2872 | + .add("max_size", max_) |
2873 | + .add("min_size", min_) |
2874 | + .add("natural_size", nux::Size(GetNaturalWidth(), GetNaturalHeight())) |
2875 | + .add("visible", visible()) |
2876 | + .add("focused", focused()) |
2877 | + .add("sensitive", sensitive()) |
2878 | + .add("mouse_owner", mouse_owner()) |
2879 | + .add("is_container", IsContainer()); |
2880 | +} |
2881 | + |
2882 | +// |
2883 | + |
2884 | +void TexturedItem::SetTexture(cu::SimpleTexture::Ptr const& tex) |
2885 | +{ |
2886 | + if (texture_.st == tex) |
2887 | + return; |
2888 | + |
2889 | + auto prev_geo = Geometry(); |
2890 | + texture_.SetTexture(tex); |
2891 | + auto const& actual_geo = Geometry(); |
2892 | + |
2893 | + if (prev_geo != actual_geo) |
2894 | + { |
2895 | + max_ = { actual_geo.width(), actual_geo.height() }; |
2896 | + min_ = max_; |
2897 | + geo_parameters_changed.emit(); |
2898 | + |
2899 | + if (!actual_geo.contains(prev_geo)) |
2900 | + cscreen_->damageRegion(prev_geo); |
2901 | + } |
2902 | + |
2903 | + Damage(); |
2904 | +} |
2905 | + |
2906 | +void TexturedItem::Draw(GLWindow* ctx, GLMatrix const& transformation, GLWindowPaintAttrib const& attrib, |
2907 | + CompRegion const& clip, unsigned mask) |
2908 | +{ |
2909 | + if (!visible || Geometry().isEmpty() || !texture_) |
2910 | + return; |
2911 | + |
2912 | + ctx->vertexBuffer()->begin(); |
2913 | + ctx->glAddGeometry({texture_.quad.matrix}, texture_.quad.box, clip); |
2914 | + |
2915 | + if (ctx->vertexBuffer()->end()) |
2916 | + ctx->glDrawTexture(texture_, transformation, attrib, mask); |
2917 | +} |
2918 | + |
2919 | +int TexturedItem::GetNaturalWidth() const |
2920 | +{ |
2921 | + return (texture_) ? texture_.st->width() : Item::GetNaturalWidth(); |
2922 | +} |
2923 | + |
2924 | +int TexturedItem::GetNaturalHeight() const |
2925 | +{ |
2926 | + return (texture_) ? texture_.st->height() : Item::GetNaturalHeight(); |
2927 | +} |
2928 | + |
2929 | +CompRect& TexturedItem::InternalGeo() |
2930 | +{ |
2931 | + return texture_.quad.box; |
2932 | +} |
2933 | + |
2934 | +void TexturedItem::SetCoords(int x, int y) |
2935 | +{ |
2936 | + texture_.SetCoords(x, y); |
2937 | +} |
2938 | + |
2939 | +// |
2940 | + |
2941 | +BasicContainer::BasicContainer() |
2942 | +{ |
2943 | + geo_parameters_changed.connect(sigc::mem_fun(this, &BasicContainer::Relayout)); |
2944 | + focused.changed.connect([this] (bool focused) { |
2945 | + for (auto const& item : items_) |
2946 | + item->focused = focused; |
2947 | + }); |
2948 | +} |
2949 | + |
2950 | +CompRect BasicContainer::ContentGeometry() const |
2951 | +{ |
2952 | + return Geometry(); |
2953 | +} |
2954 | + |
2955 | +void BasicContainer::AddProperties(debug::IntrospectionData& data) |
2956 | +{ |
2957 | + Item::AddProperties(data); |
2958 | + data.add(ContentGeometry()); |
2959 | +} |
2960 | + |
2961 | +debug::Introspectable::IntrospectableList BasicContainer::GetIntrospectableChildren() |
2962 | +{ |
2963 | + IntrospectableList children; |
2964 | + |
2965 | + for (auto const& item : items_) |
2966 | + children.push_back(item.get()); |
2967 | + |
2968 | + return children; |
2969 | +} |
2970 | + |
2971 | +// |
2972 | + |
2973 | +Layout::Layout() |
2974 | + : inner_padding(0, sigc::mem_fun(this, &Layout::SetPadding)) |
2975 | + , left_padding(0, sigc::mem_fun(this, &Layout::SetPadding)) |
2976 | + , right_padding(0, sigc::mem_fun(this, &Layout::SetPadding)) |
2977 | + , top_padding(0, sigc::mem_fun(this, &Layout::SetPadding)) |
2978 | + , bottom_padding(0, sigc::mem_fun(this, &Layout::SetPadding)) |
2979 | + , relayouting_(false) |
2980 | +{} |
2981 | + |
2982 | +void Layout::Append(Item::Ptr const& item) |
2983 | +{ |
2984 | + if (!item || std::find(items_.begin(), items_.end(), item) != items_.end()) |
2985 | + return; |
2986 | + |
2987 | + if (item->GetParent()) |
2988 | + { |
2989 | + LOG_ERROR(logger) << "Impossible to add an item that has already a parent"; |
2990 | + return; |
2991 | + } |
2992 | + |
2993 | + items_.push_back(item); |
2994 | + item->focused = focused(); |
2995 | + item->SetParent(shared_from_this()); |
2996 | + Relayout(); |
2997 | +} |
2998 | + |
2999 | +void Layout::Remove(Item::Ptr const& item) |
3000 | +{ |
3001 | + auto it = std::find(items_.begin(), items_.end(), item); |
3002 | + |
3003 | + if (it == items_.end()) |
3004 | + return; |
3005 | + |
3006 | + item->SetParent(nullptr); |
3007 | + items_.erase(it); |
3008 | + Relayout(); |
3009 | +} |
3010 | + |
3011 | +CompRect Layout::ContentGeometry() const |
3012 | +{ |
3013 | + return CompRect(rect_.x() + min(left_padding(), rect_.width()), |
3014 | + rect_.y() + min(top_padding(), rect_.height()), |
3015 | + clamp_size(rect_.width() - left_padding - right_padding), |
3016 | + clamp_size(rect_.height() - top_padding - bottom_padding)); |
3017 | +} |
3018 | + |
3019 | +void Layout::Relayout() |
3020 | +{ |
3021 | + if (relayouting_) |
3022 | + return; |
3023 | + |
3024 | + relayouting_ = true; |
3025 | + int loop = 0; |
3026 | + CompRect old_geo(rect_); |
3027 | + |
3028 | + nux::Size available_space(clamp_size(max_.width - left_padding - right_padding), |
3029 | + clamp_size(max_.height - top_padding - bottom_padding)); |
3030 | + |
3031 | + do |
3032 | + { |
3033 | + nux::Size content(min(left_padding(), max_.width), 0); |
3034 | + |
3035 | + for (auto const& item : items_) |
3036 | + { |
3037 | + if (!item->visible()) |
3038 | + continue; |
3039 | + |
3040 | + if (loop == 0) |
3041 | + { |
3042 | + item->SetMinWidth(item->GetNaturalWidth()); |
3043 | + item->SetMaxWidth(available_space.width); |
3044 | + item->SetMinHeight(min(available_space.height, item->GetNaturalHeight())); |
3045 | + item->SetMaxHeight(available_space.height); |
3046 | + } |
3047 | + |
3048 | + auto const& item_geo = item->Geometry(); |
3049 | + content.height = max(content.height, item_geo.height()); |
3050 | + item->SetX(rect_.x() + content.width); |
3051 | + |
3052 | + if (item_geo.width() > 0) |
3053 | + content.width += item_geo.width() + inner_padding; |
3054 | + } |
3055 | + |
3056 | + if (!items_.empty() && content.width > inner_padding) |
3057 | + content.width -= inner_padding; |
3058 | + |
3059 | + int actual_right_padding = max(0, min(right_padding(), max_.width - content.width)); |
3060 | + int vertical_padding = top_padding + bottom_padding; |
3061 | + |
3062 | + content.width += actual_right_padding; |
3063 | + content.height += min(vertical_padding, max_.height); |
3064 | + |
3065 | + if (content.width < min_.width) |
3066 | + content.width = min_.width; |
3067 | + |
3068 | + if (content.height < min_.height) |
3069 | + content.height = min_.height; |
3070 | + |
3071 | + int exceeding_width = content.width - max_.width + inner_padding + right_padding - actual_right_padding; |
3072 | + int content_y = rect_.y() + top_padding; |
3073 | + |
3074 | + for (auto const& item : boost::adaptors::reverse(items_)) |
3075 | + { |
3076 | + if (!item->visible()) |
3077 | + continue; |
3078 | + |
3079 | + auto const& item_geo = item->Geometry(); |
3080 | + |
3081 | + if (exceeding_width > 0) |
3082 | + exceeding_width -= inner_padding; |
3083 | + |
3084 | + if (exceeding_width > 0 && item_geo.width() > 0) |
3085 | + { |
3086 | + int old_width = item_geo.width(); |
3087 | + int max_item_width = clamp_size(old_width - exceeding_width); |
3088 | + item->SetMaxWidth(max_item_width); |
3089 | + exceeding_width -= (old_width - max_item_width); |
3090 | + } |
3091 | + |
3092 | + item->SetY(content_y + (content.height - vertical_padding - item_geo.height()) / 2); |
3093 | + } |
3094 | + |
3095 | + rect_.setWidth(content.width); |
3096 | + rect_.setHeight(content.height); |
3097 | + |
3098 | + if (loop > 1) |
3099 | + { |
3100 | + LOG_ERROR(logger) << "Relayouting is taking more than expected, process should be completed in maximum two loops!"; |
3101 | + break; |
3102 | + } |
3103 | + |
3104 | + ++loop; |
3105 | + } |
3106 | + while (rect_.width() > max_.width || rect_.height() > max_.height); |
3107 | + |
3108 | + relayouting_ = false; |
3109 | + |
3110 | + if (old_geo != rect_) |
3111 | + geo_parameters_changed.emit(); |
3112 | +} |
3113 | + |
3114 | +void Layout::Draw(GLWindow* ctx, GLMatrix const& transformation, GLWindowPaintAttrib const& attrib, |
3115 | + CompRegion const& clip, unsigned mask) |
3116 | +{ |
3117 | + for (auto const& item : items_) |
3118 | + { |
3119 | + if (item->visible()) |
3120 | + item->Draw(ctx, transformation, attrib, clip, mask); |
3121 | + } |
3122 | +} |
3123 | + |
3124 | +bool Layout::SetPadding(int& target, int new_value) |
3125 | +{ |
3126 | + int padding = clamp_size(new_value); |
3127 | + |
3128 | + if (padding == target) |
3129 | + return false; |
3130 | + |
3131 | + target = padding; |
3132 | + Relayout(); |
3133 | + |
3134 | + return true; |
3135 | +} |
3136 | + |
3137 | +void Layout::AddProperties(debug::IntrospectionData& data) |
3138 | +{ |
3139 | + Item::AddProperties(data); |
3140 | + data.add("inner_padding", inner_padding()) |
3141 | + .add("left_padding", left_padding()) |
3142 | + .add("right_padding", right_padding()) |
3143 | + .add("top_padding", top_padding()) |
3144 | + .add("bottom_padding", bottom_padding()); |
3145 | +} |
3146 | + |
3147 | +} // decoration namespace |
3148 | +} // unity namespace |
3149 | |
3150 | === added file 'decorations/DecorationsWidgets.h' |
3151 | --- decorations/DecorationsWidgets.h 1970-01-01 00:00:00 +0000 |
3152 | +++ decorations/DecorationsWidgets.h 2014-01-23 15:21:26 +0000 |
3153 | @@ -0,0 +1,190 @@ |
3154 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
3155 | +/* |
3156 | + * Copyright (C) 2013 Canonical Ltd |
3157 | + * |
3158 | + * This program is free software: you can redistribute it and/or modify |
3159 | + * it under the terms of the GNU General Public License version 3 as |
3160 | + * published by the Free Software Foundation. |
3161 | + * |
3162 | + * This program is distributed in the hope that it will be useful, |
3163 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3164 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3165 | + * GNU General Public License for more details. |
3166 | + * |
3167 | + * You should have received a copy of the GNU General Public License |
3168 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3169 | + * |
3170 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
3171 | + */ |
3172 | + |
3173 | +#ifndef UNITY_DECORATION_WIDGETS |
3174 | +#define UNITY_DECORATION_WIDGETS |
3175 | + |
3176 | +#include <deque> |
3177 | +#include <NuxCore/Size.h> |
3178 | +#include <NuxCore/Property.h> |
3179 | +#include "Introspectable.h" |
3180 | +#include "CompizUtils.h" |
3181 | + |
3182 | +namespace unity |
3183 | +{ |
3184 | +namespace decoration |
3185 | +{ |
3186 | +namespace cu = compiz_utils; |
3187 | + |
3188 | +class BasicContainer; |
3189 | + |
3190 | +class Item : public sigc::trackable, public debug::Introspectable |
3191 | +{ |
3192 | +public: |
3193 | + typedef std::shared_ptr<Item> Ptr; |
3194 | + typedef std::deque<Item::Ptr> List; |
3195 | + |
3196 | + Item(); |
3197 | + virtual ~Item() = default; |
3198 | + |
3199 | + nux::Property<bool> visible; |
3200 | + nux::Property<bool> focused; |
3201 | + nux::Property<bool> sensitive; |
3202 | + nux::Property<bool> mouse_owner; |
3203 | + |
3204 | + CompRect const& Geometry() const; |
3205 | + virtual int GetNaturalWidth() const; |
3206 | + virtual int GetNaturalHeight() const; |
3207 | + |
3208 | + virtual void SetCoords(int x, int y); |
3209 | + virtual void SetX(int x) { SetCoords(x, Geometry().y()); } |
3210 | + virtual void SetY(int y) { SetCoords(Geometry().x(), y); } |
3211 | + virtual void SetSize(int width, int height); |
3212 | + virtual void SetWidth(int width) { SetSize(width, Geometry().height()); } |
3213 | + virtual void SetHeight(int height) { SetSize(Geometry().width(), height); }; |
3214 | + |
3215 | + virtual void SetMaxWidth(int max_width); |
3216 | + virtual void SetMaxHeight(int max_height); |
3217 | + virtual void SetMinWidth(int min_width); |
3218 | + virtual void SetMinHeight(int min_height); |
3219 | + |
3220 | + int GetMaxWidth() const; |
3221 | + int GetMaxHeight() const; |
3222 | + int GetMinWidth() const; |
3223 | + int GetMinHeight() const; |
3224 | + |
3225 | + void SetParent(std::shared_ptr<BasicContainer> const&); |
3226 | + std::shared_ptr<BasicContainer> GetParent() const; |
3227 | + std::shared_ptr<BasicContainer> GetTopParent() const; |
3228 | + |
3229 | + void Damage(); |
3230 | + virtual void Draw(GLWindow*, GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask) {} |
3231 | + |
3232 | +protected: |
3233 | + virtual CompRect& InternalGeo() = 0; |
3234 | + sigc::signal<void> geo_parameters_changed; |
3235 | + |
3236 | + virtual bool IsContainer() const { return false; } |
3237 | + void RequestRelayout(); |
3238 | + |
3239 | + friend class InputMixer; |
3240 | + virtual void MotionEvent(CompPoint const&) {} |
3241 | + virtual void ButtonDownEvent(CompPoint const&, unsigned button) {} |
3242 | + virtual void ButtonUpEvent(CompPoint const&, unsigned button) {} |
3243 | + |
3244 | + std::string GetName() const { return "Item"; } |
3245 | + void AddProperties(debug::IntrospectionData&); |
3246 | + |
3247 | +private: |
3248 | + Item(Item const&) = delete; |
3249 | + Item& operator=(Item const&) = delete; |
3250 | + |
3251 | +protected: |
3252 | + nux::Size max_; |
3253 | + nux::Size min_; |
3254 | + nux::Size natural_; |
3255 | + |
3256 | +private: |
3257 | + std::weak_ptr<BasicContainer> parent_; |
3258 | +}; |
3259 | + |
3260 | +class SimpleItem : public Item |
3261 | +{ |
3262 | +protected: |
3263 | + CompRect& InternalGeo() { return rect_; } |
3264 | + CompRect rect_; |
3265 | +}; |
3266 | + |
3267 | + |
3268 | +class TexturedItem : public Item |
3269 | +{ |
3270 | +public: |
3271 | + typedef std::shared_ptr<TexturedItem> Ptr; |
3272 | + |
3273 | + void SetTexture(cu::SimpleTexture::Ptr const&); |
3274 | + void Draw(GLWindow*, GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); |
3275 | + void SetCoords(int x, int y); |
3276 | + |
3277 | + int GetNaturalWidth() const; |
3278 | + int GetNaturalHeight() const; |
3279 | + |
3280 | +protected: |
3281 | + std::string GetName() const { return "TexturedItem"; } |
3282 | + |
3283 | + CompRect& InternalGeo(); |
3284 | + cu::SimpleTextureQuad texture_; |
3285 | +}; |
3286 | + |
3287 | + |
3288 | +class BasicContainer : public SimpleItem |
3289 | +{ |
3290 | +public: |
3291 | + typedef std::shared_ptr<BasicContainer> Ptr; |
3292 | + |
3293 | + BasicContainer(); |
3294 | + Item::List const& Items() const { return items_; } |
3295 | + |
3296 | + virtual CompRect ContentGeometry() const; |
3297 | + |
3298 | +protected: |
3299 | + friend class Item; |
3300 | + virtual void Relayout() = 0; |
3301 | + bool IsContainer() const { return true; } |
3302 | + |
3303 | + std::string GetName() const { return "BasicContainer"; } |
3304 | + void AddProperties(debug::IntrospectionData&); |
3305 | + IntrospectableList GetIntrospectableChildren(); |
3306 | + |
3307 | + Item::List items_; |
3308 | +}; |
3309 | + |
3310 | + |
3311 | +class Layout : public std::enable_shared_from_this<Layout>, public BasicContainer |
3312 | +{ |
3313 | +public: |
3314 | + typedef std::shared_ptr<Layout> Ptr; |
3315 | + |
3316 | + Layout(); |
3317 | + |
3318 | + nux::Property<int> inner_padding; |
3319 | + nux::Property<int> left_padding; |
3320 | + nux::Property<int> right_padding; |
3321 | + nux::Property<int> top_padding; |
3322 | + nux::Property<int> bottom_padding; |
3323 | + |
3324 | + void Append(Item::Ptr const&); |
3325 | + void Remove(Item::Ptr const&); |
3326 | + |
3327 | + CompRect ContentGeometry() const; |
3328 | + void Draw(GLWindow*, GLMatrix const&, GLWindowPaintAttrib const&, CompRegion const&, unsigned mask); |
3329 | + |
3330 | +protected: |
3331 | + void Relayout(); |
3332 | + std::string GetName() const { return "Layout"; } |
3333 | + void AddProperties(debug::IntrospectionData&); |
3334 | + |
3335 | +private: |
3336 | + bool SetPadding(int& target, int new_value); |
3337 | + bool relayouting_; |
3338 | +}; |
3339 | + |
3340 | +} // decoration namespace |
3341 | +} // unity namespace |
3342 | + |
3343 | +#endif |
3344 | |
3345 | === added file 'decorations/DecorationsWindowButton.cpp' |
3346 | --- decorations/DecorationsWindowButton.cpp 1970-01-01 00:00:00 +0000 |
3347 | +++ decorations/DecorationsWindowButton.cpp 2014-01-23 15:21:26 +0000 |
3348 | @@ -0,0 +1,216 @@ |
3349 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
3350 | +/* |
3351 | + * Copyright (C) 2013 Canonical Ltd |
3352 | + * |
3353 | + * This program is free software: you can redistribute it and/or modify |
3354 | + * it under the terms of the GNU General Public License version 3 as |
3355 | + * published by the Free Software Foundation. |
3356 | + * |
3357 | + * This program is distributed in the hope that it will be useful, |
3358 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3359 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3360 | + * GNU General Public License for more details. |
3361 | + * |
3362 | + * You should have received a copy of the GNU General Public License |
3363 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3364 | + * |
3365 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
3366 | + */ |
3367 | + |
3368 | +#include <sigc++/adaptors/hide.h> |
3369 | +#include "DecorationsWindowButton.h" |
3370 | +#include "DecorationsDataPool.h" |
3371 | + |
3372 | +namespace unity |
3373 | +{ |
3374 | +namespace decoration |
3375 | +{ |
3376 | + |
3377 | +WindowButton::WindowButton(CompWindow* win, WindowButtonType type) |
3378 | + : type_(type) |
3379 | + , pressed_(false) |
3380 | + , was_pressed_(false) |
3381 | + , win_(win) |
3382 | +{ |
3383 | + auto cb = sigc::hide(sigc::mem_fun(this, &WindowButton::UpdateTexture)); |
3384 | + mouse_owner.changed.connect(cb); |
3385 | + focused.changed.connect(cb); |
3386 | + UpdateTexture(); |
3387 | +} |
3388 | + |
3389 | +void WindowButton::UpdateTexture() |
3390 | +{ |
3391 | + SetTexture(DataPool::Get()->ButtonTexture(type_, GetCurrentState())); |
3392 | +} |
3393 | + |
3394 | +WidgetState WindowButton::GetCurrentState() const |
3395 | +{ |
3396 | + if (focused()) |
3397 | + { |
3398 | + if (mouse_owner() && pressed_) |
3399 | + { |
3400 | + return WidgetState::PRESSED; |
3401 | + } |
3402 | + else if (mouse_owner() && !was_pressed_) |
3403 | + { |
3404 | + return WidgetState::PRELIGHT; |
3405 | + } |
3406 | + else |
3407 | + { |
3408 | + return WidgetState::NORMAL; |
3409 | + } |
3410 | + } |
3411 | + else |
3412 | + { |
3413 | + if (mouse_owner() && pressed_) |
3414 | + { |
3415 | + return WidgetState::BACKDROP_PRESSED; |
3416 | + } |
3417 | + else if (mouse_owner() && !was_pressed_) |
3418 | + { |
3419 | + return WidgetState::BACKDROP_PRELIGHT; |
3420 | + } |
3421 | + else |
3422 | + { |
3423 | + return WidgetState::BACKDROP; |
3424 | + } |
3425 | + } |
3426 | +} |
3427 | + |
3428 | +void WindowButton::ButtonDownEvent(CompPoint const& p, unsigned button) |
3429 | +{ |
3430 | + if (!pressed_ && button <= Button3) |
3431 | + { |
3432 | + pressed_ = true; |
3433 | + was_pressed_ = true; |
3434 | + UpdateTexture(); |
3435 | + } |
3436 | +} |
3437 | + |
3438 | +void WindowButton::ButtonUpEvent(CompPoint const& p, unsigned button) |
3439 | +{ |
3440 | + if (pressed_ && button <= Button3) |
3441 | + { |
3442 | + pressed_ = false; |
3443 | + UpdateTexture(); |
3444 | + |
3445 | + switch (type_) |
3446 | + { |
3447 | + case WindowButtonType::CLOSE: |
3448 | + if (win_->actions() & CompWindowActionCloseMask) |
3449 | + win_->close(screen->getCurrentTime()); |
3450 | + break; |
3451 | + case WindowButtonType::MINIMIZE: |
3452 | + if (win_->actions() & CompWindowActionMinimizeMask) |
3453 | + win_->minimize(); |
3454 | + break; |
3455 | + case WindowButtonType::MAXIMIZE: |
3456 | + switch (button) |
3457 | + { |
3458 | + case Button1: |
3459 | + if ((win_->state() & CompWindowStateMaximizedVertMask) || |
3460 | + (win_->state() & CompWindowStateMaximizedHorzMask)) |
3461 | + win_->maximize(0); |
3462 | + else if (win_->actions() & (CompWindowActionMaximizeHorzMask|CompWindowActionMaximizeVertMask)) |
3463 | + win_->maximize(MAXIMIZE_STATE); |
3464 | + break; |
3465 | + case Button2: |
3466 | + if (win_->actions() & CompWindowActionMaximizeVertMask) |
3467 | + { |
3468 | + if (!(win_->state() & CompWindowStateMaximizedVertMask)) |
3469 | + win_->maximize(CompWindowStateMaximizedVertMask); |
3470 | + else |
3471 | + win_->maximize(0); |
3472 | + } |
3473 | + break; |
3474 | + case Button3: |
3475 | + if (win_->actions() & CompWindowActionMaximizeHorzMask) |
3476 | + { |
3477 | + if (!(win_->state() & CompWindowStateMaximizedHorzMask)) |
3478 | + win_->maximize(CompWindowStateMaximizedHorzMask); |
3479 | + else |
3480 | + win_->maximize(0); |
3481 | + } |
3482 | + break; |
3483 | + } |
3484 | + break; |
3485 | + default: |
3486 | + break; |
3487 | + } |
3488 | + } |
3489 | + |
3490 | + was_pressed_ = false; |
3491 | +} |
3492 | + |
3493 | +void WindowButton::MotionEvent(CompPoint const& p) |
3494 | +{ |
3495 | + if (pressed_) |
3496 | + { |
3497 | + if (!Geometry().contains(p)) |
3498 | + { |
3499 | + pressed_ = false; |
3500 | + UpdateTexture(); |
3501 | + } |
3502 | + } |
3503 | + else if (was_pressed_) |
3504 | + { |
3505 | + if (Geometry().contains(p)) |
3506 | + { |
3507 | + pressed_ = true; |
3508 | + UpdateTexture(); |
3509 | + } |
3510 | + } |
3511 | +} |
3512 | + |
3513 | +std::string WindowButton::GetName() const |
3514 | +{ |
3515 | + switch (type_) |
3516 | + { |
3517 | + case WindowButtonType::CLOSE: |
3518 | + return "CloseWindowButton"; |
3519 | + case WindowButtonType::MINIMIZE: |
3520 | + return "MinimizeWindowButton"; |
3521 | + case WindowButtonType::MAXIMIZE: |
3522 | + return "MaximizeWindowButton"; |
3523 | + case WindowButtonType::UNMAXIMIZE: |
3524 | + return "UnmaximizeWindowButton"; |
3525 | + default: |
3526 | + return "WindowButton"; |
3527 | + } |
3528 | +} |
3529 | + |
3530 | +void WindowButton::AddProperties(debug::IntrospectionData& data) |
3531 | +{ |
3532 | + TexturedItem::AddProperties(data); |
3533 | + data.add("pressed", pressed_); |
3534 | + |
3535 | + switch(GetCurrentState()) |
3536 | + { |
3537 | + case WidgetState::NORMAL: |
3538 | + data.add("state", "normal"); |
3539 | + break; |
3540 | + case WidgetState::PRELIGHT: |
3541 | + data.add("state", "prelight"); |
3542 | + break; |
3543 | + case WidgetState::PRESSED: |
3544 | + data.add("state", "pressed"); |
3545 | + break; |
3546 | + case WidgetState::DISABLED: |
3547 | + data.add("state", "disabled"); |
3548 | + break; |
3549 | + case WidgetState::BACKDROP: |
3550 | + data.add("state", "backdrop"); |
3551 | + break; |
3552 | + case WidgetState::BACKDROP_PRELIGHT: |
3553 | + data.add("state", "backdrop_prelight"); |
3554 | + break; |
3555 | + case WidgetState::BACKDROP_PRESSED: |
3556 | + data.add("state", "backdrop_pressed"); |
3557 | + break; |
3558 | + default: |
3559 | + data.add("state", "unknown"); |
3560 | + } |
3561 | +} |
3562 | + |
3563 | +} // decoration namespace |
3564 | +} // unity namespace |
3565 | |
3566 | === added file 'decorations/DecorationsWindowButton.h' |
3567 | --- decorations/DecorationsWindowButton.h 1970-01-01 00:00:00 +0000 |
3568 | +++ decorations/DecorationsWindowButton.h 2014-01-23 15:21:26 +0000 |
3569 | @@ -0,0 +1,58 @@ |
3570 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
3571 | +/* |
3572 | + * Copyright (C) 2013 Canonical Ltd |
3573 | + * |
3574 | + * This program is free software: you can redistribute it and/or modify |
3575 | + * it under the terms of the GNU General Public License version 3 as |
3576 | + * published by the Free Software Foundation. |
3577 | + * |
3578 | + * This program is distributed in the hope that it will be useful, |
3579 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3580 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3581 | + * GNU General Public License for more details. |
3582 | + * |
3583 | + * You should have received a copy of the GNU General Public License |
3584 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3585 | + * |
3586 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
3587 | + */ |
3588 | + |
3589 | +#ifndef UNITY_DECORATION_WINDOW_BUTTON |
3590 | +#define UNITY_DECORATION_WINDOW_BUTTON |
3591 | + |
3592 | +#include "DecorationStyle.h" |
3593 | +#include "DecorationsWidgets.h" |
3594 | + |
3595 | +namespace unity |
3596 | +{ |
3597 | +namespace decoration |
3598 | +{ |
3599 | + |
3600 | +class WindowButton : public TexturedItem |
3601 | +{ |
3602 | +public: |
3603 | + WindowButton(CompWindow*, WindowButtonType type); |
3604 | + |
3605 | + WidgetState GetCurrentState() const; |
3606 | + |
3607 | +protected: |
3608 | + void ButtonDownEvent(CompPoint const&, unsigned button); |
3609 | + void ButtonUpEvent(CompPoint const&, unsigned button); |
3610 | + void MotionEvent(CompPoint const&); |
3611 | + |
3612 | + std::string GetName() const; |
3613 | + void AddProperties(debug::IntrospectionData&); |
3614 | + |
3615 | +private: |
3616 | + void UpdateTexture(); |
3617 | + |
3618 | + WindowButtonType type_; |
3619 | + bool pressed_; |
3620 | + bool was_pressed_; |
3621 | + CompWindow* win_; |
3622 | +}; |
3623 | + |
3624 | +} // decoration namespace |
3625 | +} // unity namespace |
3626 | + |
3627 | +#endif // UNITY_DECORATION_WINDOW_BUTTON |
3628 | |
3629 | === renamed file 'plugins/unityshell/src/glow_texture.h' => 'decorations/glow_texture.h' |
3630 | === added directory 'decorations/pch' |
3631 | === added file 'decorations/pch/decorations_pch.hh' |
3632 | --- decorations/pch/decorations_pch.hh 1970-01-01 00:00:00 +0000 |
3633 | +++ decorations/pch/decorations_pch.hh 2014-01-23 15:21:26 +0000 |
3634 | @@ -0,0 +1,39 @@ |
3635 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
3636 | +/* |
3637 | + * Copyright (C) 2013 Canonical Ltd |
3638 | + * |
3639 | + * This program is free software: you can redistribute it and/or modify |
3640 | + * it under the terms of the GNU General Public License version 3 as |
3641 | + * published by the Free Software Foundation. |
3642 | + * |
3643 | + * This program is distributed in the hope that it will be useful, |
3644 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3645 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3646 | + * GNU General Public License for more details. |
3647 | + * |
3648 | + * You should have received a copy of the GNU General Public License |
3649 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3650 | + * |
3651 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
3652 | + */ |
3653 | + |
3654 | +/* |
3655 | + * These are the precompiled header includes for this module. |
3656 | + * Only system header files can be listed here. |
3657 | + */ |
3658 | + |
3659 | +#include <deque> |
3660 | +#include <memory> |
3661 | +#include <unordered_map> |
3662 | + |
3663 | +#include <sigc++/sigc++.h> |
3664 | +#include <cairo/cairo.h> |
3665 | + |
3666 | +#include <core/core.h> |
3667 | +#include <opengl/opengl.h> |
3668 | +#include <composite/composite.h> |
3669 | + |
3670 | +#include <NuxCore/NuxCore.h> |
3671 | +#include <NuxCore/Property.h> |
3672 | +#include <NuxCore/Rect.h> |
3673 | +#include <NuxCore/Size.h> |
3674 | |
3675 | === modified file 'panel/PanelMenuView.cpp' |
3676 | --- panel/PanelMenuView.cpp 2013-11-19 18:48:35 +0000 |
3677 | +++ panel/PanelMenuView.cpp 2014-01-23 15:21:26 +0000 |
3678 | @@ -24,6 +24,7 @@ |
3679 | #include "PanelMenuView.h" |
3680 | #include "unity-shared/AnimationUtils.h" |
3681 | #include "unity-shared/CairoTexture.h" |
3682 | +#include "unity-shared/DecorationStyle.h" |
3683 | #include "unity-shared/PanelStyle.h" |
3684 | #include "unity-shared/UnitySettings.h" |
3685 | #include "unity-shared/UBusMessages.h" |
3686 | @@ -98,8 +99,8 @@ |
3687 | |
3688 | opacity = 0.0f; |
3689 | |
3690 | - Refresh(); |
3691 | - FullRedraw(); |
3692 | + if (Refresh()) |
3693 | + FullRedraw(); |
3694 | } |
3695 | |
3696 | PanelMenuView::~PanelMenuView() |
3697 | @@ -179,8 +180,6 @@ |
3698 | wm.window_mapped.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowMapped)); |
3699 | wm.window_moved.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowMoved)); |
3700 | wm.window_resized.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowMoved)); |
3701 | - wm.window_decorated.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowDecorated)); |
3702 | - wm.window_undecorated.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowUndecorated)); |
3703 | wm.initiate_spread.connect(sigc::mem_fun(this, &PanelMenuView::OnSpreadInitiate)); |
3704 | wm.terminate_spread.connect(sigc::mem_fun(this, &PanelMenuView::OnSpreadTerminate)); |
3705 | wm.initiate_expo.connect(sigc::mem_fun(this, &PanelMenuView::OnExpoInitiate)); |
3706 | @@ -334,15 +333,17 @@ |
3707 | |
3708 | bool PanelMenuView::ShouldDrawMenus() const |
3709 | { |
3710 | - WindowManager& wm = WindowManager::Default(); |
3711 | - bool screen_grabbed = (wm.IsExpoActive() || wm.IsScaleActive()); |
3712 | - |
3713 | - if (we_control_active_ && !screen_grabbed && |
3714 | - !switcher_showing_ && !launcher_keynav_ && !entries_.empty()) |
3715 | + if (we_control_active_ && !switcher_showing_ && !launcher_keynav_ && !entries_.empty()) |
3716 | { |
3717 | - if (is_inside_ || last_active_view_ || show_now_activated_ || new_application_) |
3718 | + WindowManager& wm = WindowManager::Default(); |
3719 | + |
3720 | + if (!wm.IsExpoActive() && !wm.IsScaleActive()) |
3721 | { |
3722 | - return true; |
3723 | + if (is_inside_ || last_active_view_ || show_now_activated_ || new_application_) |
3724 | + return true; |
3725 | + |
3726 | + if (is_maximized_) |
3727 | + return (window_buttons_->IsMouseOwner() || titlebar_grab_area_->IsMouseOwner()); |
3728 | } |
3729 | } |
3730 | |
3731 | @@ -351,15 +352,17 @@ |
3732 | |
3733 | bool PanelMenuView::ShouldDrawButtons() const |
3734 | { |
3735 | - WindowManager& wm = WindowManager::Default(); |
3736 | - bool screen_grabbed = (wm.IsExpoActive() || wm.IsScaleActive()); |
3737 | - |
3738 | - if (we_control_active_ && is_maximized_ && !screen_grabbed && |
3739 | - !launcher_keynav_ && !switcher_showing_) |
3740 | + if (we_control_active_ && is_maximized_ && !launcher_keynav_ && !switcher_showing_) |
3741 | { |
3742 | - if (is_inside_ || show_now_activated_ || new_application_) |
3743 | + WindowManager& wm = WindowManager::Default(); |
3744 | + |
3745 | + if (!wm.IsExpoActive() && !wm.IsScaleActive()) |
3746 | { |
3747 | - return true; |
3748 | + if (is_inside_ || show_now_activated_ || new_application_) |
3749 | + return true; |
3750 | + |
3751 | + if (window_buttons_->IsMouseOwner() || titlebar_grab_area_->IsMouseOwner()) |
3752 | + return true; |
3753 | } |
3754 | } |
3755 | |
3756 | @@ -709,84 +712,17 @@ |
3757 | return label; |
3758 | } |
3759 | |
3760 | -void PanelMenuView::UpdateTitleTexture(cairo_t *cr_real, nux::Geometry const& geo, std::string const& label) const |
3761 | +void PanelMenuView::UpdateTitleTexture(cairo_t *cr, nux::Geometry const& geo, std::string const& label) const |
3762 | { |
3763 | - using namespace panel; |
3764 | - cairo_t* cr; |
3765 | + using namespace decoration; |
3766 | + auto const& style = Style::Get(); |
3767 | + auto text_size = style->TitleNaturalSize(label); |
3768 | int x = MAIN_LEFT_PADDING + TITLE_PADDING + geo.x; |
3769 | - int y = geo.y; |
3770 | - |
3771 | - int text_width = 0; |
3772 | - int text_height = 0; |
3773 | - int text_space = 0; |
3774 | - |
3775 | - // Find out dimensions first |
3776 | - GdkScreen* screen = gdk_screen_get_default(); |
3777 | - PangoContext* cxt; |
3778 | - PangoRectangle log_rect; |
3779 | - PangoFontDescription* desc; |
3780 | - |
3781 | - nux::CairoGraphics util_cg(CAIRO_FORMAT_ARGB32, 1, 1); |
3782 | - cr = util_cg.GetInternalContext(); |
3783 | - |
3784 | - int dpi = Style::Instance().GetTextDPI(); |
3785 | - |
3786 | - std::string font_description(Style::Instance().GetFontDescription(PanelItem::TITLE)); |
3787 | - desc = pango_font_description_from_string(font_description.c_str()); |
3788 | - |
3789 | - glib::Object<PangoLayout> layout(pango_cairo_create_layout(cr)); |
3790 | - pango_layout_set_font_description(layout, desc); |
3791 | - pango_layout_set_markup(layout, label.c_str(), -1); |
3792 | - |
3793 | - cxt = pango_layout_get_context(layout); |
3794 | - pango_cairo_context_set_font_options(cxt, gdk_screen_get_font_options(screen)); |
3795 | - pango_cairo_context_set_resolution(cxt, dpi / static_cast<float>(PANGO_SCALE)); |
3796 | - pango_layout_context_changed(layout); |
3797 | - |
3798 | - pango_layout_get_extents(layout, nullptr, &log_rect); |
3799 | - text_width = log_rect.width / PANGO_SCALE; |
3800 | - text_height = log_rect.height / PANGO_SCALE; |
3801 | - |
3802 | - pango_font_description_free(desc); |
3803 | - |
3804 | - // Draw the text |
3805 | - GtkStyleContext* style_context = Style::Instance().GetStyleContext(); |
3806 | - text_space = geo.width - x; |
3807 | - cr = cr_real; |
3808 | - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); |
3809 | - |
3810 | - gtk_style_context_save(style_context); |
3811 | - gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUBAR); |
3812 | - gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUITEM); |
3813 | - |
3814 | - y += (geo.height - text_height) / 2; |
3815 | - |
3816 | - pango_cairo_update_layout(cr, layout); |
3817 | - |
3818 | - if (text_width > text_space) |
3819 | - { |
3820 | - cairo_pattern_t* linpat; |
3821 | - int out_pixels = text_width - text_space; |
3822 | - const int fading_pixels = 35; |
3823 | - int fading_width = out_pixels < fading_pixels ? out_pixels : fading_pixels; |
3824 | - |
3825 | - cairo_push_group(cr); |
3826 | - gtk_render_layout(style_context, cr, x, y, layout); |
3827 | - cairo_pop_group_to_source(cr); |
3828 | - |
3829 | - linpat = cairo_pattern_create_linear(geo.width - fading_width, y, geo.width, y); |
3830 | - cairo_pattern_add_color_stop_rgba(linpat, 0, 0, 0, 0, 1); |
3831 | - cairo_pattern_add_color_stop_rgba(linpat, 1, 0, 0, 0, 0); |
3832 | - cairo_mask(cr, linpat); |
3833 | - |
3834 | - cairo_pattern_destroy(linpat); |
3835 | - } |
3836 | - else |
3837 | - { |
3838 | - gtk_render_layout(style_context, cr, x, y, layout); |
3839 | - } |
3840 | - |
3841 | - gtk_style_context_restore(style_context); |
3842 | + |
3843 | + cairo_save(cr); |
3844 | + cairo_translate(cr, x, geo.y + (geo.height - text_size.height) / 2); |
3845 | + style->DrawTitle(label, WidgetState::NORMAL, cr, geo.width - x, geo.height); |
3846 | + cairo_restore(cr); |
3847 | } |
3848 | |
3849 | std::string PanelMenuView::GetCurrentTitle() const |
3850 | @@ -809,7 +745,7 @@ |
3851 | } |
3852 | else if (!we_control_active_) |
3853 | { |
3854 | - new_title = ""; |
3855 | + new_title.clear(); |
3856 | } |
3857 | else |
3858 | { |
3859 | @@ -829,40 +765,36 @@ |
3860 | } |
3861 | } |
3862 | |
3863 | -void PanelMenuView::Refresh(bool force) |
3864 | +bool PanelMenuView::Refresh(bool force) |
3865 | { |
3866 | nux::Geometry const& geo = GetGeometry(); |
3867 | |
3868 | // We can get into a race that causes the geometry to be wrong as there hasn't been a |
3869 | // layout cycle before the first callback. This is to protect from that. |
3870 | if (geo.width > monitor_geo_.width) |
3871 | - return; |
3872 | + return false; |
3873 | |
3874 | const std::string& new_title = GetCurrentTitle(); |
3875 | if (new_title == panel_title_ && !force && last_geo_ == geo && title_texture_) |
3876 | { |
3877 | // No need to redraw the title, let's save some CPU time! |
3878 | - return; |
3879 | + return false; |
3880 | } |
3881 | + |
3882 | panel_title_ = new_title; |
3883 | |
3884 | if (panel_title_.empty()) |
3885 | { |
3886 | title_texture_ = nullptr; |
3887 | - return; |
3888 | + return true; |
3889 | } |
3890 | |
3891 | nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, geo.width, geo.height); |
3892 | - cairo_t* cr = cairo_graphics.GetContext(); |
3893 | - |
3894 | - cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); |
3895 | - cairo_paint(cr); |
3896 | - |
3897 | + cairo_t* cr = cairo_graphics.GetInternalContext(); |
3898 | UpdateTitleTexture(cr, geo, panel_title_); |
3899 | - |
3900 | - cairo_destroy(cr); |
3901 | - |
3902 | title_texture_ = texture_ptr_from_cairo_graphics(cairo_graphics); |
3903 | + |
3904 | + return true; |
3905 | } |
3906 | |
3907 | void PanelMenuView::OnActiveChanged(PanelIndicatorEntryView* view, bool is_active) |
3908 | @@ -879,8 +811,8 @@ |
3909 | } |
3910 | } |
3911 | |
3912 | - Refresh(); |
3913 | - FullRedraw(); |
3914 | + if (Refresh()) |
3915 | + FullRedraw(); |
3916 | } |
3917 | |
3918 | void PanelMenuView::OnEntryAdded(indicator::Entry::Ptr const& entry) |
3919 | @@ -908,8 +840,8 @@ |
3920 | |
3921 | void PanelMenuView::OnNameChanged(BamfView* bamf_view, gchar* new_name, gchar* old_name) |
3922 | { |
3923 | - Refresh(); |
3924 | - FullRedraw(); |
3925 | + if (Refresh()) |
3926 | + FullRedraw(); |
3927 | } |
3928 | |
3929 | bool PanelMenuView::OnNewAppShow() |
3930 | @@ -1032,9 +964,7 @@ |
3931 | } |
3932 | } |
3933 | |
3934 | -void PanelMenuView::OnActiveWindowChanged(BamfMatcher *matcher, |
3935 | - BamfView* old_view, |
3936 | - BamfView* new_view) |
3937 | +void PanelMenuView::OnActiveWindowChanged(BamfMatcher *matcher, BamfView* old_view, BamfView* new_view) |
3938 | { |
3939 | show_now_activated_ = false; |
3940 | is_maximized_ = false; |
3941 | @@ -1044,30 +974,17 @@ |
3942 | |
3943 | if (BAMF_IS_WINDOW(new_view)) |
3944 | { |
3945 | - WindowManager& wm = WindowManager::Default(); |
3946 | BamfWindow* window = reinterpret_cast<BamfWindow*>(new_view); |
3947 | - guint32 xid = bamf_window_get_xid(window); |
3948 | - active_xid_ = xid; |
3949 | - is_maximized_ = wm.IsWindowMaximized(xid); |
3950 | + active_xid_ = bamf_window_get_xid(window); |
3951 | + is_maximized_ = (bamf_window_maximized(window) == BAMF_WINDOW_MAXIMIZED); |
3952 | |
3953 | if (bamf_window_get_window_type(window) == BAMF_WINDOW_DESKTOP) |
3954 | we_control_active_ = true; |
3955 | else |
3956 | - we_control_active_ = IsWindowUnderOurControl(xid); |
3957 | - |
3958 | - if (decor_map_.find(xid) == decor_map_.end()) |
3959 | - { |
3960 | - decor_map_[xid] = true; |
3961 | - |
3962 | - // if we've just started tracking this window and it is maximized, let's |
3963 | - // make sure it's undecorated just in case it slipped by us earlier |
3964 | - // (I'm looking at you, Chromium!) |
3965 | - if (is_maximized_ && wm.HasWindowDecorations(xid)) |
3966 | - { |
3967 | - wm.Undecorate(xid); |
3968 | - maximized_set_.insert(xid); |
3969 | - } |
3970 | - } |
3971 | + we_control_active_ = IsWindowUnderOurControl(active_xid_); |
3972 | + |
3973 | + if (is_maximized_) |
3974 | + maximized_set_.insert(active_xid_); |
3975 | |
3976 | // first see if we need to remove and old callback |
3977 | view_name_changed_signal_.Disconnect(); |
3978 | @@ -1078,152 +995,112 @@ |
3979 | window_buttons_->controlled_window = (is_maximized_) ? active_xid_ : 0; |
3980 | } |
3981 | |
3982 | - Refresh(); |
3983 | - FullRedraw(); |
3984 | + if (Refresh()) |
3985 | + FullRedraw(); |
3986 | } |
3987 | |
3988 | void PanelMenuView::OnSpreadInitiate() |
3989 | { |
3990 | - Refresh(); |
3991 | - QueueDraw(); |
3992 | + if (Refresh()) |
3993 | + QueueDraw(); |
3994 | } |
3995 | |
3996 | void PanelMenuView::OnSpreadTerminate() |
3997 | { |
3998 | - Refresh(); |
3999 | - QueueDraw(); |
4000 | + if (Refresh()) |
4001 | + QueueDraw(); |
4002 | } |
4003 | |
4004 | void PanelMenuView::OnExpoInitiate() |
4005 | { |
4006 | - Refresh(); |
4007 | - QueueDraw(); |
4008 | + if (Refresh()) |
4009 | + QueueDraw(); |
4010 | } |
4011 | |
4012 | void PanelMenuView::OnExpoTerminate() |
4013 | { |
4014 | - Refresh(); |
4015 | - QueueDraw(); |
4016 | -} |
4017 | - |
4018 | -void PanelMenuView::OnWindowMinimized(guint32 xid) |
4019 | -{ |
4020 | - WindowManager& wm = WindowManager::Default(); |
4021 | - if (wm.IsWindowMaximized(xid)) |
4022 | - { |
4023 | - wm.Decorate(xid); |
4024 | - maximized_set_.erase(xid); |
4025 | - |
4026 | - Refresh(); |
4027 | + if (Refresh()) |
4028 | QueueDraw(); |
4029 | +} |
4030 | + |
4031 | +void PanelMenuView::OnWindowMinimized(Window xid) |
4032 | +{ |
4033 | + maximized_set_.erase(xid); |
4034 | + |
4035 | + if (xid == active_xid_) |
4036 | + { |
4037 | + if (Refresh()) |
4038 | + QueueDraw(); |
4039 | } |
4040 | } |
4041 | |
4042 | -void PanelMenuView::OnWindowUnminimized(guint32 xid) |
4043 | +void PanelMenuView::OnWindowUnminimized(Window xid) |
4044 | { |
4045 | - WindowManager& wm = WindowManager::Default(); |
4046 | - if (wm.IsWindowMaximized(xid)) |
4047 | - { |
4048 | - wm.Undecorate(xid); |
4049 | + if (WindowManager::Default().IsWindowMaximized(xid)) |
4050 | maximized_set_.insert(xid); |
4051 | |
4052 | - Refresh(); |
4053 | - QueueDraw(); |
4054 | + if (xid == active_xid_) |
4055 | + { |
4056 | + if (Refresh()) |
4057 | + QueueDraw(); |
4058 | } |
4059 | } |
4060 | |
4061 | -void PanelMenuView::OnWindowUnmapped(guint32 xid) |
4062 | +void PanelMenuView::OnWindowUnmapped(Window xid) |
4063 | { |
4064 | // FIXME: compiz doesn't give us a valid xid (is always 0 on unmap) |
4065 | // we need to do this again on BamfView closed signal. |
4066 | - if (maximized_set_.find(xid) != maximized_set_.end()) |
4067 | + maximized_set_.erase(xid); |
4068 | + |
4069 | + if (xid == active_xid_) |
4070 | { |
4071 | - WindowManager::Default().Decorate(xid); |
4072 | - maximized_set_.erase(xid); |
4073 | - decor_map_.erase(xid); |
4074 | - |
4075 | - Refresh(); |
4076 | - QueueDraw(); |
4077 | + if (Refresh()) |
4078 | + QueueDraw(); |
4079 | } |
4080 | } |
4081 | |
4082 | -void PanelMenuView::OnWindowMapped(guint32 xid) |
4083 | +void PanelMenuView::OnWindowMapped(Window xid) |
4084 | { |
4085 | - WindowManager& wm = WindowManager::Default(); |
4086 | - if (wm.IsWindowMaximized(xid)) |
4087 | + if (WindowManager::Default().IsWindowMaximized(xid)) |
4088 | { |
4089 | - wm.Undecorate(xid); |
4090 | maximized_set_.insert(xid); |
4091 | |
4092 | - Refresh(); |
4093 | - QueueDraw(); |
4094 | - } |
4095 | -} |
4096 | - |
4097 | -void PanelMenuView::OnWindowDecorated(guint32 xid) |
4098 | -{ |
4099 | - decor_map_[xid] = true; |
4100 | - |
4101 | - if (maximized_set_.find(xid) != maximized_set_.end ()) |
4102 | - { |
4103 | - WindowManager::Default().Undecorate(xid); |
4104 | - } |
4105 | -} |
4106 | - |
4107 | -void PanelMenuView::OnWindowUndecorated(guint32 xid) |
4108 | -{ |
4109 | - decor_map_[xid] = false; |
4110 | -} |
4111 | - |
4112 | -void PanelMenuView::OnWindowMaximized(guint xid) |
4113 | -{ |
4114 | - bool updated = false; |
4115 | - bool is_active = (active_xid_ == xid); |
4116 | - |
4117 | - if (is_active) |
4118 | + if (xid == active_xid_) |
4119 | + { |
4120 | + if (Refresh()) |
4121 | + QueueDraw(); |
4122 | + } |
4123 | + } |
4124 | +} |
4125 | + |
4126 | +void PanelMenuView::OnWindowMaximized(Window xid) |
4127 | +{ |
4128 | + maximized_set_.insert(xid); |
4129 | + |
4130 | + if (xid == active_xid_) |
4131 | { |
4132 | // We need to update the is_inside_ state in the case of maximization by grab |
4133 | auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); |
4134 | is_inside_ = GetAbsoluteGeometry().IsInside(mouse); |
4135 | - |
4136 | is_maximized_ = true; |
4137 | - updated = true; |
4138 | - } |
4139 | - |
4140 | - // update the state of the window in the decor_map_ |
4141 | - WindowManager& wm = WindowManager::Default(); |
4142 | - decor_map_[xid] = wm.HasWindowDecorations(xid); |
4143 | - |
4144 | - if (decor_map_[xid]) |
4145 | - wm.Undecorate(xid); |
4146 | - |
4147 | - maximized_set_.insert(xid); |
4148 | - |
4149 | - if (updated) |
4150 | - { |
4151 | - Refresh(); |
4152 | - FullRedraw(); |
4153 | + |
4154 | + if (Refresh()) |
4155 | + FullRedraw(); |
4156 | } |
4157 | } |
4158 | |
4159 | -void PanelMenuView::OnWindowRestored(guint xid) |
4160 | +void PanelMenuView::OnWindowRestored(Window xid) |
4161 | { |
4162 | - if (maximized_set_.find(xid) == maximized_set_.end()) |
4163 | - return; |
4164 | + maximized_set_.erase(xid); |
4165 | |
4166 | if (active_xid_ == xid) |
4167 | { |
4168 | is_maximized_ = false; |
4169 | is_grabbed_ = false; |
4170 | + |
4171 | + if (Refresh()) |
4172 | + FullRedraw(); |
4173 | } |
4174 | - |
4175 | - if (decor_map_[xid]) |
4176 | - WindowManager::Default().Decorate(xid); |
4177 | - |
4178 | - maximized_set_.erase(xid); |
4179 | - |
4180 | - Refresh(); |
4181 | - FullRedraw(); |
4182 | } |
4183 | |
4184 | bool PanelMenuView::UpdateActiveWindowPosition() |
4185 | @@ -1234,14 +1111,14 @@ |
4186 | { |
4187 | we_control_active_ = we_control_window; |
4188 | |
4189 | - Refresh(); |
4190 | - QueueDraw(); |
4191 | + if (Refresh()) |
4192 | + QueueDraw(); |
4193 | } |
4194 | |
4195 | return false; |
4196 | } |
4197 | |
4198 | -void PanelMenuView::OnWindowMoved(guint xid) |
4199 | +void PanelMenuView::OnWindowMoved(Window xid) |
4200 | { |
4201 | if (active_xid_ == xid) |
4202 | { |
4203 | @@ -1468,8 +1345,8 @@ |
4204 | |
4205 | is_inside_ = true; |
4206 | is_grabbed_ = true; |
4207 | - Refresh(); |
4208 | - FullRedraw(); |
4209 | + if (Refresh()) |
4210 | + FullRedraw(); |
4211 | |
4212 | /* Ungrab the pointer and start the X move, to make the decorator handle it */ |
4213 | titlebar_grab_area_->SetGrabbed(false); |
4214 | @@ -1489,8 +1366,8 @@ |
4215 | if (!is_inside_) |
4216 | is_grabbed_ = false; |
4217 | |
4218 | - Refresh(); |
4219 | - FullRedraw(); |
4220 | + if (Refresh()) |
4221 | + FullRedraw(); |
4222 | } |
4223 | |
4224 | // Introspectable |
4225 | @@ -1546,8 +1423,8 @@ |
4226 | show_now_activated_ = false; |
4227 | } |
4228 | |
4229 | - Refresh(); |
4230 | - QueueDraw(); |
4231 | + if (Refresh()) |
4232 | + QueueDraw(); |
4233 | } |
4234 | |
4235 | void PanelMenuView::OnLauncherKeyNavStarted(GVariant* data) |
4236 | @@ -1572,8 +1449,8 @@ |
4237 | auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); |
4238 | is_inside_ = GetAbsoluteGeometry().IsInside(mouse); |
4239 | |
4240 | - Refresh(); |
4241 | - QueueDraw(); |
4242 | + if (Refresh()) |
4243 | + QueueDraw(); |
4244 | } |
4245 | |
4246 | void PanelMenuView::OnLauncherSelectionChanged(GVariant* data) |
4247 | @@ -1642,7 +1519,6 @@ |
4248 | maximized_set_.clear(); |
4249 | GList* windows = bamf_matcher_get_window_stack_for_monitor(matcher_, monitor_); |
4250 | |
4251 | - WindowManager& wm = WindowManager::Default(); |
4252 | for (GList* l = windows; l; l = l->next) |
4253 | { |
4254 | if (!BAMF_IS_WINDOW(l->data)) |
4255 | @@ -1652,21 +1528,10 @@ |
4256 | auto view = static_cast<BamfView*>(l->data); |
4257 | |
4258 | if (bamf_view_is_active(view)) |
4259 | - { |
4260 | active_xid_ = bamf_window_get_xid(window); |
4261 | - } |
4262 | |
4263 | if (bamf_window_maximized(window) == BAMF_WINDOW_MAXIMIZED) |
4264 | - { |
4265 | - Window xid = bamf_window_get_xid(window); |
4266 | - |
4267 | - decor_map_[xid] = wm.HasWindowDecorations(xid); |
4268 | - |
4269 | - if (decor_map_[xid]) |
4270 | - wm.Undecorate(xid); |
4271 | - |
4272 | - maximized_set_.insert(xid); |
4273 | - } |
4274 | + maximized_set_.insert(bamf_window_get_xid(window)); |
4275 | } |
4276 | |
4277 | Window maximized = GetMaximizedWindow(); |
4278 | @@ -1705,9 +1570,6 @@ |
4279 | } |
4280 | } |
4281 | |
4282 | -void PanelMenuView::OnPanelViewMouseMove(int x, int y, int dx, int dy, unsigned long mouse_button_state, unsigned long special_keys_state) |
4283 | -{} |
4284 | - |
4285 | void PanelMenuView::SetMousePosition(int x, int y) |
4286 | { |
4287 | if (last_active_view_ || |
4288 | |
4289 | === modified file 'panel/PanelMenuView.h' |
4290 | --- panel/PanelMenuView.h 2013-09-19 16:44:03 +0000 |
4291 | +++ panel/PanelMenuView.h 2014-01-23 15:21:26 +0000 |
4292 | @@ -92,15 +92,13 @@ |
4293 | void OnSpreadTerminate(); |
4294 | void OnExpoInitiate(); |
4295 | void OnExpoTerminate(); |
4296 | - void OnWindowMinimized(guint32 xid); |
4297 | - void OnWindowUnminimized(guint32 xid); |
4298 | - void OnWindowUnmapped(guint32 xid); |
4299 | - void OnWindowMapped(guint32 xid); |
4300 | - void OnWindowMaximized(guint32 xid); |
4301 | - void OnWindowRestored(guint32 xid); |
4302 | - void OnWindowMoved(guint32 xid); |
4303 | - void OnWindowDecorated(guint32 xid); |
4304 | - void OnWindowUndecorated(guint32 xid); |
4305 | + void OnWindowMinimized(Window xid); |
4306 | + void OnWindowUnminimized(Window xid); |
4307 | + void OnWindowUnmapped(Window xid); |
4308 | + void OnWindowMapped(Window xid); |
4309 | + void OnWindowMaximized(Window xid); |
4310 | + void OnWindowRestored(Window xid); |
4311 | + void OnWindowMoved(Window xid); |
4312 | |
4313 | void OnMaximizedActivate(int x, int y); |
4314 | void OnMaximizedRestore(int x, int y); |
4315 | @@ -111,7 +109,7 @@ |
4316 | |
4317 | void FullRedraw(); |
4318 | std::string GetCurrentTitle() const; |
4319 | - void Refresh(bool force = false); |
4320 | + bool Refresh(bool force = false); |
4321 | |
4322 | void UpdateTitleTexture(cairo_t *cr_real, nux::Geometry const& geo, std::string const& label) const; |
4323 | |
4324 | @@ -120,7 +118,6 @@ |
4325 | |
4326 | void OnPanelViewMouseEnter(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state); |
4327 | void OnPanelViewMouseLeave(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state); |
4328 | - void OnPanelViewMouseMove(int x, int y, int dx, int dy, unsigned long mouse_button_state, unsigned long special_keys_state); |
4329 | |
4330 | BamfWindow* GetBamfWindowForXid(Window xid) const; |
4331 | |
4332 | @@ -163,10 +160,8 @@ |
4333 | bool is_maximized_; |
4334 | |
4335 | PanelIndicatorEntryView* last_active_view_; |
4336 | + std::set<Window> maximized_set_; |
4337 | glib::Object<BamfApplication> new_application_; |
4338 | - |
4339 | - std::map<Window, bool> decor_map_; |
4340 | - std::set<Window> maximized_set_; |
4341 | std::list<glib::Object<BamfApplication>> new_apps_; |
4342 | std::string panel_title_; |
4343 | nux::Geometry last_geo_; |
4344 | |
4345 | === modified file 'plugins/unityshell/CMakeLists.txt' |
4346 | --- plugins/unityshell/CMakeLists.txt 2013-02-13 02:09:35 +0000 |
4347 | +++ plugins/unityshell/CMakeLists.txt 2014-01-23 15:21:26 +0000 |
4348 | @@ -21,8 +21,33 @@ |
4349 | set (CMAKE_BUILD_TYPE "" CACHE STRING "Build type (Debug/Release/RelWithDebInfo/MinSizeRe)" FORCE) |
4350 | endif() |
4351 | |
4352 | -add_dependencies(unityshell unity-core-${UNITY_API_VERSION} dash-lib launcher-lib switcher-lib hud-lib panel-lib shortcuts-lib shutdown-lib unity-shared unity-shared-compiz) |
4353 | -target_link_libraries(unityshell unity-core-${UNITY_API_VERSION} launcher-lib dash-lib switcher-lib hud-lib panel-lib shortcuts-lib shutdown-lib unity-shared unity-shared-bamf unity-shared-compiz) |
4354 | +add_dependencies(unityshell |
4355 | + dash-lib |
4356 | + decorations-lib |
4357 | + hud-lib |
4358 | + launcher-lib |
4359 | + panel-lib |
4360 | + shortcuts-lib |
4361 | + shutdown-lib |
4362 | + switcher-lib |
4363 | + unity-core-${UNITY_API_VERSION} |
4364 | + unity-shared |
4365 | + unity-shared-compiz) |
4366 | + |
4367 | +target_link_libraries(unityshell |
4368 | + dash-lib |
4369 | + decorations-lib |
4370 | + hud-lib |
4371 | + launcher-lib |
4372 | + panel-lib |
4373 | + shortcuts-lib |
4374 | + shutdown-lib |
4375 | + switcher-lib |
4376 | + unity-core-${UNITY_API_VERSION} |
4377 | + unity-shared |
4378 | + unity-shared-bamf |
4379 | + unity-shared-compiz) |
4380 | + |
4381 | set_target_properties(unityshell |
4382 | PROPERTIES INSTALL_RPATH "${CACHED_UNITY_PRIVATE_DEPS_LIBRARY_DIRS}" |
4383 | INSTALL_RPATH_USE_LINK_PATH TRUE) |
4384 | |
4385 | === modified file 'plugins/unityshell/src/unityshell.cpp' |
4386 | --- plugins/unityshell/src/unityshell.cpp 2014-01-14 16:07:59 +0000 |
4387 | +++ plugins/unityshell/src/unityshell.cpp 2014-01-23 15:21:26 +0000 |
4388 | @@ -28,6 +28,7 @@ |
4389 | #include <UnityCore/ScopeProxyInterface.h> |
4390 | #include <UnityCore/GnomeSessionManager.h> |
4391 | |
4392 | +#include "CompizUtils.h" |
4393 | #include "BaseWindowRaiserImp.h" |
4394 | #include "IconRenderer.h" |
4395 | #include "Launcher.h" |
4396 | @@ -41,7 +42,6 @@ |
4397 | #include "StartupNotifyService.h" |
4398 | #include "Timer.h" |
4399 | #include "XKeyboardUtil.h" |
4400 | -#include "glow_texture.h" |
4401 | #include "unityshell.h" |
4402 | #include "BackgroundEffectHelper.h" |
4403 | #include "UnityGestureBroker.h" |
4404 | @@ -51,6 +51,9 @@ |
4405 | #include "launcher/XdndStartStopNotifierImp.h" |
4406 | #include "CompizShortcutModeller.h" |
4407 | |
4408 | +#include "decorations/DecorationsDataPool.h" |
4409 | +#include "decorations/DecorationsManager.h" |
4410 | + |
4411 | #include <glib/gi18n-lib.h> |
4412 | #include <gtk/gtk.h> |
4413 | #include <gdk/gdk.h> |
4414 | @@ -119,6 +122,11 @@ |
4415 | return nux::Geometry(rect.x(), rect.y(), rect.width(), rect.height()); |
4416 | } |
4417 | |
4418 | +inline nux::Color NuxColorFromCompizColor(unsigned short * color) |
4419 | +{ |
4420 | + return nux::Color(color[0]/65535.0f, color[1]/65535.0f, color[2]/65535.0f, color[3]/65535.0f); |
4421 | +} |
4422 | + |
4423 | namespace local |
4424 | { |
4425 | // Tap duration in milliseconds. |
4426 | @@ -131,18 +139,6 @@ |
4427 | const std::string RELAYOUT_TIMEOUT = "relayout-timeout"; |
4428 | } // namespace local |
4429 | |
4430 | -namespace win |
4431 | -{ |
4432 | -namespace decoration |
4433 | -{ |
4434 | -const unsigned CLOSE_SIZE = 19; |
4435 | -const unsigned ITEMS_PADDING = 5; |
4436 | -const unsigned RADIUS = 8; |
4437 | -const unsigned GLOW = 5; |
4438 | -const nux::Color GLOW_COLOR(221, 72, 20); |
4439 | -} // decoration namespace |
4440 | -} // win namespace |
4441 | - |
4442 | } // anon namespace |
4443 | |
4444 | UnityScreen::UnityScreen(CompScreen* screen) |
4445 | @@ -151,6 +147,7 @@ |
4446 | , screen(screen) |
4447 | , cScreen(CompositeScreen::get(screen)) |
4448 | , gScreen(GLScreen::get(screen)) |
4449 | + , deco_manager_(std::make_shared<decoration::Manager>()) |
4450 | , debugger_(this) |
4451 | , needsRelayout(false) |
4452 | , super_keypressed_(false) |
4453 | @@ -302,7 +299,13 @@ |
4454 | uScreen = this; |
4455 | |
4456 | optionSetLockScreenInitiate(boost::bind(&UnityScreen::LockScreenInitiate, this, _1, _2, _3)); |
4457 | - |
4458 | + optionSetOverrideDecorationThemeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
4459 | + optionSetShadowXOffsetNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
4460 | + optionSetShadowYOffsetNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
4461 | + optionSetActiveShadowRadiusNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
4462 | + optionSetInactiveShadowRadiusNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
4463 | + optionSetActiveShadowColorNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
4464 | + optionSetInactiveShadowColorNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
4465 | optionSetShowHudInitiate(boost::bind(&UnityScreen::ShowHudInitiate, this, _1, _2, _3)); |
4466 | optionSetShowHudTerminate(boost::bind(&UnityScreen::ShowHudTerminate, this, _1, _2, _3)); |
4467 | optionSetBackgroundColorNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
4468 | @@ -377,9 +380,6 @@ |
4469 | ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_SWITCHER, |
4470 | sigc::mem_fun(this, &UnityScreen::OnLauncherEndKeyNav)); |
4471 | |
4472 | - ubus_manager_.RegisterInterest(UBUS_SWITCHER_START, |
4473 | - sigc::mem_fun(this, &UnityScreen::OnSwitcherStart)); |
4474 | - |
4475 | ubus_manager_.RegisterInterest(UBUS_SWITCHER_END, |
4476 | sigc::mem_fun(this, &UnityScreen::OnSwitcherEnd)); |
4477 | |
4478 | @@ -416,7 +416,11 @@ |
4479 | force_draw_countdown_ += local::FRAMES_TO_REDRAW_ON_RESUME; |
4480 | }); |
4481 | |
4482 | - panel::Style::Instance().changed.connect(sigc::mem_fun(this, &UnityScreen::OnPanelStyleChanged)); |
4483 | + Introspectable::AddChild(deco_manager_.get()); |
4484 | + auto const& deco_style = decoration::Style::Get(); |
4485 | + auto deco_style_cb = sigc::hide(sigc::mem_fun(this, &UnityScreen::OnDecorationStyleChanged)); |
4486 | + deco_style->theme.changed.connect(deco_style_cb); |
4487 | + deco_style->title_font.changed.connect(deco_style_cb); |
4488 | |
4489 | minimize_speed_controller_.DurationChanged.connect( |
4490 | sigc::mem_fun(this, &UnityScreen::OnMinimizeDurationChanged) |
4491 | @@ -502,8 +506,6 @@ |
4492 | |
4493 | void UnityScreen::OnInitiateSpread() |
4494 | { |
4495 | - UnityWindow::SetupSharedTextures(); |
4496 | - |
4497 | for (auto const& swin : ScaleScreen::get(screen)->getWindows()) |
4498 | UnityWindow::get(swin->window)->OnInitiateSpread(); |
4499 | } |
4500 | @@ -512,8 +514,6 @@ |
4501 | { |
4502 | for (auto const& swin : ScaleScreen::get(screen)->getWindows()) |
4503 | UnityWindow::get(swin->window)->OnTerminateSpread(); |
4504 | - |
4505 | - UnityWindow::CleanupSharedTextures(); |
4506 | } |
4507 | |
4508 | void UnityScreen::DamagePanelShadow() |
4509 | @@ -727,18 +727,17 @@ |
4510 | wy = y + (last_bound.height - height) / 2; |
4511 | } |
4512 | |
4513 | -void UnityScreen::OnPanelStyleChanged() |
4514 | +void UnityScreen::OnDecorationStyleChanged() |
4515 | { |
4516 | - // Reload the windows themed textures |
4517 | - UnityWindow::CleanupSharedTextures(); |
4518 | - |
4519 | - if (!fake_decorated_windows_.empty()) |
4520 | - { |
4521 | - UnityWindow::SetupSharedTextures(); |
4522 | - |
4523 | - for (UnityWindow* uwin : fake_decorated_windows_) |
4524 | - uwin->CleanupCachedTextures(); |
4525 | - } |
4526 | + for (UnityWindow* uwin : fake_decorated_windows_) |
4527 | + uwin->CleanupCachedTextures(); |
4528 | + |
4529 | + auto const& style = decoration::Style::Get(); |
4530 | + deco_manager_->shadow_offset = style->ShadowOffset(); |
4531 | + deco_manager_->active_shadow_color = style->ActiveShadowColor(); |
4532 | + deco_manager_->active_shadow_radius = style->ActiveShadowRadius(); |
4533 | + deco_manager_->inactive_shadow_color = style->InactiveShadowColor(); |
4534 | + deco_manager_->inactive_shadow_radius = style->InactiveShadowRadius(); |
4535 | } |
4536 | |
4537 | void UnityScreen::DamageBlurUpdateRegion(nux::Geometry const& blur_update) |
4538 | @@ -1141,13 +1140,14 @@ |
4539 | return window->minimized (); |
4540 | } |
4541 | |
4542 | -void UnityWindow::DoOverrideFrameRegion (CompRegion ®ion) |
4543 | +void UnityWindow::DoOverrideFrameRegion(CompRegion ®ion) |
4544 | { |
4545 | - unsigned int oldUpdateFrameRegionIndex = window->updateFrameRegionGetCurrentIndex (); |
4546 | + unsigned int oldUpdateFrameRegionIndex = window->updateFrameRegionGetCurrentIndex(); |
4547 | |
4548 | - window->updateFrameRegionSetCurrentIndex (MAXSHORT); |
4549 | - window->updateFrameRegion (region); |
4550 | - window->updateFrameRegionSetCurrentIndex (oldUpdateFrameRegionIndex); |
4551 | + window->updateFrameRegionSetCurrentIndex(MAXSHORT); |
4552 | + window->updateFrameRegion(region); |
4553 | + deco_win_->UpdateFrameRegion(region); |
4554 | + window->updateFrameRegionSetCurrentIndex(oldUpdateFrameRegionIndex); |
4555 | } |
4556 | |
4557 | void UnityWindow::DoHide () |
4558 | @@ -1194,7 +1194,7 @@ |
4559 | { |
4560 | mShowdesktopHandler.reset(); |
4561 | |
4562 | - window->updateFrameRegion (); |
4563 | + window->updateFrameRegion(); |
4564 | } |
4565 | |
4566 | compiz::WindowInputRemoverLock::Ptr |
4567 | @@ -1225,17 +1225,17 @@ |
4568 | switch(event->type) |
4569 | { |
4570 | case MotionNotify: |
4571 | - if (close_icon_state_ != panel::WindowState::PRESSED) |
4572 | + if (close_icon_state_ != decoration::WidgetState::PRESSED) |
4573 | { |
4574 | - panel::WindowState old_state = close_icon_state_; |
4575 | + auto old_state = close_icon_state_; |
4576 | |
4577 | if (close_button_geo_.IsPointInside(event->xmotion.x_root, event->xmotion.y_root)) |
4578 | { |
4579 | - close_icon_state_ = panel::WindowState::PRELIGHT; |
4580 | + close_icon_state_ = decoration::WidgetState::PRELIGHT; |
4581 | } |
4582 | else |
4583 | { |
4584 | - close_icon_state_ = panel::WindowState::NORMAL; |
4585 | + close_icon_state_ = decoration::WidgetState::NORMAL; |
4586 | } |
4587 | |
4588 | if (old_state != close_icon_state_) |
4589 | @@ -1249,7 +1249,7 @@ |
4590 | if (event->xbutton.button == Button1 && |
4591 | close_button_geo_.IsPointInside(event->xbutton.x_root, event->xbutton.y_root)) |
4592 | { |
4593 | - close_icon_state_ = panel::WindowState::PRESSED; |
4594 | + close_icon_state_ = decoration::WidgetState::PRESSED; |
4595 | cWindow->addDamageRect(CompRectFromNuxGeo(close_button_geo_)); |
4596 | handled = true; |
4597 | } |
4598 | @@ -1264,11 +1264,11 @@ |
4599 | |
4600 | case ButtonRelease: |
4601 | { |
4602 | - bool was_pressed = (close_icon_state_ == panel::WindowState::PRESSED); |
4603 | + bool was_pressed = (close_icon_state_ == decoration::WidgetState::PRESSED); |
4604 | |
4605 | - if (close_icon_state_ != panel::WindowState::NORMAL) |
4606 | + if (close_icon_state_ != decoration::WidgetState::NORMAL) |
4607 | { |
4608 | - close_icon_state_ = panel::WindowState::NORMAL; |
4609 | + close_icon_state_ = decoration::WidgetState::NORMAL; |
4610 | cWindow->addDamageRect(CompRectFromNuxGeo(close_button_geo_)); |
4611 | } |
4612 | |
4613 | @@ -1636,12 +1636,21 @@ |
4614 | } |
4615 | } |
4616 | |
4617 | +void UnityScreen::addSupportedAtoms(std::vector<Atom>& atoms) |
4618 | +{ |
4619 | + screen->addSupportedAtoms(atoms); |
4620 | + deco_manager_->AddSupportedAtoms(atoms); |
4621 | +} |
4622 | + |
4623 | /* handle X Events */ |
4624 | void UnityScreen::handleEvent(XEvent* event) |
4625 | { |
4626 | bool skip_other_plugins = false; |
4627 | PluginAdapter& wm = PluginAdapter::Default(); |
4628 | |
4629 | + if (deco_manager_->HandleEventBefore(event)) |
4630 | + return; |
4631 | + |
4632 | switch (event->type) |
4633 | { |
4634 | case FocusIn: |
4635 | @@ -1873,14 +1882,11 @@ |
4636 | if (!skip_other_plugins) |
4637 | screen->handleEvent(event); |
4638 | |
4639 | + if (deco_manager_->HandleEventAfter(event)) |
4640 | + return; |
4641 | + |
4642 | switch (event->type) |
4643 | { |
4644 | - case PropertyNotify: |
4645 | - if (event->xproperty.atom == Atoms::mwmHints) |
4646 | - { |
4647 | - PluginAdapter::Default().NotifyNewDecorationState(event->xproperty.window); |
4648 | - } |
4649 | - break; |
4650 | case MapRequest: |
4651 | ShowdesktopHandler::AllowLeaveShowdesktopMode(event->xmaprequest.window); |
4652 | break; |
4653 | @@ -2121,7 +2127,6 @@ |
4654 | show_mode = switcher::ShowMode::CURRENT_VIEWPORT; |
4655 | } |
4656 | |
4657 | - UnityWindow::SetupSharedTextures(); |
4658 | SetUpAndShowSwitcher(show_mode); |
4659 | |
4660 | return true; |
4661 | @@ -2323,20 +2328,14 @@ |
4662 | PluginAdapter::Default().RestoreInputFocus(); |
4663 | } |
4664 | |
4665 | -void UnityScreen::OnSwitcherStart(GVariant* data) |
4666 | -{ |
4667 | - if (switcher_controller_->Visible()) |
4668 | - { |
4669 | - UnityWindow::SetupSharedTextures(); |
4670 | - } |
4671 | -} |
4672 | - |
4673 | void UnityScreen::OnSwitcherEnd(GVariant* data) |
4674 | { |
4675 | - UnityWindow::CleanupSharedTextures(); |
4676 | - |
4677 | for (UnityWindow* uwin : fake_decorated_windows_) |
4678 | + { |
4679 | + uwin->close_icon_state_ = decoration::WidgetState::NORMAL; |
4680 | + uwin->middle_clicked_ = false; |
4681 | uwin->CleanupCachedTextures(); |
4682 | + } |
4683 | } |
4684 | |
4685 | bool UnityScreen::SaveInputThenFocus(const guint xid) |
4686 | @@ -2507,9 +2506,7 @@ |
4687 | { |
4688 | PluginAdapter& adapter = PluginAdapter::Default(); |
4689 | |
4690 | - CompPlugin* p = CompPlugin::find("core"); |
4691 | - |
4692 | - if (p) |
4693 | + if (CompPlugin* p = CompPlugin::find("core")) |
4694 | { |
4695 | for (CompOption& option : p->vTable->getOptions()) |
4696 | { |
4697 | @@ -2521,9 +2518,7 @@ |
4698 | } |
4699 | } |
4700 | |
4701 | - p = CompPlugin::find("expo"); |
4702 | - |
4703 | - if (p) |
4704 | + if (CompPlugin* p = CompPlugin::find("expo")) |
4705 | { |
4706 | MultiActionList expoActions; |
4707 | |
4708 | @@ -2549,9 +2544,7 @@ |
4709 | adapter.SetExpoAction(expoActions); |
4710 | } |
4711 | |
4712 | - p = CompPlugin::find("scale"); |
4713 | - |
4714 | - if (p) |
4715 | + if (CompPlugin* p = CompPlugin::find("scale")) |
4716 | { |
4717 | MultiActionList scaleActions; |
4718 | |
4719 | @@ -2584,9 +2577,7 @@ |
4720 | adapter.SetScaleAction(scaleActions); |
4721 | } |
4722 | |
4723 | - p = CompPlugin::find("unitymtgrabhandles"); |
4724 | - |
4725 | - if (p) |
4726 | + if (CompPlugin* p = CompPlugin::find("unitymtgrabhandles")) |
4727 | { |
4728 | foreach(CompOption & option, p->vTable->getOptions()) |
4729 | { |
4730 | @@ -2599,6 +2590,15 @@ |
4731 | } |
4732 | } |
4733 | |
4734 | + if (CompPlugin* p = CompPlugin::find("decor")) |
4735 | + { |
4736 | + LOG_ERROR(logger) << "Decoration plugin is active, disabling it..."; |
4737 | + screen->finiPluginForScreen(p); |
4738 | + p->vTable->finiScreen(screen); |
4739 | + CompPlugin::getPlugins().remove(p); |
4740 | + CompPlugin::unload(p); |
4741 | + } |
4742 | + |
4743 | return false; |
4744 | } |
4745 | |
4746 | @@ -2868,6 +2868,7 @@ |
4747 | uScreen->paintPanelShadow(region); |
4748 | |
4749 | bool ret = gWindow->glDraw(matrix, attrib, region, mask); |
4750 | + deco_win_->Draw(matrix, attrib, region, mask); |
4751 | |
4752 | if (draw_panel_shadow == DrawPanelShadow::OVER_WINDOW) |
4753 | uScreen->paintPanelShadow(region); |
4754 | @@ -2875,19 +2876,26 @@ |
4755 | return ret; |
4756 | } |
4757 | |
4758 | +bool UnityWindow::damageRect(bool initial, CompRect const& rect) |
4759 | +{ |
4760 | + if (initial) |
4761 | + deco_win_->Update(); |
4762 | + |
4763 | + return cWindow->damageRect(initial, rect); |
4764 | +} |
4765 | + |
4766 | void |
4767 | UnityScreen::OnMinimizeDurationChanged () |
4768 | { |
4769 | /* Update the compiz plugin setting with the new computed speed so that it |
4770 | * will be used in the following minimizations */ |
4771 | - CompPlugin *p = CompPlugin::find("animation"); |
4772 | - if (p) |
4773 | + if (CompPlugin* p = CompPlugin::find("animation")) |
4774 | { |
4775 | CompOption::Vector &opts = p->vTable->getOptions(); |
4776 | |
4777 | for (CompOption &o : opts) |
4778 | { |
4779 | - if (o.name() == std::string("minimize_durations")) |
4780 | + if (o.name() == "minimize_durations") |
4781 | { |
4782 | /* minimize_durations is a list value, but minimize applies only to |
4783 | * normal windows, so there's always one value */ |
4784 | @@ -2979,7 +2987,11 @@ |
4785 | switch (n) |
4786 | { |
4787 | case CompWindowNotifyMap: |
4788 | - if (window->type() == CompWindowTypeDesktopMask) { |
4789 | + deco_win_->Update(); |
4790 | + deco_win_->UpdateDecorationPosition(); |
4791 | + |
4792 | + if (window->type() == CompWindowTypeDesktopMask) |
4793 | + { |
4794 | if (!focus_desktop_timeout_) |
4795 | { |
4796 | focus_desktop_timeout_.reset(new glib::Timeout(1000, [this] { |
4797 | @@ -3001,8 +3013,7 @@ |
4798 | } |
4799 | /* Fall through an re-evaluate wraps on map and unmap too */ |
4800 | case CompWindowNotifyUnmap: |
4801 | - if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () && |
4802 | - window->mapNum () && |
4803 | + if (uScreen->optionGetShowMinimizedWindows() && window->mapNum() && |
4804 | !window->pendingUnmaps()) |
4805 | { |
4806 | bool wasMinimized = window->minimized (); |
4807 | @@ -3024,18 +3035,27 @@ |
4808 | window->minimizedSetEnabled (this, false); |
4809 | } |
4810 | |
4811 | + deco_win_->Update(); |
4812 | + deco_win_->UpdateDecorationPosition(); |
4813 | + |
4814 | PluginAdapter::Default().UpdateShowDesktopState(); |
4815 | - break; |
4816 | - case CompWindowNotifyBeforeDestroy: |
4817 | - being_destroyed.emit(); |
4818 | - break; |
4819 | - case CompWindowNotifyMinimize: |
4820 | - /* Updating the count in dconf will trigger a "changed" signal to which |
4821 | - * the method setting the new animation speed is attached */ |
4822 | - UnityScreen::get(screen)->minimize_speed_controller_.UpdateCount(); |
4823 | - break; |
4824 | - default: |
4825 | - break; |
4826 | + break; |
4827 | + case CompWindowNotifyBeforeDestroy: |
4828 | + being_destroyed.emit(); |
4829 | + break; |
4830 | + case CompWindowNotifyMinimize: |
4831 | + /* Updating the count in dconf will trigger a "changed" signal to which |
4832 | + * the method setting the new animation speed is attached */ |
4833 | + uScreen->minimize_speed_controller_.UpdateCount(); |
4834 | + break; |
4835 | + case CompWindowNotifyUnreparent: |
4836 | + deco_win_->Undecorate(); |
4837 | + break; |
4838 | + case CompWindowNotifyReparent: |
4839 | + deco_win_->Update(); |
4840 | + break; |
4841 | + default: |
4842 | + break; |
4843 | } |
4844 | |
4845 | |
4846 | @@ -3057,32 +3077,31 @@ |
4847 | // We do this after the notify to ensure input focus has actually been moved. |
4848 | if (n == CompWindowNotifyFocusChange) |
4849 | { |
4850 | - UnityScreen* us = UnityScreen::get(screen); |
4851 | - |
4852 | - // If focus gets moved to an external program while the Dash/Hud is open, refocus key input. |
4853 | - if (us) |
4854 | - { |
4855 | - if (us->dash_controller_->IsVisible()) |
4856 | - { |
4857 | - us->dash_controller_->ReFocusKeyInput(); |
4858 | - } |
4859 | - else if (us->hud_controller_->IsVisible()) |
4860 | - { |
4861 | - us->hud_controller_->ReFocusKeyInput(); |
4862 | - } |
4863 | + if (uScreen->dash_controller_->IsVisible()) |
4864 | + { |
4865 | + uScreen->dash_controller_->ReFocusKeyInput(); |
4866 | + } |
4867 | + else if (uScreen->hud_controller_->IsVisible()) |
4868 | + { |
4869 | + uScreen->hud_controller_->ReFocusKeyInput(); |
4870 | } |
4871 | } |
4872 | } |
4873 | |
4874 | void UnityWindow::stateChangeNotify(unsigned int lastState) |
4875 | { |
4876 | - if (window->state () & CompWindowStateFullscreenMask && |
4877 | + if (window->state() & CompWindowStateFullscreenMask && |
4878 | !(lastState & CompWindowStateFullscreenMask)) |
4879 | - UnityScreen::get (screen)->fullscreen_windows_.push_back(window); |
4880 | + { |
4881 | + uScreen->fullscreen_windows_.push_back(window); |
4882 | + } |
4883 | else if (lastState & CompWindowStateFullscreenMask && |
4884 | - !(window->state () & CompWindowStateFullscreenMask)) |
4885 | - UnityScreen::get (screen)->fullscreen_windows_.remove(window); |
4886 | + !(window->state() & CompWindowStateFullscreenMask)) |
4887 | + { |
4888 | + uScreen->fullscreen_windows_.remove(window); |
4889 | + } |
4890 | |
4891 | + deco_win_->Update(); |
4892 | PluginAdapter::Default().NotifyStateChange(window, window->state(), lastState); |
4893 | window->stateChangeNotify(lastState); |
4894 | } |
4895 | @@ -3094,29 +3113,43 @@ |
4896 | * does not have a region */ |
4897 | |
4898 | if (mMinimizeHandler) |
4899 | - mMinimizeHandler->updateFrameRegion (region); |
4900 | + { |
4901 | + mMinimizeHandler->updateFrameRegion(region); |
4902 | + } |
4903 | else if (mShowdesktopHandler) |
4904 | - mShowdesktopHandler->UpdateFrameRegion (region); |
4905 | + { |
4906 | + mShowdesktopHandler->UpdateFrameRegion(region); |
4907 | + } |
4908 | else |
4909 | - window->updateFrameRegion (region); |
4910 | + { |
4911 | + window->updateFrameRegion(region); |
4912 | + deco_win_->UpdateFrameRegion(region); |
4913 | + } |
4914 | +} |
4915 | + |
4916 | +void UnityWindow::getOutputExtents(CompWindowExtents& output) |
4917 | +{ |
4918 | + window->getOutputExtents(output); |
4919 | + deco_win_->UpdateOutputExtents(output); |
4920 | } |
4921 | |
4922 | void UnityWindow::moveNotify(int x, int y, bool immediate) |
4923 | { |
4924 | + deco_win_->UpdateDecorationPositionDelayed(); |
4925 | PluginAdapter::Default().NotifyMoved(window, x, y); |
4926 | window->moveNotify(x, y, immediate); |
4927 | } |
4928 | |
4929 | void UnityWindow::resizeNotify(int x, int y, int w, int h) |
4930 | { |
4931 | + deco_win_->UpdateDecorationPositionDelayed(); |
4932 | PluginAdapter::Default().NotifyResized(window, x, y, w, h); |
4933 | window->resizeNotify(x, y, w, h); |
4934 | } |
4935 | |
4936 | CompPoint UnityWindow::tryNotIntersectUI(CompPoint& pos) |
4937 | { |
4938 | - UnityScreen* us = UnityScreen::get(screen); |
4939 | - auto window_geo = window->borderRect (); |
4940 | + auto const& window_geo = window->borderRect(); |
4941 | nux::Geometry target_monitor; |
4942 | nux::Point result(pos.x(), pos.y()); |
4943 | |
4944 | @@ -3131,7 +3164,7 @@ |
4945 | } |
4946 | } |
4947 | |
4948 | - auto const& launchers = us->launcher_controller_->launchers(); |
4949 | + auto const& launchers = uScreen->launcher_controller_->launchers(); |
4950 | |
4951 | for (auto const& launcher : launchers) |
4952 | { |
4953 | @@ -3149,7 +3182,7 @@ |
4954 | } |
4955 | } |
4956 | |
4957 | - for (nux::Geometry const& geo : us->panel_controller_->GetGeometries()) |
4958 | + for (nux::Geometry const& geo : uScreen->panel_controller_->GetGeometries()) |
4959 | { |
4960 | if (geo.IsInside(result)) |
4961 | { |
4962 | @@ -3172,6 +3205,7 @@ |
4963 | |
4964 | if (!was_maximized) |
4965 | { |
4966 | + deco_win_->Update(); |
4967 | bool result = window->place(pos); |
4968 | |
4969 | if (window->type() & NO_FOCUS_MASK) |
4970 | @@ -3222,23 +3256,55 @@ |
4971 | break; |
4972 | case UnityshellOptions::BackgroundColor: |
4973 | { |
4974 | - nux::Color override_color (optionGetBackgroundColorRed() / 65535.0f, |
4975 | - optionGetBackgroundColorGreen() / 65535.0f, |
4976 | - optionGetBackgroundColorBlue() / 65535.0f, |
4977 | - optionGetBackgroundColorAlpha() / 65535.0f); |
4978 | - |
4979 | + auto override_color = NuxColorFromCompizColor(optionGetBackgroundColor()); |
4980 | override_color.red = override_color.red / override_color.alpha; |
4981 | override_color.green = override_color.green / override_color.alpha; |
4982 | override_color.blue = override_color.blue / override_color.alpha; |
4983 | bghash_->OverrideColor(override_color); |
4984 | break; |
4985 | } |
4986 | + case UnityshellOptions::OverrideDecorationTheme: |
4987 | + if (optionGetOverrideDecorationTheme()) |
4988 | + { |
4989 | + deco_manager_->active_shadow_color = NuxColorFromCompizColor(optionGetActiveShadowColor()); |
4990 | + deco_manager_->inactive_shadow_color = NuxColorFromCompizColor(optionGetInactiveShadowColor()); |
4991 | + deco_manager_->active_shadow_radius = optionGetActiveShadowRadius(); |
4992 | + deco_manager_->inactive_shadow_radius = optionGetInactiveShadowRadius(); |
4993 | + deco_manager_->shadow_offset = nux::Point(optionGetShadowXOffset(), optionGetShadowYOffset()); |
4994 | + } |
4995 | + else |
4996 | + { |
4997 | + OnDecorationStyleChanged(); |
4998 | + } |
4999 | + break; |
5000 | + case UnityshellOptions::ActiveShadowColor: |
PASSED: Continuous integration, rev:3890 jenkins. qa.ubuntu. com/job/ unity-ci/ 563/ jenkins. qa.ubuntu. com/job/ unity-trusty- amd64-ci/ 99 jenkins. qa.ubuntu. com/job/ unity-trusty- armhf-ci/ 95 jenkins. qa.ubuntu. com/job/ unity-trusty- i386-ci/ 97
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- ci/563/ rebuild
http://