Merge lp:~canonical-dx-team/unity/unity.startup-notification into lp:unity

Proposed by Jason Smith
Status: Merged
Merged at revision: 623
Proposed branch: lp:~canonical-dx-team/unity/unity.startup-notification
Merge into: lp:unity
Diff against target: 1099 lines (+384/-288)
11 files modified
CMakeLists.txt (+1/-1)
src/BamfLauncherIcon.cpp (+43/-8)
src/BamfLauncherIcon.h (+2/-0)
src/Launcher.cpp (+89/-92)
src/Launcher.h (+4/-1)
src/LauncherController.cpp (+2/-2)
src/LauncherIcon.cpp (+84/-151)
src/LauncherIcon.h (+33/-33)
src/StartupNotifyService.cpp (+70/-0)
src/StartupNotifyService.h (+53/-0)
src/unity.cpp (+3/-0)
To merge this branch: bzr merge lp:~canonical-dx-team/unity/unity.startup-notification
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Needs Fixing
Review via email: mp+41671@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Neil J. Patel (njpatel) wrote :

Looks good, some notes + questions:

- You need to add a dep for libstartup-notification-1.0 to CMakeLists.txt::UNITY_PLUGIN_DEPS

- The quirks, they seem to be all booleans, should they just be bit flags? I'm not sure how it'll impact API, though...

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2010-11-18 16:25:14 +0000
3+++ CMakeLists.txt 2010-11-24 15:28:12 +0000
4@@ -74,7 +74,7 @@
5 #
6 # src (Compiz Plugin)
7 #
8-set (UNITY_PLUGIN_DEPS "nux-0.9;libbamf;dbus-glib-1;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib;x11")
9+set (UNITY_PLUGIN_DEPS "nux-0.9;libbamf;dbus-glib-1;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib;x11;libstartup-notification-1.0")
10
11 find_package (Compiz REQUIRED)
12 include (CompizPlugin)
13
14=== modified file 'src/BamfLauncherIcon.cpp'
15--- src/BamfLauncherIcon.cpp 2010-11-18 14:00:53 +0000
16+++ src/BamfLauncherIcon.cpp 2010-11-24 15:28:12 +0000
17@@ -25,6 +25,9 @@
18
19 #include <gio/gdesktopappinfo.h>
20
21+#include <core/core.h>
22+#include <core/atoms.h>
23+
24 BamfLauncherIcon::BamfLauncherIcon (Launcher* IconManager, BamfApplication *app, CompScreen *screen, NUX_FILE_LINE_DECL)
25 : SimpleLauncherIcon(IconManager)
26 {
27@@ -37,12 +40,12 @@
28 SetIconType (LAUNCHER_ICON_TYPE_APPLICATION);
29
30 if (bamf_view_is_sticky (BAMF_VIEW (m_App)))
31- SetVisible (true);
32+ SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, true);
33 else
34- SetVisible (bamf_view_user_visible (BAMF_VIEW (m_App)));
35+ SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, bamf_view_user_visible (BAMF_VIEW (m_App)));
36
37- SetActive (bamf_view_is_active (BAMF_VIEW (m_App)));
38- SetRunning (bamf_view_is_running (BAMF_VIEW (m_App)));
39+ SetQuirk (LAUNCHER_ICON_QUIRK_ACTIVE, bamf_view_is_active (BAMF_VIEW (m_App)));
40+ SetQuirk (LAUNCHER_ICON_QUIRK_RUNNING, bamf_view_is_running (BAMF_VIEW (m_App)));
41
42 g_free (icon_name);
43
44@@ -84,6 +87,9 @@
45 appInfo = g_desktop_app_info_new_from_filename (bamf_application_get_desktop_file (BAMF_APPLICATION (m_App)));
46 g_app_info_launch (G_APP_INFO (appInfo), NULL, NULL, NULL);
47 g_object_unref (appInfo);
48+
49+ UpdateQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
50+
51 return;
52 }
53
54@@ -143,14 +149,14 @@
55 BamfLauncherIcon *self = (BamfLauncherIcon *) data;
56
57 if (!bamf_view_is_sticky (BAMF_VIEW (self->m_App)))
58- self->SetVisible (visible);
59+ self->SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, visible);
60 }
61
62 void
63 BamfLauncherIcon::OnRunningChanged (BamfView *view, gboolean running, gpointer data)
64 {
65 BamfLauncherIcon *self = (BamfLauncherIcon *) data;
66- self->SetRunning (running);
67+ self->SetQuirk (LAUNCHER_ICON_QUIRK_RUNNING, running);
68
69 if (running)
70 self->EnsureWindowState ();
71@@ -160,14 +166,14 @@
72 BamfLauncherIcon::OnActiveChanged (BamfView *view, gboolean active, gpointer data)
73 {
74 BamfLauncherIcon *self = (BamfLauncherIcon *) data;
75- self->SetActive (active);
76+ self->SetQuirk (LAUNCHER_ICON_QUIRK_ACTIVE, active);
77 }
78
79 void
80 BamfLauncherIcon::OnUrgentChanged (BamfView *view, gboolean urgent, gpointer data)
81 {
82 BamfLauncherIcon *self = (BamfLauncherIcon *) data;
83- self->SetUrgent (urgent);
84+ self->SetQuirk (LAUNCHER_ICON_QUIRK_URGENT, urgent);
85 }
86
87 void
88@@ -220,3 +226,32 @@
89
90 return result;
91 }
92+
93+void
94+BamfLauncherIcon::OnCenterStabilized (nux::Point3 center)
95+{
96+ GList *children, *l;
97+ BamfView *view;
98+ long data[4];
99+
100+ data[0] = center.x - 24;
101+ data[1] = center.y - 24;
102+ data[2] = 48;
103+ data[3] = 48;
104+
105+ children = bamf_view_get_children (BAMF_VIEW (m_App));
106+
107+ for (l = children; l; l = l->next)
108+ {
109+ view = (BamfView *) l->data;
110+
111+ if (BAMF_IS_WINDOW (view))
112+ {
113+ guint32 xid = bamf_window_get_xid (BAMF_WINDOW (view));
114+
115+ XChangeProperty (m_Screen->dpy (), xid, Atoms::wmIconGeometry,
116+ XA_CARDINAL, 32, PropModeReplace,
117+ (unsigned char *) data, 4);
118+ }
119+ }
120+}
121
122=== modified file 'src/BamfLauncherIcon.h'
123--- src/BamfLauncherIcon.h 2010-11-10 18:56:19 +0000
124+++ src/BamfLauncherIcon.h 2010-11-24 15:28:12 +0000
125@@ -42,6 +42,8 @@
126 protected:
127 void OnMouseClick (int button);
128 std::list<DbusmenuClient *> GetMenus ();
129+
130+ void OnCenterStabilized (nux::Point3 center);
131
132 private:
133 BamfApplication *m_App;
134
135=== modified file 'src/Launcher.cpp'
136--- src/Launcher.cpp 2010-11-23 02:58:23 +0000
137+++ src/Launcher.cpp 2010-11-24 15:28:12 +0000
138@@ -42,6 +42,10 @@
139 #define ANIM_DURATION_LONG 350
140
141 #define URGENT_BLINKS 3
142+
143+#define MAX_STARTING_BLINKS 5
144+#define STARTING_BLINK_LAMBDA 3
145+
146 #define BACKLIGHT_STRENGTH 0.9f
147
148 int
149@@ -325,37 +329,28 @@
150
151 bool Launcher::IconNeedsAnimation (LauncherIcon *icon, struct timespec current)
152 {
153- struct timespec enter_time = icon->ShowTime ();
154- if (TimeDelta (&current, &enter_time) < ANIM_DURATION_SHORT)
155- return true;
156-
157- struct timespec hide_time = icon->HideTime ();
158- if (TimeDelta (&current, &hide_time) < ANIM_DURATION_SHORT)
159- return true;
160-
161- struct timespec running_time = icon->RunningTime ();
162+ struct timespec visible_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
163+ if (TimeDelta (&current, &visible_time) < ANIM_DURATION_SHORT)
164+ return true;
165+
166+ struct timespec running_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_RUNNING);
167 if (TimeDelta (&current, &running_time) < ANIM_DURATION_SHORT)
168 return true;
169
170- if (icon->Urgent ())
171+ struct timespec starting_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
172+ if (TimeDelta (&current, &starting_time) < (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2))
173+ return true;
174+
175+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
176 {
177- struct timespec urgent_time = icon->UrgentTime ();
178+ struct timespec urgent_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_URGENT);
179 if (TimeDelta (&current, &urgent_time) < (ANIM_DURATION_LONG * URGENT_BLINKS * 2))
180 return true;
181 }
182
183- if (icon->Presented ())
184- {
185- struct timespec present_time = icon->PresentTime ();
186- if (TimeDelta (&current, &present_time) < ANIM_DURATION)
187- return true;
188- }
189- else
190- {
191- struct timespec unpresent_time = icon->UnpresentTime ();
192- if (TimeDelta (&current, &unpresent_time) < ANIM_DURATION)
193- return true;
194- }
195+ struct timespec present_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PRESENTED);
196+ if (TimeDelta (&current, &present_time) < ANIM_DURATION)
197+ return true;
198
199 return false;
200 }
201@@ -423,15 +418,15 @@
202
203 float IconVisibleProgress (LauncherIcon *icon, struct timespec current)
204 {
205- if (icon->Visible ())
206+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
207 {
208- struct timespec icon_visible_time = icon->ShowTime ();
209+ struct timespec icon_visible_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
210 int enter_ms = TimeDelta (&current, &icon_visible_time);
211 return CLAMP ((float) enter_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
212 }
213 else
214 {
215- struct timespec icon_hide_time = icon->HideTime ();
216+ struct timespec icon_hide_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_VISIBLE);
217 int hide_ms = TimeDelta (&current, &icon_hide_time);
218 return 1.0f - CLAMP ((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
219 }
220@@ -465,20 +460,72 @@
221
222 float Launcher::IconPresentProgress (LauncherIcon *icon, struct timespec current)
223 {
224- if (icon->Presented ())
225+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
226 {
227- struct timespec icon_present_time = icon->PresentTime ();
228+ struct timespec icon_present_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PRESENTED);
229 int ms = TimeDelta (&current, &icon_present_time);
230 return CLAMP ((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
231 }
232 else
233 {
234- struct timespec icon_unpresent_time = icon->UnpresentTime ();
235+ struct timespec icon_unpresent_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_PRESENTED);
236 int ms = TimeDelta (&current, &icon_unpresent_time);
237 return 1.0f - CLAMP ((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
238 }
239 }
240
241+float Launcher::IconUrgentPulseValue (LauncherIcon *icon, struct timespec current)
242+{
243+ if (!icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
244+ return 1.0f; // we are full on in a normal condition
245+
246+ struct timespec urgent_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_URGENT);
247+ int urgent_ms = TimeDelta (&current, &urgent_time);
248+ double urgent_progress = (double) CLAMP ((float) urgent_ms / (float) (ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f);
249+
250+ return 0.5f + (float) (std::cos (M_PI * (float) (URGENT_BLINKS * 2) * urgent_progress)) * 0.5f;
251+}
252+
253+float Launcher::IconStartingPulseValue (LauncherIcon *icon, struct timespec current)
254+{
255+ struct timespec starting_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
256+ int starting_ms = TimeDelta (&current, &starting_time);
257+ double starting_progress = (double) CLAMP ((float) starting_ms / (float) (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), 0.0f, 1.0f);
258+
259+ return 1.0f - (0.5f + (float) (std::cos (M_PI * (float) (MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f);
260+}
261+
262+float Launcher::IconBackgroundIntensity (LauncherIcon *icon, struct timespec current)
263+{
264+ float result = 0.0f;
265+ struct timespec running_time = icon->GetQuirkTime (LAUNCHER_ICON_QUIRK_RUNNING);
266+ int running_ms = TimeDelta (&current, &running_time);
267+ float running_progress = CLAMP ((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
268+
269+ // After we finish a fade in from running, we can reset the quirk
270+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING) && running_progress == 1.0f)
271+ icon->ResetQuirkTime (LAUNCHER_ICON_QUIRK_STARTING);
272+
273+ result = IconStartingPulseValue (icon, current) * BACKLIGHT_STRENGTH;
274+
275+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
276+ {
277+ // running progress fades in whatever the pulsing did not fill in already
278+ result += running_progress * (BACKLIGHT_STRENGTH - result);
279+
280+ // urgent serves to bring the total down only
281+ if (icon->GetQuirk (LAUNCHER_ICON_QUIRK_URGENT))
282+ result *= 0.2f + 0.8f * IconUrgentPulseValue (icon, current);
283+ }
284+ else
285+ {
286+ // modestly evil
287+ result += BACKLIGHT_STRENGTH - running_progress * BACKLIGHT_STRENGTH;
288+ }
289+
290+ return result;
291+}
292+
293 void Launcher::RenderArgs (std::list<Launcher::RenderArg> &launcher_args,
294 std::list<Launcher::RenderArg> &shelf_args,
295 nux::Geometry &box_geo, nux::Geometry &shelf_geo)
296@@ -489,6 +536,7 @@
297 float hover_progress = GetHoverProgress ();
298 float folded_z_distance = _folded_z_distance * (1.0f - hover_progress);
299 float animation_neg_rads = _neg_folded_angle * (1.0f - hover_progress);
300+ int vertical_offset = _parent->GetGeometry ().y;
301 struct timespec current;
302 clock_gettime (CLOCK_MONOTONIC, &current);
303
304@@ -599,41 +647,17 @@
305 arg.alpha = 1.0f;
306 arg.glow_intensity = 0.0f;
307 arg.running_arrow = false;
308- arg.active_arrow = icon->Active ();
309+ arg.active_arrow = icon->GetQuirk (LAUNCHER_ICON_QUIRK_ACTIVE);
310 arg.folding_rads = 0.0f;
311 arg.skip = false;
312
313 arg.window_indicators = MIN (4, icon->RelatedWindows ());
314
315 // we dont need to show strays
316- if (arg.window_indicators == 1 || !icon->Running ())
317- arg.window_indicators = 0;
318+ if (arg.window_indicators == 1 || !icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
319+ arg.window_indicators = 0;
320
321- // animate this shit
322- struct timespec running_time = icon->RunningTime ();
323- int running_ms = TimeDelta (&current, &running_time);
324- float running_progress = CLAMP ((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
325-
326- if (icon->Running ())
327- {
328- arg.backlight_intensity = running_progress * BACKLIGHT_STRENGTH;
329-
330- if (icon->Urgent ())
331- {
332- struct timespec urgent_time = icon->UrgentTime ();
333- int urgent_ms = TimeDelta (&current, &urgent_time);
334- double urgent_progress = (double) CLAMP ((float) urgent_ms / (float) (ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f);
335-
336- arg.backlight_intensity *= 0.2f + 0.8f * (0.5f + (float) (std::cos (M_PI * (float) (URGENT_BLINKS * 2) * urgent_progress)) * 0.5f);
337- }
338- }
339- else
340- {
341- if (running_ms > ANIM_DURATION_SHORT)
342- arg.backlight_intensity = 0.0f;
343- else
344- arg.backlight_intensity = BACKLIGHT_STRENGTH - running_progress * BACKLIGHT_STRENGTH;
345- }
346+ arg.backlight_intensity = IconBackgroundIntensity (icon, current);
347
348 // reset z
349 center.z = 0;
350@@ -665,7 +689,7 @@
351
352 center.y += half_size * size_modifier; // move to center
353 arg.center = nux::Point3 (center); // copy center
354- icon->SetCenter (arg.center);
355+ icon->SetCenter (nux::Point3 (center.x, center.y + vertical_offset, center.z));
356 center.y += half_size * size_modifier; // move to end
357
358 float spacing_overlap = CLAMP ((float) (center.y + (_space_between_icons * size_modifier) - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
359@@ -687,41 +711,17 @@
360 arg.alpha = 1.0f;
361 arg.glow_intensity = 0.0f;
362 arg.running_arrow = false;
363- arg.active_arrow = icon->Active ();
364+ arg.active_arrow = icon->GetQuirk (LAUNCHER_ICON_QUIRK_ACTIVE);
365 arg.folding_rads = 0.0f;
366 arg.skip = false;
367
368 arg.window_indicators = MIN (4, icon->RelatedWindows ());
369
370 // we dont need to show strays
371- if (arg.window_indicators == 1 || !icon->Running ())
372+ if (arg.window_indicators == 1 || !icon->GetQuirk (LAUNCHER_ICON_QUIRK_RUNNING))
373 arg.window_indicators = 0;
374
375- // animate this shit
376- struct timespec running_time = icon->RunningTime ();
377- int running_ms = TimeDelta (&current, &running_time);
378- float running_progress = CLAMP ((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f);
379-
380- if (icon->Running ())
381- {
382- arg.backlight_intensity = running_progress * BACKLIGHT_STRENGTH;
383-
384- if (icon->Urgent ())
385- {
386- struct timespec urgent_time = icon->UrgentTime ();
387- int urgent_ms = TimeDelta (&current, &urgent_time);
388- double urgent_progress = (double) CLAMP ((float) urgent_ms / (float) (ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f);
389-
390- arg.backlight_intensity *= 0.2f + 0.8f * (0.5f + (float) (std::cos (M_PI * (float) (URGENT_BLINKS * 2) * urgent_progress)) * 0.5f);
391- }
392- }
393- else
394- {
395- if (running_ms > ANIM_DURATION_SHORT)
396- arg.backlight_intensity = 0.0f;
397- else
398- arg.backlight_intensity = BACKLIGHT_STRENGTH - running_progress * BACKLIGHT_STRENGTH;
399- }
400+ arg.backlight_intensity = IconBackgroundIntensity (icon, current);
401
402 // reset z
403 center.z = 0;
404@@ -743,7 +743,7 @@
405
406 center.y += half_size * size_modifier; // move to center
407 arg.center = nux::Point3 (center); // copy center
408- icon->SetCenter (arg.center);
409+ icon->SetCenter (nux::Point3 (center.x, center.y + vertical_offset, center.z));
410 center.y += half_size * size_modifier; // move to end
411 center.y += _space_between_icons * size_modifier;
412
413@@ -1270,9 +1270,6 @@
414 gPainter.Paint2DQuadColor (GfxContext, shelf_shadow, shelf_zero, shelf_color, shelf_color, shelf_zero);
415 gPainter.Paint2DQuadColor (GfxContext, shelf_box, shelf_color);
416
417- CHECKGL (glLineWidth (1));
418- gPainter.Draw2DLine (GfxContext, shelf_box.x, shelf_box.y - 1, shelf_box.x + shelf_box.width, shelf_box.y - 1, nux::Color (0x66FFFFFF));
419-
420 for (it = shelf_args.begin(); it != shelf_args.end(); it++)
421 {
422 if ((*it).skip)
423@@ -1496,7 +1493,7 @@
424
425 for (it = _model->shelf_begin(); it != _model->shelf_end (); it++)
426 {
427- if (!(*it)->Visible ())
428+ if (!(*it)->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
429 continue;
430
431 nux::Point2 screen_coord [4];
432@@ -1513,7 +1510,7 @@
433 // Because of the way icons fold and stack on one another, we must proceed in 2 steps.
434 for (rev_it = _model->rbegin (); rev_it != _model->rend (); rev_it++)
435 {
436- if ((*rev_it)->_folding_angle < 0.0f || !(*rev_it)->Visible ())
437+ if ((*rev_it)->_folding_angle < 0.0f || !(*rev_it)->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
438 continue;
439
440 nux::Point2 screen_coord [4];
441@@ -1529,7 +1526,7 @@
442
443 for (it = _model->begin(); it != _model->end (); it++)
444 {
445- if ((*it)->_folding_angle >= 0.0f || !(*it)->Visible ())
446+ if ((*it)->_folding_angle >= 0.0f || !(*it)->GetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE))
447 continue;
448
449 nux::Point2 screen_coord [4];
450
451=== modified file 'src/Launcher.h'
452--- src/Launcher.h 2010-11-23 02:58:23 +0000
453+++ src/Launcher.h 2010-11-24 15:28:12 +0000
454@@ -119,7 +119,10 @@
455 float DnDExitProgress ();
456 float GetHoverProgress ();
457 float AutohideProgress ();
458- float IconPresentProgress (LauncherIcon *icon, struct timespec current);
459+ float IconPresentProgress (LauncherIcon *icon, struct timespec current);
460+ float IconUrgentPulseValue (LauncherIcon *icon, struct timespec current);
461+ float IconStartingPulseValue (LauncherIcon *icon, struct timespec current);
462+ float IconBackgroundIntensity (LauncherIcon *icon, struct timespec current);
463
464 void SetHover ();
465 void UnsetHover ();
466
467=== modified file 'src/LauncherController.cpp'
468--- src/LauncherController.cpp 2010-11-12 17:32:48 +0000
469+++ src/LauncherController.cpp 2010-11-24 15:28:12 +0000
470@@ -60,8 +60,8 @@
471
472 expoIcon->SetTooltipText ("Workspace Switcher");
473 expoIcon->SetIconName ("workspace-switcher");
474- expoIcon->SetVisible (true);
475- expoIcon->SetRunning (false);
476+ expoIcon->SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, true);
477+ expoIcon->SetQuirk (LAUNCHER_ICON_QUIRK_RUNNING, false);
478 expoIcon->SetIconType (LAUNCHER_ICON_TYPE_END);
479
480 expoIcon->MouseClick.connect (sigc::mem_fun (this, &LauncherController::OnExpoClicked));
481
482=== modified file 'src/LauncherIcon.cpp'
483--- src/LauncherIcon.cpp 2010-11-23 20:00:15 +0000
484+++ src/LauncherIcon.cpp 2010-11-24 15:28:12 +0000
485@@ -42,26 +42,13 @@
486 _launcher = launcher;
487 m_TooltipText = "blank";
488
489- _show_time.tv_sec = 0;
490- _hide_time.tv_sec = 0;
491- _running_time.tv_sec = 0;
492- _urgent_time.tv_sec = 0;
493- _present_time.tv_sec = 0;
494- _unpresent_time.tv_sec = 0;
495-
496- _show_time.tv_nsec = 0;
497- _hide_time.tv_nsec = 0;
498- _running_time.tv_nsec = 0;
499- _urgent_time.tv_nsec = 0;
500- _present_time.tv_nsec = 0;
501- _unpresent_time.tv_nsec = 0;
502-
503- _active = false;
504- _running = false;
505- _visible = false;
506- _urgent = false;
507- _presented = false;
508-
509+ for (int i = 0; i < LAUNCHER_ICON_QUIRK_LAST; i++)
510+ {
511+ _quirks[i] = 0;
512+ _quirk_times[i].tv_sec = 0;
513+ _quirk_times[i].tv_nsec = 0;
514+ }
515+
516 _related_windows = 0;
517
518 _background_color = nux::Color::White;
519@@ -86,8 +73,11 @@
520 {
521 if (_present_time_handle)
522 g_source_remove (_present_time_handle);
523-
524 _present_time_handle = 0;
525+
526+ if (_center_stabilize_handle)
527+ g_source_remove (_center_stabilize_handle);
528+ _center_stabilize_handle = 0;
529 }
530
531 nux::Color LauncherIcon::BackgroundColor ()
532@@ -242,7 +232,7 @@
533 }
534
535 int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
536- int tip_y = 24 + _center.y;
537+ int tip_y = _center.y;
538
539 _tooltip->ShowTooltipWithTipAt (tip_x, tip_y);
540
541@@ -327,7 +317,7 @@
542
543
544 int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
545- int tip_y = 24 + _center.y;
546+ int tip_y = _center.y;
547
548 _quicklist->ShowQuicklistWithTipAt (tip_x, tip_y);
549 _quicklist->EnableInputWindow (true);
550@@ -361,34 +351,19 @@
551 _tooltip->ShowWindow (false);
552 }
553
554-struct timespec LauncherIcon::ShowTime ()
555-{
556- return _show_time;
557-}
558-
559-struct timespec LauncherIcon::HideTime ()
560-{
561- return _hide_time;
562-}
563-
564-struct timespec LauncherIcon::RunningTime ()
565-{
566- return _running_time;
567-}
568-
569-struct timespec LauncherIcon::UrgentTime ()
570-{
571- return _urgent_time;
572-}
573-
574-struct timespec LauncherIcon::PresentTime ()
575-{
576- return _present_time;
577-}
578-
579-struct timespec LauncherIcon::UnpresentTime ()
580-{
581- return _unpresent_time;
582+gboolean
583+LauncherIcon::OnCenterTimeout (gpointer data)
584+{
585+ LauncherIcon *self = (LauncherIcon*)data;
586+
587+ if (self->_last_stable != self->_center)
588+ {
589+ self->OnCenterStabilized (self->_center);
590+ self->_last_stable = self->_center;
591+ }
592+
593+ self->_center_stabilize_handle = 0;
594+ return false;
595 }
596
597 void
598@@ -397,80 +372,30 @@
599 _center = center;
600
601 int tip_x = _launcher->GetBaseWidth () + 1; //icon_x + icon_w;
602- int tip_y = 24 + _center.y;
603+ int tip_y = _center.y;
604
605 if (_quicklist->IsVisible ())
606 _quicklist->ShowQuicklistWithTipAt (tip_x, tip_y);
607 else if (_tooltip->IsVisible ())
608 _tooltip->ShowTooltipWithTipAt (tip_x, tip_y);
609-}
610-
611-void
612-LauncherIcon::SetVisible (bool visible)
613-{
614- if (visible == _visible)
615- return;
616-
617- _visible = visible;
618-
619- needs_redraw.emit (this);
620-
621- if (visible)
622- {
623- Present (1500);
624- clock_gettime (CLOCK_MONOTONIC, &_show_time);
625- show.emit (this);
626- }
627- else
628- {
629- clock_gettime (CLOCK_MONOTONIC, &_hide_time);
630- hide.emit (this);
631- }
632-}
633-
634-void
635-LauncherIcon::SetActive (bool active)
636-{
637- if (active == _active)
638- return;
639-
640- _active = active;
641- needs_redraw.emit (this);
642-}
643-
644-void
645-LauncherIcon::SetRunning (bool running)
646-{
647- if (running == _running)
648- return;
649-
650- _running = running;
651- clock_gettime (CLOCK_MONOTONIC, &_running_time);
652- needs_redraw.emit (this);
653-}
654-
655-void
656-LauncherIcon::SetUrgent (bool urgent)
657-{
658- if (urgent == _urgent)
659- return;
660-
661- _urgent = urgent;
662-
663- if (urgent)
664- {
665- Present (1500);
666- clock_gettime (CLOCK_MONOTONIC, &_urgent_time);
667- }
668-
669- needs_redraw.emit (this);
670+
671+ if (_center_stabilize_handle)
672+ g_source_remove (_center_stabilize_handle);
673+
674+ _center_stabilize_handle = g_timeout_add (500, &LauncherIcon::OnCenterTimeout, this);
675+}
676+
677+nux::Point3
678+LauncherIcon::GetCenter ()
679+{
680+ return _center;
681 }
682
683 gboolean
684 LauncherIcon::OnPresentTimeout (gpointer data)
685 {
686 LauncherIcon *self = (LauncherIcon*) data;
687- if (!self->_presented)
688+ if (!self->GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
689 return false;
690
691 self->_present_time_handle = 0;
692@@ -482,28 +407,25 @@
693 void
694 LauncherIcon::Present (int length)
695 {
696- if (_presented)
697+ if (GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
698 return;
699
700- _presented = true;
701+ if (length >= 0)
702+ _present_time_handle = g_timeout_add (length, &LauncherIcon::OnPresentTimeout, this);
703
704- _present_time_handle = g_timeout_add (length, &LauncherIcon::OnPresentTimeout, this);
705- clock_gettime (CLOCK_MONOTONIC, &_present_time);
706- needs_redraw.emit (this);
707+ SetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED, true);
708 }
709
710 void
711 LauncherIcon::Unpresent ()
712 {
713- if (!_presented)
714+ if (!GetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED))
715 return;
716
717 if (_present_time_handle > 0)
718 g_source_remove (_present_time_handle);
719
720- _presented = false;
721- clock_gettime (CLOCK_MONOTONIC, &_unpresent_time);
722- needs_redraw.emit (this);
723+ SetQuirk (LAUNCHER_ICON_QUIRK_PRESENTED, false);
724 }
725
726 void
727@@ -519,7 +441,7 @@
728 void
729 LauncherIcon::Remove ()
730 {
731- SetVisible (false);
732+ SetQuirk (LAUNCHER_ICON_QUIRK_VISIBLE, false);
733 remove.emit (this);
734 }
735
736@@ -548,33 +470,44 @@
737 }
738
739 bool
740-LauncherIcon::Visible ()
741-{
742- return _visible;
743-}
744-
745-bool
746-LauncherIcon::Active ()
747-{
748- return _active;
749-}
750-
751-bool
752-LauncherIcon::Running ()
753-{
754- return _running;
755-}
756-
757-bool
758-LauncherIcon::Urgent ()
759-{
760- return _urgent;
761-}
762-
763-bool
764-LauncherIcon::Presented ()
765-{
766- return _presented;
767+LauncherIcon::GetQuirk (LauncherIconQuirk quirk)
768+{
769+ return _quirks[quirk];
770+}
771+
772+void
773+LauncherIcon::SetQuirk (LauncherIconQuirk quirk, bool value)
774+{
775+ if (_quirks[quirk] == value)
776+ return;
777+
778+ _quirks[quirk] = value;
779+ clock_gettime (CLOCK_MONOTONIC, &(_quirk_times[quirk]));
780+ needs_redraw.emit (this);
781+
782+ // Present on urgent as a general policy
783+ if ((quirk == LAUNCHER_ICON_QUIRK_URGENT || quirk == LAUNCHER_ICON_QUIRK_VISIBLE) && value)
784+ Present (1500);
785+}
786+
787+void
788+LauncherIcon::UpdateQuirkTime (LauncherIconQuirk quirk)
789+{
790+ clock_gettime (CLOCK_MONOTONIC, &(_quirk_times[quirk]));
791+ needs_redraw.emit (this);
792+}
793+
794+void
795+LauncherIcon::ResetQuirkTime (LauncherIconQuirk quirk)
796+{
797+ _quirk_times[quirk].tv_sec = 0;
798+ _quirk_times[quirk].tv_nsec = 0;
799+}
800+
801+struct timespec
802+LauncherIcon::GetQuirkTime (LauncherIconQuirk quirk)
803+{
804+ return _quirk_times[quirk];
805 }
806
807 int
808
809=== modified file 'src/LauncherIcon.h'
810--- src/LauncherIcon.h 2010-11-23 02:58:23 +0000
811+++ src/LauncherIcon.h 2010-11-24 15:28:12 +0000
812@@ -50,22 +50,28 @@
813 LAUNCHER_ICON_TYPE_END,
814 } LauncherIconType;
815
816+typedef enum
817+{
818+ LAUNCHER_ICON_QUIRK_VISIBLE,
819+ LAUNCHER_ICON_QUIRK_ACTIVE,
820+ LAUNCHER_ICON_QUIRK_RUNNING,
821+ LAUNCHER_ICON_QUIRK_URGENT,
822+ LAUNCHER_ICON_QUIRK_PRESENTED,
823+ LAUNCHER_ICON_QUIRK_STARTING,
824+
825+ LAUNCHER_ICON_QUIRK_LAST,
826+} LauncherIconQuirk;
827+
828 class LauncherIcon : public nux::InitiallyUnownedObject, public sigc::trackable
829 {
830 public:
831 LauncherIcon(Launcher* launcher);
832 ~LauncherIcon();
833
834- void SetTooltipText (const TCHAR* text);
835+ void SetTooltipText (const TCHAR* text);
836
837 nux::NString GetTooltipText ();
838
839- bool Visible ();
840- bool Active ();
841- bool Running ();
842- bool Urgent ();
843- bool Presented ();
844-
845 void RecvMouseEnter ();
846 void RecvMouseLeave ();
847 void RecvMouseDown (int button);
848@@ -75,18 +81,16 @@
849 void RecvHideQuicklist (nux::BaseWindow *quicklist);
850
851 void HideTooltip ();
852- void SetCenter (nux::Point3 center);
853+
854+ void SetCenter (nux::Point3 center);
855+ nux::Point3 GetCenter ();
856
857 int SortPriority ();
858
859 int RelatedWindows ();
860
861- struct timespec ShowTime ();
862- struct timespec HideTime ();
863- struct timespec RunningTime ();
864- struct timespec UrgentTime ();
865- struct timespec PresentTime ();
866- struct timespec UnpresentTime ();
867+ bool GetQuirk (LauncherIconQuirk quirk);
868+ struct timespec GetQuirkTime (LauncherIconQuirk quirk);
869
870 LauncherIconType Type ();
871
872@@ -98,8 +102,8 @@
873
874 sigc::signal<void, int> MouseDown;
875 sigc::signal<void, int> MouseUp;
876- sigc::signal<void> MouseEnter;
877- sigc::signal<void> MouseLeave;
878+ sigc::signal<void> MouseEnter;
879+ sigc::signal<void> MouseLeave;
880 sigc::signal<void, int> MouseClick;
881
882 sigc::signal<void, void *> show;
883@@ -107,11 +111,11 @@
884 sigc::signal<void, void *> remove;
885 sigc::signal<void, void *> needs_redraw;
886 protected:
887-
888- void SetVisible (bool visible);
889- void SetActive (bool active);
890- void SetRunning (bool running);
891- void SetUrgent (bool urgent);
892+ void SetQuirk (LauncherIconQuirk quirk, bool value);
893+
894+ void UpdateQuirkTime (LauncherIconQuirk quirk);
895+ void ResetQuirkTime (LauncherIconQuirk quirk);
896+
897 void SetRelatedWindows (int windows);
898 void Remove ();
899
900@@ -123,6 +127,8 @@
901
902 virtual std::list<DbusmenuClient *> GetMenus ();
903 virtual nux::BaseTexture * GetTextureForSize (int size) = 0;
904+
905+ virtual void OnCenterStabilized (nux::Point3 center) {};
906
907 nux::BaseTexture * TextureFromGtkTheme (const char *name, int size);
908
909@@ -153,30 +159,24 @@
910 static void child_realized (DbusmenuMenuitem *newitem, QuicklistView *quicklist);
911 static void root_changed (DbusmenuClient * client, DbusmenuMenuitem *newroot, QuicklistView *quicklist);
912 static gboolean OnPresentTimeout (gpointer data);
913+ static gboolean OnCenterTimeout (gpointer data);
914
915 nux::Color ColorForIcon (GdkPixbuf *pixbuf);
916
917 nux::Color _background_color;
918- bool _visible;
919- bool _active;
920- bool _running;
921- bool _urgent;
922- bool _presented;
923 int _sort_priority;
924 int _related_windows;
925 guint _present_time_handle;
926+ guint _center_stabilize_handle;
927 bool _quicklist_is_initialized;
928
929 nux::Point3 _center;
930-
931+ nux::Point3 _last_stable;
932 LauncherIconType _icon_type;
933
934- struct timespec _show_time;
935- struct timespec _hide_time;
936- struct timespec _running_time;
937- struct timespec _urgent_time;
938- struct timespec _present_time;
939- struct timespec _unpresent_time;
940+ bool _quirks[LAUNCHER_ICON_QUIRK_LAST];
941+ struct timespec _quirk_times[LAUNCHER_ICON_QUIRK_LAST];
942+
943 };
944
945 #endif // LAUNCHERICON_H
946
947=== added file 'src/StartupNotifyService.cpp'
948--- src/StartupNotifyService.cpp 1970-01-01 00:00:00 +0000
949+++ src/StartupNotifyService.cpp 2010-11-24 15:28:12 +0000
950@@ -0,0 +1,70 @@
951+/*
952+ * Copyright (C) 2010 Canonical Ltd
953+ *
954+ * This program is free software: you can redistribute it and/or modify
955+ * it under the terms of the GNU General Public License version 3 as
956+ * published by the Free Software Foundation.
957+ *
958+ * This program is distributed in the hope that it will be useful,
959+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
960+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
961+ * GNU General Public License for more details.
962+ *
963+ * You should have received a copy of the GNU General Public License
964+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
965+ *
966+ * Authored by: Jason Smith <jason.smith@canonical.com>
967+ */
968+
969+#include "StartupNotifyService.h"
970+#include <stdio.h>
971+
972+StartupNotifyService * StartupNotifyService::_default = 0;
973+
974+StartupNotifyService *
975+StartupNotifyService::Default ()
976+{
977+ if (!_default)
978+ _default = new StartupNotifyService ();
979+
980+ return _default;
981+}
982+
983+StartupNotifyService::StartupNotifyService()
984+{
985+}
986+
987+StartupNotifyService::~StartupNotifyService()
988+{
989+}
990+
991+void
992+StartupNotifyService::OnMonitorEvent (SnMonitorEvent *sn_event, void *user_data)
993+{
994+ StartupNotifyService *service = (StartupNotifyService*) user_data;
995+ SnStartupSequence *seq;
996+ const char *id;
997+
998+ seq = sn_monitor_event_get_startup_sequence (sn_event);
999+ id = sn_startup_sequence_get_id (seq);
1000+
1001+ switch (sn_monitor_event_get_type (sn_event))
1002+ {
1003+ case SN_MONITOR_EVENT_INITIATED:
1004+ service->StartupInitiated.emit (id);
1005+ break;
1006+ case SN_MONITOR_EVENT_COMPLETED:
1007+ service->StartupCompleted.emit (id);
1008+ break;
1009+ default:
1010+ break;
1011+ }
1012+
1013+}
1014+
1015+void
1016+StartupNotifyService::SetSnDisplay (SnDisplay *sn_display, int screen)
1017+{
1018+ _sn_display = sn_display;
1019+ _sn_monitor = sn_monitor_context_new (_sn_display, screen, &StartupNotifyService::OnMonitorEvent, this, NULL);
1020+}
1021
1022=== added file 'src/StartupNotifyService.h'
1023--- src/StartupNotifyService.h 1970-01-01 00:00:00 +0000
1024+++ src/StartupNotifyService.h 2010-11-24 15:28:12 +0000
1025@@ -0,0 +1,53 @@
1026+/*
1027+ * Copyright (C) 2010 Canonical Ltd
1028+ *
1029+ * This program is free software: you can redistribute it and/or modify
1030+ * it under the terms of the GNU General Public License version 3 as
1031+ * published by the Free Software Foundation.
1032+ *
1033+ * This program is distributed in the hope that it will be useful,
1034+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1035+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1036+ * GNU General Public License for more details.
1037+ *
1038+ * You should have received a copy of the GNU General Public License
1039+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1040+ *
1041+ * Authored by: Jason Smith <jason.smith@canonical.com>
1042+ */
1043+
1044+#ifndef STARTUPNOTIFYSERVICE_H
1045+#define STARTUPNOTIFYSERVICE_H
1046+
1047+#ifndef SN_API_NOT_YET_FROZEN
1048+#define SN_API_NOT_YET_FROZEN
1049+#endif
1050+#include <libsn/sn.h>
1051+
1052+#include <sigc++/sigc++.h>
1053+
1054+class StartupNotifyService : public sigc::trackable
1055+{
1056+
1057+public:
1058+ static StartupNotifyService * Default();
1059+
1060+ void SetSnDisplay (SnDisplay *sn_display, int screen);
1061+
1062+ sigc::signal<void, const char*> StartupInitiated;
1063+ sigc::signal<void, const char*> StartupCompleted;
1064+
1065+protected:
1066+ StartupNotifyService();
1067+ ~StartupNotifyService();
1068+
1069+private:
1070+ static void OnMonitorEvent (SnMonitorEvent *sn_event, void *user_data);
1071+
1072+ static StartupNotifyService *_default;
1073+
1074+ SnDisplay *_sn_display;
1075+ SnMonitorContext *_sn_monitor;
1076+};
1077+
1078+#endif // STARTUPNOTIFYSERVICE_H
1079
1080=== modified file 'src/unity.cpp'
1081--- src/unity.cpp 2010-11-15 23:07:58 +0000
1082+++ src/unity.cpp 2010-11-24 15:28:12 +0000
1083@@ -29,6 +29,7 @@
1084 #include "LauncherIcon.h"
1085 #include "LauncherController.h"
1086 #include "PluginAdapter.h"
1087+#include "StartupNotifyService.h"
1088 #include "unity.h"
1089
1090 #include <dbus/dbus.h>
1091@@ -438,6 +439,8 @@
1092 ScreenInterface::setHandler (screen); // Sets the screen function hook handler
1093 CompositeScreenInterface::setHandler (cScreen); // Ditto for cScreen
1094 GLScreenInterface::setHandler (gScreen); // Ditto for gScreen
1095+
1096+ StartupNotifyService::Default ()->SetSnDisplay (screen->snDisplay (), screen->screenNum ());
1097
1098 nux::NuxInitialize (0);
1099 wt = nux::CreateFromForeignWindow (cScreen->output (),