summaryrefslogtreecommitdiff
path: root/unity-shared
diff options
authorMarco Trevisan (Treviño) <mail@3v1n0.net>2015-02-05 15:35:07 +0100
committerMarco Trevisan (Treviño) <mail@3v1n0.net>2015-02-05 15:35:07 +0100
commitf790851b16a144ba7b1fb9a72ff49cdf68180639 (patch)
treeef5cbf2d638a43a967ddb0a8428e53e385b83154 /unity-shared
parentd954af67aa119b1873032047fa54212bd498adc0 (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.cpp19
-rw-r--r--unity-shared/ApplicationManager.h68
-rw-r--r--unity-shared/BamfApplicationManager.cpp324
-rw-r--r--unity-shared/BamfApplicationManager.h50
-rw-r--r--unity-shared/StandaloneAppManager.cpp110
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;
+ });
+ }
}