Merge lp:~3v1n0/unity/manage-user-invisible-windows into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Didier Roche-Tolomelli
Approved revision: no longer in the source branch.
Merged at revision: 1830
Proposed branch: lp:~3v1n0/unity/manage-user-invisible-windows
Merge into: lp:unity
Diff against target: 266 lines (+108/-24)
2 files modified
manual-tests/UserInvisibleWindows.txt (+47/-0)
plugins/unityshell/src/BamfLauncherIcon.cpp (+61/-24)
To merge this branch: bzr merge lp:~3v1n0/unity/manage-user-invisible-windows
Reviewer Review Type Date Requested Status
Mirco Müller (community) Approve
Jason Smith Pending
Review via email: mp+87706@code.launchpad.net

Description of the change

Making unity be aware of user-invisible windows, and manage them correctly.

Fixed bug #784804, but after a discussion with Jason I followed his guidelines to get the things fixed.
Basically now user-invisible windows (i.e. the ones with the skip-taskbar flag) are ignored by unity unless they don't belong to a sticky application. In that case the application is shown as running, but clicking on it makes the application to run a new instance (while the alt+tab allows to select the user-invisible windows).
When an application as both user visible and invisible windows, clicking on the launcher icon or the alt+tab gives priority to the visible windows when bringing them to focus, while when closing all the visible windows, the application is hidden from launcher and alt+tab unless it's sticky (and in this case it behaves as explained above).
Also the user-invisible windows, never increment the count of the running windows (i.e. the launcher "pips").

Read more cases in the provided manual-tests.

This branch also fixes the management of the urgent windows, that with some latest commits were not managed anymore as they should (now they get again priority when the parent application is focused).

To post a comment you must log in.
Revision history for this message
Mirco Müller (macslow) wrote :

+1 code looks ok and the manual tests work as described. I used cairo-clock and nautilus (copy large amounts of data around my disk) to reproduce the manual-tests. For future testers I strongly recommend to add these explicit hints to the manuals tests description of what applications to use for the manual-tests. Otherwise other testers will have a hard time with reproducing them.

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

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/117/console reported an error when processing this lp:~3v1n0/unity/manage-user-invisible-windows branch.
Not merging it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'manual-tests/UserInvisibleWindows.txt'
2--- manual-tests/UserInvisibleWindows.txt 1970-01-01 00:00:00 +0000
3+++ manual-tests/UserInvisibleWindows.txt 2012-01-06 01:50:28 +0000
4@@ -0,0 +1,47 @@
5+Management of user-invisible windows
6+------------------------------------
7+This test shows how unity should manage the user-invisible windows (i.e the
8+windows with the skip-taskbar flag on).
9+
10+#. Start on a clean screen
11+#. Open a window of an unsticky application with the skip-taskbar flag set to ON
12+
13+Outcome
14+ Unity should ignore it, not showing it both on the launcher and on the Alt+Tab.
15+
16+
17+Pinned Application user-invisible window
18+----------------------------------------
19+This test shows how unity should manage the user-invisible windows (i.e the
20+windows with the skip-taskbar flag on) that belongs to an application sticked
21+to launcher.
22+
23+#. Start on a clean screen
24+#. Open one or more windows of a sticky application with the skip-taskbar flag
25+ set to ON
26+
27+Outcome
28+ Unity should show the pinned application icon in the running state with only
29+ one left indicator (pip), but clicking on it should make a new instance of the
30+ application to run.
31+ Otherwise, selecting that application in the Alt+Tab should bring the user-invisible
32+ window(s) to focus.
33+
34+
35+Running Application with both visible and invisible windows
36+-----------------------------------------------------------
37+This test shows how unity should manage applications with both user visible
38+and invisible windows.
39+
40+#. Start on a clean screen
41+#. Open one or more windows of an application with the skip-taskbar flag set to OFF
42+#. Open one or more windows of that application with the skip-taskbar flag set to ON
43+
44+Outcome
45+ The launcher icon should count with left icon indicators (pips) only the visible
46+ window(s); when clicking on it or selecting it via Alt+Tab unity should bring
47+ to focus only the visible windows, while at the second click over the launcher
48+ the spread with both visible and invisible windows should be activated.
49+ When all the user-visible windows are closed, the application should stay in
50+ the launcher or in the Alt+Tab (and show as running) only if is sticky,
51+ otherwise the icon should hide.
52
53=== modified file 'plugins/unityshell/src/BamfLauncherIcon.cpp'
54--- plugins/unityshell/src/BamfLauncherIcon.cpp 2011-12-14 01:47:53 +0000
55+++ plugins/unityshell/src/BamfLauncherIcon.cpp 2012-01-06 01:50:28 +0000
56@@ -65,9 +65,10 @@
57 GList *l;
58 BamfView *view;
59
60- bool active, running;
61+ bool active, running, user_visible;
62 active = bamf_view_is_active(BAMF_VIEW(m_App));
63 running = bamf_view_is_running(BAMF_VIEW(m_App));
64+ user_visible = running;
65
66 if (arg.target && OwnsWindow (arg.target))
67 {
68@@ -81,6 +82,8 @@
69
70 if (arg.source != ActionArg::SWITCHER)
71 {
72+ user_visible = bamf_view_user_visible(BAMF_VIEW(m_App));
73+
74 bool any_visible = false;
75 for (l = bamf_view_get_children(BAMF_VIEW(m_App)); l; l = l->next)
76 {
77@@ -90,9 +93,11 @@
78 {
79 Window xid = bamf_window_get_xid(BAMF_WINDOW(view));
80
81- if (WindowManager::Default ()->IsWindowOnCurrentDesktop(xid))
82+ if (!any_visible && WindowManager::Default()->IsWindowOnCurrentDesktop(xid))
83+ {
84 any_visible = true;
85- if (!WindowManager::Default ()->IsWindowMapped(xid))
86+ }
87+ if (active && !WindowManager::Default()->IsWindowMapped(xid))
88 {
89 active = false;
90 }
91@@ -104,14 +109,14 @@
92 }
93
94 /* Behaviour:
95- * 1) Nothing running -> launch application
96+ * 1) Nothing running, or nothing visible -> launch application
97 * 2) Running and active -> spread application
98 * 3) Running and not active -> focus application
99 * 4) Spread is active and different icon pressed -> change spread
100 * 5) Spread is active -> Spread de-activated, and fall through
101 */
102
103- if (!running) // #1 above
104+ if (!running || (running && !user_visible)) // #1 above
105 {
106 if (GetQuirk(QUIRK_STARTING))
107 return;
108@@ -122,7 +127,7 @@
109 }
110
111 SetQuirk(QUIRK_STARTING, true);
112- OpenInstanceLauncherIcon(ActionArg ());
113+ OpenInstanceLauncherIcon(ActionArg());
114 }
115 else // app is running
116 {
117@@ -136,7 +141,9 @@
118 else // #2 above
119 {
120 if (arg.source != ActionArg::SWITCHER)
121+ {
122 Spread(0, false);
123+ }
124 }
125 }
126 else
127@@ -283,7 +290,7 @@
128 std::vector<Window> results;
129 GList* children, *l;
130 BamfView* view;
131- WindowManager *wm = WindowManager::Default ();
132+ WindowManager *wm = WindowManager::Default();
133
134 children = bamf_view_get_children(BAMF_VIEW(m_App));
135 for (l = children; l; l = l->next)
136@@ -294,7 +301,9 @@
137 guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view));
138
139 if (wm->IsWindowMapped(xid))
140- results.push_back ((Window) xid);
141+ {
142+ results.push_back (xid);
143+ }
144 }
145 }
146
147@@ -574,6 +583,7 @@
148 BamfView* view;
149 bool any_urgent = false;
150 bool any_visible = false;
151+ bool any_user_visible = false;
152
153 children = bamf_view_get_children(BAMF_VIEW(m_App));
154
155@@ -588,30 +598,40 @@
156 {
157 Window xid = bamf_window_get_xid(BAMF_WINDOW(view));
158 bool urgent = bamf_view_is_urgent(view);
159-
160- if (WindowManager::Default ()->IsWindowOnCurrentDesktop (xid) &&
161- WindowManager::Default ()->IsWindowVisible (xid))
162- any_visible = true;
163+ bool user_visible = bamf_view_user_visible(view);
164
165 if (any_urgent)
166 {
167 if (urgent)
168 windows.push_back(xid);
169 }
170+ else if (any_user_visible && !urgent)
171+ {
172+ if (user_visible)
173+ windows.push_back(xid);
174+ }
175 else
176 {
177- if (urgent)
178+ if (urgent || user_visible)
179 {
180 windows.clear();
181 any_visible = false;
182- any_urgent = true;
183+ any_urgent = (any_urgent || urgent);
184+ any_user_visible = (any_user_visible || user_visible);
185 }
186- }
187- windows.push_back(xid);
188+
189+ windows.push_back(xid);
190+ }
191+
192+ if (WindowManager::Default()->IsWindowOnCurrentDesktop(xid) &&
193+ WindowManager::Default()->IsWindowVisible(xid))
194+ {
195+ any_visible = true;
196+ }
197 }
198 }
199-
200 g_list_free(children);
201+
202 if (arg.source != ActionArg::SWITCHER)
203 {
204 if (any_visible)
205@@ -626,8 +646,10 @@
206 }
207 }
208 else
209+ {
210 WindowManager::Default()->FocusWindowGroup(windows,
211 WindowManager::FocusVisibility::OnlyVisible);
212+ }
213 }
214
215 bool BamfLauncherIcon::Spread(int state, bool force)
216@@ -697,7 +719,8 @@
217 void BamfLauncherIcon::EnsureWindowState()
218 {
219 GList* children, *l;
220- int count = 0;
221+ unsigned int children_count = 0;
222+ unsigned int user_visible_count = 0;
223 bool has_visible = false;
224
225 children = bamf_view_get_children(BAMF_VIEW(m_App));
226@@ -713,10 +736,23 @@
227 has_visible = true;
228 }
229
230- count++;
231- }
232-
233- SetRelatedWindows(count);
234+ if (bamf_view_user_visible (BAMF_VIEW (l->data)))
235+ {
236+ user_visible_count++;
237+ }
238+
239+ children_count++;
240+ }
241+
242+ if (user_visible_count > 0)
243+ {
244+ SetRelatedWindows(user_visible_count);
245+ }
246+ else if (children_count > 0)
247+ {
248+ SetRelatedWindows(1);
249+ }
250+
251 SetHasWindowOnViewport(has_visible);
252
253 g_list_free(children);
254@@ -892,10 +928,11 @@
255
256 const gchar* desktop_file = DesktopFile();
257 bamf_view_set_sticky(view, false);
258- if (bamf_view_is_closed(view))
259+
260+ if (bamf_view_is_closed(view) || !bamf_view_user_visible(view))
261 this->Remove();
262
263- if (desktop_file && strlen(desktop_file) > 0)
264+ if (desktop_file && desktop_file[0] != '\0')
265 FavoriteStore::GetDefault().RemoveFavorite(desktop_file);
266 }
267