summaryrefslogtreecommitdiff
diff options
authorMarco Trevisan (TreviƱo) <mail@3v1n0.net>2012-04-26 02:34:30 -0400
committerTarmac <>2012-04-26 02:34:30 -0400
commit98202ab0f76a6001811f6685f1057c223520c568 (patch)
tree5174a6e290ea02fd12becb6fd49f6c2292607c3f
parentbe388ce31f5bb1c27b35409b6d3e702b0ed42f9c (diff)
parentb3780e5cd069c8d8ae38d2cd46ce9caeb9ee3efc (diff)
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.. Fixes: https://bugs.launchpad.net/bugs/802816, https://bugs.launchpad.net/bugs/986443. Approved by Tim Penhey. (bzr r2344)
-rw-r--r--manual-tests/Launcher.txt23
-rw-r--r--plugins/unityshell/src/BamfLauncherIcon.cpp80
-rw-r--r--plugins/unityshell/src/PluginAdapter.cpp33
-rw-r--r--plugins/unityshell/src/PluginAdapter.h1
-rw-r--r--plugins/unityshell/src/WindowManager.cpp5
-rw-r--r--plugins/unityshell/src/WindowManager.h1
6 files changed, 108 insertions, 35 deletions
diff --git a/manual-tests/Launcher.txt b/manual-tests/Launcher.txt
index 67b873681..9b3c1caed 100644
--- a/manual-tests/Launcher.txt
+++ b/manual-tests/Launcher.txt
@@ -489,6 +489,7 @@ Expected Result:
The Firefox icon should *not* be highlighted during the drag&drop.
Firefox should open the folder in a new Firefox window.
+
Test Launcher with Chromium Web apps
------------------------------------
This tests shows the integration of unity with the Chromium Web Apps
@@ -517,3 +518,25 @@ Expected Results:
application icon.
* Clicking the "Home | Ubuntu" will activate its window, while clicking
in the chromium icon will activate a chromium window.
+
+
+Test Launcher raises focused non-top windows
+--------------------------------------------
+This tests shows how the focused windows should be raised to the top of the
+stack, when another non-active window is over them.
+
+Actions:
+ * Open a terminal Window
+ * Open The GIMP
+ * In GIMP load an image, say /usr/share/backgrounds/warty-final-ubuntu.png
+ * From the terminal window run the command "gimp foo-image.png"
+
+Expected Results:
+ * A gimp dialog will be raised (so the terminal window is below it), but not focused
+ * Terminal launcher icon must have a filled-in arrow on the right of the icon
+
+Actions:
+ * Click on the launcher terminal icon
+
+Expected Results:
+ * Terminal window will be raised to the top of the stack (over the GIMP window)
diff --git a/plugins/unityshell/src/BamfLauncherIcon.cpp b/plugins/unityshell/src/BamfLauncherIcon.cpp
index 84881d69e..01205fc24 100644
--- a/plugins/unityshell/src/BamfLauncherIcon.cpp
+++ b/plugins/unityshell/src/BamfLauncherIcon.cpp
@@ -208,50 +208,59 @@ void BamfLauncherIcon::ActivateLauncherIcon(ActionArg arg)
auto bamf_view = glib::object_cast<BamfView>(_bamf_app);
user_visible = bamf_view_user_visible(bamf_view);
- bool any_visible = false;
- bool any_mapped = false;
- bool any_on_monitor = (arg.monitor < 0);
- int active_monitor = arg.monitor;
- GList* children = bamf_view_get_children(bamf_view);
-
- for (GList* l = children; l; l = l->next)
+ if (active)
{
- if (!BAMF_IS_WINDOW(l->data))
- continue;
+ bool any_visible = false;
+ bool any_mapped = false;
+ bool any_on_top = false;
+ bool any_on_monitor = (arg.monitor < 0);
+ int active_monitor = arg.monitor;
+ GList* children = bamf_view_get_children(bamf_view);
+
+ for (GList* l = children; l; l = l->next)
+ {
+ if (!BAMF_IS_WINDOW(l->data))
+ continue;
- auto view = static_cast<BamfView*>(l->data);
- auto win = static_cast<BamfWindow*>(l->data);
- Window xid = bamf_window_get_xid(win);
+ auto view = static_cast<BamfView*>(l->data);
+ auto win = static_cast<BamfWindow*>(l->data);
+ Window xid = bamf_window_get_xid(win);
- if (!any_visible && wm->IsWindowOnCurrentDesktop(xid))
- {
- any_visible = true;
- }
+ if (!any_visible && wm->IsWindowOnCurrentDesktop(xid))
+ {
+ any_visible = true;
+ }
- if (!any_mapped && wm->IsWindowMapped(xid))
- {
- any_mapped = true;
- }
+ if (!any_mapped && wm->IsWindowMapped(xid))
+ {
+ any_mapped = true;
+ }
- if (!any_on_monitor && bamf_window_get_monitor(win) == arg.monitor &&
- wm->IsWindowMapped(xid) && wm->IsWindowVisible(xid))
- {
- any_on_monitor = true;
- }
+ if (!any_on_top && wm->IsWindowOnTop(xid))
+ {
+ any_on_top = true;
+ }
- if (bamf_view_is_active(view))
- {
- active_monitor = bamf_window_get_monitor(win);
+ if (!any_on_monitor && bamf_window_get_monitor(win) == arg.monitor &&
+ wm->IsWindowMapped(xid) && wm->IsWindowVisible(xid))
+ {
+ any_on_monitor = true;
+ }
+
+ if (bamf_view_is_active(view))
+ {
+ active_monitor = bamf_window_get_monitor(win);
+ }
}
- }
- g_list_free(children);
+ g_list_free(children);
- if (!any_visible || !any_mapped)
- active = false;
+ if (!any_visible || !any_mapped || !any_on_top)
+ active = false;
- if (any_on_monitor && arg.monitor >= 0 && active_monitor != arg.monitor)
- active = false;
+ if (any_on_monitor && arg.monitor >= 0 && active_monitor != arg.monitor)
+ active = false;
+ }
}
/* Behaviour:
@@ -635,7 +644,8 @@ void BamfLauncherIcon::Focus(ActionArg arg)
}
}
- wm->FocusWindowGroup(windows, visibility, arg.monitor);
+ bool only_top_win = !any_urgent;
+ wm->FocusWindowGroup(windows, visibility, arg.monitor, only_top_win);
}
bool BamfLauncherIcon::Spread(bool current_desktop, int state, bool force)
diff --git a/plugins/unityshell/src/PluginAdapter.cpp b/plugins/unityshell/src/PluginAdapter.cpp
index ad069a059..e9008c224 100644
--- a/plugins/unityshell/src/PluginAdapter.cpp
+++ b/plugins/unityshell/src/PluginAdapter.cpp
@@ -530,6 +530,39 @@ PluginAdapter::IsWindowVisible(guint32 xid)
}
bool
+PluginAdapter::IsWindowOnTop(guint32 xid)
+{
+ Window win = xid;
+ CompWindow* window;
+
+ window = m_Screen->findWindow(win);
+
+ if (window)
+ {
+ if (window->inShowDesktopMode() || !window->isMapped() || !window->isViewable() || window->minimized())
+ return false;
+
+ CompPoint window_vp = window->defaultViewport();
+ std::vector<Window> const& our_xids = nux::XInputWindow::NativeHandleList();
+
+ for (CompWindow* sibling = window->next; sibling; sibling = sibling->next)
+ {
+ if (sibling->defaultViewport() == window_vp && !sibling->minimized() &&
+ sibling->isMapped() && sibling->isViewable() && !sibling->inShowDesktopMode() &&
+ !(sibling->state() & CompWindowStateAboveMask) &&
+ std::find(our_xids.begin(), our_xids.end(), sibling->id()) == our_xids.end())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
PluginAdapter::IsWindowClosable(guint32 xid)
{
Window win = xid;
diff --git a/plugins/unityshell/src/PluginAdapter.h b/plugins/unityshell/src/PluginAdapter.h
index 43300914b..70d5e433c 100644
--- a/plugins/unityshell/src/PluginAdapter.h
+++ b/plugins/unityshell/src/PluginAdapter.h
@@ -121,6 +121,7 @@ public:
bool IsWindowObscured(guint xid);
bool IsWindowMapped(guint xid);
bool IsWindowVisible(guint32 xid);
+ bool IsWindowOnTop(guint32 xid);
bool IsWindowClosable(guint32 xid);
bool IsWindowMinimizable(guint32 xid);
bool IsWindowMaximizable(guint32 xid);
diff --git a/plugins/unityshell/src/WindowManager.cpp b/plugins/unityshell/src/WindowManager.cpp
index c4f5c7486..cde2dc149 100644
--- a/plugins/unityshell/src/WindowManager.cpp
+++ b/plugins/unityshell/src/WindowManager.cpp
@@ -78,6 +78,11 @@ class WindowManagerDummy : public WindowManager
return true;
}
+ bool IsWindowOnTop(guint32 xid)
+ {
+ return false;
+ }
+
bool IsWindowClosable(guint32 xid)
{
return true;
diff --git a/plugins/unityshell/src/WindowManager.h b/plugins/unityshell/src/WindowManager.h
index 9b9590c24..4e74b022a 100644
--- a/plugins/unityshell/src/WindowManager.h
+++ b/plugins/unityshell/src/WindowManager.h
@@ -57,6 +57,7 @@ public:
virtual bool IsWindowObscured(guint32 xid) = 0;
virtual bool IsWindowMapped(guint32 xid) = 0;
virtual bool IsWindowVisible(guint32 xid) = 0;
+ virtual bool IsWindowOnTop(guint32 xid) = 0;
virtual bool IsWindowClosable(guint32 xid) = 0;
virtual bool IsWindowMinimizable(guint32 xid) = 0;
virtual bool IsWindowMaximizable(guint32 xid) = 0;