summaryrefslogtreecommitdiff
diff options
authorMarco Trevisan (TreviƱo) <mail@3v1n0.net>2013-02-05 03:42:21 +0000
committerTarmac <>2013-02-05 03:42:21 +0000
commitea2828e34f0b7c7bfebf78461a473dc59723afa2 (patch)
tree164f24ecd924b905c2ab1ba4548723f6ec4804c0
parent3b28ba08632b0c60d905ac6db71f7755b2573ffd (diff)
parent1774e6f71c05f5576ef7e1baf62145c4a9fdcacd (diff)
ApplicationLauncherIcon: add a custom implementation of GetQuirk for Quirk::ACTIVE
We need to make sure that an application is set as active also if the WindowManager active window is contained in the application windows list. Fixes: https://bugs.launchpad.net/bugs/1115775. Approved by Brandon Schaefer. (bzr r3124)
-rw-r--r--launcher/ApplicationLauncherIcon.cpp25
-rw-r--r--launcher/ApplicationLauncherIcon.h2
-rw-r--r--launcher/SwitcherController.cpp7
-rw-r--r--launcher/SwitcherModel.cpp46
-rw-r--r--launcher/SwitcherModel.h17
-rw-r--r--tests/mock-application.h51
-rw-r--r--tests/test_application_launcher_icon.cpp17
-rw-r--r--tests/test_switcher_model.cpp11
-rw-r--r--unity-shared/BamfApplicationManager.cpp1
9 files changed, 134 insertions, 43 deletions
diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp
index 80144a04f..f4ae396bd 100644
--- a/launcher/ApplicationLauncherIcon.cpp
+++ b/launcher/ApplicationLauncherIcon.cpp
@@ -173,6 +173,31 @@ ApplicationLauncherIcon::~ApplicationLauncherIcon()
}
}
+bool ApplicationLauncherIcon::GetQuirk(AbstractLauncherIcon::Quirk quirk) const
+{
+ if (quirk == Quirk::ACTIVE)
+ {
+ if (!SimpleLauncherIcon::GetQuirk(Quirk::ACTIVE))
+ return false;
+
+ if (app_->type() == "webapp")
+ return true;
+
+ // Sometimes BAMF is not fast enough to update the active application
+ // while quickly switching between apps, so we double check that the
+ // real active window is part of the selection (see bug #1111620)
+ Window active = WindowManager::Default().GetActiveWindow();
+
+ for (auto& window : app_->GetWindows())
+ if (window->window_id() == active)
+ return true;
+
+ return false;
+ }
+
+ return SimpleLauncherIcon::GetQuirk(quirk);
+}
+
void ApplicationLauncherIcon::Remove()
{
/* Removing the unity-seen flag to the wrapped bamf application, on remove
diff --git a/launcher/ApplicationLauncherIcon.h b/launcher/ApplicationLauncherIcon.h
index f46e126a6..0a03f3e84 100644
--- a/launcher/ApplicationLauncherIcon.h
+++ b/launcher/ApplicationLauncherIcon.h
@@ -51,6 +51,8 @@ public:
bool IsRunning() const;
bool IsUrgent() const;
+ virtual bool GetQuirk(Quirk quirk) const;
+
virtual void Quit();
virtual void AboutToRemove();
diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp
index 6cbe798a7..fc9cd6807 100644
--- a/launcher/SwitcherController.cpp
+++ b/launcher/SwitcherController.cpp
@@ -547,17 +547,16 @@ Selection Controller::Impl::GetCurrentSelection() const
if (model_)
{
application = model_->Selection();
+
if (application)
{
if (model_->detail_selection)
{
window = model_->DetailSelectionWindow();
}
- else if (application->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE))
+ else if (model_->SelectionIsActive())
{
- auto const& xids = model_->DetailXids();
- if (!xids.empty())
- window = xids.front();
+ window = model_->DetailXids().front();
}
}
}
diff --git a/launcher/SwitcherModel.cpp b/launcher/SwitcherModel.cpp
index 66c6ab9d3..afaec75fb 100644
--- a/launcher/SwitcherModel.cpp
+++ b/launcher/SwitcherModel.cpp
@@ -49,7 +49,7 @@ SwitcherModel::SwitcherModel(std::vector<AbstractLauncherIcon::Ptr> const& icons
SwitcherModel::~SwitcherModel()
{
- for (auto application : applications_)
+ for (auto const& application : applications_)
{
RemoveChild(application.GetPointer());
}
@@ -71,69 +71,64 @@ void SwitcherModel::AddProperties(GVariantBuilder* builder)
.add("last-selection-index", LastSelectionIndex());
}
-SwitcherModel::iterator
-SwitcherModel::begin()
+SwitcherModel::iterator SwitcherModel::begin()
{
return applications_.begin();
}
-SwitcherModel::iterator
-SwitcherModel::end()
+SwitcherModel::iterator SwitcherModel::end()
{
return applications_.end();
}
-SwitcherModel::reverse_iterator
-SwitcherModel::rbegin()
+SwitcherModel::reverse_iterator SwitcherModel::rbegin()
{
return applications_.rbegin();
}
-SwitcherModel::reverse_iterator
-SwitcherModel::rend()
+SwitcherModel::reverse_iterator SwitcherModel::rend()
{
return applications_.rend();
}
-AbstractLauncherIcon::Ptr
-SwitcherModel::at(unsigned int index)
+AbstractLauncherIcon::Ptr SwitcherModel::at(unsigned int index) const
{
if ((int) index >= Size ())
return AbstractLauncherIcon::Ptr();
return applications_[index];
}
-int
-SwitcherModel::Size()
+int SwitcherModel::Size() const
{
return applications_.size();
}
-AbstractLauncherIcon::Ptr
-SwitcherModel::Selection()
+AbstractLauncherIcon::Ptr SwitcherModel::Selection() const
{
return applications_.at(index_);
}
-int
-SwitcherModel::SelectionIndex()
+int SwitcherModel::SelectionIndex() const
{
return index_;
}
-AbstractLauncherIcon::Ptr
-SwitcherModel::LastSelection()
+bool SwitcherModel::SelectionIsActive() const
+{
+ return Selection()->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE);
+}
+
+AbstractLauncherIcon::Ptr SwitcherModel::LastSelection() const
{
return applications_.at(last_index_);
}
-int SwitcherModel::LastSelectionIndex()
+int SwitcherModel::LastSelectionIndex() const
{
return last_index_;
}
-
-std::vector<Window> SwitcherModel::DetailXids()
+std::vector<Window> SwitcherModel::DetailXids() const
{
WindowManager& wm = WindowManager::Default();
std::vector<Window> results;
@@ -159,7 +154,7 @@ std::vector<Window> SwitcherModel::DetailXids()
return results;
}
-Window SwitcherModel::DetailSelectionWindow()
+Window SwitcherModel::DetailSelectionWindow() const
{
auto windows = DetailXids();
if (!detail_selection || windows.empty())
@@ -209,7 +204,7 @@ void SwitcherModel::NextDetail()
detail_selection_index = 0;
}
-void SwitcherModel::PrevDetail ()
+void SwitcherModel::PrevDetail()
{
if (!detail_selection())
return;
@@ -242,8 +237,7 @@ void SwitcherModel::Select(AbstractLauncherIcon::Ptr const& selection)
}
}
-void
-SwitcherModel::Select(unsigned int index)
+void SwitcherModel::Select(unsigned int index)
{
unsigned int target = CLAMP(index, 0, applications_.size() - 1);
diff --git a/launcher/SwitcherModel.h b/launcher/SwitcherModel.h
index 86e644cd5..2b2368e03 100644
--- a/launcher/SwitcherModel.h
+++ b/launcher/SwitcherModel.h
@@ -70,18 +70,19 @@ public:
reverse_iterator rbegin();
reverse_iterator rend();
- launcher::AbstractLauncherIcon::Ptr at(unsigned int index);
+ launcher::AbstractLauncherIcon::Ptr at(unsigned int index) const;
- int Size();
+ int Size() const;
- launcher::AbstractLauncherIcon::Ptr Selection();
- int SelectionIndex();
+ launcher::AbstractLauncherIcon::Ptr Selection() const;
+ int SelectionIndex() const;
+ bool SelectionIsActive() const;
- launcher::AbstractLauncherIcon::Ptr LastSelection();
- int LastSelectionIndex();
+ launcher::AbstractLauncherIcon::Ptr LastSelection() const;
+ int LastSelectionIndex() const;
- std::vector<Window> DetailXids ();
- Window DetailSelectionWindow ();
+ std::vector<Window> DetailXids() const;
+ Window DetailSelectionWindow() const;
void Next();
void Prev();
diff --git a/tests/mock-application.h b/tests/mock-application.h
index cabc82ae1..aafa0a2d6 100644
--- a/tests/mock-application.h
+++ b/tests/mock-application.h
@@ -25,9 +25,45 @@
namespace testmocks
{
-class MockApplication : public unity::Application
+struct MockApplicationWindow : unity::ApplicationWindow
+{
+ MockApplicationWindow(Window xid)
+ : xid_(xid)
+ , monitor_(0)
+ , type_("window")
+ , visible_(true)
+ , active_(false)
+ , urgent_(false)
+ {
+ visible.SetGetterFunction([this] { return visible_; });
+ active.SetGetterFunction([this] { return active_; });
+ urgent.SetGetterFunction([this] { return urgent_; });
+ }
+
+ Window xid_;
+ int monitor_;
+ std::string title_;
+ std::string icon_;
+ std::string type_;
+
+ bool visible_;
+ bool active_;
+ bool urgent_;
+
+ virtual std::string title() const { return title_; }
+ virtual std::string icon() const { return icon_; }
+ virtual std::string type() const { return type_; }
+
+ virtual Window window_id() const { return xid_; }
+ virtual int monitor() const { return monitor_; }
+
+ virtual unity::ApplicationPtr application() const { return unity::ApplicationPtr(); }
+ virtual bool Focus() const { return false; }
+ virtual void Quit() const {}
+};
+
+struct MockApplication : unity::Application
{
-public:
MockApplication(std::string const& desktop_file,
std::string const& icon = "",
std::string const& title = "")
@@ -51,6 +87,7 @@ public:
urgent.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetUrgent));
}
+ unity::WindowList window_list_;
std::string desktop_file_;
std::string icon_;
std::string title_;
@@ -67,7 +104,7 @@ public:
virtual std::string type() const { return "mock"; }
virtual std::string repr() const { return "MockApplication"; }
- virtual unity::WindowList GetWindows() const { return unity::WindowList(); }
+ virtual unity::WindowList GetWindows() const { return window_list_; }
virtual bool OwnsWindow(Window window_id) const { return false; }
virtual std::vector<std::string> GetSupportedMimeTypes() const { return {}; }
@@ -98,6 +135,14 @@ public:
return false;
}
+ void SetActiveState(bool state)
+ {
+ if (active_ == state)
+ return;
+ active_ = state;
+ active.changed.emit(state);
+ }
+
bool GetVisible() const { return visible_; }
bool GetActive() const { return active_; }
bool GetRunning() const { return running_; }
diff --git a/tests/test_application_launcher_icon.cpp b/tests/test_application_launcher_icon.cpp
index f409473d9..5c5122b2d 100644
--- a/tests/test_application_launcher_icon.cpp
+++ b/tests/test_application_launcher_icon.cpp
@@ -28,7 +28,7 @@
#include "ApplicationLauncherIcon.h"
#include "FavoriteStore.h"
#include "mock-application.h"
-
+#include "StandaloneWindowManager.h"
using namespace unity;
using namespace testmocks;
@@ -45,6 +45,7 @@ class TestApplicationLauncherIcon : public testing::Test
public:
virtual void SetUp()
{
+ WM = dynamic_cast<StandaloneWindowManager*>(&WindowManager::Default());
usc_app.reset(new MockApplication(USC_DESKTOP, "softwarecenter"));
usc_icon = new launcher::ApplicationLauncherIcon(usc_app);
ASSERT_EQ(usc_icon->DesktopFile(), USC_DESKTOP);
@@ -58,6 +59,7 @@ public:
ASSERT_TRUE(mock_icon->DesktopFile().empty());
}
+ StandaloneWindowManager* WM;
std::shared_ptr<MockApplication> usc_app;
std::shared_ptr<MockApplication> empty_app;
std::shared_ptr<MockApplication> mock_app;
@@ -165,4 +167,17 @@ TEST_F(TestApplicationLauncherIcon, InvalidIconUpdatesOnRunning)
EXPECT_EQ(mock_icon->icon_name(), "icon-name");
}
+TEST_F(TestApplicationLauncherIcon, ActiveQuirkWMCrossCheck)
+{
+ auto win = std::make_shared<MockApplicationWindow>(g_random_int());
+ mock_app->window_list_ = { win };
+ ASSERT_FALSE(mock_icon->IsActive());
+
+ mock_app->SetActiveState(true);
+ ASSERT_FALSE(mock_icon->IsActive());
+
+ WM->AddStandaloneWindow(std::make_shared<StandaloneWindow>(win->window_id()));
+ EXPECT_TRUE(mock_icon->IsActive());
+}
+
}
diff --git a/tests/test_switcher_model.cpp b/tests/test_switcher_model.cpp
index b5e49adc6..9643a39ae 100644
--- a/tests/test_switcher_model.cpp
+++ b/tests/test_switcher_model.cpp
@@ -147,4 +147,15 @@ TEST_F(TestSwitcherModel, TestActiveDetailWindowSort)
EXPECT_EQ(sorted, unsorted);
}
+TEST_F(TestSwitcherModel, SelectionIsActive)
+{
+ SwitcherModel model(icons_);
+
+ model.Selection()->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, false);
+ EXPECT_FALSE(model.SelectionIsActive());
+
+ model.Selection()->SetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, true);
+ EXPECT_TRUE(model.SelectionIsActive());
+}
+
}
diff --git a/unity-shared/BamfApplicationManager.cpp b/unity-shared/BamfApplicationManager.cpp
index 8192265a8..ed8a0d881 100644
--- a/unity-shared/BamfApplicationManager.cpp
+++ b/unity-shared/BamfApplicationManager.cpp
@@ -68,7 +68,6 @@ bool View::GetVisible() const
bool View::GetActive() const
{
return bamf_view_is_active(bamf_view_);
-
}
bool View::GetRunning() const