Merge lp:~3v1n0/unity/globalmenu-discovery-new-apps into lp:unity
- globalmenu-discovery-new-apps
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Marco Trevisan (Treviño) |
Approved revision: | no longer in the source branch. |
Merged at revision: | 1780 |
Proposed branch: | lp:~3v1n0/unity/globalmenu-discovery-new-apps |
Merge into: | lp:unity |
Diff against target: |
1779 lines (+878/-289) 16 files modified
manual-tests/Panel.txt (+15/-0) plugins/unityshell/src/Animator.cpp (+91/-82) plugins/unityshell/src/Animator.h (+21/-23) plugins/unityshell/src/LauncherController.cpp (+4/-1) plugins/unityshell/src/PanelController.cpp (+33/-1) plugins/unityshell/src/PanelController.h (+2/-0) plugins/unityshell/src/PanelMenuView.cpp (+282/-144) plugins/unityshell/src/PanelMenuView.h (+31/-8) plugins/unityshell/src/PanelView.cpp (+7/-0) plugins/unityshell/src/PanelView.h (+2/-0) plugins/unityshell/src/unityshell.cpp (+21/-0) plugins/unityshell/unityshell.xml.in (+41/-1) tests/CMakeLists.txt (+3/-0) tests/test_animator.cpp (+295/-0) tests/test_lens.cpp (+4/-29) tests/test_utils.h (+26/-0) |
To merge this branch: | bzr merge lp:~3v1n0/unity/globalmenu-discovery-new-apps |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Penhey (community) | Approve | ||
Review via email: mp+83367@code.launchpad.net |
Commit message
Description of the change
Implemented the design bug #874254 to make a newly opened application to quickly show its menus when firstly mapped using a slightly longer fade effect (now set to 200ms to fade in and 300ms to fade out).
To work properly, this feature, requires the merge of the BAMF branch lp:~3v1n0/bamf/always-notify-view otherwise sticky applications won't be show their menus when opened.
I've also added some fixes and features to the Animator class, and improved the drawing of the fading panel entries.
Plus, I've integrated the bug #875472, introducing 5 new configuration parameters to customize the fading timings and the menu discover-ability time.
Tests for this will be done when the autopilot system will be ready.
Mikkel Kamstrup Erlandsen (kamstrup) wrote : | # |
Didier Roche-Tolomelli (didrocks) wrote : | # |
Bamf is handled by unity-merger, but it's not activated right now as make check doesn't pass on headless server. Please do not merge anything manually in bamf, make check should be fixed first.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Mikkel: I've not these rights :(
However, I knew about the BAMF status in the unity-merger...
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Ok, I've fixed some issues on the configuration side, now it should work as expected.
Charles Kerr (charlesk) wrote : | # |
I'm hesitant to suggest this because it's nitpicky, but std::set might be more appropriate than std::list for _new_apps...
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Will that save so much computation in our case? Mh... Maybe not so much, but I can do that.
Tim Penhey (thumper) wrote : | # |
What is the _new_apps for exactly? std::list is fine if you are going to be constantly adding and removing items, but if speed is needed more often than addition or removal then std::vector is better due to cache-coherency. If there are a lot of items, perhaps std::set is better.
Tim Penhey (thumper) wrote : | # |
> Bamf is handled by unity-merger, but it's not activated right now as make
> check doesn't pass on headless server. Please do not merge anything manually
> in bamf, make check should be fixed first.
Didier, this isn't your decision to make. Yes I agree that make check needs to be fixed, but that will not block other changes.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> What is the _new_apps for exactly? std::list is fine if you are going to be
> constantly adding and removing items, but if speed is needed more often than
> addition or removal then std::vector is better due to cache-coherency. If
> there are a lot of items, perhaps std::set is better.
This is a list of new launched applications. Generally that is just containing one item, but if you quickly launch many applications together (i.e. you're doing something like "nautilus & baobab & gedit & shotwell &" in your terminal) we need to check that once one of the new applications has been focused, its menus are shown.
Using just a pointer for that is not good, otherwise we would control only the last opened application.
Tim Penhey (thumper) wrote : | # |
> plugins/
Can we move the "unity-seen" inline constant to a named
file level one?
Hmm... just looked in the Animator.h file. Since you are messing
with this anyway, I'm going to dump some fun changes on you :-)
Only because I know you can handle it.
Animator.h doesn't need <Nux/Nux.h>, please remove it.
While we could change the properties to use nux properties,
lets not do that right now, but instead you can make GetRate,
GetDuration, GetProgress and IsRunning all const methods.
Can you change the member variables to use the trailing underscore.
Why is there a class FadableObject2? 2? Really? Any idea?
The logic inside TimerTimeOut should be moved into a method of the
animator class so it can be unit tested without needing the timer
itself (or timeout events).
Also, can you add a google-test style unit test for the animator
class?
It needs to test the setters, getters, constructors, timeout, start,
stop, event generation, in fact the entire public interface to the
animator :-) I can help with direction here if you need it.
Thanks.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> > plugins/
>
> Can we move the "unity-seen" inline constant to a named
> file level one?
Ehm, what do you mean?
I didn't write that code, however that data parameter is used to check if that bamf application has not already been added to the launcher, and according to Jason that should survive to crashes.
> Hmm... just looked in the Animator.h file. Since you are messing
> with this anyway, I'm going to dump some fun changes on you :-)
> Only because I know you can handle it.
>
> Animator.h doesn't need <Nux/Nux.h>, please remove it.
Ok, I added it to avoid to manually include all the needed libraries and classes, that already Nux uses; so we're sure that we support them also at the linking level.
However, done!
> While we could change the properties to use nux properties,
> lets not do that right now, but instead you can make GetRate,
> GetDuration, GetProgress and IsRunning all const methods.
Fine, done.
> Can you change the member variables to use the trailing underscore.
Ok (also if the unity code actually is missing both the styles, and IMHO the prefixed underscore is better, also for quickly finding private members).
> Why is there a class FadableObject2? 2? Really? Any idea?
Oh, sorry. That was an abstract class that I initially wrote for testing purposes, but it seems that apparently I didn't remove it before committing. Sorry, I'm moving that out.
> The logic inside TimerTimeOut should be moved into a method of the
> animator class so it can be unit tested without needing the timer
> itself (or timeout events).
Ok, I've added a DoStep() method, that we could use for testing I guess.
> Also, can you add a google-test style unit test for the animator
> class?
>
> It needs to test the setters, getters, constructors, timeout, start,
> stop, event generation, in fact the entire public interface to the
> animator :-) I can help with direction here if you need it.
Ok, I do something something for this. I'll contact you directly if I've something to ask.
Then, about the glib::Object work we talked, this http://
The fact is that actually when creating a new glib::Object we can't optionally ref it, but this is something that can be needed. Especially when we're wrapping an object passed by a signal (as in this case).
Not reffing a new object is good only if we're firstly allocating it.
> Thanks.
Thank you for your review.
Tim Penhey (thumper) wrote : | # |
Firstly, thanks for the changes in the variable names.
Can I also get you to move the method names and return types on to the same
line? That'd be great.
Can you move the member variables initialisation into an initialiser list?
Animator:
: start_time(0)
, timeout_id(0)
, // and the rest.
My idea behind having a DoStep to test it, was to allow us to specify a fake
time to illustrate that the animation does in fact stop :)
We could do this by having:
bool Animator:
And then:
gboolean Animator:
{
return self->DoStep(
}
This way we can call DoStep in the tests.
To have complete control over the start_time_ member, we'd probably want to
have an optional guint64 parameter for both Start methods that defaults to 0.
Inside the start method we get the clock time if the time is 0. That way from
the tests we have complete control over the state of the object. This does
bring up a problem with having default parameters making two different
functions seem like a choice. Need to think about that.
We seem to have a rate, but it doesn't look like it is used anywhere.
Don't bother about the "unity-seen" string just now.
Instead of having the g_signal_connect ids, there is the signal manager that
Neil wrote. It handles the disconnections for you.
Hmm...
auto tmp_animator = Animator(200, 25);
This is wrong for two reasons:
* The animator class isn't a value type, so shouldn't be copyable or
assignable
* Using auto in this way.
Animator tmp_animator(200, 25); // is the correct way.
You should hide the copy constructor and assignment operator.
You can do this in two ways:
* declare them private yourself
* inherit privately from boost::noncopyable (from boost/utility.hpp)
Inside the tests, you can then have better control over the simulation for
steps.
{
guint64 start_time = g_get_monotonic
test_
test_
// test progress
}
Do we ever start an animation with a non-zero progress?
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> Firstly, thanks for the changes in the variable names.
>
> Can I also get you to move the method names and return types on to the same
> line? That'd be great.
Done.
> Can you move the member variables initialisation into an initialiser list?
Ok
> We seem to have a rate, but it doesn't look like it is used anywhere.
As I've already explained on IRC, the rate is used to compute the timeout used by the timer.
> Don't bother about the "unity-seen" string just now.
Fine
> Instead of having the g_signal_connect ids, there is the signal manager that
> Neil wrote. It handles the disconnections for you.
Moving to that...
> Hmm...
>
> Animator tmp_animator(200, 25); // is the correct way.
Moved to that.
> You should hide the copy constructor and assignment operator.
> * inherit privately from boost::noncopyable (from boost/utility.hpp)
Done.
> My idea behind having a DoStep to test it, was to allow us to specify a fake
> time to illustrate that the animation does in fact stop :)
>
> We could do this by having:
>
> bool Animator:
>
> And then:
>
> gboolean Animator:
> {
> return self->DoStep(
> }
>
> This way we can call DoStep in the tests.
> To have complete control over the start_time_ member, we'd probably want to
> have an optional guint64 parameter for both Start methods that defaults to 0.
> Inside the start method we get the clock time if the time is 0. That way from
> the tests we have complete control over the state of the object. This does
> bring up a problem with having default parameters making two different
> functions seem like a choice. Need to think about that.
> Inside the tests, you can then have better control over the simulation for
> steps.
>
> {
> guint64 start_time = g_get_monotonic
> test_animator_
> test_animator_
> // test progress
> }
I'm not sure I'd like this for two reasons:
1) Putting an unneeded value like the start time on a public interface,
only for testing is something good on test side, but bad on the API side.
Also because no one would need it. At least that we use that start time
to support a "delayed start time" (basically, if it's greater than "now",
we add a timeout to delay the start of the animation).
So in this case would be useful in some rare cases.
2) Also if we would allow what I've stated above, the Start function would
also fire a timeout that could interfere with our DoStep() test, and disabing
the timeout in some cases is something I wouldn't do.
A workaround that allows to test is to use somewhat:
/* Using a low frame rate and a long duration we're sure that the first
* step is not called after we call Start and before the Stop get called
* since that should happen after one second.
* Also when we call the DoStep() the private start time is near to the actual
* time, so this would make DoStep() more testable as it is now. */
test_
test_
test_
test_
test_
Tim Penhey (thumper) : | # |
Unity Merger (unity-merger) wrote : | # |
Attempt to merge into lp:unity failed due to conflicts:
text conflict in plugins/
text conflict in tests/CMakeList
Preview Diff
1 | === modified file 'manual-tests/Panel.txt' |
2 | --- manual-tests/Panel.txt 2011-12-08 04:14:22 +0000 |
3 | +++ manual-tests/Panel.txt 2011-12-14 17:24:33 +0000 |
4 | @@ -16,3 +16,18 @@ |
5 | should become opaque, also if the opacity setting is set to 0.0. |
6 | Once all the maximized windows are closed, restored or not visible, |
7 | the panel should go back to its defined opacity. |
8 | + |
9 | + |
10 | +Panel Menus Revelation |
11 | +---------------------- |
12 | +This test shows how the menus should be revealed when a new application has been |
13 | +launched. |
14 | + |
15 | +#. Start with a clear screen |
16 | +#. Open a new application that has menus (i.e. gnome-terminal) |
17 | + |
18 | +Outcome |
19 | + The panel should show the menus in global menu bar for two seconds. |
20 | + If a new gnome-terminal window is opened, the menus are not shown again. |
21 | + If more than one application is open at once, the menus of each application |
22 | + are shown once is focused. |
23 | |
24 | === modified file 'plugins/unityshell/src/Animator.cpp' |
25 | --- plugins/unityshell/src/Animator.cpp 2011-09-27 06:52:31 +0000 |
26 | +++ plugins/unityshell/src/Animator.cpp 2011-12-14 17:24:33 +0000 |
27 | @@ -22,112 +22,121 @@ |
28 | namespace unity |
29 | { |
30 | |
31 | -Animator::Animator(unsigned int duration, unsigned int fps_rate) |
32 | +Animator::Animator(unsigned int default_duration, unsigned int fps_rate) |
33 | + : start_time_(0) |
34 | + , rate_(1) |
35 | + , duration_(0) |
36 | + , one_time_duration_(0) |
37 | + , timeout_id_(0) |
38 | + , start_progress_(0.0f) |
39 | + , progress_(0.0f) |
40 | { |
41 | - _start_time = 0; |
42 | - _timeout_id = 0; |
43 | - _progress = 0.0f; |
44 | - _start_progress = 0.0f; |
45 | - _rate = 1; |
46 | - _duration = 0; |
47 | - |
48 | - SetDuration(duration); |
49 | + SetDuration(default_duration); |
50 | SetRate(fps_rate); |
51 | } |
52 | |
53 | Animator::~Animator() |
54 | { |
55 | - if (_timeout_id != 0) |
56 | - g_source_remove (_timeout_id); |
57 | + Stop(); |
58 | } |
59 | |
60 | -void |
61 | -Animator::SetRate(unsigned int fps_rate) |
62 | +void Animator::SetRate(unsigned int fps_rate) |
63 | { |
64 | if (fps_rate != 0) |
65 | - _rate = 1000 / fps_rate; |
66 | -} |
67 | - |
68 | -void |
69 | -Animator::SetDuration(unsigned int duration) |
70 | -{ |
71 | - if (duration != 0) |
72 | - _duration = duration * 1000; |
73 | -} |
74 | - |
75 | -unsigned int |
76 | -Animator::GetRate() |
77 | -{ |
78 | - return _rate; |
79 | -} |
80 | - |
81 | -unsigned int |
82 | -Animator::GetDuration() |
83 | -{ |
84 | - return _duration; |
85 | -} |
86 | - |
87 | -bool |
88 | -Animator::IsRunning() |
89 | -{ |
90 | - return (_timeout_id != 0); |
91 | -} |
92 | - |
93 | -double |
94 | -Animator::GetProgress() |
95 | -{ |
96 | - return _progress; |
97 | -} |
98 | - |
99 | -void |
100 | -Animator::Start(double start_progress) |
101 | -{ |
102 | - if (_timeout_id == 0 && start_progress < 1.0f) |
103 | + rate_ = 1000 / fps_rate; |
104 | +} |
105 | + |
106 | +void Animator::SetDuration(unsigned int duration) |
107 | +{ |
108 | + duration_ = duration * 1000; |
109 | +} |
110 | + |
111 | +unsigned int Animator::GetRate() const |
112 | +{ |
113 | + if (rate_ != 0) |
114 | + return 1000 / rate_; |
115 | + |
116 | + return rate_; |
117 | +} |
118 | + |
119 | +unsigned int Animator::GetDuration() const |
120 | +{ |
121 | + return (one_time_duration_ > 0 ? one_time_duration_ : duration_) / 1000; |
122 | +} |
123 | + |
124 | +bool Animator::IsRunning() const |
125 | +{ |
126 | + return (timeout_id_ != 0); |
127 | +} |
128 | + |
129 | +double Animator::GetProgress() const |
130 | +{ |
131 | + return progress_; |
132 | +} |
133 | + |
134 | +void Animator::Start(unsigned int one_time_duration, double start_progress) |
135 | +{ |
136 | + if (timeout_id_ == 0 && start_progress < 1.0f) |
137 | { |
138 | if (start_progress < 0.0f) |
139 | start_progress = 0.0f; |
140 | |
141 | - _start_progress = start_progress; |
142 | - _progress = _start_progress; |
143 | - _start_time = g_get_monotonic_time(); |
144 | - _timeout_id = g_timeout_add(_rate, (GSourceFunc) &Animator::TimerTimeOut, this); |
145 | + one_time_duration_ = one_time_duration * 1000; |
146 | + start_progress_ = start_progress; |
147 | + progress_ = start_progress_; |
148 | + start_time_ = g_get_monotonic_time(); |
149 | + timeout_id_ = g_timeout_add(rate_, (GSourceFunc) &Animator::TimerTimeOut, this); |
150 | + animation_started.emit(); |
151 | } |
152 | } |
153 | |
154 | -void |
155 | -Animator::Stop() |
156 | -{ |
157 | - if (_timeout_id != 0) |
158 | +void Animator::Start(double start_progress) |
159 | +{ |
160 | + Start(0, start_progress); |
161 | +} |
162 | + |
163 | +void Animator::Stop() |
164 | +{ |
165 | + if (timeout_id_ != 0) |
166 | { |
167 | - g_source_remove(_timeout_id); |
168 | - animation_updated.emit(_progress); |
169 | + g_source_remove(timeout_id_); |
170 | + animation_updated.emit(progress_); |
171 | animation_ended.emit(); |
172 | - animation_stopped.emit(_progress); |
173 | - _timeout_id = 0; |
174 | + animation_stopped.emit(progress_); |
175 | + one_time_duration_ = 0; |
176 | + timeout_id_ = 0; |
177 | } |
178 | } |
179 | |
180 | -gboolean |
181 | -Animator::TimerTimeOut(Animator *self) |
182 | +bool Animator::DoStep() |
183 | { |
184 | const gint64 current_time = g_get_monotonic_time(); |
185 | - const gint64 end_time = self->_start_time + self->_duration; |
186 | - |
187 | - if (current_time < end_time && self->_progress < 1.0f) |
188 | - { |
189 | - const double diff_time = current_time - self->_start_time; |
190 | - self->_progress = CLAMP(self->_start_progress + (diff_time / self->_duration), 0.0f, 1.0f); |
191 | - self->animation_updated.emit(self->_progress); |
192 | - |
193 | - return TRUE; |
194 | - } else { |
195 | - self->_progress = 1.0f; |
196 | - self->animation_updated.emit(1.0f); |
197 | - self->animation_ended.emit(); |
198 | - self->_timeout_id = 0; |
199 | - |
200 | - return FALSE; |
201 | - } |
202 | + const gint64 duration = one_time_duration_ > 0 ? one_time_duration_ : duration_; |
203 | + const gint64 end_time = start_time_ + duration; |
204 | + |
205 | + if (current_time < end_time && progress_ < 1.0f && duration > 0) |
206 | + { |
207 | + const double diff_time = current_time - start_time_; |
208 | + progress_ = CLAMP(start_progress_ + (diff_time / duration), 0.0f, 1.0f); |
209 | + animation_updated.emit(progress_); |
210 | + |
211 | + return true; |
212 | + } |
213 | + else |
214 | + { |
215 | + progress_ = 1.0f; |
216 | + animation_updated.emit(1.0f); |
217 | + animation_ended.emit(); |
218 | + one_time_duration_ = 0; |
219 | + timeout_id_ = 0; |
220 | + |
221 | + return false; |
222 | + } |
223 | +} |
224 | + |
225 | +gboolean Animator::TimerTimeOut(Animator *self) |
226 | +{ |
227 | + return self->DoStep() ? TRUE : FALSE; |
228 | } |
229 | |
230 | } //namespace |
231 | |
232 | === modified file 'plugins/unityshell/src/Animator.h' |
233 | --- plugins/unityshell/src/Animator.h 2011-09-23 00:31:08 +0000 |
234 | +++ plugins/unityshell/src/Animator.h 2011-12-14 17:24:33 +0000 |
235 | @@ -20,33 +20,30 @@ |
236 | #ifndef UNITY_ANIMATOR_H_ |
237 | #define UNITY_ANIMATOR_H_ |
238 | |
239 | -#include <Nux/Nux.h> |
240 | +#include <glib.h> |
241 | +#include <cstdint> |
242 | +#include <sigc++/sigc++.h> |
243 | +#include <boost/utility.hpp> |
244 | |
245 | namespace unity |
246 | { |
247 | - |
248 | -class FadableObject2 |
249 | -{ |
250 | -public: |
251 | - virtual void SetOpacity(double value) = 0; |
252 | - virtual double GetOpacity() = 0; |
253 | -}; |
254 | - |
255 | -class Animator |
256 | -{ |
257 | -public: |
258 | - Animator(unsigned int duration, unsigned int fps_rate = 30); |
259 | +class Animator : boost::noncopyable |
260 | +{ |
261 | +public: |
262 | + Animator(unsigned int default_duration, unsigned int fps_rate = 30); |
263 | ~Animator(); |
264 | |
265 | void SetRate(unsigned int fps_rate); |
266 | void SetDuration(unsigned int duration); |
267 | |
268 | - unsigned int GetRate(); |
269 | - unsigned int GetDuration(); |
270 | - double GetProgress(); |
271 | - bool IsRunning(); |
272 | + unsigned int GetRate() const; |
273 | + unsigned int GetDuration() const; |
274 | + double GetProgress() const; |
275 | + bool IsRunning() const; |
276 | |
277 | void Start(double start_progress = 0.0f); |
278 | + void Start(unsigned int one_time_duration, double start_progress = 0.0f); |
279 | + bool DoStep(); |
280 | void Stop(); |
281 | |
282 | sigc::signal<void> animation_started; |
283 | @@ -56,12 +53,13 @@ |
284 | sigc::signal<void, double> animation_stopped; |
285 | |
286 | private: |
287 | - int64_t _start_time; |
288 | - unsigned int _rate; |
289 | - unsigned int _duration; |
290 | - unsigned int _timeout_id; |
291 | - double _start_progress; |
292 | - double _progress; |
293 | + int64_t start_time_; |
294 | + unsigned int rate_; |
295 | + unsigned int duration_; |
296 | + unsigned int one_time_duration_; |
297 | + unsigned int timeout_id_; |
298 | + double start_progress_; |
299 | + double progress_; |
300 | |
301 | static gboolean TimerTimeOut(Animator *self); |
302 | }; |
303 | |
304 | === modified file 'plugins/unityshell/src/LauncherController.cpp' |
305 | --- plugins/unityshell/src/LauncherController.cpp 2011-11-30 03:06:44 +0000 |
306 | +++ plugins/unityshell/src/LauncherController.cpp 2011-12-14 17:24:33 +0000 |
307 | @@ -403,8 +403,11 @@ |
308 | |
309 | app = BAMF_APPLICATION(view); |
310 | |
311 | - if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"))) |
312 | + if (bamf_view_is_sticky(view) || |
313 | + g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"))) |
314 | + { |
315 | return; |
316 | + } |
317 | |
318 | BamfLauncherIcon* icon = new BamfLauncherIcon(self->launcher_.GetPointer(), app); |
319 | icon->SetIconType(LauncherIcon::TYPE_APPLICATION); |
320 | |
321 | === modified file 'plugins/unityshell/src/PanelController.cpp' |
322 | --- plugins/unityshell/src/PanelController.cpp 2011-11-16 00:09:59 +0000 |
323 | +++ plugins/unityshell/src/PanelController.cpp 2011-12-14 17:24:33 +0000 |
324 | @@ -55,6 +55,9 @@ |
325 | |
326 | float opacity() const; |
327 | |
328 | + void SetMenuShowTimings(int fadein, int fadeout, int discovery, |
329 | + int discovery_fadein, int discovery_fadeout); |
330 | + |
331 | private: |
332 | unity::PanelView* ViewForWindow(nux::BaseWindow* window); |
333 | void OnScreenChanged(int primary_monitor, std::vector<nux::Geometry>& monitors); |
334 | @@ -68,6 +71,11 @@ |
335 | float opacity_; |
336 | bool opacity_maximized_toggle_; |
337 | bool open_menu_start_received_; |
338 | + int menus_fadein_; |
339 | + int menus_fadeout_; |
340 | + int menus_discovery_; |
341 | + int menus_discovery_fadein_; |
342 | + int menus_discovery_fadeout_; |
343 | }; |
344 | |
345 | |
346 | @@ -147,12 +155,28 @@ |
347 | { |
348 | opacity_maximized_toggle_ = enabled; |
349 | |
350 | - for (auto window : windows_) |
351 | + for (auto window: windows_) |
352 | { |
353 | ViewForWindow(window)->SetOpacityMaximizedToggle(opacity_maximized_toggle_); |
354 | } |
355 | } |
356 | |
357 | +void Controller::Impl::SetMenuShowTimings(int fadein, int fadeout, int discovery, |
358 | + int discovery_fadein, int discovery_fadeout) |
359 | +{ |
360 | + menus_fadein_ = fadein; |
361 | + menus_fadeout_ = fadeout; |
362 | + menus_discovery_ = discovery; |
363 | + menus_discovery_fadein_ = discovery_fadein; |
364 | + menus_discovery_fadeout_ = discovery_fadeout; |
365 | + |
366 | + for (auto window: windows_) |
367 | + { |
368 | + ViewForWindow(window)->SetMenuShowTimings(fadein, fadeout, discovery, |
369 | + discovery_fadein, discovery_fadeout); |
370 | + } |
371 | +} |
372 | + |
373 | void Controller::Impl::QueueRedraw() |
374 | { |
375 | for (auto window: windows_) |
376 | @@ -216,6 +240,8 @@ |
377 | view->SetMaximumHeight(24); |
378 | view->SetOpacity(opacity_); |
379 | view->SetOpacityMaximizedToggle(opacity_maximized_toggle_); |
380 | + view->SetMenuShowTimings(menus_fadein_, menus_fadeout_, menus_discovery_, |
381 | + menus_discovery_fadein_, menus_discovery_fadeout_); |
382 | view->SetPrimary(i == primary_monitor); |
383 | view->SetMonitor(i); |
384 | |
385 | @@ -301,6 +327,12 @@ |
386 | pimpl->SetOpacityMaximizedToggle(enabled); |
387 | } |
388 | |
389 | +void Controller::SetMenuShowTimings(int fadein, int fadeout, int discovery, |
390 | + int discovery_fadein, int discovery_fadeout) |
391 | +{ |
392 | + pimpl->SetMenuShowTimings(fadein, fadeout, discovery, discovery_fadein, discovery_fadeout); |
393 | +} |
394 | + |
395 | void Controller::QueueRedraw() |
396 | { |
397 | pimpl->QueueRedraw(); |
398 | |
399 | === modified file 'plugins/unityshell/src/PanelController.h' |
400 | --- plugins/unityshell/src/PanelController.h 2011-11-16 00:09:59 +0000 |
401 | +++ plugins/unityshell/src/PanelController.h 2011-12-14 17:24:33 +0000 |
402 | @@ -48,6 +48,8 @@ |
403 | // NOTE: nux::Property maybe? |
404 | void SetOpacity(float opacity); |
405 | void SetOpacityMaximizedToggle(bool enabled); |
406 | + void SetMenuShowTimings(int fadein, int fadeout, int discovery, int discovery_fadein, int discovery_fadeout); |
407 | + |
408 | float opacity() const; |
409 | |
410 | private: |
411 | |
412 | === modified file 'plugins/unityshell/src/PanelMenuView.cpp' |
413 | --- plugins/unityshell/src/PanelMenuView.cpp 2011-12-14 16:18:41 +0000 |
414 | +++ plugins/unityshell/src/PanelMenuView.cpp 2011-12-14 17:24:33 +0000 |
415 | @@ -49,44 +49,40 @@ |
416 | |
417 | #define WINDOW_TITLE_FONT_KEY "/apps/metacity/general/titlebar_font" |
418 | |
419 | -#define PANEL_ENTRIES_FADEIN 100 |
420 | -#define PANEL_ENTRIES_FADEOUT 120 |
421 | - |
422 | namespace unity |
423 | { |
424 | |
425 | -static void on_active_window_changed(BamfMatcher* matcher, |
426 | - BamfView* old_view, |
427 | - BamfView* new_view, |
428 | - PanelMenuView* self); |
429 | - |
430 | -static void on_name_changed(BamfView* bamf_view, |
431 | - gchar* old_name, |
432 | - gchar* new_name, |
433 | - PanelMenuView* self); |
434 | - |
435 | PanelMenuView::PanelMenuView(int padding) |
436 | - : _matcher(NULL), |
437 | - _title_layer(NULL), |
438 | + : _matcher(bamf_matcher_get_default()), |
439 | + _title_layer(nullptr), |
440 | _util_cg(CAIRO_FORMAT_ARGB32, 1, 1), |
441 | - _gradient_texture(NULL), |
442 | + _gradient_texture(nullptr), |
443 | _is_inside(false), |
444 | _is_maximized(false), |
445 | _is_own_window(false), |
446 | - _last_active_view(NULL), |
447 | + _last_active_view(nullptr), |
448 | + _new_application(nullptr), |
449 | _last_width(0), |
450 | _last_height(0), |
451 | _places_showing(false), |
452 | _show_now_activated(false), |
453 | _we_control_active(false), |
454 | + _new_app_menu_shown(false), |
455 | _monitor(0), |
456 | _active_xid(0), |
457 | _active_moved_id(0), |
458 | _update_show_now_id(0), |
459 | + _new_app_show_id(0), |
460 | + _new_app_hide_id(0), |
461 | _place_shown_interest(0), |
462 | _place_hidden_interest(0), |
463 | - _fade_in_animator(NULL), |
464 | - _fade_out_animator(NULL) |
465 | + _menus_fadein(100), |
466 | + _menus_fadeout(120), |
467 | + _menus_discovery(2), |
468 | + _menus_discovery_fadein(200), |
469 | + _menus_discovery_fadeout(300), |
470 | + _fade_in_animator(nullptr), |
471 | + _fade_out_animator(nullptr) |
472 | { |
473 | WindowManager* win_manager; |
474 | |
475 | @@ -100,13 +96,16 @@ |
476 | */ |
477 | layout_ = _menu_layout; |
478 | |
479 | - _matcher = bamf_matcher_get_default(); |
480 | - _activate_window_changed_id = g_signal_connect(_matcher, "active-window-changed", |
481 | - G_CALLBACK(on_active_window_changed), this); |
482 | + _view_opened_signal.Connect(_matcher, "view-opened", |
483 | + sigc::mem_fun(this, &PanelMenuView::OnViewOpened)); |
484 | + _view_closed_signal.Connect(_matcher, "view-closed", |
485 | + sigc::mem_fun(this, &PanelMenuView::OnViewClosed)); |
486 | + _active_win_changed_signal.Connect(_matcher, "active-window-changed", |
487 | + sigc::mem_fun(this, &PanelMenuView::OnActiveWindowChanged)); |
488 | + _active_app_changed_signal.Connect(_matcher, "active-application-changed", |
489 | + sigc::mem_fun(this, &PanelMenuView::OnActiveAppChanged)); |
490 | |
491 | _padding = padding; |
492 | - _name_changed_callback_instance = NULL; |
493 | - _name_changed_callback_id = 0; |
494 | |
495 | _window_buttons = new WindowButtons(); |
496 | _window_buttons->SetParentObject(this); |
497 | @@ -163,8 +162,8 @@ |
498 | (UBusCallback)PanelMenuView::OnPlaceViewHidden, |
499 | this); |
500 | |
501 | - _fade_in_animator = new Animator(PANEL_ENTRIES_FADEIN); |
502 | - _fade_out_animator = new Animator(PANEL_ENTRIES_FADEOUT); |
503 | + _fade_in_animator = new Animator(_menus_fadein); |
504 | + _fade_out_animator = new Animator(_menus_fadeout); |
505 | |
506 | _fade_in_animator->animation_updated.connect(sigc::mem_fun(this, &PanelMenuView::OnFadeInChanged)); |
507 | _fade_in_animator->animation_ended.connect(sigc::mem_fun(this, &PanelMenuView::FullRedraw)); |
508 | @@ -180,15 +179,15 @@ |
509 | |
510 | PanelMenuView::~PanelMenuView() |
511 | { |
512 | - if (_name_changed_callback_id) |
513 | - g_signal_handler_disconnect(_name_changed_callback_instance, |
514 | - _name_changed_callback_id); |
515 | - if (_activate_window_changed_id) |
516 | - g_signal_handler_disconnect(_matcher, |
517 | - _activate_window_changed_id); |
518 | if (_active_moved_id) |
519 | g_source_remove(_active_moved_id); |
520 | |
521 | + if (_new_app_show_id) |
522 | + g_source_remove(_new_app_show_id); |
523 | + |
524 | + if (_new_app_hide_id) |
525 | + g_source_remove(_new_app_hide_id); |
526 | + |
527 | if (_title_layer) |
528 | delete _title_layer; |
529 | |
530 | @@ -208,6 +207,35 @@ |
531 | |
532 | if (_place_hidden_interest != 0) |
533 | ubus_server_unregister_interest(ubus, _place_hidden_interest); |
534 | + |
535 | + for (auto app : _new_apps) |
536 | + g_object_unref(app); |
537 | +} |
538 | + |
539 | +void |
540 | +PanelMenuView::SetMenuShowTimings(int fadein, int fadeout, int discovery, |
541 | + int discovery_fadein, int discovery_fadeout) |
542 | +{ |
543 | + if (fadein > -1) |
544 | + { |
545 | + _menus_fadein = fadein; |
546 | + _fade_in_animator->SetDuration(_menus_fadein); |
547 | + } |
548 | + |
549 | + if (fadeout > -1) |
550 | + { |
551 | + _menus_fadeout = fadeout; |
552 | + _fade_out_animator->SetDuration(_menus_fadeout); |
553 | + } |
554 | + |
555 | + if (discovery > -1) |
556 | + _menus_discovery = discovery; |
557 | + |
558 | + if (discovery_fadein > -1) |
559 | + _menus_discovery_fadein = discovery_fadein; |
560 | + |
561 | + if (discovery_fadeout > -1) |
562 | + _menus_discovery_fadeout = discovery_fadeout; |
563 | } |
564 | |
565 | void |
566 | @@ -224,9 +252,9 @@ |
567 | bool mouse_inside = TestMousePointerInclusionFilterMouseWheel(mouse_position, event_type); |
568 | |
569 | if (mouse_inside == false) |
570 | - return NULL; |
571 | + return nullptr; |
572 | |
573 | - Area* found_area = NULL; |
574 | + Area* found_area = nullptr; |
575 | if (!_we_control_active) |
576 | { |
577 | found_area = _panel_titlebar_grab_area->FindAreaUnderMouse(mouse_position, event_type); |
578 | @@ -327,7 +355,7 @@ |
579 | { |
580 | if (!_is_own_window && !_places_showing && _we_control_active) |
581 | { |
582 | - if (_is_inside || _last_active_view || _show_now_activated) |
583 | + if (_is_inside || _last_active_view || _show_now_activated || _new_application) |
584 | { |
585 | return true; |
586 | } |
587 | @@ -344,7 +372,7 @@ |
588 | |
589 | if (!_is_own_window && _we_control_active && _is_maximized) |
590 | { |
591 | - if (_is_inside || _show_now_activated) |
592 | + if (_is_inside || _show_now_activated || _new_application) |
593 | { |
594 | return true; |
595 | } |
596 | @@ -382,23 +410,28 @@ |
597 | if (_title_layer && !_is_own_window) |
598 | { |
599 | guint blend_alpha = 0, blend_src = 0, blend_dest = 0; |
600 | + bool draw_menus = DrawMenus(); |
601 | + bool draw_window_buttons = DrawWindowButtons(); |
602 | + bool has_menu = false; |
603 | bool draw_faded_title = false; |
604 | |
605 | GfxContext.GetRenderStates().GetBlend(blend_alpha, blend_src, blend_dest); |
606 | |
607 | - if (!DrawWindowButtons() && _we_control_active && |
608 | - (DrawMenus() || (GetOpacity() > 0.0f && _window_buttons->GetOpacity() == 0.0f))) |
609 | + for (auto entry : entries_) |
610 | { |
611 | - for (auto entry : entries_) |
612 | + if (entry.second->IsEntryValid()) |
613 | { |
614 | - if (entry.second->IsEntryValid()) |
615 | - { |
616 | - draw_faded_title = true; |
617 | - break; |
618 | - } |
619 | + has_menu = true; |
620 | + break; |
621 | } |
622 | } |
623 | |
624 | + if (!draw_window_buttons && _we_control_active && has_menu && |
625 | + (draw_menus || (GetOpacity() > 0.0f && _window_buttons->GetOpacity() == 0.0f))) |
626 | + { |
627 | + draw_faded_title = true; |
628 | + } |
629 | + |
630 | if (draw_faded_title) |
631 | { |
632 | bool build_gradient = false; |
633 | @@ -412,7 +445,7 @@ |
634 | } |
635 | else |
636 | { |
637 | - if (_gradient_texture->LockRect(0, &lockrect, NULL) != OGL_OK) |
638 | + if (_gradient_texture->LockRect(0, &lockrect, nullptr) != OGL_OK) |
639 | build_gradient = true; |
640 | else |
641 | locked = true; |
642 | @@ -433,44 +466,55 @@ |
643 | _gradient_texture = nux::GetGraphicsDisplay()->GetGpuDevice()-> |
644 | CreateSystemCapableDeviceTexture(texture_data.GetWidth(), |
645 | texture_data.GetHeight(), 1, texture_data.GetFormat()); |
646 | - locked = (_gradient_texture->LockRect(0, &lockrect, NULL) == OGL_OK); |
647 | + locked = (_gradient_texture->LockRect(0, &lockrect, nullptr) == OGL_OK); |
648 | } |
649 | |
650 | + BYTE* dest_buffer = (BYTE*) lockrect.pBits; |
651 | int gradient_opacity = 255.0f * GetOpacity(); |
652 | - BYTE* dest_buffer = (BYTE*) lockrect.pBits; |
653 | + int buttons_opacity = 255.0f * _window_buttons->GetOpacity(); |
654 | + |
655 | + int first_step = button_width * (factor - 1); |
656 | + int second_step = button_width * factor; |
657 | |
658 | for (int x = 0; x < geo.width && dest_buffer && locked; x++) |
659 | { |
660 | - BYTE a; |
661 | - if (x < button_width * (factor - 1)) |
662 | + BYTE r, g, b, a; |
663 | + |
664 | + r = 223; |
665 | + g = 219; |
666 | + b = 210; |
667 | + |
668 | + if (x < first_step) |
669 | { |
670 | - a = 0xff; |
671 | + int color_increment = (first_step - x) * 4; |
672 | + |
673 | + r = CLAMP(r + color_increment, r, 0xff); |
674 | + g = CLAMP(g + color_increment, g, 0xff); |
675 | + b = CLAMP(b + color_increment, b, 0xff); |
676 | + a = 0xff - buttons_opacity; |
677 | } |
678 | - else if (x < button_width * factor) |
679 | + else if (x < second_step) |
680 | { |
681 | - a = 0xff - gradient_opacity * (((float)x - (button_width * (factor - 1))) / (float)(button_width)); |
682 | + a = 0xff - gradient_opacity * (((float)x - (first_step)) / |
683 | + (float)(button_width)); |
684 | } |
685 | else |
686 | { |
687 | - if (!DrawMenus()) |
688 | + if (!draw_menus) |
689 | { |
690 | a = 0xff - gradient_opacity; |
691 | } |
692 | - else if (0xff - gradient_opacity > 0x55) |
693 | + else |
694 | { |
695 | // If we're fading-out the title, it's better to quickly hide |
696 | // the transparent right-most area |
697 | - a = 0xff - gradient_opacity - 0x55; |
698 | - } |
699 | - else |
700 | - { |
701 | - a = 0x00; |
702 | + a = CLAMP(0xff - gradient_opacity - 0x55, 0x00, 0xff); |
703 | } |
704 | } |
705 | |
706 | - *(dest_buffer + 4 * x + 0) = (223 * a) / 255; //red |
707 | - *(dest_buffer + 4 * x + 1) = (219 * a) / 255; //green |
708 | - *(dest_buffer + 4 * x + 2) = (210 * a) / 255; //blue |
709 | + *(dest_buffer + 4 * x + 0) = (r * a) / 0xff; //red |
710 | + *(dest_buffer + 4 * x + 1) = (g * a) / 0xff; //green |
711 | + *(dest_buffer + 4 * x + 2) = (b * a) / 0xff; //blue |
712 | *(dest_buffer + 4 * x + 3) = a; |
713 | } |
714 | |
715 | @@ -491,37 +535,39 @@ |
716 | _title_layer->GetDeviceTexture(), |
717 | texxform1, |
718 | nux::color::White); |
719 | - |
720 | - // The previous blend is too aggressive on the texture and therefore there |
721 | - // is a slight loss of clarity. This fixes that |
722 | - geo.width = button_width * (factor - 1); |
723 | - nux::GetPainter().PushDrawLayer(GfxContext, geo, _title_layer); |
724 | - geo = GetGeometry(); |
725 | } |
726 | - else if (_window_buttons->GetOpacity() < 1.0f && |
727 | - _window_buttons->GetOpacity() > 0.0f && !_places_showing) |
728 | + else if (!_places_showing) |
729 | { |
730 | - double title_opacity = 1.0f - _window_buttons->GetOpacity(); |
731 | - |
732 | - if (!DrawWindowButtons()) |
733 | + if (_we_control_active && _window_buttons->GetOpacity() == 0.0 && |
734 | + (!has_menu || (has_menu && GetOpacity() == 0.0))) |
735 | { |
736 | - // If we're fading-out the buttons/menus, let's fade-in quickly the title |
737 | - title_opacity = CLAMP(title_opacity + 0.25f, 0.0f, 1.0f); |
738 | + nux::GetPainter().PushDrawLayer(GfxContext, geo, _title_layer); |
739 | } |
740 | else |
741 | { |
742 | - // If we're fading-in the buttons/menus, let's fade-out quickly the title |
743 | - title_opacity = CLAMP(title_opacity - 0.25f, 0.0f, 1.0f); |
744 | + double title_opacity = 1.0f; |
745 | + |
746 | + if (has_menu) |
747 | + title_opacity -= MAX(GetOpacity(), _window_buttons->GetOpacity()); |
748 | + else |
749 | + title_opacity -= _window_buttons->GetOpacity(); |
750 | + |
751 | + if (!draw_window_buttons && !draw_menus) |
752 | + { |
753 | + // If we're fading-out the buttons/menus, let's fade-in quickly the title |
754 | + title_opacity = CLAMP(title_opacity + 0.1f, 0.0f, 1.0f); |
755 | + } |
756 | + else |
757 | + { |
758 | + // If we're fading-in the buttons/menus, let's fade-out quickly the title |
759 | + title_opacity = CLAMP(title_opacity - 0.2f, 0.0f, 1.0f); |
760 | + } |
761 | + |
762 | + nux::TexCoordXForm texxform; |
763 | + GfxContext.QRP_1Tex(geo.x, geo.y, geo.width, geo.height, |
764 | + _title_layer->GetDeviceTexture(), texxform, |
765 | + nux::color::White * title_opacity); |
766 | } |
767 | - |
768 | - nux::TexCoordXForm texxform; |
769 | - GfxContext.QRP_1Tex(geo.x, geo.y, geo.width, geo.height, |
770 | - _title_layer->GetDeviceTexture(), texxform, |
771 | - nux::color::White * title_opacity); |
772 | - } |
773 | - else if (_window_buttons->GetOpacity() == 0.0f && _we_control_active) |
774 | - { |
775 | - nux::GetPainter().PushDrawLayer(GfxContext, geo, _title_layer); |
776 | } |
777 | |
778 | GfxContext.GetRenderStates().SetBlend(blend_alpha, blend_src, blend_dest); |
779 | @@ -549,7 +595,16 @@ |
780 | _menu_layout->ProcessDraw(GfxContext, true); |
781 | |
782 | _fade_out_animator->Stop(); |
783 | - _fade_in_animator->Start(GetOpacity()); |
784 | + |
785 | + if (_new_application && !_is_inside) |
786 | + { |
787 | + _fade_in_animator->Start(_menus_discovery_fadein, GetOpacity()); |
788 | + } |
789 | + else |
790 | + { |
791 | + _fade_in_animator->Start(GetOpacity()); |
792 | + _new_app_menu_shown = false; |
793 | + } |
794 | } |
795 | else |
796 | { |
797 | @@ -563,14 +618,14 @@ |
798 | |
799 | _fade_in_animator->Stop(); |
800 | |
801 | - if (_fade_out_animator->GetDuration() != PANEL_ENTRIES_FADEOUT) |
802 | - { |
803 | - if (_fade_out_animator->IsRunning()) |
804 | - _fade_out_animator->Stop(); |
805 | - |
806 | - _fade_out_animator->SetDuration(PANEL_ENTRIES_FADEOUT); |
807 | - } |
808 | - _fade_out_animator->Start(1.0f - GetOpacity()); |
809 | + if (!_new_app_menu_shown) |
810 | + { |
811 | + _fade_out_animator->Start(1.0f - GetOpacity()); |
812 | + } |
813 | + else |
814 | + { |
815 | + _fade_out_animator->Start(_menus_discovery_fadeout, 1.0f - GetOpacity()); |
816 | + } |
817 | } |
818 | |
819 | if (draw_buttons) |
820 | @@ -589,8 +644,7 @@ |
821 | /* If we try to hide only the buttons, then use a faster fadeout */ |
822 | if (!_fade_out_animator->IsRunning()) |
823 | { |
824 | - _fade_out_animator->SetDuration(PANEL_ENTRIES_FADEOUT/5); |
825 | - _fade_out_animator->Start(1.0f - _window_buttons->GetOpacity()); |
826 | + _fade_out_animator->Start(_menus_fadeout/3, 1.0f - _window_buttons->GetOpacity()); |
827 | } |
828 | } |
829 | |
830 | @@ -600,7 +654,7 @@ |
831 | gchar* |
832 | PanelMenuView::GetActiveViewName() |
833 | { |
834 | - gchar* label = NULL; |
835 | + gchar* label = nullptr; |
836 | BamfWindow* window; |
837 | |
838 | _is_own_window = false; |
839 | @@ -659,7 +713,7 @@ |
840 | } |
841 | } |
842 | |
843 | - if (label == NULL) |
844 | + if (label == nullptr) |
845 | { |
846 | BamfView* active_view; |
847 | |
848 | @@ -691,8 +745,8 @@ |
849 | int increase_size |
850 | ) |
851 | { |
852 | - PangoLayout* layout = NULL; |
853 | - PangoFontDescription* desc = NULL; |
854 | + PangoLayout* layout = nullptr; |
855 | + PangoFontDescription* desc = nullptr; |
856 | GtkSettings* settings = gtk_settings_get_default(); |
857 | cairo_t* cr; |
858 | cairo_pattern_t* linpat; |
859 | @@ -712,9 +766,9 @@ |
860 | |
861 | cr = _util_cg.GetContext(); |
862 | |
863 | - g_object_get(settings, "gtk-xft-dpi", &dpi, NULL); |
864 | + g_object_get(settings, "gtk-xft-dpi", &dpi, nullptr); |
865 | |
866 | - font_description = gconf_client_get_string(client, WINDOW_TITLE_FONT_KEY, NULL); |
867 | + font_description = gconf_client_get_string(client, WINDOW_TITLE_FONT_KEY, nullptr); |
868 | desc = pango_font_description_from_string(font_description); |
869 | |
870 | if (font_desc) |
871 | @@ -742,7 +796,7 @@ |
872 | pango_cairo_context_set_resolution(cxt, (float)dpi / (float)PANGO_SCALE); |
873 | pango_layout_context_changed(layout); |
874 | |
875 | - pango_layout_get_extents(layout, NULL, &log_rect); |
876 | + pango_layout_get_extents(layout, nullptr, &log_rect); |
877 | text_width = log_rect.width / PANGO_SCALE; |
878 | text_height = log_rect.height / PANGO_SCALE; |
879 | |
880 | @@ -833,7 +887,7 @@ |
881 | y = 0; |
882 | |
883 | if (label) |
884 | - DrawText(cr, x, y, width, height, NULL, label); |
885 | + DrawText(cr, x, y, width, height, nullptr, label); |
886 | |
887 | cairo_destroy(cr); |
888 | |
889 | @@ -869,7 +923,7 @@ |
890 | { |
891 | if (_last_active_view == view) |
892 | { |
893 | - _last_active_view = NULL; |
894 | + _last_active_view = nullptr; |
895 | } |
896 | } |
897 | |
898 | @@ -894,28 +948,139 @@ |
899 | { |
900 | auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); |
901 | _is_inside = GetAbsoluteGeometry().IsPointInside(mouse.x, mouse.y); |
902 | - _last_active_view = NULL; |
903 | + _last_active_view = nullptr; |
904 | |
905 | FullRedraw(); |
906 | } |
907 | |
908 | void |
909 | -PanelMenuView::OnNameChanged(gchar* new_name, gchar* old_name) |
910 | +PanelMenuView::OnNameChanged(BamfView* bamf_view, gchar* new_name, gchar* old_name) |
911 | { |
912 | Refresh(); |
913 | FullRedraw(); |
914 | } |
915 | |
916 | -void |
917 | -PanelMenuView::OnActiveWindowChanged(BamfView* old_view, |
918 | +gboolean |
919 | +PanelMenuView::OnNewAppShow(PanelMenuView* self) |
920 | +{ |
921 | + self->_new_application = bamf_matcher_get_active_application(self->_matcher); |
922 | + self->QueueDraw(); |
923 | + |
924 | + if (self->_new_app_hide_id) |
925 | + { |
926 | + g_source_remove(self->_new_app_hide_id); |
927 | + self->_new_app_hide_id = 0; |
928 | + self->_new_app_menu_shown = false; |
929 | + } |
930 | + |
931 | + self->_new_app_hide_id = g_timeout_add_seconds(self->_menus_discovery, |
932 | + (GSourceFunc)PanelMenuView::OnNewAppHide, |
933 | + self); |
934 | + self->_new_app_show_id = 0; |
935 | + |
936 | + return FALSE; |
937 | +} |
938 | + |
939 | +gboolean |
940 | +PanelMenuView::OnNewAppHide(PanelMenuView* self) |
941 | +{ |
942 | + self->OnViewClosed(self->_matcher, BAMF_VIEW(self->_new_application.RawPtr())); |
943 | + self->_new_app_hide_id = 0; |
944 | + self->_new_app_menu_shown = true; |
945 | + self->QueueDraw(); |
946 | + |
947 | + return FALSE; |
948 | +} |
949 | + |
950 | +void |
951 | +PanelMenuView::OnViewOpened(BamfMatcher *matcher, BamfView *view) |
952 | +{ |
953 | + /* FIXME: here we should also check for if the view is also user_visible |
954 | + * but it seems that BAMF doesn't handle this correctly after some |
955 | + * stress tests (repeated launches). */ |
956 | + if (!BAMF_IS_APPLICATION(view)) |
957 | + return; |
958 | + |
959 | + _new_apps.push_front(BAMF_APPLICATION(g_object_ref(view))); |
960 | +} |
961 | + |
962 | +void |
963 | +PanelMenuView::OnViewClosed(BamfMatcher *matcher, BamfView *view) |
964 | +{ |
965 | + if (!BAMF_IS_APPLICATION(view)) |
966 | + return; |
967 | + |
968 | + BamfApplication* app = BAMF_APPLICATION(view); |
969 | + |
970 | + if (std::find(_new_apps.begin(), _new_apps.end(), app) != _new_apps.end()) |
971 | + { |
972 | + _new_apps.remove(app); |
973 | + g_object_unref(app); |
974 | + |
975 | + if (_new_application == app) |
976 | + _new_application = nullptr; |
977 | + } |
978 | +} |
979 | + |
980 | +void |
981 | +PanelMenuView::OnActiveAppChanged(BamfMatcher *matcher, |
982 | + BamfApplication* old_app, |
983 | + BamfApplication* new_app) |
984 | +{ |
985 | + if (BAMF_IS_APPLICATION(new_app)) |
986 | + { |
987 | + if (std::find(_new_apps.begin(), _new_apps.end(), new_app) != _new_apps.end()) |
988 | + { |
989 | + if (_new_application != new_app) |
990 | + { |
991 | + /* Add a small delay before showing the menus, this is done both |
992 | + * to fix the issues with applications that takes some time to loads |
993 | + * menus and to show the menus only when an application has been |
994 | + * kept active for some time */ |
995 | + |
996 | + if (_new_app_show_id) |
997 | + g_source_remove(_new_app_show_id); |
998 | + |
999 | + _new_app_show_id = g_timeout_add(300, |
1000 | + (GSourceFunc)PanelMenuView::OnNewAppShow, |
1001 | + this); |
1002 | + } |
1003 | + } |
1004 | + else |
1005 | + { |
1006 | + if (_new_app_show_id) |
1007 | + { |
1008 | + g_source_remove(_new_app_show_id); |
1009 | + _new_app_show_id = 0; |
1010 | + } |
1011 | + |
1012 | + if (_new_app_hide_id) |
1013 | + { |
1014 | + g_source_remove(_new_app_hide_id); |
1015 | + _new_app_hide_id = 0; |
1016 | + _new_app_menu_shown = false; |
1017 | + } |
1018 | + |
1019 | + if (_new_application) |
1020 | + OnViewClosed(matcher, BAMF_VIEW(_new_application.RawPtr())); |
1021 | + } |
1022 | + } |
1023 | +} |
1024 | + |
1025 | +void |
1026 | +PanelMenuView::OnActiveWindowChanged(BamfMatcher *matcher, |
1027 | + BamfView* old_view, |
1028 | BamfView* new_view) |
1029 | { |
1030 | _show_now_activated = false; |
1031 | _is_maximized = false; |
1032 | _active_xid = 0; |
1033 | + |
1034 | if (_active_moved_id) |
1035 | + { |
1036 | g_source_remove(_active_moved_id); |
1037 | - _active_moved_id = 0; |
1038 | + _active_moved_id = 0; |
1039 | + } |
1040 | |
1041 | if (BAMF_IS_WINDOW(new_view)) |
1042 | { |
1043 | @@ -944,16 +1109,11 @@ |
1044 | } |
1045 | |
1046 | // first see if we need to remove and old callback |
1047 | - if (_name_changed_callback_id != 0) |
1048 | - g_signal_handler_disconnect(_name_changed_callback_instance, |
1049 | - _name_changed_callback_id); |
1050 | + _view_name_changed_signal.Disconnect(); |
1051 | |
1052 | - // register callback for new view and store handler-id |
1053 | - _name_changed_callback_instance = G_OBJECT(new_view); |
1054 | - _name_changed_callback_id = g_signal_connect(_name_changed_callback_instance, |
1055 | - "name-changed", |
1056 | - (GCallback) on_name_changed, |
1057 | - this); |
1058 | + // register callback for new view |
1059 | + _view_name_changed_signal.Connect(new_view, "name-changed", |
1060 | + sigc::mem_fun(this, &PanelMenuView::OnNameChanged)); |
1061 | } |
1062 | |
1063 | Refresh(); |
1064 | @@ -1129,7 +1289,7 @@ |
1065 | { |
1066 | if (_places_showing) |
1067 | { |
1068 | - ubus_server_send_message(ubus_server_get_default(), UBUS_PLACE_VIEW_CLOSE_REQUEST, NULL); |
1069 | + ubus_server_send_message(ubus_server_get_default(), UBUS_PLACE_VIEW_CLOSE_REQUEST, nullptr); |
1070 | } |
1071 | else |
1072 | { |
1073 | @@ -1342,35 +1502,13 @@ |
1074 | const gchar* |
1075 | PanelMenuView::GetChildsName() |
1076 | { |
1077 | - return NULL; |
1078 | + return nullptr; |
1079 | } |
1080 | |
1081 | void PanelMenuView::AddProperties(GVariantBuilder* builder) |
1082 | { |
1083 | } |
1084 | |
1085 | -/* |
1086 | - * C code for callbacks |
1087 | - */ |
1088 | -static void |
1089 | - |
1090 | -on_active_window_changed(BamfMatcher* matcher, |
1091 | - BamfView* old_view, |
1092 | - BamfView* new_view, |
1093 | - PanelMenuView* self) |
1094 | -{ |
1095 | - self->OnActiveWindowChanged(old_view, new_view); |
1096 | -} |
1097 | - |
1098 | -static void |
1099 | -on_name_changed(BamfView* bamf_view, |
1100 | - gchar* old_name, |
1101 | - gchar* new_name, |
1102 | - PanelMenuView* self) |
1103 | -{ |
1104 | - self->OnNameChanged(new_name, old_name); |
1105 | -} |
1106 | - |
1107 | void |
1108 | PanelMenuView::OnPlaceViewShown(GVariant* data, PanelMenuView* self) |
1109 | { |
1110 | |
1111 | === modified file 'plugins/unityshell/src/PanelMenuView.h' |
1112 | --- plugins/unityshell/src/PanelMenuView.h 2011-12-14 16:18:41 +0000 |
1113 | +++ plugins/unityshell/src/PanelMenuView.h 2011-12-14 17:24:33 +0000 |
1114 | @@ -31,6 +31,8 @@ |
1115 | #include "PluginAdapter.h" |
1116 | #include "Animator.h" |
1117 | |
1118 | +#include <UnityCore/GLibWrapper.h> |
1119 | +#include <UnityCore/GLibSignal.h> |
1120 | #include <libbamf/libbamf.h> |
1121 | |
1122 | namespace unity |
1123 | @@ -54,6 +56,9 @@ |
1124 | PanelMenuView(int padding = 6); |
1125 | ~PanelMenuView(); |
1126 | |
1127 | + void SetMenuShowTimings(int fadein, int fadeout, int discovery, |
1128 | + int discovery_fadein, int discovery_fadeout); |
1129 | + |
1130 | void FullRedraw(); |
1131 | |
1132 | virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw); |
1133 | @@ -63,8 +68,11 @@ |
1134 | void SetMousePosition(int x, int y); |
1135 | |
1136 | void OnActiveChanged(PanelIndicatorEntryView* view, bool is_active); |
1137 | - void OnActiveWindowChanged(BamfView* old_view, BamfView* new_view); |
1138 | - void OnNameChanged(gchar* new_name, gchar* old_name); |
1139 | + void OnViewOpened(BamfMatcher* matcher, BamfView* view); |
1140 | + void OnViewClosed(BamfMatcher* matcher, BamfView* view); |
1141 | + void OnActiveWindowChanged(BamfMatcher* matcher, BamfView* old_view, BamfView* new_view); |
1142 | + void OnActiveAppChanged(BamfMatcher* matcher, BamfApplication* old_app, BamfApplication* new_app); |
1143 | + void OnNameChanged(BamfView* bamf_view, gchar* new_name, gchar* old_name); |
1144 | |
1145 | void OnSpreadInitiate(); |
1146 | void OnSpreadTerminate(); |
1147 | @@ -116,6 +124,8 @@ |
1148 | void UpdateShowNow(bool ignore); |
1149 | static gboolean UpdateActiveWindowPosition(PanelMenuView* self); |
1150 | static gboolean UpdateShowNowWithDelay(PanelMenuView* self); |
1151 | + static gboolean OnNewAppShow(PanelMenuView* self); |
1152 | + static gboolean OnNewAppHide(PanelMenuView* self); |
1153 | void DrawText(cairo_t *cr_real, |
1154 | int &x, int y, int width, int height, |
1155 | const char* font_desc, |
1156 | @@ -130,7 +140,7 @@ |
1157 | void OnFadeOutChanged(double); |
1158 | |
1159 | private: |
1160 | - BamfMatcher* _matcher; |
1161 | + glib::Object<BamfMatcher> _matcher; |
1162 | |
1163 | nux::TextureLayer* _title_layer; |
1164 | nux::HLayout* _menu_layout; |
1165 | @@ -142,34 +152,47 @@ |
1166 | bool _is_maximized; |
1167 | bool _is_own_window; |
1168 | PanelIndicatorEntryView* _last_active_view; |
1169 | + glib::Object<BamfApplication> _new_application; |
1170 | |
1171 | WindowButtons* _window_buttons; |
1172 | PanelTitlebarGrabArea* _panel_titlebar_grab_area; |
1173 | |
1174 | std::map<guint32, bool> _decor_map; |
1175 | std::set<guint32> _maximized_set; |
1176 | + std::list<BamfApplication*> _new_apps; |
1177 | + |
1178 | int _padding; |
1179 | - gpointer _name_changed_callback_instance; |
1180 | - gulong _name_changed_callback_id; |
1181 | - |
1182 | int _last_width; |
1183 | int _last_height; |
1184 | |
1185 | bool _places_showing; |
1186 | bool _show_now_activated; |
1187 | - |
1188 | bool _we_control_active; |
1189 | + bool _new_app_menu_shown; |
1190 | + |
1191 | int _monitor; |
1192 | guint32 _active_xid; |
1193 | guint32 _active_moved_id; |
1194 | guint32 _update_show_now_id; |
1195 | + guint32 _new_app_show_id; |
1196 | + guint32 _new_app_hide_id; |
1197 | nux::Geometry _monitor_geo; |
1198 | |
1199 | - gulong _activate_window_changed_id; |
1200 | + glib::Signal<void, BamfMatcher*, BamfView*> _view_opened_signal; |
1201 | + glib::Signal<void, BamfMatcher*, BamfView*> _view_closed_signal; |
1202 | + glib::Signal<void, BamfMatcher*, BamfView*, BamfView*> _active_win_changed_signal; |
1203 | + glib::Signal<void, BamfMatcher*, BamfApplication*, BamfApplication*> _active_app_changed_signal; |
1204 | + glib::Signal<void, BamfView*, gchar*, gchar*> _view_name_changed_signal; |
1205 | |
1206 | guint32 _place_shown_interest; |
1207 | guint32 _place_hidden_interest; |
1208 | |
1209 | + int _menus_fadein; |
1210 | + int _menus_fadeout; |
1211 | + int _menus_discovery; |
1212 | + int _menus_discovery_fadein; |
1213 | + int _menus_discovery_fadeout; |
1214 | + |
1215 | Animator* _fade_in_animator; |
1216 | Animator* _fade_out_animator; |
1217 | }; |
1218 | |
1219 | === modified file 'plugins/unityshell/src/PanelView.cpp' |
1220 | --- plugins/unityshell/src/PanelView.cpp 2011-12-14 16:18:41 +0000 |
1221 | +++ plugins/unityshell/src/PanelView.cpp 2011-12-14 17:24:33 +0000 |
1222 | @@ -621,6 +621,13 @@ |
1223 | } |
1224 | |
1225 | void |
1226 | +PanelView::SetMenuShowTimings(int fadein, int fadeout, int discovery, |
1227 | + int discovery_fadein, int discovery_fadeout) |
1228 | +{ |
1229 | + _menu_view->SetMenuShowTimings(fadein, fadeout, discovery, discovery_fadein, discovery_fadeout); |
1230 | +} |
1231 | + |
1232 | +void |
1233 | PanelView::SetOpacityMaximizedToggle(bool enabled) |
1234 | { |
1235 | if (_opacity_maximized_toggle != enabled) |
1236 | |
1237 | === modified file 'plugins/unityshell/src/PanelView.h' |
1238 | --- plugins/unityshell/src/PanelView.h 2011-12-14 16:18:41 +0000 |
1239 | +++ plugins/unityshell/src/PanelView.h 2011-12-14 17:24:33 +0000 |
1240 | @@ -71,6 +71,8 @@ |
1241 | |
1242 | void SetOpacity(float opacity); |
1243 | void SetOpacityMaximizedToggle(bool enabled); |
1244 | + void SetMenuShowTimings(int fadein, int fadeout, int discovery, |
1245 | + int discovery_fadein, int discovery_fadeout); |
1246 | |
1247 | void TrackMenuPointer(); |
1248 | |
1249 | |
1250 | === modified file 'plugins/unityshell/src/unityshell.cpp' |
1251 | --- plugins/unityshell/src/unityshell.cpp 2011-12-14 16:18:41 +0000 |
1252 | +++ plugins/unityshell/src/unityshell.cpp 2011-12-14 17:24:33 +0000 |
1253 | @@ -240,6 +240,11 @@ |
1254 | optionSetUrgentAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1255 | optionSetPanelOpacityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1256 | optionSetPanelOpacityMaximizedToggleNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1257 | + optionSetMenusFadeinNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1258 | + optionSetMenusFadeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1259 | + optionSetMenusDiscoveryDurationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1260 | + optionSetMenusDiscoveryFadeinNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1261 | + optionSetMenusDiscoveryFadeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1262 | optionSetLauncherOpacityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1263 | optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1264 | optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); |
1265 | @@ -2025,6 +2030,17 @@ |
1266 | case UnityshellOptions::PanelOpacityMaximizedToggle: |
1267 | panel_controller_->SetOpacityMaximizedToggle(optionGetPanelOpacityMaximizedToggle()); |
1268 | break; |
1269 | + case UnityshellOptions::MenusFadein: |
1270 | + case UnityshellOptions::MenusFadeout: |
1271 | + case UnityshellOptions::MenusDiscoveryFadein: |
1272 | + case UnityshellOptions::MenusDiscoveryFadeout: |
1273 | + case UnityshellOptions::MenusDiscoveryDuration: |
1274 | + panel_controller_->SetMenuShowTimings(optionGetMenusFadein(), |
1275 | + optionGetMenusFadeout(), |
1276 | + optionGetMenusDiscoveryDuration(), |
1277 | + optionGetMenusDiscoveryFadein(), |
1278 | + optionGetMenusDiscoveryFadeout()); |
1279 | + break; |
1280 | case UnityshellOptions::LauncherOpacity: |
1281 | launcher.SetBackgroundAlpha(optionGetLauncherOpacity()); |
1282 | break; |
1283 | @@ -2412,6 +2428,11 @@ |
1284 | /* Setup panel */ |
1285 | timer.Reset(); |
1286 | panel_controller_.reset(new panel::Controller()); |
1287 | + panel_controller_->SetMenuShowTimings(optionGetMenusFadein(), |
1288 | + optionGetMenusFadeout(), |
1289 | + optionGetMenusDiscoveryDuration(), |
1290 | + optionGetMenusDiscoveryFadein(), |
1291 | + optionGetMenusDiscoveryFadeout()); |
1292 | LOG_INFO(logger) << "initLauncher-Panel " << timer.ElapsedSeconds() << "s"; |
1293 | |
1294 | /* Setup Places */ |
1295 | |
1296 | === modified file 'plugins/unityshell/unityshell.xml.in' |
1297 | --- plugins/unityshell/unityshell.xml.in 2011-12-08 04:13:56 +0000 |
1298 | +++ plugins/unityshell/unityshell.xml.in 2011-12-14 17:24:33 +0000 |
1299 | @@ -342,12 +342,52 @@ |
1300 | </desc> |
1301 | </option> |
1302 | |
1303 | - <option name="show_desktop_icon" type="bool"> |
1304 | + <option name="show_desktop_icon" type="bool"> |
1305 | <_short>Show "Desktop Icon" in the launcher</_short> |
1306 | <_long>Enable/Disable "Show Dekstop icon" in the launcher.</_long> |
1307 | <default>false</default> |
1308 | </option> |
1309 | |
1310 | + <option name="menus_fadein" type="int"> |
1311 | + <_short>Menus Fade-in duration</_short> |
1312 | + <_long>Duration (in milliseconds) of the menus fade-in animation, used when the mouse goes over the top-panel.</_long> |
1313 | + <min>0</min> |
1314 | + <max>1000</max> |
1315 | + <default>100</default> |
1316 | + </option> |
1317 | + |
1318 | + <option name="menus_fadeout" type="int"> |
1319 | + <_short>Menus fade-out duration</_short> |
1320 | + <_long>Duration (in milliseconds) of the menus fade-out animation, used when the mouse goes over the top-panel.</_long> |
1321 | + <min>0</min> |
1322 | + <max>1000</max> |
1323 | + <default>120</default> |
1324 | + </option> |
1325 | + |
1326 | + <option name="menus_discovery_duration" type="int"> |
1327 | + <_short>Menus discovery duration</_short> |
1328 | + <_long>How many seconds the menus should be shown when a new application has been launched.</_long> |
1329 | + <min>0</min> |
1330 | + <max>10</max> |
1331 | + <default>2</default> |
1332 | + </option> |
1333 | + |
1334 | + <option name="menus_discovery_fadein" type="int"> |
1335 | + <_short>Menus discovery fade-in duration</_short> |
1336 | + <_long>Duration (in milliseconds) of the menus fade-in animation, used when the menus of a new launched application have been shown.</_long> |
1337 | + <min>0</min> |
1338 | + <max>1000</max> |
1339 | + <default>200</default> |
1340 | + </option> |
1341 | + |
1342 | + <option name="menus_discovery_fadeout" type="int"> |
1343 | + <_short>Menus discovery fade-out duration</_short> |
1344 | + <_long>Duration (in milliseconds) of the menus fade-out animation, used when the menus of a new launched application have been shown.</_long> |
1345 | + <min>0</min> |
1346 | + <max>1000</max> |
1347 | + <default>300</default> |
1348 | + </option> |
1349 | + |
1350 | </group> |
1351 | </options> |
1352 | </plugin> |
1353 | |
1354 | === modified file 'tests/CMakeLists.txt' |
1355 | --- tests/CMakeLists.txt 2011-12-14 16:18:41 +0000 |
1356 | +++ tests/CMakeLists.txt 2011-12-14 17:24:33 +0000 |
1357 | @@ -99,6 +99,7 @@ |
1358 | |
1359 | # The actual test executable (xless) - do not put anything that requires X in here |
1360 | add_executable(test-gtest-xless |
1361 | + test_animator.cpp |
1362 | test_glib_signals.cpp |
1363 | test_glib_signals_utils.cpp |
1364 | test_glib_signals_utils.h |
1365 | @@ -107,6 +108,8 @@ |
1366 | test_introspection.cpp |
1367 | test_main_xless.cpp |
1368 | ${UNITY_SRC}/AbstractLauncherIcon.h |
1369 | + ${UNITY_SRC}/Animator.cpp |
1370 | + ${UNITY_SRC}/Animator.h |
1371 | ${UNITY_SRC}/DebugDBusInterface.h |
1372 | ${UNITY_SRC}/DebugDBusInterface.cpp |
1373 | ${UNITY_SRC}/XPathQueryPart.h |
1374 | |
1375 | === added file 'tests/test_animator.cpp' |
1376 | --- tests/test_animator.cpp 1970-01-01 00:00:00 +0000 |
1377 | +++ tests/test_animator.cpp 2011-12-14 17:24:33 +0000 |
1378 | @@ -0,0 +1,295 @@ |
1379 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1380 | +/* |
1381 | + * Copyright (C) 2011 Canonical Ltd |
1382 | + * |
1383 | + * This program is free software: you can redistribute it and/or modify |
1384 | + * it under the terms of the GNU General Public License version 3 as |
1385 | + * published by the Free Software Foundation. |
1386 | + * |
1387 | + * This program is distributed in the hope that it will be useful, |
1388 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1389 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1390 | + * GNU General Public License for more details. |
1391 | + * |
1392 | + * You should have received a copy of the GNU General Public License |
1393 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1394 | + * |
1395 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
1396 | + */ |
1397 | + |
1398 | +#include <gtest/gtest.h> |
1399 | + |
1400 | +#include "Animator.h" |
1401 | +#include "test_utils.h" |
1402 | + |
1403 | +using namespace std; |
1404 | +using namespace unity; |
1405 | + |
1406 | +namespace |
1407 | +{ |
1408 | + |
1409 | +class TestAnimator : public ::testing::Test |
1410 | +{ |
1411 | +public: |
1412 | + TestAnimator() : |
1413 | + test_animator_(100), |
1414 | + n_steps_(0), |
1415 | + current_progress_(0.0f), |
1416 | + got_update_(false), |
1417 | + half_reached_(false), |
1418 | + started_(false), |
1419 | + stopped_(false), |
1420 | + ended_(false) |
1421 | + { |
1422 | + test_animator_.animation_started.connect([&started_]() { |
1423 | + started_ = true; |
1424 | + }); |
1425 | + |
1426 | + test_animator_.animation_ended.connect([&ended_]() { |
1427 | + ended_ = true; |
1428 | + }); |
1429 | + |
1430 | + test_animator_.animation_stopped.connect([&stopped_](double progress) { |
1431 | + stopped_ = true; |
1432 | + }); |
1433 | + |
1434 | + test_animator_.animation_updated.connect([&](double progress) { |
1435 | + n_steps_++; |
1436 | + current_progress_ = progress; |
1437 | + got_update_ = true; |
1438 | + |
1439 | + if (progress >= 0.5f) |
1440 | + half_reached_ = true; |
1441 | + }); |
1442 | + } |
1443 | + |
1444 | +protected: |
1445 | + void ResetValues() |
1446 | + { |
1447 | + n_steps_ = 0; |
1448 | + current_progress_ = 0.0f; |
1449 | + started_ = false; |
1450 | + stopped_ = false; |
1451 | + ended_ = false; |
1452 | + got_update_ = false; |
1453 | + half_reached_ = false; |
1454 | + } |
1455 | + |
1456 | + Animator test_animator_; |
1457 | + unsigned int n_steps_; |
1458 | + double current_progress_; |
1459 | + bool got_update_; |
1460 | + bool half_reached_; |
1461 | + bool started_; |
1462 | + bool stopped_; |
1463 | + bool ended_; |
1464 | +}; |
1465 | + |
1466 | +TEST_F(TestAnimator, ConstructDestroy) |
1467 | +{ |
1468 | + bool stopped = false; |
1469 | + double progress = 0.0f; |
1470 | + |
1471 | + { |
1472 | + Animator tmp_animator(200, 25); |
1473 | + |
1474 | + EXPECT_EQ(tmp_animator.GetDuration(), 200); |
1475 | + EXPECT_EQ(tmp_animator.GetRate(), 25); |
1476 | + |
1477 | + bool got_update = false; |
1478 | + tmp_animator.animation_updated.connect([&progress, &got_update](double p) { |
1479 | + progress = p; |
1480 | + got_update = true; |
1481 | + }); |
1482 | + |
1483 | + tmp_animator.animation_stopped.connect([&stopped](double p) { |
1484 | + stopped = true; |
1485 | + }); |
1486 | + |
1487 | + tmp_animator.Start(); |
1488 | + |
1489 | + Utils::WaitUntil(got_update); |
1490 | + |
1491 | + EXPECT_EQ(tmp_animator.IsRunning(), true); |
1492 | + EXPECT_GT(progress, 0.0f); |
1493 | + EXPECT_EQ(stopped, false); |
1494 | + } |
1495 | + |
1496 | + EXPECT_EQ(stopped, true); |
1497 | +} |
1498 | + |
1499 | +TEST_F(TestAnimator, SetGetValues) |
1500 | +{ |
1501 | + test_animator_.SetRate(30); |
1502 | + EXPECT_EQ(test_animator_.GetRate(), 30); |
1503 | + |
1504 | + test_animator_.SetDuration(100); |
1505 | + EXPECT_EQ(test_animator_.GetDuration(), 100); |
1506 | + |
1507 | + EXPECT_EQ(test_animator_.GetProgress(), 0.0f); |
1508 | + EXPECT_EQ(test_animator_.IsRunning(), false); |
1509 | +} |
1510 | + |
1511 | +TEST_F(TestAnimator, SimulateStep) |
1512 | +{ |
1513 | + test_animator_.DoStep(); |
1514 | + EXPECT_EQ(test_animator_.IsRunning(), false); |
1515 | + EXPECT_EQ(n_steps_, 1); |
1516 | + EXPECT_GT(test_animator_.GetProgress(), 0.0f); |
1517 | + ResetValues(); |
1518 | +} |
1519 | + |
1520 | +TEST_F(TestAnimator, SimulateAnimation) |
1521 | +{ |
1522 | + test_animator_.SetRate(20); |
1523 | + test_animator_.SetDuration(200); |
1524 | + long long start_time = g_get_monotonic_time() / 1000; |
1525 | + test_animator_.Start(); |
1526 | + |
1527 | + EXPECT_EQ(started_, true); |
1528 | + EXPECT_EQ(test_animator_.IsRunning(), true); |
1529 | + |
1530 | + Utils::WaitUntil(got_update_); |
1531 | + EXPECT_GT(test_animator_.GetProgress(), 0.0f); |
1532 | + EXPECT_EQ(test_animator_.GetProgress(), current_progress_); |
1533 | + EXPECT_EQ(n_steps_, 1); |
1534 | + |
1535 | + Utils::WaitUntil(ended_); |
1536 | + EXPECT_EQ(stopped_, false); |
1537 | + EXPECT_EQ(ended_, true); |
1538 | + |
1539 | + unsigned int expected_steps = (test_animator_.GetDuration() / 1000.0f) * test_animator_.GetRate(); |
1540 | + EXPECT_EQ(n_steps_, ceil(expected_steps)); |
1541 | + |
1542 | + long long actual_time = g_get_monotonic_time() / 1000; |
1543 | + long long expected_end = start_time+test_animator_.GetDuration(); |
1544 | + EXPECT_GE(actual_time, expected_end); |
1545 | + EXPECT_LE(actual_time-expected_end, test_animator_.GetRate()*2); |
1546 | + |
1547 | + ResetValues(); |
1548 | +} |
1549 | + |
1550 | +TEST_F(TestAnimator, SimulateStoppedAnimation) |
1551 | +{ |
1552 | + test_animator_.SetRate(30); |
1553 | + test_animator_.SetDuration(100); |
1554 | + test_animator_.Start(); |
1555 | + EXPECT_EQ(started_, true); |
1556 | + EXPECT_EQ(test_animator_.IsRunning(), true); |
1557 | + |
1558 | + Utils::WaitUntil(half_reached_); |
1559 | + EXPECT_GT(test_animator_.GetProgress(), 0.5f); |
1560 | + EXPECT_EQ(test_animator_.GetProgress(), current_progress_); |
1561 | + EXPECT_EQ(test_animator_.IsRunning(), true); |
1562 | + |
1563 | + test_animator_.Stop(); |
1564 | + EXPECT_EQ(test_animator_.IsRunning(), false); |
1565 | + EXPECT_LT(test_animator_.GetProgress(), 1.0f); |
1566 | + EXPECT_EQ(stopped_, true); |
1567 | + EXPECT_EQ(ended_, true); |
1568 | + |
1569 | + ResetValues(); |
1570 | +} |
1571 | + |
1572 | +TEST_F(TestAnimator, SimulateStoppedAndContinueAnimation) |
1573 | +{ |
1574 | + test_animator_.SetRate(30); |
1575 | + test_animator_.SetDuration(100); |
1576 | + test_animator_.Start(); |
1577 | + EXPECT_EQ(started_, true); |
1578 | + EXPECT_EQ(test_animator_.IsRunning(), true); |
1579 | + |
1580 | + Utils::WaitUntil(half_reached_); |
1581 | + test_animator_.Stop(); |
1582 | + |
1583 | + EXPECT_LT(test_animator_.GetProgress(), 1.0f); |
1584 | + EXPECT_EQ(stopped_, true); |
1585 | + EXPECT_EQ(ended_, true); |
1586 | + stopped_ = false; |
1587 | + ended_ = false; |
1588 | + |
1589 | + long long start_time = g_get_monotonic_time() / 1000; |
1590 | + long long expected_end = start_time + (test_animator_.GetDuration() / current_progress_); |
1591 | + test_animator_.Start(test_animator_.GetProgress()); |
1592 | + Utils::WaitUntil(ended_); |
1593 | + EXPECT_EQ(stopped_, false); |
1594 | + EXPECT_EQ(ended_, true); |
1595 | + |
1596 | + long long actual_time = g_get_monotonic_time() / 1000; |
1597 | + EXPECT_LT(expected_end-actual_time, test_animator_.GetDuration()); |
1598 | + |
1599 | + ResetValues(); |
1600 | +} |
1601 | + |
1602 | +TEST_F(TestAnimator, SimulateOneTimeDurationStart) |
1603 | +{ |
1604 | + unsigned int default_duration = 100; |
1605 | + |
1606 | + test_animator_.SetRate(30); |
1607 | + test_animator_.SetDuration(default_duration); |
1608 | + |
1609 | + unsigned int one_time_duration = 75; |
1610 | + test_animator_.Start(one_time_duration); |
1611 | + EXPECT_EQ(started_, true); |
1612 | + EXPECT_EQ(test_animator_.IsRunning(), true); |
1613 | + |
1614 | + Utils::WaitUntil(half_reached_); |
1615 | + EXPECT_LT(test_animator_.GetProgress(), 1.0f); |
1616 | + EXPECT_EQ(test_animator_.GetDuration(), one_time_duration); |
1617 | + EXPECT_EQ(ended_, false); |
1618 | + |
1619 | + Utils::WaitUntil(ended_); |
1620 | + EXPECT_EQ(stopped_, false); |
1621 | + EXPECT_EQ(ended_, true); |
1622 | + |
1623 | + EXPECT_EQ(test_animator_.GetDuration(), default_duration); |
1624 | + |
1625 | + ResetValues(); |
1626 | +} |
1627 | + |
1628 | +TEST_F(TestAnimator, SimulateOneTimeDurationStartStop) |
1629 | +{ |
1630 | + unsigned int default_duration = 100; |
1631 | + |
1632 | + test_animator_.SetRate(30); |
1633 | + test_animator_.SetDuration(default_duration); |
1634 | + |
1635 | + unsigned int one_time_duration = 75; |
1636 | + test_animator_.Start(one_time_duration); |
1637 | + EXPECT_EQ(started_, true); |
1638 | + EXPECT_EQ(test_animator_.IsRunning(), true); |
1639 | + |
1640 | + Utils::WaitUntil(half_reached_); |
1641 | + EXPECT_EQ(test_animator_.GetDuration(), one_time_duration); |
1642 | + EXPECT_EQ(ended_, false); |
1643 | + |
1644 | + test_animator_.Stop(); |
1645 | + EXPECT_EQ(stopped_, true); |
1646 | + EXPECT_EQ(ended_, true); |
1647 | + EXPECT_EQ(test_animator_.GetDuration(), default_duration); |
1648 | + |
1649 | + ResetValues(); |
1650 | +} |
1651 | + |
1652 | +TEST_F(TestAnimator, SimulateZeroDuration) |
1653 | +{ |
1654 | + test_animator_.SetRate(30); |
1655 | + test_animator_.SetDuration(0); |
1656 | + |
1657 | + EXPECT_EQ(started_, false); |
1658 | + EXPECT_EQ(ended_, false); |
1659 | + EXPECT_EQ(test_animator_.IsRunning(), false); |
1660 | + |
1661 | + long long start_time = g_get_monotonic_time() / 1000; |
1662 | + test_animator_.Start(); |
1663 | + EXPECT_EQ(started_, true); |
1664 | + |
1665 | + Utils::WaitUntil(ended_); |
1666 | + EXPECT_EQ(ended_, true); |
1667 | + |
1668 | + long long end_time = g_get_monotonic_time() / 1000; |
1669 | + EXPECT_LT(end_time - start_time, test_animator_.GetRate()*2); |
1670 | +} |
1671 | + |
1672 | + |
1673 | +} // Namespace |
1674 | |
1675 | === modified file 'tests/test_lens.cpp' |
1676 | --- tests/test_lens.cpp 2011-10-12 12:02:17 +0000 |
1677 | +++ tests/test_lens.cpp 2011-12-14 17:24:33 +0000 |
1678 | @@ -48,36 +48,11 @@ |
1679 | { |
1680 | n_filters_++; |
1681 | } |
1682 | - |
1683 | - static gboolean TimeoutCallback(gpointer data) |
1684 | - { |
1685 | - *(bool*)data = true; |
1686 | - return FALSE; |
1687 | - }; |
1688 | - |
1689 | - guint32 ScheduleTimeout(bool* timeout_reached) |
1690 | - { |
1691 | - return g_timeout_add_seconds(10, TimeoutCallback, timeout_reached); |
1692 | - } |
1693 | - |
1694 | - void WaitUntil(bool& success) |
1695 | - { |
1696 | - bool timeout_reached = false; |
1697 | - guint32 timeout_id = ScheduleTimeout(&timeout_reached); |
1698 | - |
1699 | - while (!success && !timeout_reached) |
1700 | - g_main_context_iteration(g_main_context_get_thread_default(), TRUE); |
1701 | - |
1702 | - if (success) |
1703 | - g_source_remove(timeout_id); |
1704 | - |
1705 | - EXPECT_TRUE(success); |
1706 | - } |
1707 | |
1708 | void WaitForConnected() |
1709 | { |
1710 | bool timeout_reached = false; |
1711 | - guint32 timeout_id = ScheduleTimeout(&timeout_reached); |
1712 | + guint32 timeout_id = Utils::ScheduleTimeout(&timeout_reached); |
1713 | |
1714 | while (!lens_->connected && !timeout_reached) |
1715 | { |
1716 | @@ -93,7 +68,7 @@ |
1717 | void WaitForModel(Model<Adaptor>* model, unsigned int n_rows) |
1718 | { |
1719 | bool timeout_reached = false; |
1720 | - guint32 timeout_id = ScheduleTimeout(&timeout_reached); |
1721 | + guint32 timeout_id = Utils::ScheduleTimeout(&timeout_reached); |
1722 | |
1723 | while (model->count != n_rows && !timeout_reached) |
1724 | { |
1725 | @@ -229,7 +204,7 @@ |
1726 | lens_->activated.connect(sigc::slot<void, std::string const&, HandledType,Lens::Hints const&>(activated_cb)); |
1727 | |
1728 | lens_->Activate(uri); |
1729 | - WaitUntil(activated); |
1730 | + Utils::WaitUntil(activated); |
1731 | } |
1732 | |
1733 | TEST_F(TestLens, TestPreview) |
1734 | @@ -262,7 +237,7 @@ |
1735 | lens_->preview_ready.connect(sigc::slot<void, std::string const&, Preview::Ptr>(preview_cb)); |
1736 | |
1737 | lens_->Preview(uri); |
1738 | - WaitUntil(previewed); |
1739 | + Utils::WaitUntil(previewed); |
1740 | } |
1741 | |
1742 | TEST_F(TestLens, TestFilterSync) |
1743 | |
1744 | === modified file 'tests/test_utils.h' |
1745 | --- tests/test_utils.h 2011-07-25 10:54:25 +0000 |
1746 | +++ tests/test_utils.h 2011-12-14 17:24:33 +0000 |
1747 | @@ -31,6 +31,32 @@ |
1748 | if (model.count == n_rows) |
1749 | g_source_remove(timeout_id); |
1750 | } |
1751 | + |
1752 | + static void WaitUntil(bool& success, unsigned int max_wait = 10) |
1753 | + { |
1754 | + bool timeout_reached = false; |
1755 | + guint32 timeout_id = ScheduleTimeout(&timeout_reached, max_wait); |
1756 | + |
1757 | + while (!success && !timeout_reached) |
1758 | + g_main_context_iteration(g_main_context_get_thread_default(), TRUE); |
1759 | + |
1760 | + if (success) |
1761 | + g_source_remove(timeout_id); |
1762 | + |
1763 | + EXPECT_TRUE(success); |
1764 | + } |
1765 | + |
1766 | + static guint32 ScheduleTimeout(bool* timeout_reached, unsigned int timeout_duration = 10) |
1767 | + { |
1768 | + return g_timeout_add_seconds(timeout_duration, TimeoutCallback, timeout_reached); |
1769 | + } |
1770 | + |
1771 | +private: |
1772 | + static gboolean TimeoutCallback(gpointer data) |
1773 | + { |
1774 | + *(bool*)data = true; |
1775 | + return FALSE; |
1776 | + }; |
1777 | }; |
1778 | |
1779 | } |
If you have rights to merge lp:~3v1n0/bamf/always-notify-view yourself I think you can go ahead as that module is not being handled by unity-merger afaik, If you don't have the rights I think we need to make sure you have :-)