summaryrefslogtreecommitdiff
diff options
-rw-r--r--tests/mock-application.h108
-rw-r--r--unity-shared/ApplicationManager.cpp35
-rw-r--r--unity-shared/ApplicationManager.h142
-rw-r--r--unity-shared/BamfApplicationManager.cpp681
-rw-r--r--unity-shared/BamfApplicationManager.h177
-rw-r--r--unity-shared/CMakeLists.txt5
-rw-r--r--unity-shared/StandaloneAppManager.cpp245
-rw-r--r--unity-shared/StandaloneWindowManager.cpp6
8 files changed, 1396 insertions, 3 deletions
diff --git a/tests/mock-application.h b/tests/mock-application.h
new file mode 100644
index 000000000..fb9d09279
--- /dev/null
+++ b/tests/mock-application.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with this program. If not, see
+ * <http://www.gnu.org/licenses/>
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+#ifndef TESTS_MOCK_APPLICATION_H
+#define TESTS_MOCK_APPLICATION_H
+
+#include "unity-shared/ApplicationManager.h"
+
+namespace testmocks
+{
+class MockApplication : public unity::Application
+{
+public:
+ MockApplication(std::string const& desktop_file,
+ std::string const& icon = "",
+ std::string const& title = "")
+ : desktop_file_(desktop_file)
+ , icon_(icon)
+ , title_(title)
+ , seen_(false)
+ , sticky_(false)
+ , visible_(false)
+ , active_(false)
+ , running_(false)
+ , urgent_(false)
+ {
+ seen.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetSeen));
+ seen.SetSetterFunction(sigc::mem_fun(this, &MockApplication::SetSeen));
+ sticky.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetSticky));
+ sticky.SetSetterFunction(sigc::mem_fun(this, &MockApplication::SetSticky));
+ visible.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetVisible));
+ active.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetActive));
+ running.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetRunning));
+ urgent.SetGetterFunction(sigc::mem_fun(this, &MockApplication::GetUrgent));
+ }
+
+ std::string desktop_file_;
+ std::string icon_;
+ std::string title_;
+ bool seen_;
+ bool sticky_;
+ bool visible_;
+ bool active_;
+ bool running_;
+ bool urgent_;
+
+ virtual std::string icon() const { return icon_; }
+ virtual std::string title() const { return title_; }
+ virtual std::string desktop_file() const { return desktop_file_; }
+ virtual std::string type() const { return "mock"; }
+ virtual std::string repr() const { return "MockApplication"; }
+
+ virtual unity::WindowList GetWindows() const { return unity::WindowList(); }
+ virtual bool OwnsWindow(Window window_id) const { return false; }
+
+ virtual std::vector<std::string> GetSupportedMimeTypes() const { return {}; }
+ virtual std::vector<unity::ApplicationMenu> GetRemoteMenus() const { return {}; }
+
+ virtual unity::ApplicationWindowPtr GetFocusableWindow() const { return unity::ApplicationWindowPtr(); }
+ virtual void Focus(bool show_on_visible, int monitor) const {}
+ virtual void Quit() const {}
+ void SetRunState(bool state) {
+ running_ = state;
+ running.changed.emit(state);
+ }
+
+ bool GetSeen() const { return seen_; }
+ bool SetSeen(bool const& param) {
+ if (param != seen_) {
+ seen_ = param;
+ return true;
+ }
+ return false;
+ }
+
+ bool GetSticky() const { return sticky_; }
+ bool SetSticky(bool const& param) {
+ if (param != sticky_) {
+ sticky_ = param;
+ return true;
+ }
+ return false;
+ }
+
+ bool GetVisible() const { return visible_; }
+ bool GetActive() const { return active_; }
+ bool GetRunning() const { return running_; }
+ bool GetUrgent() const { return urgent_; }
+};
+
+}
+
+#endif
diff --git a/unity-shared/ApplicationManager.cpp b/unity-shared/ApplicationManager.cpp
new file mode 100644
index 000000000..401dab68f
--- /dev/null
+++ b/unity-shared/ApplicationManager.cpp
@@ -0,0 +1,35 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include "unity-shared/ApplicationManager.h"
+
+
+namespace unity
+{
+// This function is used by the static Default method on the ApplicationManager
+// class, and uses link time to make sure there is a function available.
+std::shared_ptr<ApplicationManager> create_application_manager();
+
+ApplicationManager& ApplicationManager::Default()
+{
+ static std::shared_ptr<ApplicationManager> instance(create_application_manager());
+ return *instance;
+}
+
+} // namespace unity
diff --git a/unity-shared/ApplicationManager.h b/unity-shared/ApplicationManager.h
new file mode 100644
index 000000000..cadc0e800
--- /dev/null
+++ b/unity-shared/ApplicationManager.h
@@ -0,0 +1,142 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#ifndef UNITYSHARED_APPLICATION_MANAGER_H
+#define UNITYSHARED_APPLICATION_MANAGER_H
+
+#include <memory>
+#include <vector>
+
+#include <sigc++/signal.h>
+#include <NuxCore/Property.h>
+#include <unity-shared/WindowManager.h>
+
+
+namespace unity
+{
+
+class Application;
+class ApplicationManager;
+class ApplicationWindow;
+typedef std::shared_ptr<Application> ApplicationPtr;
+typedef std::shared_ptr<ApplicationWindow> ApplicationWindowPtr;
+
+typedef std::vector<ApplicationPtr> ApplicationList;
+typedef std::vector<ApplicationWindowPtr> WindowList;
+
+
+class ApplicationWindow
+{
+public:
+ virtual ~ApplicationWindow() {}
+
+ virtual std::string title() const = 0;
+ virtual std::string icon() const = 0;
+ virtual std::string type() const = 0; // 'window' or 'tab'
+
+ virtual Window window_id() const = 0;
+ virtual int monitor() const = 0;
+
+ // It is possible for this to be null, especially in situations where
+ // the application is starting up or shutting down.
+ virtual ApplicationPtr application() const = 0;
+ // Returns true if we made a best effort at focusing the window, or
+ // false if this was not possible for some reason (like a missing window_id).
+ virtual bool Focus() const = 0;
+ // Closes the window, or the browser tab if a webapp.
+ virtual void Quit() const = 0;
+
+ nux::ROProperty<bool> visible;
+ nux::ROProperty<bool> active;
+ nux::ROProperty<bool> urgent;
+};
+
+// Used for dbus menus, and nicer than a std::pair of strings.
+struct ApplicationMenu
+{
+ ApplicationMenu(std::string const& path, std::string const& address)
+ : path(path), remote_address(address) {}
+ std::string path;
+ std::string remote_address;
+};
+
+
+class Application
+{
+public:
+ virtual ~Application() {}
+
+ virtual std::string icon() const = 0;
+ virtual std::string title() const = 0;
+ virtual std::string desktop_file() const = 0;
+ virtual std::string type() const = 0;
+
+ // A string representation of the object.
+ virtual std::string repr() const = 0;
+
+ virtual WindowList GetWindows() const = 0;
+ virtual bool OwnsWindow(Window window_id) const = 0;
+
+ virtual std::vector<std::string> GetSupportedMimeTypes() const = 0;
+ virtual std::vector<ApplicationMenu> GetRemoteMenus() const = 0;
+
+ virtual ApplicationWindowPtr GetFocusableWindow() const = 0;
+ virtual void Focus(bool show_on_visible, int monitor) const = 0;
+ // Calls quit on all the Windows for this application.
+ virtual void Quit() const = 0;
+
+ // Considering using a property for the "unity-seen" quark
+ nux::RWProperty<bool> seen;
+ nux::RWProperty<bool> sticky;
+
+ nux::ROProperty<bool> visible;
+ nux::ROProperty<bool> active;
+ nux::ROProperty<bool> running;
+ nux::ROProperty<bool> urgent;
+
+ sigc::signal<void> closed;
+
+ sigc::signal<void, ApplicationWindow const&> window_opened;
+ sigc::signal<void, ApplicationWindow const&> window_moved;
+ sigc::signal<void> window_closed;
+};
+
+
+class ApplicationManager
+{
+public:
+ virtual ~ApplicationManager() {}
+
+ static ApplicationManager& Default();
+
+ virtual ApplicationWindowPtr GetActiveWindow() const = 0;
+
+ virtual ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file) const = 0;
+
+ virtual ApplicationList GetRunningApplications() const = 0;
+
+ sigc::signal<void, ApplicationPtr const&> application_started;
+
+ sigc::signal<void, ApplicationPtr const&> active_application_changed;
+ sigc::signal<void, ApplicationWindowPtr const&> active_window_changed;
+};
+
+}
+
+#endif // UNITYSHARED_APPLICATION_MANAGER_H
diff --git a/unity-shared/BamfApplicationManager.cpp b/unity-shared/BamfApplicationManager.cpp
new file mode 100644
index 000000000..afc8665e4
--- /dev/null
+++ b/unity-shared/BamfApplicationManager.cpp
@@ -0,0 +1,681 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include "unity-shared/BamfApplicationManager.h"
+
+#include <NuxCore/Logger.h>
+
+#include "unity-shared/WindowManager.h"
+
+
+DECLARE_LOGGER(logger, "unity.appmanager.bamf");
+
+
+namespace unity
+{
+// This function is used by the static Default method on the ApplicationManager
+// class, and uses link time to make sure there is a function available.
+std::shared_ptr<ApplicationManager> create_application_manager()
+{
+ return std::shared_ptr<ApplicationManager>(new bamf::Manager());
+}
+
+namespace bamf
+{
+namespace
+{
+const char* UNSEEN_QUARK = "unity-unseen";
+}
+
+
+// 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.
+View::View(Manager const& manager, glib::Object<BamfView> const& view)
+ : manager_(manager)
+ , bamf_view_(view)
+{
+}
+
+std::string View::title() const
+{
+ return glib::String(bamf_view_get_name(bamf_view_)).Str();
+}
+
+std::string View::icon() const
+{
+ return glib::String(bamf_view_get_icon(bamf_view_)).Str();
+}
+
+std::string View::type() const
+{
+ const gchar* t = bamf_view_get_view_type(bamf_view_);
+ return (t ? t : "");
+}
+
+bool View::GetVisible() const
+{
+ return bamf_view_is_user_visible(bamf_view_);
+}
+
+bool View::GetActive() const
+{
+ return bamf_view_is_active(bamf_view_);
+
+}
+
+bool View::GetRunning() const
+{
+ return bamf_view_is_running(bamf_view_);
+}
+
+bool View::GetUrgent() const
+{
+ return bamf_view_is_urgent(bamf_view_);
+}
+
+
+WindowBase::WindowBase(Manager const& manager,
+ glib::Object<BamfView> const& window)
+ : View(manager, window)
+{
+ HookUpEvents();
+}
+
+std::string WindowBase::title() const
+{
+ return View::title();
+}
+
+std::string WindowBase::icon() const
+{
+ return View::icon();
+}
+
+std::string WindowBase::type() const
+{
+ return View::type();
+}
+
+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);
+ return true;
+ }
+ return false;
+}
+
+void WindowBase::HookUpEvents()
+{
+ visible.SetGetterFunction(sigc::mem_fun(this, &View::GetVisible));
+ active.SetGetterFunction(sigc::mem_fun(this, &View::GetActive));
+ urgent.SetGetterFunction(sigc::mem_fun(this, &View::GetUrgent));
+
+ glib::SignalBase* sig;
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "user-visible-changed",
+ [this] (BamfView*, gboolean visible) {
+ this->visible.changed.emit(visible);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "active-changed",
+ [this] (BamfView*, gboolean active) {
+ this->active.changed.emit(active);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "urgent-changed",
+ [this] (BamfView*, gboolean urgent) {
+ this->urgent.changed.emit(urgent);
+ });
+ signals_.Add(sig);
+}
+
+AppWindow::AppWindow(Manager const& manager, glib::Object<BamfView> const& window)
+ : WindowBase(manager, window)
+ , bamf_window_(glib::object_cast<BamfWindow>(window))
+{
+}
+
+
+Window AppWindow::window_id() const
+{
+ return bamf_window_get_xid(bamf_window_);
+}
+
+int AppWindow::monitor() const
+{
+ return bamf_window_get_monitor(bamf_window_);
+}
+
+ApplicationPtr AppWindow::application() const
+{
+ return manager_.GetApplicationForWindow(bamf_window_);
+}
+
+void AppWindow::Quit() const
+{
+ WindowManager::Default().Close(window_id());
+}
+
+Tab::Tab(Manager const& manager, glib::Object<BamfView> const& tab)
+ : WindowBase(manager, tab)
+ , bamf_tab_(glib::object_cast<BamfTab>(tab))
+{}
+
+Window Tab::window_id() const
+{
+ return bamf_tab_get_xid(bamf_tab_);
+}
+
+int Tab::monitor() const
+{
+ // TODO, we could find the real window for the window_id, and get the monitor for that.
+ return -1;
+}
+
+ApplicationPtr Tab::application() const
+{
+ // TODO, we could find the real window for the window_id, and return the application for that.
+ return ApplicationPtr();
+}
+
+bool Tab::Focus() const
+{
+ // Raise the tab in the browser.
+ bamf_tab_raise(bamf_tab_);
+ // Then raise the browser window.
+ return WindowBase::Focus();
+}
+
+void Tab::Quit() const
+{
+ bamf_tab_close(bamf_tab_);
+}
+
+// Being brutal with this function.
+ApplicationWindowPtr create_window(Manager const& manager, glib::Object<BamfView> const& view)
+{
+ ApplicationWindowPtr result;
+ if (view.IsType(BAMF_TYPE_TAB))
+ {
+ result.reset(new Tab(manager, view));
+ }
+ else if (view.IsType(BAMF_TYPE_WINDOW))
+ {
+ result.reset(new AppWindow(manager, view));
+ }
+ // We don't handle applications nor indicators here.
+ return result;
+}
+
+Application::Application(Manager const& manager, glib::Object<BamfView> const& app)
+ : View(manager, app)
+ , bamf_app_(glib::object_cast<BamfApplication>(app))
+{
+ HookUpEvents();
+}
+
+Application::Application(Manager 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
+ seen.SetGetterFunction(sigc::mem_fun(this, &Application::GetSeen));
+ seen.SetSetterFunction(sigc::mem_fun(this, &Application::SetSeen));
+ sticky.SetGetterFunction(sigc::mem_fun(this, &Application::GetSticky));
+ sticky.SetSetterFunction(sigc::mem_fun(this, &Application::SetSticky));
+ visible.SetGetterFunction(sigc::mem_fun(this, &View::GetVisible));
+ active.SetGetterFunction(sigc::mem_fun(this, &View::GetActive));
+ running.SetGetterFunction(sigc::mem_fun(this, &View::GetRunning));
+ urgent.SetGetterFunction(sigc::mem_fun(this, &View::GetUrgent));
+
+ glib::SignalBase* sig;
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "user-visible-changed",
+ [this] (BamfView*, gboolean visible) {
+ LOG_DEBUG(logger) << "user-visible-changed " << visible;
+ this->visible.changed.emit(visible);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "active-changed",
+ [this] (BamfView*, gboolean active) {
+ LOG_DEBUG(logger) << "active-changed " << visible;
+ this->active.changed.emit(active);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "running-changed",
+ [this] (BamfView*, gboolean running) {
+ LOG_DEBUG(logger) << "running " << visible;
+ this->running.changed.emit(running);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*, gboolean>(bamf_view_, "urgent-changed",
+ [this] (BamfView*, gboolean urgent) {
+ this->urgent.changed.emit(urgent);
+ });
+ signals_.Add(sig);
+ sig = new glib::Signal<void, BamfView*>(bamf_view_, "closed",
+ [this] (BamfView*) {
+ this->closed.emit();
+ });
+ signals_.Add(sig);
+
+
+ sig = new glib::Signal<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 win = create_window(this->manager_, view);
+ if (win)
+ this->window_opened.emit(*win);
+ });
+ signals_.Add(sig);
+
+ sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view_, "child-removed",
+ [this] (BamfView*, BamfView* child) {
+ this->window_closed.emit();
+ });
+ signals_.Add(sig);
+
+ sig = new glib::Signal<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 win = create_window(this->manager_, view);
+ if (win)
+ this->window_moved.emit(*win);
+ });
+ signals_.Add(sig);
+}
+
+Application::~Application()
+{
+}
+
+std::string Application::title() const
+{
+ return View::title();
+}
+
+std::string Application::icon() const
+{
+ return View::icon();
+}
+
+std::string Application::desktop_file() const
+{
+ const gchar* file = bamf_application_get_desktop_file(bamf_app_);
+ return file ? file : "";
+}
+
+std::string 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;
+ }
+ return result;
+}
+
+std::string Application::repr() const
+{
+ std::ostringstream sout;
+ sout << "<bamf::Application " << bamf_app_.RawPtr() << " >";
+ return sout.str();
+}
+
+WindowList Application::GetWindows() const
+{
+ WindowList result;
+
+ if (!bamf_app_)
+ return result;
+
+ WindowManager& wm = WindowManager::Default();
+ 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 window(create_window(manager_, view));
+ if (!window)
+ continue;
+
+ Window window_id = window->window_id();
+
+ if (wm.IsWindowMapped(window_id))
+ {
+ result.push_back(window);
+ }
+ }
+ return result;
+}
+
+bool Application::OwnsWindow(Window window_id) const
+{
+ if (!window_id)
+ return false;
+
+ bool owns = false;
+ std::shared_ptr<GList> children(bamf_view_get_children(bamf_view_), g_list_free);
+ for (GList* l = children.get(); l && !owns; l = l->next)
+ {
+ owns = BAMF_IS_WINDOW(l->data) &&
+ bamf_window_get_xid(static_cast<BamfWindow*>(l->data)) == window_id;
+ }
+
+ return owns;
+}
+
+std::vector<std::string> Application::GetSupportedMimeTypes() const
+{
+ std::vector<std::string> result;
+ std::unique_ptr<gchar*[], void(*)(gchar**)> mimes(
+ bamf_application_get_supported_mime_types(bamf_app_), g_strfreev);
+
+ if (mimes)
+ {
+ for (int i = 0; mimes[i]; i++)
+ {
+ result.push_back(mimes[i]);
+ }
+ }
+ return result;
+}
+
+std::vector<ApplicationMenu> Application::GetRemoteMenus() const
+{
+ std::vector<ApplicationMenu> result;
+ std::shared_ptr<GList> children(bamf_view_get_children(bamf_view_), g_list_free);
+ for (GList* l = children.get(); l; l = l->next)
+ {
+ if (!BAMF_IS_INDICATOR(l->data))
+ continue;
+
+ auto indicator = static_cast<BamfIndicator*>(l->data);
+ const gchar* path = bamf_indicator_get_dbus_menu_path(indicator);
+ const gchar* address = bamf_indicator_get_remote_address(indicator);
+
+ // It is possible for path or address to be null on error condintions, or if
+ // the remote is not ready.
+ if (path && address)
+ result.push_back(ApplicationMenu(path, address));
+ }
+ return result;
+}
+
+ApplicationWindowPtr Application::GetFocusableWindow() const
+{
+ glib::Object<BamfView> view(bamf_application_get_focusable_child(bamf_app_),
+ glib::AddRef());
+ return create_window(manager_, view);
+}
+
+void Application::Focus(bool show_only_visible, int monitor) const
+{
+ WindowManager& wm = WindowManager::Default();
+ std::vector<Window> urgent_windows;
+ std::vector<Window> visible_windows;
+ std::vector<Window> non_visible_windows;
+ bool any_visible = false;
+
+ for (auto& window : GetWindows())
+ {
+ Window window_id = window->window_id();
+ if (window->urgent())
+ urgent_windows.push_back(window_id);
+ else if (window->visible())
+ visible_windows.push_back(window_id);
+ else
+ non_visible_windows.push_back(window_id);
+
+ if (wm.IsWindowOnCurrentDesktop(window_id) &&
+ wm.IsWindowVisible(window_id))
+ {
+ any_visible = true;
+ }
+ }
+
+ // This logic seems overly convoluted, but copying the behaviour from
+ // the launcher icon for now.
+ auto visibility = WindowManager::FocusVisibility::OnlyVisible;
+ if (!show_only_visible)
+ {
+ visibility = any_visible
+ ? WindowManager::FocusVisibility::ForceUnminimizeInvisible
+ : WindowManager::FocusVisibility::ForceUnminimizeOnCurrentDesktop;
+ }
+ if (!urgent_windows.empty())
+ {
+ // Last param is whether to show only the top most window. In the situation
+ // where we have urgent windows, we want to raise all the urgent windows on
+ // the current workspace, or the workspace of the top most urgent window.
+ wm.FocusWindowGroup(urgent_windows, visibility, monitor, false);
+ }
+ else if (!visible_windows.empty())
+ {
+ wm.FocusWindowGroup(visible_windows, visibility, monitor, true);
+ }
+ else
+ {
+ // Not sure what the use case is for this behaviour, but at this stage,
+ // copying behaviour from ApplicationLauncherIcon.
+ wm.FocusWindowGroup(non_visible_windows, visibility, monitor, true);
+ }
+}
+
+
+void Application::Quit() const
+{
+ for (auto& window : GetWindows())
+ {
+ window->Quit();
+ }
+}
+
+
+bool Application::GetSeen() const
+{
+ return g_object_get_qdata(G_OBJECT(bamf_app_.RawPtr()),
+ g_quark_from_string(UNSEEN_QUARK));
+}
+
+bool Application::SetSeen(bool const& param)
+{
+ bool is_seen = GetSeen();
+ if (param == is_seen)
+ return false; // unchanged
+
+ void* data = param ? reinterpret_cast<void*>(1) : nullptr;
+ g_object_set_qdata(G_OBJECT(bamf_app_.RawPtr()),
+ g_quark_from_string(UNSEEN_QUARK),
+ data);
+ return true; // value updated
+
+}
+
+
+
+bool Application::GetSticky() const
+{
+ return bamf_view_is_sticky(bamf_view_);
+}
+
+bool Application::SetSticky(bool const& param)
+{
+ bool is_sticky = GetSticky();
+ if (param == is_sticky)
+ return false; // unchanged
+
+ bamf_view_set_sticky(bamf_view_, true);
+ return true; // value updated
+}
+
+
+Manager::Manager()
+ : matcher_(bamf_matcher_get_default())
+{
+ LOG_TRACE(logger) << "Create BAMF Application Manager";
+ glib::SignalBase* sig;
+ sig = new glib::Signal<void, BamfMatcher*, BamfView*>
+ (matcher_, "view-opened",
+ sigc::mem_fun(this, &Manager::OnViewOpened));
+ signals_.Add(sig);
+
+ sig = new glib::Signal<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 win = create_window(*this, view);
+ if (win)
+ this->active_window_changed.emit(win);
+ });
+ signals_.Add(sig);
+
+ sig = new glib::Signal<void, BamfMatcher*, BamfApplication*, BamfApplication*>
+ (matcher_, "active-application-changed",
+ [this](BamfMatcher*, BamfApplication* /* from */, BamfApplication* to) {
+ // Ownership is not passed on signals
+ glib::Object<BamfApplication> app(to, glib::AddRef());
+ ApplicationPtr active_app;
+ if (app) active_app.reset(new Application(*this, app));
+ this->active_application_changed.emit(active_app);
+ });
+ signals_.Add(sig);
+}
+
+Manager::~Manager()
+{
+ LOG_DEBUG(logger) << "Manager::~Manager";
+}
+
+ApplicationWindowPtr Manager::GetActiveWindow() const
+{
+ ApplicationWindowPtr result;
+ // No transfer of ownership for bamf_matcher_get_active_window.
+ BamfWindow* active_win = bamf_matcher_get_active_window(matcher_);
+
+ // If the active window is a dock type, then we want the first visible, non-dock type.
+ if (active_win &&
+ bamf_window_get_window_type(active_win) == BAMF_WINDOW_DOCK)
+ {
+ 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();
+ 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 win = static_cast<BamfWindow*>(l->data);
+ auto view = static_cast<BamfView*>(l->data);
+ Window 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;
+ }
+ }
+ }
+
+ auto view = reinterpret_cast<BamfView*>(active_win);
+ if (active_win)
+ result.reset(new AppWindow(*this, glib::Object<BamfView>(view, glib::AddRef())));
+ return result;
+}
+
+
+ApplicationPtr Manager::GetApplicationForDesktopFile(std::string const& desktop_file) const
+{
+ ApplicationPtr result;
+ glib::Object<BamfApplication> app(bamf_matcher_get_application_for_desktop_file(
+ matcher_, desktop_file.c_str(), true), glib::AddRef());
+
+ if (app)
+ result.reset(new Application(*this, app));
+
+ return result;
+}
+
+ApplicationPtr Manager::GetApplicationForWindow(glib::Object<BamfWindow> const& window) const
+{
+ ApplicationPtr result;
+ glib::Object<BamfApplication> app(bamf_matcher_get_application_for_window(matcher_, window),
+ glib::AddRef());
+ if (app)
+ result.reset(new Application(*this, app));
+ return result;
+}
+
+ApplicationList Manager::GetRunningApplications() const
+{
+ ApplicationList result;
+ std::shared_ptr<GList> apps(bamf_matcher_get_applications(matcher_), g_list_free);
+
+ for (GList *l = apps.get(); l; l = l->next)
+ {
+ if (!BAMF_IS_APPLICATION(l->data))
+ {
+ LOG_INFO(logger) << "Running apps given something not an app.";
+ continue;
+ }
+
+ glib::Object<BamfApplication> app(static_cast<BamfApplication*>(l->data));
+
+ result.push_back(ApplicationPtr(new Application(*this, app)));
+ }
+ return result;
+}
+
+
+void Manager::OnViewOpened(BamfMatcher* matcher, BamfView* view)
+{
+ LOG_DEBUG_BLOCK(logger);
+ if (!BAMF_IS_APPLICATION(view))
+ {
+ LOG_DEBUG(logger) << "view is not an app";
+ return;
+ }
+
+ glib::Object<BamfApplication> app(reinterpret_cast<BamfApplication*>(view), glib::AddRef());
+ application_started.emit(ApplicationPtr(new Application(*this, app)));
+}
+
+} // namespace bamf
+} // namespace unity
diff --git a/unity-shared/BamfApplicationManager.h b/unity-shared/BamfApplicationManager.h
new file mode 100644
index 000000000..bfee51c72
--- /dev/null
+++ b/unity-shared/BamfApplicationManager.h
@@ -0,0 +1,177 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#ifndef UNITYSHARED_BAMF_APPLICATION_MANAGER_H
+#define UNITYSHARED_BAMF_APPLICATION_MANAGER_H
+
+#include <libbamf/libbamf.h>
+#include <UnityCore/GLibWrapper.h>
+#include <UnityCore/GLibSignal.h>
+
+#include "unity-shared/ApplicationManager.h"
+
+
+namespace unity
+{
+namespace bamf
+{
+class Manager;
+class View
+{
+public:
+ View(Manager const& manager,
+ glib::Object<BamfView> const& view);
+
+ std::string title() const;
+ std::string icon() const;
+ std::string type() const;
+
+ bool GetVisible() const;
+ bool GetActive() const;
+ bool GetRunning() const;
+ bool GetUrgent() const;
+
+protected:
+ Manager const& manager_;
+ glib::Object<BamfView> bamf_view_;
+};
+
+
+class WindowBase: public ::unity::ApplicationWindow, public View
+{
+protected:
+ WindowBase(Manager const& manager,
+ glib::Object<BamfView> const& window);
+
+public:
+ virtual std::string title() const;
+ virtual std::string icon() const;
+ virtual std::string type() const; // 'window' or 'tab'
+
+ virtual bool Focus() const;
+
+private: // Property getters and setters
+ void HookUpEvents();
+
+private:
+ glib::SignalManager signals_;
+};
+
+// NOTE: Can't use Window as a type as there is a #define for Window to some integer value.
+class AppWindow: public WindowBase
+{
+public:
+ AppWindow(Manager const& manager,
+ glib::Object<BamfView> const& window);
+
+ virtual Window window_id() const;
+ virtual int monitor() const;
+ virtual ApplicationPtr application() const;
+ virtual void Quit() const;
+
+private:
+ glib::Object<BamfWindow> bamf_window_;
+};
+
+class Tab: public WindowBase
+{
+public:
+ Tab(Manager 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;
+
+private:
+ glib::Object<BamfTab> bamf_tab_;
+};
+
+
+class Application : public ::unity::Application, public View
+{
+public:
+ Application(Manager const& manager,
+ glib::Object<BamfView> const& app);
+ Application(Manager const& manager,
+ glib::Object<BamfApplication> const& app);
+ ~Application();
+
+ virtual std::string title() const;
+ virtual std::string icon() const;
+ virtual std::string desktop_file() const;
+ virtual std::string type() const;
+
+ virtual WindowList GetWindows() const;
+ virtual bool OwnsWindow(Window window_id) const;
+
+ virtual std::vector<std::string> GetSupportedMimeTypes() const;
+ virtual std::vector<ApplicationMenu> GetRemoteMenus() const;
+
+ virtual ApplicationWindowPtr GetFocusableWindow() const;
+ virtual void Focus(bool show_on_visible, int monitor) const;
+
+ virtual void Quit() const;
+
+ virtual std::string repr() const;
+
+private: // Property getters and setters
+ void HookUpEvents();
+
+ bool GetSeen() const;
+ bool SetSeen(bool const& param);
+
+ bool GetSticky() const;
+ bool SetSticky(bool const& param);
+
+private:
+ glib::Object< ::BamfApplication> bamf_app_;
+ glib::SignalManager signals_;
+ std::string type_;
+};
+
+class Manager : public ::unity::ApplicationManager
+{
+public:
+ Manager();
+ ~Manager();
+
+ virtual ApplicationWindowPtr GetActiveWindow() const;
+
+ virtual ApplicationPtr GetApplicationForDesktopFile(std::string const& desktop_file) const;
+
+ virtual ApplicationList GetRunningApplications() const;
+
+
+ virtual ApplicationPtr GetApplicationForWindow(glib::Object<BamfWindow> const& window) const;
+
+private:
+ void OnViewOpened(BamfMatcher* matcher, BamfView* view);
+
+private:
+ glib::Object<BamfMatcher> matcher_;
+ glib::SignalManager signals_;
+};
+
+} // namespace bamf
+} // namespace unity
+
+#endif // UNITYSHARED_APPLICATION_MANAGER_H
diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt
index 355e5bfe0..fa1e911ae 100644
--- a/unity-shared/CMakeLists.txt
+++ b/unity-shared/CMakeLists.txt
@@ -27,6 +27,7 @@ include_directories (. .. ../services ../UnityCore ${UNITY_SRC} ${CMAKE_BINARY_D
#
set (UNITY_SHARED_SOURCES
AbstractSeparator.cpp
+ ApplicationManager.cpp
Animator.cpp
BGHash.cpp
CoverArt.cpp
@@ -74,6 +75,7 @@ set (UNITY_SHARED_SOURCES
if(ENABLE_X_SUPPORT)
set (UNITY_SHARED_SOURCES
+ BamfApplicationManager.cpp
XKeyboardUtil.cpp
XWindowManager.cpp
${UNITY_SHARED_SOURCES}
@@ -112,4 +114,7 @@ add_library (unity-shared-standalone STATIC ${UNITY_SHARED_STANDALONE_SOURCES})
target_link_libraries (unity-shared-standalone ${LIBS})
add_dependencies (unity-shared-standalone unity-shared)
+add_executable (app-manager StandaloneAppManager.cpp)
+add_dependencies (app-manager unity-shared)
+target_link_libraries (app-manager unity-shared unity-shared-standalone)
diff --git a/unity-shared/StandaloneAppManager.cpp b/unity-shared/StandaloneAppManager.cpp
new file mode 100644
index 000000000..589b40b4f
--- /dev/null
+++ b/unity-shared/StandaloneAppManager.cpp
@@ -0,0 +1,245 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Tim Penhey <tim.penhey@canonical.com>
+ */
+
+#include <iostream>
+#include <vector>
+
+#include <NuxCore/Logger.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <signal.h>
+
+#include "unity-shared/ApplicationManager.h"
+#include "UnityCore/GLibSource.h"
+
+using namespace std;
+using namespace unity;
+
+DECLARE_LOGGER(logger, "unity.appmanager.test");
+
+GMainLoop *loop;
+
+void dump_app(ApplicationPtr const& app, std::string const& prefix = "")
+{
+ if (app)
+ {
+ cout << prefix << "Application: " << app->title()
+ << ", seen: " << (app->seen() ? "yes" : "no")
+ << ", sticky: " << (app->sticky() ? "yes" : "no")
+ << ", visible: " << (app->visible() ? "yes" : "no")
+ << ", active: " << (app->active() ? "yes" : "no")
+ << ", running: " << (app->running() ? "yes" : "no")
+ << ", urgent: " << (app->urgent() ? "yes" : "no")
+ << ", repr: " << app->repr()
+ << "\n icon: \"" << app->icon() << "\""
+ << "\n desktop file: \"" << app->desktop_file() << "\""
+ << "\n type: \"" << app->type() << "\""
+ << endl;
+
+ for (auto win : app->GetWindows())
+ {
+ std::cout << " Window: " << win->title()
+ << ", window_id: " << win->window_id()
+ << ", monitor: " << win->monitor()
+ << ", type: " << win->type()
+ << endl;
+ }
+ }
+ else
+ {
+ cout << "App ptr is null" << endl;
+ }
+}
+
+void connect_events(ApplicationPtr const& app)
+{
+ if (app->seen())
+ {
+ cout << "Already seen " << app->title() << ", skipping event connection.\n";
+ return;
+ }
+ std::string app_name = app->title();
+ app->visible.changed.connect([app_name](bool const& value) {
+ cout << app_name << " visibility changed: " << (value ? "yes" : "no") << endl;
+ });
+ app->running.changed.connect([app_name](bool const& value) {
+ cout << app_name << " running changed: " << (value ? "yes" : "no") << endl;
+ });
+ app->active.changed.connect([app_name](bool const& value) {
+ cout << app_name << " active changed: " << (value ? "yes" : "no") << endl;
+ });
+ app->urgent.changed.connect([app_name](bool const& value) {
+ cout << app_name << " urgent changed: " << (value ? "yes" : "no") << endl;
+ });
+ app->closed.connect([app_name]() {
+ cout << app_name << " closed." << endl;
+ });
+ app->window_opened.connect([app_name](ApplicationWindow const& window) {
+ cout << "** " << app_name << " window opened: " << window.title() << endl;
+ });
+ app->window_closed.connect([app_name]() {
+ cout << "** " << app_name << " window closed" << endl;
+ });
+ app->window_moved.connect([app_name](ApplicationWindow const& window) {
+ cout << "** " << app_name << " window moved: " << window.title() << endl;
+ });
+ app->seen = true;
+}
+
+
+
+nux::logging::Level glog_level_to_nux(GLogLevelFlags log_level)
+{
+ // For some weird reason, ERROR is more critical than CRITICAL in gnome.
+ if (log_level & G_LOG_LEVEL_ERROR)
+ return nux::logging::Critical;
+ if (log_level & G_LOG_LEVEL_CRITICAL)
+ return nux::logging::Error;
+ if (log_level & G_LOG_LEVEL_WARNING)
+ return nux::logging::Warning;
+ if (log_level & G_LOG_LEVEL_MESSAGE ||
+ log_level & G_LOG_LEVEL_INFO)
+ return nux::logging::Info;
+ // default to debug.
+ return nux::logging::Debug;
+}
+
+void capture_g_log_calls(const gchar* log_domain,
+ GLogLevelFlags log_level,
+ const gchar* message,
+ gpointer user_data)
+{
+ // If the environment variable is set, we capture the backtrace.
+ static bool glog_backtrace = ::getenv("UNITY_LOG_GLOG_BACKTRACE");
+ // If nothing else, all log messages from unity should be identified as such
+ std::string module("unity");
+ if (log_domain)
+ {
+ module += std::string(".") + log_domain;
+ }
+ nux::logging::Logger logger(module);
+ nux::logging::Level level = glog_level_to_nux(log_level);
+ if (level >= logger.GetEffectiveLogLevel())
+ {
+ std::string backtrace;
+ if (glog_backtrace && level >= nux::logging::Warning)
+ {
+ backtrace = "\n" + nux::logging::Backtrace();
+ }
+ nux::logging::LogStream(level, logger.module(), "<unknown>", 0).stream()
+ << message << backtrace;
+ }
+}
+
+void print_active_window(ApplicationManager& manager)
+{
+ ApplicationWindowPtr win = manager.GetActiveWindow();
+ if (win)
+ {
+ ApplicationPtr app = win->application();
+ if (app)
+ cout << "\n\nActive App: " << app->title();
+ else
+ cout << "\n\nNo app for window:";
+ cout << "\nActive Window: " << win->title() << endl;
+ }
+ else
+ cout << "\n\nNo active window: " << endl;
+}
+
+void clean_exit(int sig)
+{
+ if (loop && g_main_loop_is_running(loop))
+ g_main_loop_quit(loop);
+}
+
+namespace unity
+{
+// This function is used by the static Default method on the ApplicationManager
+// class, and uses link time to make sure there is a function available.
+std::shared_ptr<ApplicationManager> create_application_manager();
+}
+
+int main(int argc, char* argv[])
+{
+ g_type_init();
+ gtk_init(&argc, &argv);
+ nux::logging::configure_logging(::getenv("UNITY_APP_LOG_SEVERITY"));
+ g_log_set_default_handler(capture_g_log_calls, NULL);
+
+ bool show_active = (argc > 1 && std::string(argv[1]) == "show-active");
+ //std::shared_ptr<ApplicationManager> manager_ptr = create_application_manager();
+ //ApplicationManager& manager = *manager_ptr;
+ ApplicationManager& manager = ApplicationManager::Default();
+
+ ApplicationPtr terminal = manager.GetApplicationForDesktopFile(
+ "/usr/share/applications/gnome-terminal.desktop");
+ terminal->sticky = true; // this is needed to get the notifications...
+ dump_app(terminal);
+ connect_events(terminal);
+
+ ApplicationList apps = manager.GetRunningApplications();
+
+ for (auto app : apps)
+ {
+ dump_app(app);
+ connect_events(app);
+ }
+
+ dump_app(manager.GetApplicationForDesktopFile(
+ "/usr/share/applications/gnome-terminal.desktop"));
+
+ // Get some desktop files for checking
+ ApplicationPtr pgadmin = manager.GetApplicationForDesktopFile(
+ "/usr/share/applications/pgadmin3.desktop");
+ dump_app(pgadmin);
+ ApplicationPtr gedit = manager.GetApplicationForDesktopFile(
+ "/usr/share/applications/gedit.desktop");
+ dump_app(gedit);
+ // dump new apps
+ manager.application_started.connect([&apps](ApplicationPtr const& app) {
+ apps.push_back(app);
+ dump_app(app, "\nApp started: ");
+ connect_events(app);
+ });
+ manager.active_application_changed.connect([](ApplicationPtr const& app) {
+ if (app)
+ cout << "Manager::active_application_changed: " << app->title() << endl;
+ else
+ cout << "Manager::active_application_changed to nothing\n";
+ });
+ manager.active_window_changed.connect([](ApplicationWindowPtr const& win) {
+ cout << "Manager::active_window_changed: " << win->title() << endl;
+ });
+
+ shared_ptr<GMainLoop> main_loop(g_main_loop_new(nullptr, FALSE),
+ g_main_loop_unref);
+ loop = main_loop.get();
+ signal(SIGINT, clean_exit);
+ {
+ glib::SourceManager source_manager;
+ if (show_active)
+ source_manager.AddTimeoutSeconds(5, [&manager]() {
+ print_active_window(manager);
+ return true;
+ });
+ g_main_loop_run(loop);
+ }
+ cout << "After main loop.\n";
+}
diff --git a/unity-shared/StandaloneWindowManager.cpp b/unity-shared/StandaloneWindowManager.cpp
index 91b96a421..e352f059d 100644
--- a/unity-shared/StandaloneWindowManager.cpp
+++ b/unity-shared/StandaloneWindowManager.cpp
@@ -98,7 +98,7 @@ bool StandaloneWindowManager::IsWindowOnCurrentDesktop(Window window_id) const
if (it != standalone_windows_.end())
return (it->second->current_desktop == current_desktop_);
- return false;
+ return true;
}
bool StandaloneWindowManager::IsWindowObscured(Window window_id) const
@@ -112,7 +112,7 @@ bool StandaloneWindowManager::IsWindowMapped(Window window_id) const
if (it != standalone_windows_.end())
return it->second->mapped;
- return false;
+ return true;
}
bool StandaloneWindowManager::IsWindowVisible(Window window_id) const
@@ -121,7 +121,7 @@ bool StandaloneWindowManager::IsWindowVisible(Window window_id) const
if (it != standalone_windows_.end())
return it->second->visible;
- return false;
+ return true;
}
bool StandaloneWindowManager::IsWindowOnTop(Window window_id) const