diff options
| author | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2015-02-05 15:35:07 +0100 |
|---|---|---|
| committer | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2015-02-05 15:35:07 +0100 |
| commit | f790851b16a144ba7b1fb9a72ff49cdf68180639 (patch) | |
| tree | ef5cbf2d638a43a967ddb0a8428e53e385b83154 /unity-shared | |
| parent | d954af67aa119b1873032047fa54212bd498adc0 (diff) | |
ApplicationManager: add missing features, keep a copy of views around
This might be still improved when BAMF crashes/reloads, so that we can rebuild the table (bzr r3899.4.1)
Diffstat (limited to 'unity-shared')
| -rw-r--r-- | unity-shared/ApplicationManager.cpp | 19 | ||||
| -rw-r--r-- | unity-shared/ApplicationManager.h | 68 | ||||
| -rw-r--r-- | unity-shared/BamfApplicationManager.cpp | 324 | ||||
| -rw-r--r-- | unity-shared/BamfApplicationManager.h | 50 | ||||
| -rw-r--r-- | unity-shared/StandaloneAppManager.cpp | 110 |
5 files changed, 385 insertions, 186 deletions
diff --git a/unity-shared/ApplicationManager.cpp b/unity-shared/ApplicationManager.cpp index b510901f0..8b4e0222e 100644 --- a/unity-shared/ApplicationManager.cpp +++ b/unity-shared/ApplicationManager.cpp @@ -33,6 +33,25 @@ ApplicationManager& ApplicationManager::Default() return *instance; } +bool operator==(ApplicationPtr const& lhs, ApplicationPtr const& rhs) +{ + return (lhs.get() == rhs.get() || (lhs && rhs && *lhs == *rhs)); +} + +bool operator!=(ApplicationPtr const& lhs, ApplicationPtr const& rhs) +{ + return !(lhs == rhs); +} + +bool operator==(ApplicationWindowPtr const& lhs, ApplicationWindowPtr const& rhs) +{ + return (lhs.get() == rhs.get() || (lhs && rhs && *lhs == *rhs)); +} + +bool operator!=(ApplicationWindowPtr const& lhs, ApplicationWindowPtr const& rhs) +{ + return !(lhs == rhs); +} // This method is needed to create an unresolved external for the // WindowManager::Default method. This is because it is highly likely that diff --git a/unity-shared/ApplicationManager.h b/unity-shared/ApplicationManager.h index c35ace48b..52bf0be6e 100644 --- a/unity-shared/ApplicationManager.h +++ b/unity-shared/ApplicationManager.h @@ -50,13 +50,33 @@ enum class ApplicationEventType LEAVE }; +enum class AppType +{ + NORMAL, + WEBAPP, + UNKNOWN +}; + +enum class WindowType +{ + NORMAL, + DESKTOP, + DOCK, + DIALOG, + TOOLBAR, + MENU, + UTILITY, + SPLASHSCREEN, + UNKNOWN, + TAB +}; + class ApplicationWindow { public: virtual ~ApplicationWindow() = default; - virtual std::string type() const = 0; // 'window' or 'tab' - + virtual WindowType type() const = 0; virtual Window window_id() const = 0; virtual int monitor() const = 0; @@ -69,20 +89,32 @@ public: // Closes the window, or the browser tab if a webapp. virtual void Quit() const = 0; + virtual bool operator==(ApplicationWindow const& other) const + { + return (window_id() == other.window_id()); + } + + virtual bool operator!=(ApplicationWindow const& other) const + { + return !(operator==(other)); + } + nux::ROProperty<std::string> title; nux::ROProperty<std::string> icon; nux::ROProperty<bool> visible; nux::ROProperty<bool> active; nux::ROProperty<bool> urgent; + nux::ROProperty<bool> maximized; }; + class Application { public: virtual ~Application() = default; - virtual std::string type() const = 0; + virtual AppType type() const = 0; // A string representation of the object. virtual std::string repr() const = 0; @@ -102,6 +134,17 @@ public: virtual void LogEvent(ApplicationEventType, ApplicationSubjectPtr const&) const = 0; virtual std::string desktop_id() const = 0; + + virtual bool operator==(Application const& other) const + { + return (!desktop_id().empty() && (desktop_id() == other.desktop_id())); + } + + virtual bool operator!=(Application const& other) const + { + return !(operator==(other)); + } + nux::ROProperty<std::string> desktop_file; nux::ROProperty<std::string> title; nux::ROProperty<std::string> icon; @@ -117,11 +160,12 @@ public: sigc::signal<void> closed; - sigc::signal<void, ApplicationWindow const&> window_opened; - sigc::signal<void, ApplicationWindow const&> window_moved; - sigc::signal<void> window_closed; + sigc::signal<void, ApplicationWindowPtr const&> window_opened; + sigc::signal<void, ApplicationWindowPtr const&> window_moved; + sigc::signal<void, ApplicationWindowPtr const&> window_closed; }; + class ApplicationSubject { public: @@ -165,16 +209,28 @@ public: static ApplicationManager& Default(); virtual ApplicationPtr GetUnityApplication() const = 0; + virtual ApplicationPtr GetActiveApplication() const = 0; virtual ApplicationWindowPtr GetActiveWindow() const = 0; virtual ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file) const = 0; virtual ApplicationList GetRunningApplications() const = 0; + virtual WindowList GetWindowsForMonitor(int monitor = -1) const = 0; virtual ApplicationPtr GetApplicationForWindow(Window xid) const = 0; + virtual ApplicationWindowPtr GetWindowForId(Window xid) const = 0; sigc::signal<void, ApplicationPtr const&> application_started; + sigc::signal<void, ApplicationPtr const&> application_stopped; sigc::signal<void, ApplicationPtr const&> active_application_changed; + sigc::signal<void, ApplicationWindowPtr const&> window_opened; + sigc::signal<void, ApplicationWindowPtr const&> window_closed; sigc::signal<void, ApplicationWindowPtr const&> active_window_changed; }; + +bool operator==(ApplicationPtr const&, ApplicationPtr const&); +bool operator!=(ApplicationPtr const&, ApplicationPtr const&); +bool operator==(ApplicationWindowPtr const&, ApplicationWindowPtr const&); +bool operator!=(ApplicationWindowPtr const&, ApplicationWindowPtr const&); + } #endif // UNITYSHARED_APPLICATION_MANAGER_H diff --git a/unity-shared/BamfApplicationManager.cpp b/unity-shared/BamfApplicationManager.cpp index 7e8cf11d9..3db880532 100644 --- a/unity-shared/BamfApplicationManager.cpp +++ b/unity-shared/BamfApplicationManager.cpp @@ -34,8 +34,48 @@ namespace bamf namespace { const char* UNSEEN_QUARK = "unity-unseen"; + +namespace pool +{ +// We keep a cache on views here, it would be nice to clean these on BAMF reload +std::unordered_map<BamfView*, ApplicationPtr> apps_; +std::unordered_map<BamfView*, ApplicationWindowPtr> wins_; + +ApplicationPtr EnsureApplication(ApplicationManager const& manager, BamfView* view) +{ + if (!BAMF_IS_APPLICATION(view)) + return nullptr; + + auto it = apps_.find(view); + + if (it != apps_.end()) + return it->second; + + glib::Object<BamfApplication> bamfapp(reinterpret_cast<BamfApplication*>(view), glib::AddRef()); + auto const& app = std::make_shared<Application>(manager, bamfapp); + apps_.insert({view, app}); + return app; +} + +ApplicationWindowPtr EnsureWindow(ApplicationManager const& manager, BamfView* view) +{ + if (!BAMF_IS_WINDOW(view)) + return nullptr; + + auto it = wins_.find(view); + + if (it != wins_.end()) + return it->second; + + glib::Object<BamfWindow> bamfwin(reinterpret_cast<BamfWindow*>(view), glib::AddRef()); + auto const& win = std::make_shared<AppWindow>(manager, bamfwin); + wins_.insert({view, win}); + return win; } +} // pool namespace +} // anonymous namespace + // Due to the way glib handles object inheritance, we need to cast between pointer types. // In order to make the up-call for the base class easy, we pass through a void* for the view. @@ -54,11 +94,6 @@ std::string View::GetIcon() const return glib::String(bamf_view_get_icon(bamf_view_)).Str(); } -std::string View::type() const -{ - return glib::gchar_to_string(bamf_view_get_view_type(bamf_view_)); -} - bool View::GetVisible() const { return bamf_view_is_user_visible(bamf_view_); @@ -80,11 +115,6 @@ bool View::GetUrgent() const } -std::string WindowBase::type() const -{ - return View::type(); -} - WindowBase::WindowBase(ApplicationManager const& manager, glib::Object<BamfView> const& window) : View(manager, window) @@ -122,13 +152,10 @@ bool WindowBase::Focus() const Window xid = window_id(); if (xid) { - std::vector<Window> windows = { xid }; - // TODO: we should simplify the use case of focusing one window. - // Somewhat outside the scope of these changes however. - WindowManager::Default().FocusWindowGroup( - windows, - WindowManager::FocusVisibility::ForceUnminimizeInvisible, - monitor(),true); + auto& wm = WindowManager::Default(); + wm.UnMinimize(xid); + wm.Raise(xid); + wm.Activate(xid); return true; } return false; @@ -136,14 +163,25 @@ bool WindowBase::Focus() const AppWindow::AppWindow(ApplicationManager const& manager, glib::Object<BamfWindow> const& window) - : WindowBase(manager, glib::object_cast<BamfView>(window)) - , bamf_window_(window) + : AppWindow(manager, glib::object_cast<BamfView>(window)) {} AppWindow::AppWindow(ApplicationManager const& manager, glib::Object<BamfView> const& window) : WindowBase(manager, window) , bamf_window_(glib::object_cast<BamfWindow>(window)) -{} +{ + maximized.SetGetterFunction(std::bind(&AppWindow::GetMaximized, this)); + signals_.Add<void, BamfWindow*, gint, gint>(bamf_window_, "maximized-changed", + [this] (BamfWindow*, gint old_state, gint state) { + if ((old_state == BAMF_WINDOW_MAXIMIZED) != (state == BAMF_WINDOW_MAXIMIZED)) + this->maximized.changed.emit(state == BAMF_WINDOW_MAXIMIZED); + }); +} + +bool AppWindow::GetMaximized() const +{ + return bamf_window_maximized(bamf_window_) == BAMF_WINDOW_MAXIMIZED; +} Window AppWindow::window_id() const { @@ -155,6 +193,11 @@ int AppWindow::monitor() const return bamf_window_get_monitor(bamf_window_); } +WindowType AppWindow::type() const +{ + return WindowType(bamf_window_get_window_type(bamf_window_)); +} + ApplicationPtr AppWindow::application() const { // Moderately evil, but better than changing the method to non-const. @@ -183,6 +226,11 @@ Window Tab::window_id() const return bamf_tab_get_xid(bamf_tab_); } +WindowType Tab::type() const +{ + return WindowType::TAB; +} + int Tab::monitor() const { // TODO, we could find the real window for the window_id, and get the monitor for that. @@ -208,37 +256,14 @@ void Tab::Quit() const bamf_tab_close(bamf_tab_); } -// Being brutal with this function. -ApplicationWindowPtr create_window(ApplicationManager const& manager, glib::Object<BamfView> const& view) -{ - if (view.IsType(BAMF_TYPE_WINDOW)) - { - return std::make_shared<AppWindow>(manager, view); - } - else if (view.IsType(BAMF_TYPE_TAB)) - { - return std::make_shared<Tab>(manager, view); - } - // We don't handle applications here. - return nullptr; -} - Application::Application(ApplicationManager const& manager, glib::Object<BamfView> const& app) - : View(manager, app) - , bamf_app_(glib::object_cast<BamfApplication>(app)) -{ - HookUpEvents(); -} + : Application(manager, glib::object_cast<BamfApplication>(app)) +{} Application::Application(ApplicationManager const& manager, glib::Object<BamfApplication> const& app) : View(manager, glib::object_cast<BamfView>(app)) , bamf_app_(app) { - HookUpEvents(); -} - -void Application::HookUpEvents() -{ // Hook up the property set/get functions using namespace std::placeholders; desktop_file.SetGetterFunction(std::bind(&Application::GetDesktopFile, this)); @@ -292,24 +317,21 @@ void Application::HookUpEvents() signals_.Add<void, BamfView*, BamfView*>(bamf_view_, "child-added", [this] (BamfView*, BamfView* child) { // Ownership is not passed on signals - glib::Object<BamfView> view(child, glib::AddRef()); - ApplicationWindowPtr const& win = create_window(this->manager_, view); - if (win) - this->window_opened.emit(*win); + if (ApplicationWindowPtr const& win = pool::EnsureWindow(manager_, child)) + this->window_opened.emit(win); }); signals_.Add<void, BamfView*, BamfView*>(bamf_view_, "child-removed", [this] (BamfView*, BamfView* child) { - this->window_closed.emit(); + if (ApplicationWindowPtr const& win = pool::EnsureWindow(manager_, child)) + this->window_closed.emit(win); }); signals_.Add<void, BamfView*, BamfView*>(bamf_view_, "child-moved", [this] (BamfView*, BamfView* child) { // Ownership is not passed on signals - glib::Object<BamfView> view(child, glib::AddRef()); - ApplicationWindowPtr const& win = create_window(this->manager_, view); - if (win) - this->window_moved.emit(*win); + if (ApplicationWindowPtr const& win = pool::EnsureWindow(manager_, child)) + this->window_moved.emit(win); }); } @@ -318,16 +340,21 @@ std::string Application::GetDesktopFile() const return glib::gchar_to_string(bamf_application_get_desktop_file(bamf_app_)); } -std::string Application::type() const +AppType Application::type() const { // Can't determine the type of a non-running app. - std::string result = "unknown"; if (running()) { - const gchar* type = bamf_application_get_application_type(bamf_app_); - if (type) result = type; + auto type = glib::gchar_to_string(bamf_application_get_application_type(bamf_app_)); + + if (type == "system") + return AppType::NORMAL; + + if (type == "webapp") + return AppType::WEBAPP; } - return result; + + return AppType::UNKNOWN; } std::string Application::repr() const @@ -347,9 +374,7 @@ WindowList Application::GetWindows() const std::shared_ptr<GList> children(bamf_view_get_children(bamf_view_), g_list_free); for (GList* l = children.get(); l; l = l->next) { - glib::Object<BamfView> view(BAMF_VIEW(l->data), glib::AddRef()); - ApplicationWindowPtr const& window(create_window(manager_, view)); - if (window) + if (ApplicationWindowPtr const& window = pool::EnsureWindow(manager_, static_cast<BamfView*>(l->data))) result.push_back(window); } return result; @@ -389,9 +414,7 @@ std::vector<std::string> Application::GetSupportedMimeTypes() const ApplicationWindowPtr Application::GetFocusableWindow() const { - glib::Object<BamfView> view(bamf_application_get_focusable_child(bamf_app_), - glib::AddRef()); - return create_window(manager_, view); + return pool::EnsureWindow(manager_, bamf_application_get_focusable_child(bamf_app_)); } void Application::Focus(bool show_only_visible, int monitor) const @@ -507,29 +530,18 @@ Manager::Manager() LOG_TRACE(logger) << "Create BAMF Application Manager"; signals_.Add<void, BamfMatcher*, BamfView*> (matcher_, "view-opened", sigc::mem_fun(this, &Manager::OnViewOpened)); + signals_.Add<void, BamfMatcher*, BamfView*> (matcher_, "view-closed", + sigc::mem_fun(this, &Manager::OnViewClosed)); signals_.Add<void, BamfMatcher*, BamfView*, BamfView*>(matcher_, "active-window-changed", [this](BamfMatcher*, BamfView* /* from */, BamfView* to) { - // Ownership is not passed on signals - glib::Object<BamfView> view(to, glib::AddRef()); - ApplicationWindowPtr const& win = create_window(*this, view); - if (win) + if (ApplicationWindowPtr const& win = pool::EnsureWindow(*this, to)) this->active_window_changed.emit(win); }); signals_.Add<void, BamfMatcher*, BamfApplication*, BamfApplication*> (matcher_, "active-application-changed", [this](BamfMatcher*, BamfApplication* /* from */, BamfApplication* to) { - if (to) - { - // Ownership is not passed on signals - glib::Object<BamfApplication> bamf_app(to, glib::AddRef()); - auto app = std::make_shared<Application>(*this, bamf_app); - this->active_application_changed.emit(app); - } - else - { - this->active_application_changed.emit(nullptr); - } + this->active_application_changed.emit(pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(to))); }); } @@ -546,81 +558,79 @@ ApplicationPtr Manager::GetUnityApplication() const { auto *app_ptr = bamf_matcher_get_application_for_xid(matcher_, xid); - if (BAMF_IS_APPLICATION(app_ptr)) - { - glib::Object<BamfApplication> app(app_ptr, glib::AddRef()); - return std::make_shared<Application>(*this, app); - } + if (ApplicationPtr const& app = pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(app_ptr))) + return app; } return GetApplicationForDesktopFile(DesktopUtilities::GetDesktopPathById("compiz.desktop")); } -ApplicationWindowPtr Manager::GetActiveWindow() const +ApplicationPtr Manager::GetActiveApplication() const { - // No transfer of ownership for bamf_matcher_get_active_window. - BamfWindow* active_win = bamf_matcher_get_active_window(matcher_); + auto *app_ptr = bamf_matcher_get_active_application(matcher_); + return pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(app_ptr)); +} - if (!active_win) - return nullptr; +ApplicationWindowPtr Manager::GetActiveWindow() const +{ + if (BamfWindow* active_win = bamf_matcher_get_active_window(matcher_)) + { + if (bamf_window_get_window_type(active_win) != BAMF_WINDOW_DOCK) + return pool::EnsureWindow(*this, reinterpret_cast<BamfView*>(active_win)); + } // If the active window is a dock type, then we want the first visible, non-dock type. - if (bamf_window_get_window_type(active_win) == BAMF_WINDOW_DOCK) - { - LOG_DEBUG(logger) << "Is a dock, looking at the window stack."; + LOG_DEBUG(logger) << "Is a dock, looking at the window stack."; - std::shared_ptr<GList> windows(bamf_matcher_get_window_stack_for_monitor(matcher_, -1), g_list_free); - WindowManager& wm = WindowManager::Default(); - active_win = nullptr; + auto const& wins = GetWindowsForMonitor(); + WindowManager& wm = WindowManager::Default(); + + for (auto it = wins.rbegin(); it != wins.rend(); ++it) + { + auto const& win = *it; + auto xid = win->window_id(); - for (GList *l = windows.get(); l; l = l->next) + if (win->visible() && + win->type() != WindowType::DOCK && + wm.IsWindowOnCurrentDesktop(xid) && + wm.IsWindowVisible(xid)) { - if (!BAMF_IS_WINDOW(l->data)) - { - LOG_DEBUG(logger) << "Window stack returned something not a window, WTF?"; - continue; - } - - auto win = static_cast<BamfWindow*>(l->data); - auto view = static_cast<BamfView*>(l->data); - auto xid = bamf_window_get_xid(win); - - if (bamf_view_is_user_visible(view) && - bamf_window_get_window_type(win) != BAMF_WINDOW_DOCK && - wm.IsWindowOnCurrentDesktop(xid) && - wm.IsWindowVisible(xid)) - { - active_win = win; - } + return win; } } - if (active_win) - { - glib::Object<BamfWindow> win(active_win, glib::AddRef()); - return std::make_shared<AppWindow>(*this, win); - } - return nullptr; } ApplicationPtr Manager::GetApplicationForDesktopFile(std::string const& desktop_file) const { - glib::Object<BamfApplication> app(bamf_matcher_get_application_for_desktop_file( - matcher_, desktop_file.c_str(), TRUE), glib::AddRef()); - - if (app) - return std::make_shared<Application>(*this, app); - - return nullptr; + auto* app = bamf_matcher_get_application_for_desktop_file(matcher_, desktop_file.c_str(), TRUE); + return pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(app)); } ApplicationPtr Manager::GetApplicationForWindow(Window xid) const { - glib::Object<BamfApplication> app(bamf_matcher_get_application_for_xid(matcher_, xid), - glib::AddRef()); - if (app) - return std::make_shared<Application>(*this, app); + auto* app = bamf_matcher_get_application_for_xid(matcher_, xid); + return pool::EnsureApplication(*this, reinterpret_cast<BamfView*>(app)); +} + +ApplicationWindowPtr Manager::GetWindowForId(Window xid) const +{ + if (xid == 0) + return nullptr; + + std::shared_ptr<GList> windows(bamf_matcher_get_windows(matcher_), g_list_free); + + for (GList* l = windows.get(); l; l = l->next) + { + if (!BAMF_IS_WINDOW(l->data)) + continue; + + auto win = static_cast<BamfWindow*>(l->data); + + if (bamf_window_get_xid(win) == xid) + return pool::EnsureWindow(*this, static_cast<BamfView*>(l->data)); + } return nullptr; } @@ -638,26 +648,60 @@ ApplicationList Manager::GetRunningApplications() const continue; } - glib::Object<BamfApplication> bamf_app(static_cast<BamfApplication*>(l->data), glib::AddRef()); - auto app = std::make_shared<Application>(*this, bamf_app); - result.push_back(app); - LOG_DEBUG(logger) << "Running app: " << app->title(); + result.push_back(pool::EnsureApplication(*this, static_cast<BamfView*>(l->data))); } return result; } +WindowList Manager::GetWindowsForMonitor(int monitor) const +{ + WindowList wins; + std::shared_ptr<GList> windows(bamf_matcher_get_window_stack_for_monitor(matcher_, monitor), g_list_free); + + for (GList *l = windows.get(); l; l = l->next) + { + if (!BAMF_IS_WINDOW(l->data)) + { + LOG_DEBUG(logger) << "Window stack returned something not a window, WTF?"; + continue; + } + + auto bamf_win = static_cast<BamfWindow*>(l->data); + + if (bamf_window_get_window_type(bamf_win) != BAMF_WINDOW_DOCK) + wins.push_back(pool::EnsureWindow(*this, static_cast<BamfView*>(l->data))); + } + + return wins; +} void Manager::OnViewOpened(BamfMatcher* matcher, BamfView* view) { LOG_TRACE_BLOCK(logger); - if (!BAMF_IS_APPLICATION(view)) + if (BAMF_IS_APPLICATION(view)) { - LOG_DEBUG(logger) << "view is not an app"; - return; + application_started.emit(pool::EnsureApplication(*this, view)); } + else if (BAMF_IS_WINDOW(view)) + { + window_opened.emit(pool::EnsureWindow(*this, view)); + } +} - glib::Object<BamfView> app(view, glib::AddRef()); - application_started.emit(std::make_shared<Application>(*this, app)); +void Manager::OnViewClosed(BamfMatcher* matcher, BamfView* view) +{ + LOG_TRACE_BLOCK(logger); + if (BAMF_IS_APPLICATION(view)) + { + auto app = pool::EnsureApplication(*this, view); + application_stopped.emit(app); + pool::apps_.erase(view); + } + else if (BAMF_IS_WINDOW(view)) + { + window_closed.emit(pool::EnsureWindow(*this, view)); + pool::wins_.erase(view); + } } } // namespace bamf diff --git a/unity-shared/BamfApplicationManager.h b/unity-shared/BamfApplicationManager.h index f016d3bc2..6dacac12e 100644 --- a/unity-shared/BamfApplicationManager.h +++ b/unity-shared/BamfApplicationManager.h @@ -20,6 +20,7 @@ #ifndef UNITYSHARED_BAMF_APPLICATION_MANAGER_H #define UNITYSHARED_BAMF_APPLICATION_MANAGER_H +#include <unordered_map> #include <libbamf/libbamf.h> #include <UnityCore/GLibWrapper.h> #include <UnityCore/GLibSignal.h> @@ -39,7 +40,6 @@ public: std::string GetTitle() const; std::string GetIcon() const; - std::string type() const; bool GetVisible() const; bool GetActive() const; @@ -59,11 +59,15 @@ protected: glib::Object<BamfView> const& window); public: - virtual std::string type() const; // 'window' or 'tab' + bool Focus() const override; - virtual bool Focus() const; + bool operator==(unity::ApplicationWindow const& other) const override + { + return static_cast<WindowBase const*>(this)->bamf_view_ == static_cast<WindowBase const&>(other).bamf_view_; + } + bool operator!=(unity::ApplicationWindow const& other) const override { return !(operator==(other)); } -private: +protected: glib::SignalManager signals_; }; @@ -76,10 +80,12 @@ public: AppWindow(ApplicationManager const& manager, glib::Object<BamfView> const& window); - virtual Window window_id() const; - virtual int monitor() const; - virtual ApplicationPtr application() const; - virtual void Quit() const; + WindowType type() const override; + Window window_id() const override; + int monitor() const override; + ApplicationPtr application() const override; + void Quit() const override; + bool GetMaximized() const; private: glib::Object<BamfWindow> bamf_window_; @@ -93,11 +99,12 @@ public: Tab(ApplicationManager const& manager, glib::Object<BamfView> const& tab); - virtual Window window_id() const; - virtual int monitor() const; - virtual ApplicationPtr application() const; - virtual bool Focus() const; - virtual void Quit() const; + WindowType type() const override; + Window window_id() const override; + int monitor() const override; + ApplicationPtr application() const override; + bool Focus() const override; + void Quit() const override; private: glib::Object<BamfTab> bamf_tab_; @@ -112,7 +119,7 @@ public: Application(ApplicationManager const& manager, glib::Object<BamfView> const& app); - virtual std::string type() const; + virtual AppType type() const; virtual WindowList GetWindows() const; virtual bool OwnsWindow(Window window_id) const; @@ -128,9 +135,13 @@ public: virtual std::string repr() const; -private: // Property getters and setters - void HookUpEvents(); + bool operator==(unity::Application const& other) const override + { + return static_cast<Application const*>(this)->bamf_app_ == static_cast<Application const&>(other).bamf_app_; + } + bool operator!=(unity::Application const& other) const override { return !(operator==(other)); } +private: // Property getters and setters std::string GetDesktopFile() const; bool GetSeen() const; @@ -152,13 +163,20 @@ public: ~Manager(); ApplicationPtr GetUnityApplication() const override; + ApplicationPtr GetActiveApplication() const override; ApplicationWindowPtr GetActiveWindow() const override; ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file) const override; ApplicationList GetRunningApplications() const override; + WindowList GetWindowsForMonitor(int monitor = -1) const override; ApplicationPtr GetApplicationForWindow(Window xid) const override; + ApplicationWindowPtr GetWindowForId(Window xid) const override; + + ApplicationPtr EnsureApplication(BamfView*) const; + ApplicationWindowPtr EnsureWindow(BamfView*) const; private: void OnViewOpened(BamfMatcher* matcher, BamfView* view); + void OnViewClosed(BamfMatcher* matcher, BamfView* view); private: glib::Object<BamfMatcher> matcher_; diff --git a/unity-shared/StandaloneAppManager.cpp b/unity-shared/StandaloneAppManager.cpp index 9bb830e8c..558eff046 100644 --- a/unity-shared/StandaloneAppManager.cpp +++ b/unity-shared/StandaloneAppManager.cpp @@ -33,6 +33,50 @@ using namespace unity; GMainLoop *loop; +std::ostream& operator<<(std::ostream &os, AppType at) +{ + switch (at) + { + case AppType::NORMAL: + return os << "NORMAL"; + case AppType::WEBAPP: + return os << "WEBAPP"; + case AppType::UNKNOWN: + return os << "UNKNOWN"; + } + + return os; +} + +std::ostream& operator<<(std::ostream &os, WindowType wt) +{ + switch (wt) + { + case WindowType::NORMAL: + return os << "NORMAL"; + case WindowType::DESKTOP: + return os << "DESKTOP"; + case WindowType::DOCK: + return os << "DOCK"; + case WindowType::DIALOG: + return os << "DIALOG"; + case WindowType::TOOLBAR: + return os << "TOOLBAR"; + case WindowType::MENU: + return os << "MENU"; + case WindowType::UTILITY: + return os << "UTILITY"; + case WindowType::SPLASHSCREEN: + return os << "SPLASHSCREEN"; + case WindowType::UNKNOWN: + return os << "UNKNOWN"; + case WindowType::TAB: + return os << "TAB"; + } + + return os; +} + void dump_app(ApplicationPtr const& app, std::string const& prefix = "") { if (app) @@ -55,6 +99,7 @@ void dump_app(ApplicationPtr const& app, std::string const& prefix = "") std::cout << " Window: " << win->title() << ", window_id: " << win->window_id() << ", monitor: " << win->monitor() + << ", maximized: " << win->maximized() << ", type: " << win->type() << endl; } @@ -65,6 +110,8 @@ void dump_app(ApplicationPtr const& app, std::string const& prefix = "") } } +std::vector<std::string> names; + void connect_events(ApplicationPtr const& app) { if (app->seen()) @@ -72,42 +119,57 @@ void connect_events(ApplicationPtr const& app) cout << "Already seen " << app->title() << ", skipping event connection.\n"; return; } - std::string app_name = app->title(); - app->title.changed.connect([&app_name](std::string const& value) { - cout << app_name << " changed name to: " << value << endl; - app_name = value; + + auto idx = names.empty() ? 0 : names.size()-1; + names.push_back(app->title()); + app->title.changed.connect([idx](std::string const& value) { + cout << names[idx] << " changed name to: " << value << endl; + names[idx] = value; }); - app->icon.changed.connect([&app_name](std::string const& value) { - cout << app_name << " icon changed: " << value << endl; + app->icon.changed.connect([idx](std::string const& value) { + cout << names[idx] << " icon changed: " << value << endl; }); - app->desktop_file.changed.connect([&app_name](std::string const& value) { - cout << app_name << " desktop file changed: " << value << endl; + app->desktop_file.changed.connect([idx](std::string const& value) { + cout << names[idx] << " desktop file changed: " << value << endl; }); - app->visible.changed.connect([&app_name](bool value) { - cout << app_name << " visibility changed: " << (value ? "yes" : "no") << endl; + app->visible.changed.connect([idx](bool value) { + cout << names[idx] << " visibility changed: " << (value ? "yes" : "no") << endl; }); - app->running.changed.connect([&app_name](bool value) { - cout << app_name << " running changed: " << (value ? "yes" : "no") << endl; + app->running.changed.connect([idx](bool value) { + cout << names[idx] << " running changed: " << (value ? "yes" : "no") << endl; }); - app->active.changed.connect([&app_name](bool value) { - cout << app_name << " active changed: " << (value ? "yes" : "no") << endl; + app->active.changed.connect([idx](bool value) { + cout << names[idx] << " active changed: " << (value ? "yes" : "no") << endl; }); - app->urgent.changed.connect([&app_name](bool value) { - cout << app_name << " urgent changed: " << (value ? "yes" : "no") << endl; + app->urgent.changed.connect([idx](bool value) { + cout << names[idx] << " urgent changed: " << (value ? "yes" : "no") << endl; }); - app->closed.connect([&app_name]() { - cout << app_name << " closed." << endl; + app->closed.connect([idx]() { + cout << names[idx] << " closed." << endl; }); - app->window_opened.connect([&app_name](ApplicationWindow const& window) { - cout << "** " << app_name << " window opened: " << window.title() << endl; + app->window_opened.connect([idx](ApplicationWindowPtr const& window) { + cout << "** " << names[idx] << " window opened: " << window->title() << endl; }); - app->window_closed.connect([&app_name]() { - cout << "** " << app_name << " window closed" << endl; + app->window_closed.connect([idx](ApplicationWindowPtr const& window) { + cout << "** " << names[idx] << " window closed: " << window->title() << endl; }); - app->window_moved.connect([&app_name](ApplicationWindow const& window) { - cout << "** " << app_name << " window moved: " << window.title() << endl; + app->window_moved.connect([idx](ApplicationWindowPtr const& window) { + cout << "** " << names[idx] << " window moved: " << window->title() << endl; }); app->seen = true; + + for (auto win : app->GetWindows()) + { + win->title.changed.connect([win] (std::string const& t) { + std::cout << "Window "<< win->window_id()<< " title changed to "<< t << endl; + }); + win->maximized.changed.connect([win] (bool m) { + std::cout << "Window "<< win->window_id()<< " maximized changed to "<< m << endl; + }); + win->active.changed.connect([win] (bool a) { + std::cout << "Window "<< win->window_id()<< " active changed to "<< a << endl; + }); + } } |
