Merge lp:~3v1n0/unity/focused-non-top-windows-fix into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: no longer in the source branch.
Merged at revision: 2344
Proposed branch: lp:~3v1n0/unity/focused-non-top-windows-fix
Merge into: lp:unity
Diff against target: 237 lines (+116/-43)
6 files modified
manual-tests/Launcher.txt (+23/-0)
plugins/unityshell/src/BamfLauncherIcon.cpp (+53/-43)
plugins/unityshell/src/PluginAdapter.cpp (+33/-0)
plugins/unityshell/src/PluginAdapter.h (+1/-0)
plugins/unityshell/src/WindowManager.cpp (+5/-0)
plugins/unityshell/src/WindowManager.h (+1/-0)
To merge this branch: bzr merge lp:~3v1n0/unity/focused-non-top-windows-fix
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Alex Launi (community) quality Needs Fixing
Review via email: mp+102958@code.launchpad.net

Commit message

BamfLauncherIcon: Focus an application if no child window is actually on top of the stack. Raises all urgent windows.

This fixes bug #802816 that happens when an application raises a window on the top of the stack but the focus doesn't change.

Plus, don't perform unneeded checks when focusing non-active applications.

Description of the change

When a launcher icon is clicked, it should focus a window if the window is currently not on top of the stack (excluding from that the unity or other invalid windows).
To do that I've implemented a new method into PluginAdapter that checks if a Window is on top.

Also, when activating a launcher icon, we should always raise all the urgent windows, not only the top one.

Added manual tests, due to the fact that AP at the moment can't create such kind of windows on the fly.

To post a comment you must log in.
Revision history for this message
Alex Launi (alexlauni) wrote :

This is autopilot testable. Start gimp, execute gimp foo-image.png (we'll need to ship an image to test with). Then check state. Simple.

review: Needs Fixing (quality)
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Alex, I can't get this into an AP test... It fails to work like it should.
Also it's too application dependent and not always reproducible, so we must go with manual test.

Revision history for this message
Tim Penhey (thumper) wrote :

I'm ok with a manual test for this at this stage.

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

Attempt to merge into lp:unity failed due to conflicts:

text conflict in manual-tests/Launcher.txt

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'manual-tests/Launcher.txt'
2--- manual-tests/Launcher.txt 2012-04-26 04:58:58 +0000
3+++ manual-tests/Launcher.txt 2012-04-26 06:00:26 +0000
4@@ -489,6 +489,7 @@
5 The Firefox icon should *not* be highlighted during the drag&drop.
6 Firefox should open the folder in a new Firefox window.
7
8+
9 Test Launcher with Chromium Web apps
10 ------------------------------------
11 This tests shows the integration of unity with the Chromium Web Apps
12@@ -517,3 +518,25 @@
13 application icon.
14 * Clicking the "Home | Ubuntu" will activate its window, while clicking
15 in the chromium icon will activate a chromium window.
16+
17+
18+Test Launcher raises focused non-top windows
19+--------------------------------------------
20+This tests shows how the focused windows should be raised to the top of the
21+stack, when another non-active window is over them.
22+
23+Actions:
24+ * Open a terminal Window
25+ * Open The GIMP
26+ * In GIMP load an image, say /usr/share/backgrounds/warty-final-ubuntu.png
27+ * From the terminal window run the command "gimp foo-image.png"
28+
29+Expected Results:
30+ * A gimp dialog will be raised (so the terminal window is below it), but not focused
31+ * Terminal launcher icon must have a filled-in arrow on the right of the icon
32+
33+Actions:
34+ * Click on the launcher terminal icon
35+
36+Expected Results:
37+ * Terminal window will be raised to the top of the stack (over the GIMP window)
38
39=== modified file 'plugins/unityshell/src/BamfLauncherIcon.cpp'
40--- plugins/unityshell/src/BamfLauncherIcon.cpp 2012-04-26 00:35:37 +0000
41+++ plugins/unityshell/src/BamfLauncherIcon.cpp 2012-04-26 06:00:26 +0000
42@@ -208,50 +208,59 @@
43 auto bamf_view = glib::object_cast<BamfView>(_bamf_app);
44 user_visible = bamf_view_user_visible(bamf_view);
45
46- bool any_visible = false;
47- bool any_mapped = false;
48- bool any_on_monitor = (arg.monitor < 0);
49- int active_monitor = arg.monitor;
50- GList* children = bamf_view_get_children(bamf_view);
51-
52- for (GList* l = children; l; l = l->next)
53+ if (active)
54 {
55- if (!BAMF_IS_WINDOW(l->data))
56- continue;
57-
58- auto view = static_cast<BamfView*>(l->data);
59- auto win = static_cast<BamfWindow*>(l->data);
60- Window xid = bamf_window_get_xid(win);
61-
62- if (!any_visible && wm->IsWindowOnCurrentDesktop(xid))
63- {
64- any_visible = true;
65- }
66-
67- if (!any_mapped && wm->IsWindowMapped(xid))
68- {
69- any_mapped = true;
70- }
71-
72- if (!any_on_monitor && bamf_window_get_monitor(win) == arg.monitor &&
73- wm->IsWindowMapped(xid) && wm->IsWindowVisible(xid))
74- {
75- any_on_monitor = true;
76- }
77-
78- if (bamf_view_is_active(view))
79- {
80- active_monitor = bamf_window_get_monitor(win);
81- }
82+ bool any_visible = false;
83+ bool any_mapped = false;
84+ bool any_on_top = false;
85+ bool any_on_monitor = (arg.monitor < 0);
86+ int active_monitor = arg.monitor;
87+ GList* children = bamf_view_get_children(bamf_view);
88+
89+ for (GList* l = children; l; l = l->next)
90+ {
91+ if (!BAMF_IS_WINDOW(l->data))
92+ continue;
93+
94+ auto view = static_cast<BamfView*>(l->data);
95+ auto win = static_cast<BamfWindow*>(l->data);
96+ Window xid = bamf_window_get_xid(win);
97+
98+ if (!any_visible && wm->IsWindowOnCurrentDesktop(xid))
99+ {
100+ any_visible = true;
101+ }
102+
103+ if (!any_mapped && wm->IsWindowMapped(xid))
104+ {
105+ any_mapped = true;
106+ }
107+
108+ if (!any_on_top && wm->IsWindowOnTop(xid))
109+ {
110+ any_on_top = true;
111+ }
112+
113+ if (!any_on_monitor && bamf_window_get_monitor(win) == arg.monitor &&
114+ wm->IsWindowMapped(xid) && wm->IsWindowVisible(xid))
115+ {
116+ any_on_monitor = true;
117+ }
118+
119+ if (bamf_view_is_active(view))
120+ {
121+ active_monitor = bamf_window_get_monitor(win);
122+ }
123+ }
124+
125+ g_list_free(children);
126+
127+ if (!any_visible || !any_mapped || !any_on_top)
128+ active = false;
129+
130+ if (any_on_monitor && arg.monitor >= 0 && active_monitor != arg.monitor)
131+ active = false;
132 }
133-
134- g_list_free(children);
135-
136- if (!any_visible || !any_mapped)
137- active = false;
138-
139- if (any_on_monitor && arg.monitor >= 0 && active_monitor != arg.monitor)
140- active = false;
141 }
142
143 /* Behaviour:
144@@ -635,7 +644,8 @@
145 }
146 }
147
148- wm->FocusWindowGroup(windows, visibility, arg.monitor);
149+ bool only_top_win = !any_urgent;
150+ wm->FocusWindowGroup(windows, visibility, arg.monitor, only_top_win);
151 }
152
153 bool BamfLauncherIcon::Spread(bool current_desktop, int state, bool force)
154
155=== modified file 'plugins/unityshell/src/PluginAdapter.cpp'
156--- plugins/unityshell/src/PluginAdapter.cpp 2012-04-24 21:26:30 +0000
157+++ plugins/unityshell/src/PluginAdapter.cpp 2012-04-26 06:00:26 +0000
158@@ -530,6 +530,39 @@
159 }
160
161 bool
162+PluginAdapter::IsWindowOnTop(guint32 xid)
163+{
164+ Window win = xid;
165+ CompWindow* window;
166+
167+ window = m_Screen->findWindow(win);
168+
169+ if (window)
170+ {
171+ if (window->inShowDesktopMode() || !window->isMapped() || !window->isViewable() || window->minimized())
172+ return false;
173+
174+ CompPoint window_vp = window->defaultViewport();
175+ std::vector<Window> const& our_xids = nux::XInputWindow::NativeHandleList();
176+
177+ for (CompWindow* sibling = window->next; sibling; sibling = sibling->next)
178+ {
179+ if (sibling->defaultViewport() == window_vp && !sibling->minimized() &&
180+ sibling->isMapped() && sibling->isViewable() && !sibling->inShowDesktopMode() &&
181+ !(sibling->state() & CompWindowStateAboveMask) &&
182+ std::find(our_xids.begin(), our_xids.end(), sibling->id()) == our_xids.end())
183+ {
184+ return false;
185+ }
186+ }
187+
188+ return true;
189+ }
190+
191+ return false;
192+}
193+
194+bool
195 PluginAdapter::IsWindowClosable(guint32 xid)
196 {
197 Window win = xid;
198
199=== modified file 'plugins/unityshell/src/PluginAdapter.h'
200--- plugins/unityshell/src/PluginAdapter.h 2012-04-24 21:26:30 +0000
201+++ plugins/unityshell/src/PluginAdapter.h 2012-04-26 06:00:26 +0000
202@@ -121,6 +121,7 @@
203 bool IsWindowObscured(guint xid);
204 bool IsWindowMapped(guint xid);
205 bool IsWindowVisible(guint32 xid);
206+ bool IsWindowOnTop(guint32 xid);
207 bool IsWindowClosable(guint32 xid);
208 bool IsWindowMinimizable(guint32 xid);
209 bool IsWindowMaximizable(guint32 xid);
210
211=== modified file 'plugins/unityshell/src/WindowManager.cpp'
212--- plugins/unityshell/src/WindowManager.cpp 2012-04-25 23:30:51 +0000
213+++ plugins/unityshell/src/WindowManager.cpp 2012-04-26 06:00:26 +0000
214@@ -78,6 +78,11 @@
215 return true;
216 }
217
218+ bool IsWindowOnTop(guint32 xid)
219+ {
220+ return false;
221+ }
222+
223 bool IsWindowClosable(guint32 xid)
224 {
225 return true;
226
227=== modified file 'plugins/unityshell/src/WindowManager.h'
228--- plugins/unityshell/src/WindowManager.h 2012-04-24 21:26:30 +0000
229+++ plugins/unityshell/src/WindowManager.h 2012-04-26 06:00:26 +0000
230@@ -57,6 +57,7 @@
231 virtual bool IsWindowObscured(guint32 xid) = 0;
232 virtual bool IsWindowMapped(guint32 xid) = 0;
233 virtual bool IsWindowVisible(guint32 xid) = 0;
234+ virtual bool IsWindowOnTop(guint32 xid) = 0;
235 virtual bool IsWindowClosable(guint32 xid) = 0;
236 virtual bool IsWindowMinimizable(guint32 xid) = 0;
237 virtual bool IsWindowMaximizable(guint32 xid) = 0;