diff options
| author | Marco Trevisan (TreviƱo) <mail@3v1n0.net> | 2013-02-05 03:42:21 +0000 |
|---|---|---|
| committer | Tarmac <> | 2013-02-05 03:42:21 +0000 |
| commit | ea2828e34f0b7c7bfebf78461a473dc59723afa2 (patch) | |
| tree | 164f24ecd924b905c2ab1ba4548723f6ec4804c0 | |
| parent | 3b28ba08632b0c60d905ac6db71f7755b2573ffd (diff) | |
| parent | 1774e6f71c05f5576ef7e1baf62145c4a9fdcacd (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.cpp | 25 | ||||
| -rw-r--r-- | launcher/ApplicationLauncherIcon.h | 2 | ||||
| -rw-r--r-- | launcher/SwitcherController.cpp | 7 | ||||
| -rw-r--r-- | launcher/SwitcherModel.cpp | 46 | ||||
| -rw-r--r-- | launcher/SwitcherModel.h | 17 | ||||
| -rw-r--r-- | tests/mock-application.h | 51 | ||||
| -rw-r--r-- | tests/test_application_launcher_icon.cpp | 17 | ||||
| -rw-r--r-- | tests/test_switcher_model.cpp | 11 | ||||
| -rw-r--r-- | unity-shared/BamfApplicationManager.cpp | 1 |
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 |
