summaryrefslogtreecommitdiff
diff options
-rw-r--r--UnityCore/DesktopUtilities.cpp5
-rw-r--r--UnityCore/DesktopUtilities.h1
-rw-r--r--UnityCore/GLibDBusProxy.cpp6
-rw-r--r--debian/control1
-rw-r--r--launcher/AbstractLauncherIcon.h12
-rw-r--r--launcher/ApplicationLauncherIcon.cpp789
-rw-r--r--launcher/ApplicationLauncherIcon.h133
-rw-r--r--launcher/CMakeLists.txt3
-rw-r--r--launcher/DesktopLauncherIcon.cpp5
-rw-r--r--launcher/DesktopLauncherIcon.h1
-rw-r--r--launcher/DeviceLauncherSection.h4
-rw-r--r--launcher/FileManagerLauncherIcon.cpp128
-rw-r--r--launcher/FileManagerLauncherIcon.h52
-rw-r--r--launcher/Launcher.cpp11
-rw-r--r--launcher/LauncherController.cpp31
-rw-r--r--launcher/LauncherControllerPrivate.h3
-rw-r--r--launcher/LauncherIcon.cpp14
-rw-r--r--launcher/LauncherIcon.h16
-rw-r--r--launcher/MockLauncherIcon.h54
-rw-r--r--launcher/SoftwareCenterLauncherIcon.cpp3
-rw-r--r--launcher/StorageLauncherIcon.cpp119
-rw-r--r--launcher/StorageLauncherIcon.h55
-rw-r--r--launcher/SwitcherController.cpp25
-rw-r--r--launcher/SwitcherModel.cpp36
-rw-r--r--launcher/SwitcherView.cpp2
-rw-r--r--launcher/TrashLauncherIcon.cpp64
-rw-r--r--launcher/TrashLauncherIcon.h12
-rw-r--r--launcher/VolumeLauncherIcon.cpp156
-rw-r--r--launcher/VolumeLauncherIcon.h12
-rw-r--r--launcher/WindowedLauncherIcon.cpp618
-rw-r--r--launcher/WindowedLauncherIcon.h100
-rw-r--r--plugins/unityshell/src/inputremover.cpp9
-rw-r--r--services/panel-indicator-entry-accessible.c2
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/mock-application.h14
-rw-r--r--tests/test_application_launcher_icon.cpp45
-rw-r--r--tests/test_launcher_controller.cpp101
-rw-r--r--tests/test_mock_filemanager.h13
-rw-r--r--tests/test_software_center_launcher_icon.cpp5
-rw-r--r--tests/test_switcher_controller.h22
-rw-r--r--tests/test_switcher_controller_class.cpp27
-rw-r--r--tests/test_trash_launcher_icon.cpp74
-rw-r--r--tests/test_volume_launcher_icon.cpp186
-rw-r--r--unity-shared/ApplicationManager.h3
-rw-r--r--unity-shared/BamfApplicationManager.cpp12
-rw-r--r--unity-shared/BamfApplicationManager.h4
-rw-r--r--unity-shared/FileManager.h11
-rw-r--r--unity-shared/GnomeFileManager.cpp157
-rw-r--r--unity-shared/GnomeFileManager.h7
49 files changed, 1995 insertions, 1169 deletions
diff --git a/UnityCore/DesktopUtilities.cpp b/UnityCore/DesktopUtilities.cpp
index a9a41c5e7..5b841cd0d 100644
--- a/UnityCore/DesktopUtilities.cpp
+++ b/UnityCore/DesktopUtilities.cpp
@@ -90,6 +90,11 @@ std::string DesktopUtilities::GetUserRuntimeDirectory()
return "";
}
+std::string DesktopUtilities::GetUserTrashDirectory()
+{
+ return GetUserDataDirectory().append(G_DIR_SEPARATOR_S "Trash" G_DIR_SEPARATOR_S "files" G_DIR_SEPARATOR_S);
+}
+
std::vector<std::string> DesktopUtilities::GetSystemDataDirectories()
{
const char* const* system_dirs = g_get_system_data_dirs();
diff --git a/UnityCore/DesktopUtilities.h b/UnityCore/DesktopUtilities.h
index 203603ea1..5c0488eaf 100644
--- a/UnityCore/DesktopUtilities.h
+++ b/UnityCore/DesktopUtilities.h
@@ -33,6 +33,7 @@ public:
static std::string GetUserCacheDirectory();
static std::string GetUserRuntimeDirectory();
static std::string GetUserConfigDirectory();
+ static std::string GetUserTrashDirectory();
static std::vector<std::string> GetSystemDataDirectories();
static std::vector<std::string> GetDataDirectories();
diff --git a/UnityCore/GLibDBusProxy.cpp b/UnityCore/GLibDBusProxy.cpp
index 1cd6f4d3d..7e89f6ddf 100644
--- a/UnityCore/GLibDBusProxy.cpp
+++ b/UnityCore/GLibDBusProxy.cpp
@@ -301,7 +301,7 @@ void DBusProxy::Impl::OnPropertyChanged(GDBusProxy* proxy, GVariant* changed_pro
}
}
- g_variant_iter_free (iter);
+ g_variant_iter_free(iter);
}
for (const gchar *property_name = *invalidated; property_name; property_name = *(++invalidated))
@@ -624,7 +624,7 @@ void DBusProxy::GetProperty(std::string const& name, ReplyCallback const& callba
[] (GObject *source, GAsyncResult *res, gpointer user_data) {
glib::Error err;
std::unique_ptr<ReplyCallback> callback(static_cast<ReplyCallback*>(user_data));
- Variant result(g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &err));
+ Variant result(g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &err), StealRef());
if (err)
{
@@ -660,7 +660,7 @@ void DBusProxy::SetProperty(std::string const& name, GVariant* value)
nullptr, G_DBUS_CALL_FLAGS_NONE, -1, pimpl->cancellable_,
[] (GObject *source, GAsyncResult *res, gpointer user_data) {
glib::Error err;
- Variant result(g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &err));
+ Variant result(g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &err), StealRef());
if (err)
{
LOG_ERROR(logger) << "Impossible to set property: " << err;
diff --git a/debian/control b/debian/control
index 69db232f8..7c30e36b2 100644
--- a/debian/control
+++ b/debian/control
@@ -83,6 +83,7 @@ Depends: ${shlibs:Depends},
Provides: indicator-renderer
Recommends: unity-control-center,
${unity-default-masterscopes}
+ nautilus,
indicator-appmenu (>= 15.02.0),
indicator-application,
indicator-sound,
diff --git a/launcher/AbstractLauncherIcon.h b/launcher/AbstractLauncherIcon.h
index 926736be1..ed40c8f71 100644
--- a/launcher/AbstractLauncherIcon.h
+++ b/launcher/AbstractLauncherIcon.h
@@ -174,13 +174,17 @@ public:
virtual WindowList Windows() = 0;
- virtual std::vector<Window> WindowsForMonitor(int monitor) = 0;
+ virtual WindowList WindowsForMonitor(int monitor) = 0;
- virtual std::vector<Window> WindowsOnViewport() = 0;
+ virtual WindowList WindowsOnViewport() = 0;
- virtual const bool WindowVisibleOnMonitor(int monitor) = 0;
+ virtual bool WindowVisibleOnMonitor(int monitor) const = 0;
- virtual const bool WindowVisibleOnViewport() = 0;
+ virtual bool WindowVisibleOnViewport() const = 0;
+
+ virtual size_t WindowsVisibleOnMonitor(int monitor) const = 0;
+
+ virtual size_t WindowsVisibleOnViewport() const = 0;
virtual float PresentUrgency() = 0;
diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp
index 3e6889825..91ea82107 100644
--- a/launcher/ApplicationLauncherIcon.cpp
+++ b/launcher/ApplicationLauncherIcon.cpp
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2010-2012 Canonical Ltd
+ * Copyright (C) 2010-2015 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
@@ -19,10 +19,8 @@
*/
#include "config.h"
-#include <boost/algorithm/string.hpp>
#include <Nux/Nux.h>
-#include <Nux/BaseWindow.h>
#include <NuxCore/Logger.h>
#include <UnityCore/GLibWrapper.h>
@@ -30,12 +28,7 @@
#include "ApplicationLauncherIcon.h"
#include "FavoriteStore.h"
-#include "MultiMonitor.h"
#include "unity-shared/DesktopApplicationManager.h"
-#include "unity-shared/GnomeFileManager.h"
-#include "unity-shared/UBusWrapper.h"
-#include "unity-shared/UBusMessages.h"
-#include "unity-shared/UScreen.h"
#include <glib/gi18n-lib.h>
#include <gio/gdesktopappinfo.h>
@@ -44,15 +37,13 @@ namespace unity
{
namespace launcher
{
-DECLARE_LOGGER(logger, "unity.launcher.icon.application");
namespace
{
-// We use the "bamf-" prefix since the manager is protected, to avoid name clash
-const std::string ICON_REMOVE_TIMEOUT = "bamf-icon-remove";
-const std::string ICON_DND_OVER_TIMEOUT = "bamf-icon-dnd-over";
+DECLARE_LOGGER(logger, "unity.launcher.icon.application");
+
+// We use the "application-" prefix since the manager is protected, to avoid name clash
+const std::string ICON_REMOVE_TIMEOUT = "application-icon-remove";
const std::string DEFAULT_ICON = "application-default-icon";
-const int MAXIMUM_QUICKLIST_WIDTH = 300;
-const int COMPIZ_SCALE_DND_SPREAD = 1 << 7;
enum MenuItemType
{
@@ -67,10 +58,8 @@ enum MenuItemType
NUX_IMPLEMENT_OBJECT_TYPE(ApplicationLauncherIcon);
ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app)
- : SimpleLauncherIcon(IconType::APPLICATION)
- , _startup_notification_timestamp(0)
- , _last_scroll_timestamp(0)
- , _progressive_scroll(0)
+ : WindowedLauncherIcon(IconType::APPLICATION)
+ , startup_notification_timestamp_(0)
, use_custom_bg_color_(false)
, bg_color_(nux::color::White)
{
@@ -83,13 +72,6 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app)
<< ", running: " << (app->running() ? "yes" : "no");
SetApplication(app);
-
- WindowManager& wm = WindowManager::Default();
- wm.window_minimized.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::OnWindowMinimized));
- wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState));
- wm.terminate_expo.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState));
- UScreen::GetDefault()->changed.connect(sigc::hide(sigc::hide(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowsLocation))));
-
EnsureWindowsLocation();
}
@@ -157,23 +139,19 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections()
signals_conn_.Add(app_->window_opened.connect([this](ApplicationWindowPtr const& win) {
signals_conn_.Add(win->monitor.changed.connect([this] (int) { EnsureWindowsLocation(); }));
EnsureWindowsLocation();
-
- if (WindowManager::Default().IsScaleActiveForGroup() && IsActive())
- Spread(true, 0, false);
}));
- auto ensure_win_location_cb = sigc::hide(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowsLocation));
- signals_conn_.Add(app_->window_closed.connect(ensure_win_location_cb));
+ signals_conn_.Add(app_->window_closed.connect([this] (ApplicationWindowPtr const&) { EnsureWindowsLocation(); }));
for (auto& win : app_->GetWindows())
- signals_conn_.Add(win->monitor.changed.connect(ensure_win_location_cb));
+ signals_conn_.Add(win->monitor.changed.connect([this] (int) { EnsureWindowsLocation(); }));
- signals_conn_.Add(app_->urgent.changed.connect([this](bool const& urgent) {
+ signals_conn_.Add(app_->urgent.changed.connect([this](bool urgent) {
LOG_DEBUG(logger) << tooltip_text() << " urgent now " << (urgent ? "true" : "false");
SetQuirk(Quirk::URGENT, urgent);
}));
- signals_conn_.Add(app_->active.changed.connect([this](bool const& active) {
+ signals_conn_.Add(app_->active.changed.connect([this](bool active) {
LOG_DEBUG(logger) << tooltip_text() << " active now " << (active ? "true" : "false");
SetQuirk(Quirk::ACTIVE, active);
}));
@@ -185,8 +163,8 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections()
signals_conn_.Add(app_->title.changed.connect([this](std::string const& name) {
LOG_DEBUG(logger) << tooltip_text() << " name now " << name;
- if (_menu_items.size() == MenuItemType::SIZE)
- _menu_items[MenuItemType::APP_NAME] = nullptr;
+ if (menu_items_.size() == MenuItemType::SIZE)
+ menu_items_[MenuItemType::APP_NAME] = nullptr;
tooltip_text = name;
}));
@@ -195,7 +173,7 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections()
icon_name = (icon.empty() ? DEFAULT_ICON : icon);
}));
- signals_conn_.Add(app_->running.changed.connect([this](bool const& running) {
+ signals_conn_.Add(app_->running.changed.connect([this](bool running) {
LOG_DEBUG(logger) << tooltip_text() << " running now " << (running ? "true" : "false");
SetQuirk(Quirk::RUNNING, running);
@@ -208,35 +186,47 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections()
}
}));
- signals_conn_.Add(app_->visible.changed.connect([this](bool const& visible) {
+ signals_conn_.Add(app_->visible.changed.connect([this](bool visible) {
SetQuirk(Quirk::VISIBLE, IsSticky() ? true : visible);
}));
- signals_conn_.Add(app_->closed.connect([this]() {
- if (!IsSticky())
- {
- SetQuirk(Quirk::VISIBLE, false);
- HideTooltip();
-
- /* Use a timeout to remove the icon, this avoids
- * that we remove an application that is going
- * to be reopened soon. So applications that
- * have a splash screen won't be removed from
- * the launcher while the splash is closed and
- * a new window is opened. */
- _source_manager.AddTimeoutSeconds(1, [this] {
- Remove();
- return false;
- }, ICON_REMOVE_TIMEOUT);
- }
+ signals_conn_.Add(app_->closed.connect([this] {
+ LOG_DEBUG(logger) << tooltip_text() << " closed";
+ OnApplicationClosed();
}));
}
+WindowList ApplicationLauncherIcon::GetManagedWindows() const
+{
+ return app_ ? app_->GetWindows() : WindowList();
+}
+
+void ApplicationLauncherIcon::OnApplicationClosed()
+{
+ if (IsSticky())
+ return;
+
+ SetQuirk(Quirk::VISIBLE, false);
+ HideTooltip();
+
+ /* Use a timeout to remove the icon, this avoids
+ * that we remove an application that is going
+ * to be reopened soon. So applications that
+ * have a splash screen won't be removed from
+ * the launcher while the splash is closed and
+ * a new window is opened. */
+ _source_manager.AddTimeoutSeconds(1, [this] {
+ Remove();
+ return false;
+ }, ICON_REMOVE_TIMEOUT);
+}
+
+// Move to WindowedLauncherIcon?!
bool ApplicationLauncherIcon::GetQuirk(AbstractLauncherIcon::Quirk quirk, int monitor) const
{
if (quirk == Quirk::ACTIVE)
{
- if (!SimpleLauncherIcon::GetQuirk(Quirk::ACTIVE, monitor))
+ if (!WindowedLauncherIcon::GetQuirk(Quirk::ACTIVE, monitor))
return false;
if (app_->type() == AppType::WEBAPP)
@@ -248,304 +238,35 @@ bool ApplicationLauncherIcon::GetQuirk(AbstractLauncherIcon::Quirk quirk, int mo
return app_->OwnsWindow(WindowManager::Default().GetActiveWindow());
}
- return SimpleLauncherIcon::GetQuirk(quirk, monitor);
+ return WindowedLauncherIcon::GetQuirk(quirk, monitor);
}
void ApplicationLauncherIcon::Remove()
{
LogUnityEvent(ApplicationEventType::LEAVE);
UnsetApplication();
- SimpleLauncherIcon::Remove();
+ WindowedLauncherIcon::Remove();
}
bool ApplicationLauncherIcon::IsSticky() const
{
if (app_)
- return app_->sticky() && SimpleLauncherIcon::IsSticky();
+ return app_->sticky() && WindowedLauncherIcon::IsSticky();
return false;
}
-bool ApplicationLauncherIcon::IsActive() const
-{
- return GetQuirk(Quirk::ACTIVE);
-}
-
-bool ApplicationLauncherIcon::IsRunning() const
-{
- return GetQuirk(Quirk::RUNNING);
-}
-
-bool ApplicationLauncherIcon::IsUrgent() const
-{
- return GetQuirk(Quirk::URGENT);
-}
-
-void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
-{
- SimpleLauncherIcon::ActivateLauncherIcon(arg);
- WindowManager& wm = WindowManager::Default();
-
- // This is a little awkward as the target is only set from the switcher.
- if (arg.target)
- {
- // thumper: should we Raise too? should the WM raise?
- wm.Activate(arg.target);
- return;
- }
-
- bool scale_was_active = wm.IsScaleActive();
- bool active = IsActive();
- bool user_visible = IsRunning();
- /* We should check each child to see if there is
- * an unmapped (!= minimized) window around and
- * if so force "Focus" behaviour */
-
- if (arg.source != ActionArg::Source::SWITCHER)
- {
- user_visible = app_->visible();
-
- if (active)
- {
- bool any_visible = false;
- bool any_mapped = false;
- bool any_on_top = false;
- bool any_on_monitor = (arg.monitor < 0);
- int active_monitor = arg.monitor;
-
- for (auto const& window : app_->GetWindows())
- {
- Window xid = window->window_id();
-
- if (!any_visible && wm.IsWindowOnCurrentDesktop(xid))
- {
- any_visible = true;
- }
-
- if (!any_mapped && wm.IsWindowMapped(xid))
- {
- any_mapped = true;
- }
-
- if (!any_on_top && wm.IsWindowOnTop(xid))
- {
- any_on_top = true;
- }
-
- if (!any_on_monitor && window->monitor() == arg.monitor &&
- wm.IsWindowMapped(xid) && wm.IsWindowVisible(xid))
- {
- any_on_monitor = true;
- }
-
- if (window->active())
- {
- active_monitor = window->monitor();
- }
- }
-
- if (!any_visible || !any_mapped || !any_on_top)
- active = false;
-
- if (any_on_monitor && arg.monitor >= 0 && active_monitor != arg.monitor)
- active = false;
- }
-
- if (user_visible && IsSticky() && IsFileManager())
- {
- // See bug #753938
- unsigned minimum_windows = 0;
- auto const& file_manager = GnomeFileManager::Get();
-
- if (file_manager->IsTrashOpened())
- ++minimum_windows;
-
- if (file_manager->IsDeviceOpened())
- ++minimum_windows;
-
- if (minimum_windows > 0)
- {
- if (file_manager->OpenedLocations().size() == minimum_windows &&
- GetWindows(WindowFilter::USER_VISIBLE|WindowFilter::MAPPED).size() == minimum_windows)
- {
- user_visible = false;
- }
- }
- }
- }
-
- /* Behaviour:
- * 1) Nothing running, or nothing visible -> launch application
- * 2) Running and active -> spread application
- * 3) Running and not active -> focus application
- * 4) Spread is active and different icon pressed -> change spread
- * 5) Spread is active -> Spread de-activated, and fall through
- */
-
- if (!IsRunning() || (IsRunning() && !user_visible)) // #1 above
- {
- if (GetQuirk(Quirk::STARTING, arg.monitor))
- return;
-
- wm.TerminateScale();
- SetQuirk(Quirk::STARTING, true, arg.monitor);
- OpenInstanceLauncherIcon(arg.timestamp);
- }
- else // app is running
- {
- if (active)
- {
- if (scale_was_active) // #5 above
- {
- wm.TerminateScale();
-
- if (minimize_window_on_click())
- {
- for (auto const& win : GetWindows(WindowFilter::ON_CURRENT_DESKTOP))
- wm.Minimize(win->window_id());
- }
- else
- {
- Focus(arg);
- }
- }
- else // #2 above
- {
- if (arg.source != ActionArg::Source::SWITCHER)
- {
- bool minimized = false;
-
- if (minimize_window_on_click())
- {
- WindowList const& windows = GetWindows(WindowFilter::ON_CURRENT_DESKTOP);
-
- if (windows.size() == 1)
- {
- wm.Minimize(windows[0]->window_id());
- minimized = true;
- }
- }
-
- if (!minimized)
- {
- Spread(true, 0, false);
- }
- }
- }
- }
- else
- {
- if (scale_was_active) // #4 above
- {
- if (GetWindows(WindowFilter::ON_CURRENT_DESKTOP).size() <= 1)
- wm.TerminateScale();
-
- Focus(arg);
-
- if (arg.source != ActionArg::Source::SWITCHER)
- Spread(true, 0, false);
- }
- else // #3 above
- {
- Focus(arg);
- }
- }
- }
-}
-
-WindowList ApplicationLauncherIcon::GetWindows(WindowFilterMask filter, int monitor)
-{
- WindowManager& wm = WindowManager::Default();
- WindowList results;
-
- monitor = (filter & WindowFilter::ON_ALL_MONITORS) ? -1 : monitor;
- bool mapped = (filter & WindowFilter::MAPPED);
- bool user_visible = (filter & WindowFilter::USER_VISIBLE);
- bool current_desktop = (filter & WindowFilter::ON_CURRENT_DESKTOP);
-
- for (auto& window : app_->GetWindows())
- {
- if ((monitor >= 0 && window->monitor() == monitor) || monitor < 0)
- {
- if ((user_visible && window->visible()) || !user_visible)
- {
- Window xid = window->window_id();
-
- if ((mapped && wm.IsWindowMapped(xid)) || !mapped)
- {
- if ((current_desktop && wm.IsWindowOnCurrentDesktop(xid)) || !current_desktop)
- {
- results.push_back(window);
- }
- }
- }
- }
- }
-
- return results;
-}
-
-WindowList ApplicationLauncherIcon::Windows()
+bool ApplicationLauncherIcon::IsUserVisible() const
{
- return GetWindows(WindowFilter::MAPPED|WindowFilter::ON_ALL_MONITORS);
-}
-
-std::vector<Window> ApplicationLauncherIcon::WindowsOnViewport()
-{
- WindowFilterMask filter = 0;
- filter |= WindowFilter::MAPPED;
- filter |= WindowFilter::USER_VISIBLE;
- filter |= WindowFilter::ON_CURRENT_DESKTOP;
- filter |= WindowFilter::ON_ALL_MONITORS;
-
- std::vector<Window> windows;
- for (auto& window : GetWindows(filter))
- {
- windows.push_back(window->window_id());
- }
- return windows;
-}
-
-std::vector<Window> ApplicationLauncherIcon::WindowsForMonitor(int monitor)
-{
- WindowFilterMask filter = 0;
- filter |= WindowFilter::MAPPED;
- filter |= WindowFilter::USER_VISIBLE;
- filter |= WindowFilter::ON_CURRENT_DESKTOP;
-
- std::vector<Window> windows;
- for (auto& window : GetWindows(filter, monitor))
- {
- windows.push_back(window->window_id());
- }
- return windows;
-}
-
-void ApplicationLauncherIcon::OnWindowMinimized(guint32 xid)
-{
- for (auto const& window: app_->GetWindows())
- {
- if (xid == window->window_id())
- {
- int monitor = GetCenterForMonitor(window->monitor()).first;
-
- if (monitor >= 0)
- {
- Present(0.5f, 600, monitor);
- FullyAnimateQuirkDelayed(300, Quirk::SHIMMER, monitor);
- }
-
- break;
- }
- }
+ return app_ ? app_->visible() : false;
}
void ApplicationLauncherIcon::UpdateDesktopFile()
{
std::string const& filename = app_->desktop_file();
- if (_desktop_file_monitor)
- _gsignals.Disconnect(_desktop_file_monitor, "changed");
+ if (desktop_file_monitor_)
+ glib_signals_.Disconnect(desktop_file_monitor_, "changed");
auto old_uri = RemoteUri();
UpdateRemoteUri();
@@ -559,11 +280,11 @@ void ApplicationLauncherIcon::UpdateDesktopFile()
// we can remove ourself from the launcher and when it's changed
// we can update the quicklist.
glib::Object<GFile> desktop_file(g_file_new_for_path(filename.c_str()));
- _desktop_file_monitor = g_file_monitor_file(desktop_file, G_FILE_MONITOR_NONE,
+ desktop_file_monitor_ = g_file_monitor_file(desktop_file, G_FILE_MONITOR_NONE,
nullptr, nullptr);
- g_file_monitor_set_rate_limit(_desktop_file_monitor, 2000);
+ g_file_monitor_set_rate_limit(desktop_file_monitor_, 2000);
- _gsignals.Add<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent>(_desktop_file_monitor, "changed",
+ glib_signals_.Add<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent>(desktop_file_monitor_, "changed",
[this, desktop_file] (GFileMonitor*, GFile*, GFile*, GFileMonitorEvent event_type) {
switch (event_type)
{
@@ -600,7 +321,7 @@ void ApplicationLauncherIcon::UpdateDesktopFile()
bool update_saved_uri = (!filename.empty() && app_->sticky());
if (update_saved_uri)
- SimpleLauncherIcon::UnStick();
+ WindowedLauncherIcon::UnStick();
uri_changed.emit(new_uri);
@@ -614,22 +335,6 @@ std::string ApplicationLauncherIcon::DesktopFile() const
return app_->desktop_file();
}
-void ApplicationLauncherIcon::AddProperties(debug::IntrospectionData& introspection)
-{
- SimpleLauncherIcon::AddProperties(introspection);
-
- std::vector<Window> xids;
- for (auto const& window : GetWindows())
- xids.push_back(window->window_id());
-
- introspection
- .add("desktop_file", DesktopFile())
- .add("desktop_id", app_->desktop_id())
- .add("xids", glib::Variant::FromVector(xids))
- .add("sticky", IsSticky())
- .add("startup_notification_timestamp", _startup_notification_timestamp);
-}
-
void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const& uris, Time timestamp)
{
glib::Error error;
@@ -639,9 +344,9 @@ void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const&
GdkDisplay* display = gdk_display_get_default();
glib::Object<GdkAppLaunchContext> app_launch_context(gdk_display_get_app_launch_context(display));
- _startup_notification_timestamp = timestamp;
- if (_startup_notification_timestamp > 0)
- gdk_app_launch_context_set_timestamp(app_launch_context, _startup_notification_timestamp);
+ startup_notification_timestamp_ = timestamp;
+ if (startup_notification_timestamp_ > 0)
+ gdk_app_launch_context_set_timestamp(app_launch_context, startup_notification_timestamp_);
if (g_app_info_supports_uris(appInfo))
{
@@ -705,83 +410,40 @@ void ApplicationLauncherIcon::Focus(ActionArg arg)
app_->Focus(show_only_visible, arg.monitor);
}
-bool ApplicationLauncherIcon::Spread(bool current_desktop, int state, bool force)
-{
- std::vector<Window> windows;
- for (auto& window : GetWindows(current_desktop ? WindowFilter::ON_CURRENT_DESKTOP : 0))
- windows.push_back(window->window_id());
-
- return WindowManager::Default().ScaleWindowGroup(windows, state, force);
-}
-
-void ApplicationLauncherIcon::EnsureWindowState()
-{
- std::vector<int> number_of_windows_on_monitor(monitors::MAX);
-
- for (auto& window: app_->GetWindows())
- {
- int monitor = window->monitor();
- Window window_id = window->window_id();
-
- if (WindowManager::Default().IsWindowOnCurrentDesktop(window_id))
- {
- // If monitor is -1 (or negative), show on all monitors.
- if (monitor < 0)
- {
- for (unsigned j; j < monitors::MAX; ++j)
- ++number_of_windows_on_monitor[j];
- }
- else
- {
- ++number_of_windows_on_monitor[monitor];
- }
- }
- }
-
- for (unsigned i = 0; i < monitors::MAX; ++i)
- SetNumberOfWindowsVisibleOnMonitor(number_of_windows_on_monitor[i], i);
-}
-
-void ApplicationLauncherIcon::EnsureWindowsLocation()
-{
- EnsureWindowState();
- UpdateIconGeometries(GetCenters());
-}
-
void ApplicationLauncherIcon::UpdateDesktopQuickList()
{
std::string const& desktop_file = DesktopFile();
- if (_menu_desktop_shortcuts)
+ if (menu_desktop_shortcuts_)
{
- for (GList *l = dbusmenu_menuitem_get_children(_menu_desktop_shortcuts); l; l = l->next)
+ for (GList *l = dbusmenu_menuitem_get_children(menu_desktop_shortcuts_); l; l = l->next)
{
- _gsignals.Disconnect(l->data, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED);
+ glib_signals_.Disconnect(l->data, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED);
}
- _menu_desktop_shortcuts = nullptr;
+ menu_desktop_shortcuts_ = nullptr;
}
if (desktop_file.empty())
return;
- _menu_desktop_shortcuts = dbusmenu_menuitem_new();
- dbusmenu_menuitem_set_root(_menu_desktop_shortcuts, TRUE);
+ menu_desktop_shortcuts_ = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_set_root(menu_desktop_shortcuts_, TRUE);
// Build a desktop shortcuts object and tell it that our
// environment is Unity to handle the filtering
- _desktop_shortcuts = indicator_desktop_shortcuts_new(desktop_file.c_str(), "Unity");
+ desktop_shortcuts_ = indicator_desktop_shortcuts_new(desktop_file.c_str(), "Unity");
// This will get us a list of the nicks available, it should
// always be at least one entry of NULL if there either aren't
// any or they're filtered for the environment we're in
- const gchar** nicks = indicator_desktop_shortcuts_get_nicks(_desktop_shortcuts);
+ const gchar** nicks = indicator_desktop_shortcuts_get_nicks(desktop_shortcuts_);
for (int index = 0; nicks[index]; ++index)
{
// Build a dbusmenu item for each nick that is the desktop
// file that is built from it's name and includes a callback
// to the desktop shortcuts object to execute the nick
- glib::String name(indicator_desktop_shortcuts_nick_get_name(_desktop_shortcuts,
+ glib::String name(indicator_desktop_shortcuts_nick_get_name(desktop_shortcuts_,
nicks[index]));
glib::Object<DbusmenuMenuitem> item(dbusmenu_menuitem_new());
dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, name);
@@ -789,16 +451,16 @@ void ApplicationLauncherIcon::UpdateDesktopQuickList()
dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
auto nick = glib::gchar_to_string(nicks[index]);
- _gsignals.Add<void, DbusmenuMenuitem*, gint>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ glib_signals_.Add<void, DbusmenuMenuitem*, gint>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
[this, nick] (DbusmenuMenuitem* item, unsigned timestamp) {
GdkDisplay* display = gdk_display_get_default();
glib::Object<GdkAppLaunchContext> context(gdk_display_get_app_launch_context(display));
gdk_app_launch_context_set_timestamp(context, timestamp);
auto gcontext = glib::object_cast<GAppLaunchContext>(context);
- indicator_desktop_shortcuts_nick_exec_with_context(_desktop_shortcuts, nick.c_str(), gcontext);
+ indicator_desktop_shortcuts_nick_exec_with_context(desktop_shortcuts_, nick.c_str(), gcontext);
});
- dbusmenu_menuitem_child_append(_menu_desktop_shortcuts, item);
+ dbusmenu_menuitem_child_append(menu_desktop_shortcuts_, item);
}
}
@@ -821,60 +483,16 @@ void ApplicationLauncherIcon::UpdateBackgroundColor()
}
}
-void ApplicationLauncherIcon::EnsureMenuItemsWindowsReady()
-{
- // delete all menu items for windows
- _menu_items_windows.clear();
-
- auto const& windows = Windows();
-
- // We only add quicklist menu-items for windows if we have more than one window
- if (windows.size() < 2)
- return;
-
- // add menu items for all open windows
- for (auto const& w : windows)
- {
- auto const& title = w->title();
-
- if (title.empty())
- continue;
-
- glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, title.c_str());
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- dbusmenu_menuitem_property_set_bool(menu_item, QuicklistMenuItem::MARKUP_ACCEL_DISABLED_PROPERTY, true);
- dbusmenu_menuitem_property_set_int(menu_item, QuicklistMenuItem::MAXIMUM_LABEL_WIDTH_PROPERTY, MAXIMUM_QUICKLIST_WIDTH);
-
- Window xid = w->window_id();
- _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- [xid] (DbusmenuMenuitem*, unsigned) {
- WindowManager& wm = WindowManager::Default();
- wm.Activate(xid);
- wm.Raise(xid);
- });
-
- if (w->active())
- {
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_RADIO);
- dbusmenu_menuitem_property_set_int(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED);
- }
-
- _menu_items_windows.push_back(menu_item);
- }
-}
-
void ApplicationLauncherIcon::EnsureMenuItemsStaticQuicklist()
{
// make a client for desktop file actions
- if (!_menu_desktop_shortcuts.IsType(DBUSMENU_TYPE_MENUITEM))
+ if (!menu_desktop_shortcuts_.IsType(DBUSMENU_TYPE_MENUITEM))
{
UpdateDesktopQuickList();
}
}
-void ApplicationLauncherIcon::Quit()
+void ApplicationLauncherIcon::Quit() const
{
app_->Quit();
}
@@ -899,7 +517,7 @@ void ApplicationLauncherIcon::Stick(bool save)
}
else
{
- SimpleLauncherIcon::Stick(save);
+ WindowedLauncherIcon::Stick(save);
if (save)
LogUnityEvent(ApplicationEventType::ACCESS);
@@ -912,11 +530,11 @@ void ApplicationLauncherIcon::UnStick()
return;
LogUnityEvent(ApplicationEventType::ACCESS);
- SimpleLauncherIcon::UnStick();
+ WindowedLauncherIcon::UnStick();
SetQuirk(Quirk::VISIBLE, app_->visible());
app_->sticky = false;
- if (!app_->running())
+ if (!IsRunning())
Remove();
}
@@ -956,10 +574,10 @@ ApplicationSubjectPtr ApplicationLauncherIcon::GetSubject()
void ApplicationLauncherIcon::EnsureMenuItemsDefaultReady()
{
- if (_menu_items.size() == MenuItemType::SIZE)
+ if (menu_items_.size() == MenuItemType::SIZE)
return;
- _menu_items.resize(MenuItemType::SIZE);
+ menu_items_.resize(MenuItemType::SIZE);
/* (Un)Stick to Launcher */
glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
@@ -968,12 +586,12 @@ void ApplicationLauncherIcon::EnsureMenuItemsDefaultReady()
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ glib_signals_.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
[this] (DbusmenuMenuitem*, unsigned) {
ToggleSticky();
});
- _menu_items[MenuItemType::STICK] = menu_item;
+ menu_items_[MenuItemType::STICK] = menu_item;
/* Quit */
menu_item = dbusmenu_menuitem_new();
@@ -981,17 +599,17 @@ void ApplicationLauncherIcon::EnsureMenuItemsDefaultReady()
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ glib_signals_.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
[this] (DbusmenuMenuitem*, unsigned) {
Quit();
});
- _menu_items[MenuItemType::QUIT] = menu_item;
+ menu_items_[MenuItemType::QUIT] = menu_item;
/* Separator */
menu_item = dbusmenu_menuitem_new();
dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- _menu_items[MenuItemType::SEPARATOR] = menu_item;
+ menu_items_[MenuItemType::SEPARATOR] = menu_item;
}
AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
@@ -1003,7 +621,7 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
EnsureMenuItemsDefaultReady();
EnsureMenuItemsStaticQuicklist();
- for (auto const& menus : {GetRemoteMenus(), _menu_desktop_shortcuts})
+ for (auto const& menus : {GetRemoteMenus(), menu_desktop_shortcuts_})
{
if (!menus.IsType(DBUSMENU_TYPE_MENUITEM))
continue;
@@ -1049,11 +667,11 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
if (separator_needed)
{
- result.push_back(_menu_items[MenuItemType::SEPARATOR]);
+ result.push_back(menu_items_[MenuItemType::SEPARATOR]);
separator_needed = false;
}
- if (!_menu_items[MenuItemType::APP_NAME])
+ if (!menu_items_[MenuItemType::APP_NAME])
{
glib::String app_name(g_markup_escape_text(app_->title().c_str(), -1));
std::string bold_app_name("<b>"+app_name.Str()+"</b>");
@@ -1064,7 +682,7 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
dbusmenu_menuitem_property_set_bool(item, QuicklistMenuItem::MARKUP_ENABLED_PROPERTY, TRUE);
- _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ glib_signals_.Add<void, DbusmenuMenuitem*, unsigned>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
[this] (DbusmenuMenuitem*, unsigned timestamp) {
_source_manager.AddIdle([this, timestamp] {
ActivateLauncherIcon(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp));
@@ -1072,25 +690,23 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
});
});
- _menu_items[MenuItemType::APP_NAME] = item;
+ menu_items_[MenuItemType::APP_NAME] = item;
}
- result.push_back(_menu_items[MenuItemType::APP_NAME]);
- result.push_back(_menu_items[MenuItemType::SEPARATOR]);
+ result.push_back(menu_items_[MenuItemType::APP_NAME]);
+ result.push_back(menu_items_[MenuItemType::SEPARATOR]);
- EnsureMenuItemsWindowsReady();
+ auto const& windows_menu_items = GetWindowsMenuItems();
- if (!_menu_items_windows.empty())
+ if (!windows_menu_items.empty())
{
- for (auto const& it : _menu_items_windows)
- result.push_back(it);
-
- result.push_back(_menu_items[MenuItemType::SEPARATOR]);
+ result.insert(end(result), begin(windows_menu_items), end(windows_menu_items));
+ result.push_back(menu_items_[MenuItemType::SEPARATOR]);
}
const char* label = !IsSticky() ? _("Lock to Launcher") : _("Unlock from Launcher");
- dbusmenu_menuitem_property_set(_menu_items[MenuItemType::STICK], DBUSMENU_MENUITEM_PROP_LABEL, label);
- result.push_back(_menu_items[MenuItemType::STICK]);
+ dbusmenu_menuitem_property_set(menu_items_[MenuItemType::STICK], DBUSMENU_MENUITEM_PROP_LABEL, label);
+ result.push_back(menu_items_[MenuItemType::STICK]);
if (IsRunning())
{
@@ -1102,7 +718,7 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ glib_signals_.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
[this] (DbusmenuMenuitem*, unsigned) {
app_->CreateLocalDesktopFile();
});
@@ -1111,7 +727,7 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
}
if (!quit_item)
- quit_item = _menu_items[MenuItemType::QUIT];
+ quit_item = menu_items_[MenuItemType::QUIT];
dbusmenu_menuitem_property_set(quit_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Quit"));
result.push_back(quit_item);
@@ -1125,28 +741,7 @@ void ApplicationLauncherIcon::UpdateIconGeometries(std::vector<nux::Point3> cons
if (app_->type() == AppType::WEBAPP)
return;
- nux::Geometry geo(0, 0, icon_size, icon_size);
-
- for (auto& window : app_->GetWindows())
- {
- Window xid = window->window_id();
- int monitor = GetCenterForMonitor(window->monitor()).first;
-
- if (monitor < 0)
- {
- WindowManager::Default().SetWindowIconGeometry(xid, nux::Geometry());
- continue;
- }
-
- geo.x = centers[monitor].x - icon_size / 2;
- geo.y = centers[monitor].y - icon_size / 2;
- WindowManager::Default().SetWindowIconGeometry(xid, geo);
- }
-}
-
-void ApplicationLauncherIcon::OnCenterStabilized(std::vector<nux::Point3> const& centers)
-{
- UpdateIconGeometries(centers);
+ return WindowedLauncherIcon::UpdateIconGeometries(centers);
}
void ApplicationLauncherIcon::UpdateRemoteUri()
@@ -1155,69 +750,21 @@ void ApplicationLauncherIcon::UpdateRemoteUri()
if (!desktop_id.empty())
{
- _remote_uri = FavoriteStore::URI_PREFIX_APP + desktop_id;
+ remote_uri_ = FavoriteStore::URI_PREFIX_APP + desktop_id;
}
else
{
- _remote_uri.clear();
+ remote_uri_.clear();
}
}
std::string ApplicationLauncherIcon::GetRemoteUri() const
{
- return _remote_uri;
-}
-
-void ApplicationLauncherIcon::OnDndEnter()
-{
- auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
-
- _source_manager.AddTimeout(1000, [this, timestamp] {
- bool to_spread = GetWindows(WindowFilter::ON_CURRENT_DESKTOP).size() > 1;
-
- if (!to_spread)
- WindowManager::Default().TerminateScale();
-
- if (!IsRunning())
- return false;
-
- UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
- Focus(ActionArg(ActionArg::Source::LAUNCHER, 1, timestamp));
-
- if (to_spread)
- Spread(true, COMPIZ_SCALE_DND_SPREAD, false);
-
- return false;
- }, ICON_DND_OVER_TIMEOUT);
-}
-
-void ApplicationLauncherIcon::OnDndLeave()
-{
- _source_manager.Remove(ICON_DND_OVER_TIMEOUT);
-}
-
-bool ApplicationLauncherIcon::IsFileManager()
-{
- auto const& desktop_file = DesktopFile();
-
- return boost::algorithm::ends_with(desktop_file, "org.gnome.Nautilus.desktop") ||
- boost::algorithm::ends_with(desktop_file, "nautilus.desktop") ||
- boost::algorithm::ends_with(desktop_file, "nautilus-folder-handler.desktop") ||
- boost::algorithm::ends_with(desktop_file, "nautilus-home.desktop");
+ return remote_uri_;
}
bool ApplicationLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data)
{
- if (IsFileManager())
- {
- for (auto const& uri : dnd_data.Uris())
- {
- if (boost::algorithm::starts_with(uri, "file://"))
- return true;
- }
- return false;
- }
-
for (auto type : dnd_data.Types())
{
for (auto supported_type : GetSupportedTypes())
@@ -1248,28 +795,6 @@ void ApplicationLauncherIcon::OnAcceptDrop(DndData const& dnd_data)
OpenInstanceWithUris(dnd_data.Uris(), timestamp);
}
-bool ApplicationLauncherIcon::ShowInSwitcher(bool current)
-{
- if (!removed() && IsRunning() && IsVisible())
- {
- // If current is true, we only want to show the current workspace.
- if (!current)
- {
- return true;
- }
- else
- {
- for (unsigned i = 0; i < monitors::MAX; ++i)
- {
- if (WindowVisibleOnMonitor(i))
- return true;
- }
- }
- }
-
- return false;
-}
-
bool ApplicationLauncherIcon::AllowDetailViewInSwitcher() const
{
return app_->type() != AppType::WEBAPP;
@@ -1277,18 +802,11 @@ bool ApplicationLauncherIcon::AllowDetailViewInSwitcher() const
uint64_t ApplicationLauncherIcon::SwitcherPriority()
{
- uint64_t result = 0;
// Webapps always go at the back.
if (app_->type() == AppType::WEBAPP)
- return result;
+ return 0;
- for (auto& window : app_->GetWindows())
- {
- Window xid = window->window_id();
- result = std::max(result, WindowManager::Default().GetWindowActiveNumber(xid));
- }
-
- return result;
+ return WindowedLauncherIcon::SwitcherPriority();
}
nux::Color ApplicationLauncherIcon::BackgroundColor() const
@@ -1296,7 +814,7 @@ nux::Color ApplicationLauncherIcon::BackgroundColor() const
if (use_custom_bg_color_)
return bg_color_;
- return SimpleLauncherIcon::BackgroundColor();
+ return WindowedLauncherIcon::BackgroundColor();
}
const std::set<std::string> ApplicationLauncherIcon::GetSupportedTypes()
@@ -1312,102 +830,17 @@ const std::set<std::string> ApplicationLauncherIcon::GetSupportedTypes()
return supported_types;
}
-void PerformScrollUp(WindowList const& windows, unsigned int progressive_scroll)
-{
- if (progressive_scroll == windows.size() - 1)
- {
- //RestackAbove to preserve Global Stacking Order
- WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(1)->window_id());
- WindowManager::Default().RestackBelow(windows.at(1)->window_id(), windows.at(0)->window_id());
- windows.back()->Focus();
- return;
- }
-
- WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(progressive_scroll + 1)->window_id());
- windows.at(progressive_scroll + 1)->Focus();
-}
-
-void PerformScrollDown(WindowList const& windows, unsigned int progressive_scroll)
-{
- if (!progressive_scroll)
- {
- WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.back()->window_id());
- windows.at(1)->Focus();
- return;
- }
-
- WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(progressive_scroll)->window_id());
- windows.at(progressive_scroll)->Focus();
-}
-
-void ApplicationLauncherIcon::PerformScroll(ScrollDirection direction, Time timestamp)
+std::string ApplicationLauncherIcon::GetName() const
{
- if (timestamp - _last_scroll_timestamp < 150)
- return;
- else if (timestamp - _last_scroll_timestamp > 1500)
- _progressive_scroll = 0;
-
- _last_scroll_timestamp = timestamp;
-
- auto const& windows = GetWindowsOnCurrentDesktopInStackingOrder();
-
- if (windows.empty())
- return;
-
- if (scroll_inactive_icons && !IsActive())
- {
- windows.at(0)->Focus();
- return;
- }
-
- if (!scroll_inactive_icons && !IsActive())
- return;
-
- if (windows.size() <= 1)
- return;
-
- if (direction == ScrollDirection::DOWN)
- ++_progressive_scroll;
- else
- //--_progressive_scroll; but roll to the top of windows
- _progressive_scroll += windows.size() - 1;
- _progressive_scroll %= windows.size();
-
- switch(direction)
- {
- case ScrollDirection::UP:
- PerformScrollUp(windows, _progressive_scroll);
- break;
- case ScrollDirection::DOWN:
- PerformScrollDown(windows, _progressive_scroll);
- break;
- }
+ return "ApplicationLauncherIcon";
}
-WindowList ApplicationLauncherIcon::GetWindowsOnCurrentDesktopInStackingOrder()
+void ApplicationLauncherIcon::AddProperties(debug::IntrospectionData& introspection)
{
- auto windows = GetWindows(WindowFilter::ON_CURRENT_DESKTOP | WindowFilter::ON_ALL_MONITORS);
- auto sorted_windows = WindowManager::Default().GetWindowsInStackingOrder();
-
- // Order the windows
- std::sort(windows.begin(), windows.end(), [&sorted_windows] (ApplicationWindowPtr const& win1, ApplicationWindowPtr const& win2) {
- for (auto const& window : sorted_windows)
- {
- if (window == win1->window_id())
- return false;
- else if (window == win2->window_id())
- return true;
- }
+ WindowedLauncherIcon::AddProperties(introspection);
- return true;
- });
-
- return windows;
-}
-
-std::string ApplicationLauncherIcon::GetName() const
-{
- return "ApplicationLauncherIcon";
+ introspection.add("desktop_file", DesktopFile())
+ .add("desktop_id", app_->desktop_id());
}
} // namespace launcher
diff --git a/launcher/ApplicationLauncherIcon.h b/launcher/ApplicationLauncherIcon.h
index 2ea48c184..afdf0118e 100644
--- a/launcher/ApplicationLauncherIcon.h
+++ b/launcher/ApplicationLauncherIcon.h
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2010-2012 Canonical Ltd
+ * Copyright (C) 2010-2015 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
@@ -18,17 +18,15 @@
* Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
*/
-#ifndef APPLICATIONLAUNCHERICON_H
-#define APPLICATIONLAUNCHERICON_H
+#ifndef APPLICATION_LAUNCHER_ICON_H
+#define APPLICATION_LAUNCHER_ICON_H
-#include <UnityCore/GLibSignal.h>
-#include <UnityCore/GLibWrapper.h>
#include <UnityCore/ConnectionManager.h>
#include <UnityCore/Variant.h>
#include <libindicator/indicator-desktop-shortcuts.h>
-#include "SimpleLauncherIcon.h"
+#include "WindowedLauncherIcon.h"
namespace unity
{
@@ -37,115 +35,74 @@ namespace launcher
class Launcher;
-class ApplicationLauncherIcon : public SimpleLauncherIcon
+class ApplicationLauncherIcon : public virtual WindowedLauncherIcon
{
- NUX_DECLARE_OBJECT_TYPE(ApplicationLauncherIcon, SimpleLauncherIcon);
+ NUX_DECLARE_OBJECT_TYPE(ApplicationLauncherIcon, WindowedLauncherIcon);
public:
- ApplicationLauncherIcon(ApplicationPtr const& app);
+ ApplicationLauncherIcon(ApplicationPtr const&);
virtual ~ApplicationLauncherIcon();
- virtual void ActivateLauncherIcon(ActionArg arg);
-
std::string DesktopFile() const;
- bool IsSticky() const;
- bool IsActive() const;
- bool IsRunning() const;
- bool IsUrgent() const;
-
- virtual bool GetQuirk(Quirk quirk, int monitor = 0) const override;
-
- virtual void Quit();
- virtual void AboutToRemove();
-
- virtual void Stick(bool save = true);
- virtual void UnStick();
-
- virtual bool ShowInSwitcher(bool current);
- virtual bool AllowDetailViewInSwitcher() const override;
- virtual uint64_t SwitcherPriority();
-
- virtual nux::Color BackgroundColor() const;
+ bool IsSticky() const override;
+ bool IsUserVisible() const override;
+ bool GetQuirk(Quirk quirk, int monitor = 0) const override;
- WindowList Windows();
- std::vector<Window> WindowsOnViewport();
- std::vector<Window> WindowsForMonitor(int monitor);
+ void Quit() const override;
- void PerformScroll(ScrollDirection direction, Time timestamp) override;
+ void Stick(bool save = true) override;
+ void UnStick() override;
protected:
void SetApplication(ApplicationPtr const& app);
ApplicationPtr GetApplication() const;
- void Remove();
- void UpdateIconGeometries(std::vector<nux::Point3> const& centers);
- void OnCenterStabilized(std::vector<nux::Point3> const& centers);
- void AddProperties(debug::IntrospectionData&);
- void OnAcceptDrop(DndData const& dnd_data);
- void OnDndEnter();
- void OnDndLeave();
- void OpenInstanceLauncherIcon(Time timestamp) override;
- void ToggleSticky();
- void LogUnityEvent(ApplicationEventType);
- bool IsFileManager();
+ WindowList GetManagedWindows() const override;
- bool OnShouldHighlightOnDrag(DndData const& dnd_data);
- nux::DndAction OnQueryAcceptDrop(DndData const& dnd_data);
+ void LogUnityEvent(ApplicationEventType);
+ void Remove();
- MenuItemsVector GetMenus();
+ void AboutToRemove() override;
+ bool AllowDetailViewInSwitcher() const override;
+ uint64_t SwitcherPriority() override;
+ void UpdateIconGeometries(std::vector<nux::Point3> const& centers) override;
+ nux::Color BackgroundColor() const override;
+ MenuItemsVector GetMenus() override;
+ std::string GetRemoteUri() const override;
- std::string GetRemoteUri() const;
+ void OpenInstanceLauncherIcon(Time timestamp) override;
+ void OpenInstanceWithUris(std::set<std::string> const& uris, Time timestamp);
+ void Focus(ActionArg arg) override;
- bool HandlesSpread() { return true; }
- std::string GetName() const;
+ void OnAcceptDrop(DndData const&) override;
+ bool OnShouldHighlightOnDrag(DndData const&) override;
+ nux::DndAction OnQueryAcceptDrop(DndData const&) override;
- void UpdateDesktopFile();
- void UpdateRemoteUri();
- std::string _desktop_file;
-
-private:
- typedef unsigned long int WindowFilterMask;
- enum WindowFilter
- {
- MAPPED = (1 << 0),
- USER_VISIBLE = (1 << 1),
- ON_CURRENT_DESKTOP = (1 << 2),
- ON_ALL_MONITORS = (1 << 3),
- };
+ std::string GetName() const override;
+ void AddProperties(debug::IntrospectionData&) override;
void UnsetApplication();
void SetupApplicationSignalsConnections();
- void EnsureWindowState();
- void EnsureWindowsLocation();
- void EnsureMenuItemsWindowsReady();
void EnsureMenuItemsDefaultReady();
void EnsureMenuItemsStaticQuicklist();
void UpdateBackgroundColor();
void UpdateDesktopQuickList();
+ void UpdateDesktopFile();
+ void UpdateRemoteUri();
+ void ToggleSticky();
+ void OnApplicationClosed();
- void OpenInstanceWithUris(std::set<std::string> const& uris, Time timestamp);
- void Focus(ActionArg arg);
- bool Spread(bool current_desktop, int state, bool force);
-
- void OnWindowMinimized(guint32 xid);
-
- WindowList GetWindows(WindowFilterMask filter = 0, int monitor = -1);
const std::set<std::string> GetSupportedTypes();
- WindowList GetWindowsOnCurrentDesktopInStackingOrder();
ApplicationSubjectPtr GetSubject();
ApplicationPtr app_;
- std::string _remote_uri;
- Time _startup_notification_timestamp;
- Time _last_scroll_timestamp;
- unsigned int _progressive_scroll;
- std::set<std::string> _supported_types;
- std::vector<glib::Object<DbusmenuMenuitem>> _menu_items;
- std::vector<glib::Object<DbusmenuMenuitem>> _menu_items_windows;
- glib::Object<IndicatorDesktopShortcuts> _desktop_shortcuts;
- glib::Object<DbusmenuMenuitem> _menu_desktop_shortcuts;
- glib::Object<GFileMonitor> _desktop_file_monitor;
- glib::SignalManager _gsignals;
+ std::string remote_uri_;
+ Time startup_notification_timestamp_;
+ std::set<std::string> supported_types_;
+ MenuItemsVector menu_items_;
+ glib::Object<IndicatorDesktopShortcuts> desktop_shortcuts_;
+ glib::Object<DbusmenuMenuitem> menu_desktop_shortcuts_;
+ glib::Object<GFileMonitor> desktop_file_monitor_;
bool use_custom_bg_color_;
nux::Color bg_color_;
@@ -153,7 +110,7 @@ private:
connection::Manager signals_conn_;
};
-}
-}
+} // namespace launcher
+} // namespace unity
-#endif // BAMFLAUNCHERICON_H
+#endif // APPLICATION_LAUNCHER_ICON_H
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index f832a23e9..229d981c9 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -32,6 +32,7 @@ set (LAUNCHER_SOURCES
FavoriteStore.cpp
FavoriteStoreGSettings.cpp
FavoriteStorePrivate.cpp
+ FileManagerLauncherIcon.cpp
HudLauncherIcon.cpp
Launcher.cpp
LauncherController.cpp
@@ -55,12 +56,14 @@ set (LAUNCHER_SOURCES
SingleMonitorLauncherIcon.cpp
SoftwareCenterLauncherIcon.cpp
SpacerLauncherIcon.cpp
+ StorageLauncherIcon.cpp
Tooltip.cpp
TooltipManager.cpp
TrashLauncherIcon.cpp
VolumeImp.cpp
VolumeLauncherIcon.cpp
VolumeMonitorWrapper.cpp
+ WindowedLauncherIcon.cpp
XdndCollectionWindowImp.cpp
XdndManagerImp.cpp
XdndStartStopNotifier.cpp
diff --git a/launcher/DesktopLauncherIcon.cpp b/launcher/DesktopLauncherIcon.cpp
index cec293077..df9a982aa 100644
--- a/launcher/DesktopLauncherIcon.cpp
+++ b/launcher/DesktopLauncherIcon.cpp
@@ -77,5 +77,10 @@ bool DesktopLauncherIcon::ShowInSwitcher(bool current)
return show_in_switcher_;
}
+uint64_t DesktopLauncherIcon::SwitcherPriority()
+{
+ return std::numeric_limits<uint64_t>::max();
+}
+
} // namespace launcher
} // namespace unity
diff --git a/launcher/DesktopLauncherIcon.h b/launcher/DesktopLauncherIcon.h
index 6778b59a6..c17099165 100644
--- a/launcher/DesktopLauncherIcon.h
+++ b/launcher/DesktopLauncherIcon.h
@@ -37,6 +37,7 @@ public:
protected:
void ActivateLauncherIcon(ActionArg arg);
+ uint64_t SwitcherPriority() override;
std::string GetName() const;
std::string GetRemoteUri() const;
diff --git a/launcher/DeviceLauncherSection.h b/launcher/DeviceLauncherSection.h
index 358b405c4..7824cca79 100644
--- a/launcher/DeviceLauncherSection.h
+++ b/launcher/DeviceLauncherSection.h
@@ -37,10 +37,14 @@ namespace launcher
class DeviceLauncherSection : public sigc::trackable
{
public:
+ typedef std::shared_ptr<DeviceLauncherSection> Ptr;
+
DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr const& volume_monitor = nullptr,
DevicesSettings::Ptr const& devices_settings = nullptr,
DeviceNotificationDisplay::Ptr const& notifications = nullptr);
+ virtual ~DeviceLauncherSection() = default;
+
std::vector<VolumeLauncherIcon::Ptr> GetIcons() const;
sigc::signal<void, AbstractLauncherIcon::Ptr const&> icon_added;
diff --git a/launcher/FileManagerLauncherIcon.cpp b/launcher/FileManagerLauncherIcon.cpp
new file mode 100644
index 000000000..d5895ad0f
--- /dev/null
+++ b/launcher/FileManagerLauncherIcon.cpp
@@ -0,0 +1,128 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 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: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#include "FileManagerLauncherIcon.h"
+
+#include <boost/algorithm/string.hpp>
+#include <NuxCore/Logger.h>
+#include <UnityCore/DesktopUtilities.h>
+
+#include "unity-shared/GnomeFileManager.h"
+
+namespace unity
+{
+namespace launcher
+{
+namespace
+{
+DECLARE_LOGGER(logger, "unity.launcher.icon.filemanager");
+const std::string TRASH_URI = "trash:";
+const std::string TRASH_PATH = "file://" + DesktopUtilities::GetUserTrashDirectory();
+const std::string DEFAULT_ICON = "system-file-manager";
+}
+
+FileManagerLauncherIcon::FileManagerLauncherIcon(ApplicationPtr const& app, DeviceLauncherSection::Ptr const& dev, FileManager::Ptr const& fm)
+ : WindowedLauncherIcon(IconType::APPLICATION)
+ , ApplicationLauncherIcon(app)
+ , StorageLauncherIcon(GetIconType(), fm ? fm : GnomeFileManager::Get())
+ , devices_(dev)
+{
+ // We disconnect from ApplicationLauncherIcon app signals, as we manage them manually
+ signals_conn_.Clear();
+
+ signals_conn_.Add(app_->desktop_file.changed.connect([this](std::string const& desktop_file) {
+ LOG_DEBUG(logger) << tooltip_text() << " desktop_file now " << desktop_file;
+ UpdateDesktopFile();
+ }));
+
+ signals_conn_.Add(app_->closed.connect([this] {
+ LOG_DEBUG(logger) << tooltip_text() << " closed";
+ OnApplicationClosed();
+ }));
+
+ signals_conn_.Add(app_->title.changed.connect([this](std::string const& name) {
+ LOG_DEBUG(logger) << tooltip_text() << " name now " << name;
+ menu_items_.clear();
+ tooltip_text = name;
+ }));
+
+ signals_conn_.Add(app_->icon.changed.connect([this](std::string const& icon) {
+ LOG_DEBUG(logger) << tooltip_text() << " icon now " << icon;
+ icon_name = (icon.empty() ? DEFAULT_ICON : icon);
+ }));
+
+ UpdateStorageWindows();
+}
+
+void FileManagerLauncherIcon::Focus(ActionArg arg)
+{
+ WindowedLauncherIcon::Focus(arg);
+}
+
+void FileManagerLauncherIcon::Quit() const
+{
+ WindowedLauncherIcon::Quit();
+}
+
+bool FileManagerLauncherIcon::IsLocationManaged(std::string const& location) const
+{
+ if (location.empty())
+ return true;
+
+ if (boost::algorithm::starts_with(location, TRASH_URI))
+ return false;
+
+ if (boost::algorithm::starts_with(location, TRASH_PATH))
+ return false;
+
+ for (auto const& volume_icon : devices_->GetIcons())
+ {
+ auto const& volume_uri = volume_icon->GetVolumeUri();
+ if (!volume_uri.empty() && boost::algorithm::starts_with(location, volume_uri))
+ return false;
+ }
+
+ return true;
+}
+
+WindowList FileManagerLauncherIcon::GetManagedWindows() const
+{
+ return StorageLauncherIcon::GetManagedWindows();
+}
+
+WindowList FileManagerLauncherIcon::GetStorageWindows() const
+{
+ WindowList fm_windows;
+
+ for (auto const& app_win : ApplicationLauncherIcon::GetManagedWindows())
+ {
+ if (IsLocationManaged(file_manager_->LocationForWindow(app_win)))
+ fm_windows.push_back(app_win);
+ }
+
+ return fm_windows;
+}
+
+bool FileManagerLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data)
+{
+ return StorageLauncherIcon::OnShouldHighlightOnDrag(dnd_data);
+}
+
+} // namespace launcher
+} // namespace unity
diff --git a/launcher/FileManagerLauncherIcon.h b/launcher/FileManagerLauncherIcon.h
new file mode 100644
index 000000000..1996747a3
--- /dev/null
+++ b/launcher/FileManagerLauncherIcon.h
@@ -0,0 +1,52 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 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: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#ifndef FILEMANAGER_LAUNCHER_ICON_H
+#define FILEMANAGER_LAUNCHER_ICON_H
+
+#include "ApplicationLauncherIcon.h"
+#include "StorageLauncherIcon.h"
+#include "DeviceLauncherSection.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class FileManagerLauncherIcon : public ApplicationLauncherIcon, public StorageLauncherIcon
+{
+public:
+ FileManagerLauncherIcon(ApplicationPtr const&, DeviceLauncherSection::Ptr const&, FileManager::Ptr const& = nullptr);
+
+private:
+ WindowList GetManagedWindows() const override;
+ WindowList GetStorageWindows() const override;
+ void Focus(ActionArg arg) override;
+ void Quit() const override;
+ bool OnShouldHighlightOnDrag(DndData const& dnd_data) override;
+
+ bool IsLocationManaged(std::string const&) const;
+
+ DeviceLauncherSection::Ptr devices_;
+};
+
+} // namespace launcher
+} // namespace unity
+
+#endif // FILEMANAGER_LAUNCHER_ICON_H
diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp
index dc6b725ca..62fa5fb1b 100644
--- a/launcher/Launcher.cpp
+++ b/launcher/Launcher.cpp
@@ -578,16 +578,9 @@ void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, RenderArg&
else
{
if (options()->show_for_all)
- arg.window_indicators = std::max<int> (icon->WindowsOnViewport().size(), 1);
+ arg.window_indicators = std::max<int>(icon->WindowsVisibleOnViewport(), 1);
else
- arg.window_indicators = std::max<int> (icon->WindowsForMonitor(monitor).size(), 1);
-
- if (icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH ||
- icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
- {
- // TODO: also these icons should respect the actual windows they have
- arg.window_indicators = 0;
- }
+ arg.window_indicators = std::max<int>(icon->WindowsVisibleOnMonitor(monitor), 1);
}
arg.backlight_intensity = IconBackgroundIntensity(icon);
diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp
index 778a0637c..be9516fa9 100644
--- a/launcher/LauncherController.cpp
+++ b/launcher/LauncherController.cpp
@@ -21,6 +21,7 @@
#include "config.h"
#include <glib/gi18n-lib.h>
+#include <boost/algorithm/string.hpp>
#include <Nux/Nux.h>
#include <Nux/HLayout.h>
@@ -32,6 +33,7 @@
#include "DesktopLauncherIcon.h"
#include "VolumeLauncherIcon.h"
#include "FavoriteStore.h"
+#include "FileManagerLauncherIcon.h"
#include "HudLauncherIcon.h"
#include "LauncherController.h"
#include "LauncherControllerPrivate.h"
@@ -102,13 +104,13 @@ std::string CreateAppUriNameFromDesktopPath(const std::string &desktop_path)
return FavoriteStore::URI_PREFIX_APP + DesktopUtilities::GetDesktopID(desktop_path);
}
-
}
Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager, ui::EdgeBarrierController::Ptr const& edge_barriers)
: parent_(parent)
, model_(std::make_shared<LauncherModel>())
, xdnd_manager_(xdnd_manager)
+ , device_section_(std::make_shared<DeviceLauncherSection>())
, expo_icon_(new ExpoLauncherIcon())
, desktop_icon_(new DesktopLauncherIcon())
, edge_barriers_(edge_barriers)
@@ -342,6 +344,21 @@ Launcher* Controller::Impl::CreateLauncher()
return launcher;
}
+ApplicationLauncherIcon* Controller::Impl::CreateAppLauncherIcon(ApplicationPtr const& app)
+{
+ auto const& desktop_file = app->desktop_file();
+
+ if (boost::algorithm::ends_with(desktop_file, "org.gnome.Nautilus.desktop") ||
+ boost::algorithm::ends_with(desktop_file, "nautilus.desktop") ||
+ boost::algorithm::ends_with(desktop_file, "nautilus-folder-handler.desktop") ||
+ boost::algorithm::ends_with(desktop_file, "nautilus-home.desktop"))
+ {
+ return new FileManagerLauncherIcon(app, device_section_);
+ }
+
+ return new ApplicationLauncherIcon(app);
+}
+
void Controller::Impl::OnLauncherAddRequest(std::string const& icon_uri, AbstractLauncherIcon::Ptr const& icon_before)
{
std::string app_uri;
@@ -838,7 +855,7 @@ void Controller::Impl::OnApplicationStarted(ApplicationPtr const& app)
if (app->sticky() || app->seen())
return;
- AbstractLauncherIcon::Ptr icon(new ApplicationLauncherIcon(app));
+ AbstractLauncherIcon::Ptr icon(CreateAppLauncherIcon(app));
RegisterIcon(icon, GetLastIconPriority<ApplicationLauncherIcon>(local::RUNNING_APPS_URI));
}
@@ -875,11 +892,11 @@ AbstractLauncherIcon::Ptr Controller::Impl::CreateFavoriteIcon(std::string const
if (!app || app->seen())
return result;
- result = AbstractLauncherIcon::Ptr(new ApplicationLauncherIcon(app));
+ result = AbstractLauncherIcon::Ptr(CreateAppLauncherIcon(app));
}
else if (icon_uri.find(FavoriteStore::URI_PREFIX_DEVICE) == 0)
{
- auto const& devices = device_section_.GetIcons();
+ auto const& devices = device_section_->GetIcons();
auto const& icon = std::find_if(devices.begin(), devices.end(),
[&icon_uri](AbstractLauncherIcon::Ptr const& i) { return (i->RemoteUri() == icon_uri); });
@@ -954,7 +971,7 @@ void Controller::Impl::AddRunningApps()
<< (app->seen() ? "yes" : "no");
if (!app->seen())
{
- AbstractLauncherIcon::Ptr icon(new ApplicationLauncherIcon(app));
+ AbstractLauncherIcon::Ptr icon(CreateAppLauncherIcon(app));
icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::VISIBLE);
RegisterIcon(icon, ++sort_priority_);
}
@@ -964,7 +981,7 @@ void Controller::Impl::AddRunningApps()
void Controller::Impl::AddDevices()
{
auto& fav_store = FavoriteStore::Instance();
- for (auto const& icon : device_section_.GetIcons())
+ for (auto const& icon : device_section_->GetIcons())
{
if (!icon->IsSticky() && !fav_store.IsFavorite(icon->RemoteUri()))
{
@@ -1044,7 +1061,7 @@ void Controller::Impl::SetupIcons()
ApplicationManager::Default().application_started
.connect(sigc::mem_fun(this, &Impl::OnApplicationStarted));
- device_section_.icon_added.connect(sigc::mem_fun(this, &Impl::OnDeviceIconAdded));
+ device_section_->icon_added.connect(sigc::mem_fun(this, &Impl::OnDeviceIconAdded));
favorite_store.favorite_added.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteAdded));
favorite_store.favorite_removed.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteRemoved));
favorite_store.reordered.connect(sigc::mem_fun(this, &Impl::ResetIconPriorities));
diff --git a/launcher/LauncherControllerPrivate.h b/launcher/LauncherControllerPrivate.h
index 30a0886b9..914e6877b 100644
--- a/launcher/LauncherControllerPrivate.h
+++ b/launcher/LauncherControllerPrivate.h
@@ -87,6 +87,7 @@ public:
void RegisterIcon(AbstractLauncherIcon::Ptr const& icon, int priority = std::numeric_limits<int>::min());
+ ApplicationLauncherIcon* CreateAppLauncherIcon(ApplicationPtr const&);
AbstractLauncherIcon::Ptr CreateFavoriteIcon(std::string const& icon_uri, bool emit_signal = false);
AbstractLauncherIcon::Ptr GetIconByUri(std::string const& icon_uri);
SoftwareCenterLauncherIcon::Ptr CreateSCLauncherIcon(std::string const& file_path, std::string const& aptdaemon_trans_id, std::string const& icon_path);
@@ -122,7 +123,7 @@ public:
nux::ObjectPtr<Launcher> launcher_;
nux::ObjectPtr<Launcher> keyboard_launcher_;
XdndManager::Ptr xdnd_manager_;
- DeviceLauncherSection device_section_;
+ DeviceLauncherSection::Ptr device_section_;
LauncherEntryRemoteModel remote_model_;
AbstractLauncherIcon::Ptr expo_icon_;
AbstractLauncherIcon::Ptr desktop_icon_;
diff --git a/launcher/LauncherIcon.cpp b/launcher/LauncherIcon.cpp
index 5da35d1ce..1825ac60a 100644
--- a/launcher/LauncherIcon.cpp
+++ b/launcher/LauncherIcon.cpp
@@ -150,16 +150,26 @@ void LauncherIcon::LoadQuicklist()
QuicklistManager::Default()->RegisterQuicklist(_quicklist);
}
-const bool LauncherIcon::WindowVisibleOnMonitor(int monitor)
+bool LauncherIcon::WindowVisibleOnMonitor(int monitor) const
{
return _has_visible_window[monitor];
}
-const bool LauncherIcon::WindowVisibleOnViewport()
+bool LauncherIcon::WindowVisibleOnViewport() const
{
return _has_visible_window.any();
}
+size_t LauncherIcon::WindowsVisibleOnMonitor(int monitor) const
+{
+ return _number_of_visible_windows[monitor];
+}
+
+size_t LauncherIcon::WindowsVisibleOnViewport() const
+{
+ return std::accumulate(begin(_number_of_visible_windows), end(_number_of_visible_windows), 0);
+}
+
std::string
LauncherIcon::GetName() const
{
diff --git a/launcher/LauncherIcon.h b/launcher/LauncherIcon.h
index 65af7e08f..d42668ed5 100644
--- a/launcher/LauncherIcon.h
+++ b/launcher/LauncherIcon.h
@@ -82,7 +82,7 @@ public:
nux::Point3 GetCenter(int monitor);
- virtual void Activate(ActionArg arg);
+ void Activate(ActionArg arg);
void OpenInstance(ActionArg arg);
@@ -94,15 +94,19 @@ public:
void SetOrder(int order);
- virtual WindowList Windows() { return WindowList(); }
+ WindowList Windows() { return WindowList(); }
- virtual std::vector<Window> WindowsOnViewport() { return std::vector<Window> (); }
+ WindowList WindowsOnViewport() { return WindowList(); }
- virtual std::vector<Window> WindowsForMonitor(int monitor) { return std::vector<Window> (); }
+ WindowList WindowsForMonitor(int monitor) { return WindowList(); }
- const bool WindowVisibleOnMonitor(int monitor);
+ bool WindowVisibleOnMonitor(int monitor) const;
- const bool WindowVisibleOnViewport();
+ bool WindowVisibleOnViewport() const;
+
+ size_t WindowsVisibleOnMonitor(int monitor) const;
+
+ size_t WindowsVisibleOnViewport() const;
float PresentUrgency();
diff --git a/launcher/MockLauncherIcon.h b/launcher/MockLauncherIcon.h
index 335f1e64b..1dae29cd8 100644
--- a/launcher/MockLauncherIcon.h
+++ b/launcher/MockLauncherIcon.h
@@ -112,34 +112,34 @@ public:
return result;
}
- std::vector<Window> WindowsOnViewport ()
+ WindowList WindowsOnViewport()
{
- std::vector<Window> result;
+ WindowList result;
- result.push_back ((100 << 16) + 200);
- result.push_back ((500 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((200 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((100 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((600 << 16) + 200);
+ result.push_back(std::make_shared<MockApplicationWindow>((100 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((500 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((200 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((100 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((600 << 16) + 200));
return result;
}
- std::vector<Window> WindowsForMonitor (int monitor)
+ WindowList WindowsForMonitor(int monitor)
{
- std::vector<Window> result;
+ WindowList result;
- result.push_back ((100 << 16) + 200);
- result.push_back ((500 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((200 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((100 << 16) + 200);
- result.push_back ((300 << 16) + 200);
- result.push_back ((600 << 16) + 200);
+ result.push_back(std::make_shared<MockApplicationWindow>((100 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((500 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((200 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((100 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((300 << 16) + 200));
+ result.push_back(std::make_shared<MockApplicationWindow>((600 << 16) + 200));
return result;
}
@@ -194,16 +194,26 @@ public:
return 7;
}
- const bool WindowVisibleOnViewport()
+ bool WindowVisibleOnViewport() const
{
return false;
}
- const bool WindowVisibleOnMonitor(int monitor)
+ bool WindowVisibleOnMonitor(int monitor) const
{
return false;
}
+ size_t WindowsVisibleOnMonitor(int monitor) const
+ {
+ return 0;
+ }
+
+ size_t WindowsVisibleOnViewport() const
+ {
+ return 0;
+ }
+
void SetVisibleOnMonitor(int monitor, bool visible) {}
bool IsVisibleOnMonitor(int monitor) const
diff --git a/launcher/SoftwareCenterLauncherIcon.cpp b/launcher/SoftwareCenterLauncherIcon.cpp
index abd6abedf..fc842e9cb 100644
--- a/launcher/SoftwareCenterLauncherIcon.cpp
+++ b/launcher/SoftwareCenterLauncherIcon.cpp
@@ -46,7 +46,8 @@ NUX_IMPLEMENT_OBJECT_TYPE(SoftwareCenterLauncherIcon);
SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(ApplicationPtr const& app,
std::string const& aptdaemon_trans_id,
std::string const& icon_path)
- : ApplicationLauncherIcon(app)
+ : WindowedLauncherIcon(IconType::APPLICATION)
+ , ApplicationLauncherIcon(app)
, aptdaemon_trans_(std::make_shared<glib::DBusProxy>("org.debian.apt",
aptdaemon_trans_id,
"org.debian.apt.transaction",
diff --git a/launcher/StorageLauncherIcon.cpp b/launcher/StorageLauncherIcon.cpp
new file mode 100644
index 000000000..fcc367b72
--- /dev/null
+++ b/launcher/StorageLauncherIcon.cpp
@@ -0,0 +1,119 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 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: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#include "StorageLauncherIcon.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+StorageLauncherIcon::StorageLauncherIcon(AbstractLauncherIcon::IconType icon_type, FileManager::Ptr const& fm)
+ : WindowedLauncherIcon(icon_type)
+ , file_manager_(fm)
+{
+ file_manager_->locations_changed.connect(sigc::mem_fun(this, &StorageLauncherIcon::UpdateStorageWindows));
+}
+
+void StorageLauncherIcon::UpdateStorageWindows()
+{
+ bool active = false;
+ bool urgent = false;
+ bool check_visibility = (GetIconType() == IconType::APPLICATION);
+ bool visible = IsSticky();
+
+ managed_windows_ = GetStorageWindows();
+ windows_connections_.Clear();
+
+ for (auto const& win : managed_windows_)
+ {
+ windows_connections_.Add(win->monitor.changed.connect([this] (int) { EnsureWindowsLocation(); }));
+ windows_connections_.Add(win->urgent.changed.connect([this] (bool) { OnWindowStateChanged(); }));
+ windows_connections_.Add(win->active.changed.connect([this] (bool) { OnWindowStateChanged(); }));
+ windows_connections_.Add(win->closed.connect([this] { UpdateStorageWindows(); }));
+
+ if (!active && win->active())
+ active = true;
+
+ if (!urgent && win->urgent())
+ urgent = true;
+
+ if (check_visibility)
+ {
+ windows_connections_.Add(win->visible.changed.connect([this] (bool) { OnWindowStateChanged(); }));
+
+ if (!visible && win->visible())
+ visible = true;
+ }
+ }
+
+ SetQuirk(Quirk::RUNNING, !managed_windows_.empty());
+ SetQuirk(Quirk::ACTIVE, active);
+ SetQuirk(Quirk::URGENT, urgent);
+
+ if (check_visibility)
+ SetQuirk(Quirk::VISIBLE, visible);
+
+ EnsureWindowsLocation();
+}
+
+WindowList StorageLauncherIcon::GetManagedWindows() const
+{
+ return managed_windows_;
+}
+
+void StorageLauncherIcon::OnWindowStateChanged()
+{
+ bool active = false;
+ bool urgent = false;
+ bool check_visibility = (GetIconType() == IconType::APPLICATION);
+ bool visible = IsSticky();
+
+ for (auto const& win : managed_windows_)
+ {
+ if (!active && win->active())
+ active = true;
+
+ if (!urgent && win->urgent())
+ urgent = true;
+
+ if (check_visibility && !visible && win->visible())
+ visible = true;
+ }
+
+ SetQuirk(Quirk::ACTIVE, active);
+ SetQuirk(Quirk::URGENT, urgent);
+
+ if (check_visibility)
+ SetQuirk(Quirk::VISIBLE, visible);
+}
+
+bool StorageLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data)
+{
+ for (auto const& uri : dnd_data.Uris())
+ {
+ if (uri.find("file://") == 0)
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace launcher
+} // namespace unity
diff --git a/launcher/StorageLauncherIcon.h b/launcher/StorageLauncherIcon.h
new file mode 100644
index 000000000..a552f88d5
--- /dev/null
+++ b/launcher/StorageLauncherIcon.h
@@ -0,0 +1,55 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 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: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#ifndef STORAGE_LAUNCHER_ICON_H
+#define STORAGE_LAUNCHER_ICON_H
+
+#include "WindowedLauncherIcon.h"
+#include "unity-shared/FileManager.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class StorageLauncherIcon : public virtual WindowedLauncherIcon
+{
+public:
+ StorageLauncherIcon(AbstractLauncherIcon::IconType, FileManager::Ptr const&);
+
+protected:
+ void UpdateStorageWindows();
+ WindowList GetManagedWindows() const override;
+ virtual WindowList GetStorageWindows() const = 0;
+
+ bool OnShouldHighlightOnDrag(DndData const& dnd_data) override;
+
+private:
+ void OnWindowStateChanged();
+
+protected:
+ FileManager::Ptr file_manager_;
+ WindowList managed_windows_;
+ connection::Manager windows_connections_;
+};
+
+} // namespace launcher
+} // namespace unity
+
+#endif // STORAGE_LAUNCHER_ICON_H
diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp
index 9b9711218..5f9c6e3f0 100644
--- a/launcher/SwitcherController.cpp
+++ b/launcher/SwitcherController.cpp
@@ -325,11 +325,18 @@ void Controller::Impl::Show(ShowMode show_mode, SortMode sort_mode, std::vector<
model_->selection_changed.connect(sigc::mem_fun(this, &Controller::Impl::OnModelSelectionChanged));
model_->detail_selection.changed.connect([this] (bool) { sources_.Remove(DETAIL_TIMEOUT); });
model_->updated.connect([this] { if (!model_->Size()) Hide(false); });
- obj_->AddChild(model_.get());
+
+ if (!model_->Size())
+ {
+ model_.reset();
+ return;
+ }
SelectFirstItem();
+ obj_->AddChild(model_.get());
obj_->visible_ = true;
+
int real_wait = obj_->timeout_length() - fade_animator_.Duration();
if (real_wait > 0)
@@ -442,7 +449,6 @@ void Controller::Impl::ConstructView()
sources_.Remove(VIEW_CONSTRUCT_IDLE);
view_ = SwitcherView::Ptr(new SwitcherView(icon_renderer_));
- obj_->AddChild(view_.GetPointer());
view_->SetModel(model_);
view_->background_color = WindowManager::Default().average_color();
view_->monitor = obj_->monitor_;
@@ -462,6 +468,7 @@ void Controller::Impl::ConstructView()
view_->switcher_start_detail.connect(sigc::mem_fun(this, &Impl::StartDetailMode));
view_->switcher_stop_detail.connect(sigc::mem_fun(this, &Impl::StopDetailMode));
view_->switcher_close_current.connect(sigc::mem_fun(this, &Impl::CloseSelection));
+ obj_->AddChild(view_.GetPointer());
ConstructWindow();
main_layout_->AddView(view_.GetPointer(), 1);
@@ -507,6 +514,9 @@ void Controller::Impl::HideWindow()
view_window_->ShowWindow(false);
view_window_->PushToBack();
+ obj_->RemoveChild(model_.get());
+ obj_->RemoveChild(view_.GetPointer());
+
model_.reset();
view_.Release();
}
@@ -720,14 +730,11 @@ void Controller::Impl::SelectFirstItem()
uint64_t second_first = 0; // second icons first highest active
WindowManager& wm = WindowManager::Default();
- for (auto& window : first->Windows())
- {
- Window xid = window->window_id();
-
- if (model_->only_apps_on_viewport && !wm.IsWindowOnCurrentDesktop(xid))
- continue;
+ auto const& windows = (model_->only_apps_on_viewport) ? first->WindowsOnViewport() : first->Windows();
- uint64_t num = wm.GetWindowActiveNumber(xid);
+ for (auto& window : windows)
+ {
+ uint64_t num = wm.GetWindowActiveNumber(window->window_id());
if (num > first_highest)
{
diff --git a/launcher/SwitcherModel.cpp b/launcher/SwitcherModel.cpp
index df3264328..4d8889435 100644
--- a/launcher/SwitcherModel.cpp
+++ b/launcher/SwitcherModel.cpp
@@ -37,16 +37,7 @@ namespace
bool CompareSwitcherItemsPriority(AbstractLauncherIcon::Ptr const& first,
AbstractLauncherIcon::Ptr const& second)
{
- if (first->GetIconType() == second->GetIconType())
- return first->SwitcherPriority() > second->SwitcherPriority();
-
- if (first->GetIconType() == AbstractLauncherIcon::IconType::DESKTOP)
- return true;
-
- if (second->GetIconType() == AbstractLauncherIcon::IconType::DESKTOP)
- return false;
-
- return first->GetIconType() < second->GetIconType();
+ return first->SwitcherPriority() > second->SwitcherPriority();
}
}
@@ -174,7 +165,7 @@ void SwitcherModel::ConnectToIconSignals(launcher::AbstractLauncherIcon::Ptr con
void SwitcherModel::AddIcon(AbstractLauncherIcon::Ptr const& icon)
{
- if (!icon || icon->GetIconType() != AbstractLauncherIcon::IconType::APPLICATION)
+ if (!icon)
return;
if (icon->ShowInSwitcher(only_apps_on_viewport))
@@ -318,7 +309,7 @@ size_t SwitcherModel::Size() const
AbstractLauncherIcon::Ptr SwitcherModel::Selection() const
{
- return applications_.at(index_);
+ return index_ < applications_.size() ? applications_.at(index_) : AbstractLauncherIcon::Ptr();
}
int SwitcherModel::SelectionIndex() const
@@ -328,7 +319,8 @@ int SwitcherModel::SelectionIndex() const
bool SwitcherModel::SelectionIsActive() const
{
- return Selection()->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE);
+ auto const& selection = Selection();
+ return selection ? selection->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE) : false;
}
AbstractLauncherIcon::Ptr SwitcherModel::LastSelection() const
@@ -353,8 +345,12 @@ std::vector<Window> SwitcherModel::SelectionWindows() const
WindowManager& wm = WindowManager::Default();
std::vector<Window> results;
+ auto const& selection = Selection();
+
+ if (!selection)
+ return results;
- for (auto& window : Selection()->Windows())
+ for (auto& window : selection->Windows())
{
Window xid = window->window_id();
@@ -369,7 +365,7 @@ std::vector<Window> SwitcherModel::SelectionWindows() const
return wm.GetWindowActiveNumber(first) > wm.GetWindowActiveNumber(second);
});
- if (Selection() == last_active_application_)
+ if (selection == last_active_application_)
{
results.push_back(results.front());
results.erase(results.begin());
@@ -406,6 +402,9 @@ void SwitcherModel::UnsetDetailSelection()
void SwitcherModel::NextIndex()
{
+ if (applications_.empty())
+ return;
+
last_index_ = index_;
++index_ %= applications_.size();
}
@@ -419,6 +418,9 @@ void SwitcherModel::Next()
void SwitcherModel::PrevIndex()
{
+ if (applications_.empty())
+ return;
+
last_index_ = index_;
index_ = ((index_ > 0 && index_ < applications_.size()) ? index_ : applications_.size()) - 1;
}
@@ -432,7 +434,7 @@ void SwitcherModel::Prev()
void SwitcherModel::NextDetail()
{
- if (!detail_selection())
+ if (!detail_selection() || detail_xids_.empty())
return;
detail_selection_index = (detail_selection_index + 1) % detail_xids_.size();
@@ -441,7 +443,7 @@ void SwitcherModel::NextDetail()
void SwitcherModel::PrevDetail()
{
- if (!detail_selection())
+ if (!detail_selection() || detail_xids_.empty())
return;
detail_selection_index = ((detail_selection_index() > 0) ? detail_selection_index : detail_xids_.size()) - 1;
diff --git a/launcher/SwitcherView.cpp b/launcher/SwitcherView.cpp
index b81eeef5d..302901ba4 100644
--- a/launcher/SwitcherView.cpp
+++ b/launcher/SwitcherView.cpp
@@ -538,7 +538,7 @@ RenderArg SwitcherView::CreateBaseArgForIcon(AbstractLauncherIcon::Ptr const& ic
// tells the renderer to render arrows by number
arg.running_on_viewport = true;
- arg.window_indicators = icon->WindowsForMonitor(monitor).size();
+ arg.window_indicators = icon->WindowsVisibleOnMonitor(monitor);
if (arg.window_indicators > 1)
arg.running_arrow = true;
else
diff --git a/launcher/TrashLauncherIcon.cpp b/launcher/TrashLauncherIcon.cpp
index fdc540e43..b8239aabd 100644
--- a/launcher/TrashLauncherIcon.cpp
+++ b/launcher/TrashLauncherIcon.cpp
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2010-2013 Canonical Ltd
+ * Copyright (C) 2010-2015 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
@@ -24,6 +24,7 @@
#include "config.h"
#include <glib/gi18n-lib.h>
#include <NuxCore/Logger.h>
+#include <UnityCore/DesktopUtilities.h>
#include <zeitgeist.h>
#include "QuicklistMenuItemLabel.h"
@@ -39,20 +40,19 @@ namespace
DECLARE_LOGGER(logger, "unity.launcher.icon.trash");
const std::string ZEITGEIST_UNITY_ACTOR = "application://compiz.desktop";
const std::string TRASH_URI = "trash:";
+ const std::string TRASH_PATH = "file://" + DesktopUtilities::GetUserTrashDirectory();
}
-TrashLauncherIcon::TrashLauncherIcon(FileManager::Ptr const& fmo)
- : SimpleLauncherIcon(IconType::TRASH)
+TrashLauncherIcon::TrashLauncherIcon(FileManager::Ptr const& fm)
+ : WindowedLauncherIcon(IconType::TRASH)
+ , StorageLauncherIcon(GetIconType(), fm ? fm : GnomeFileManager::Get())
, empty_(true)
- , file_manager_(fmo ? fmo : GnomeFileManager::Get())
{
tooltip_text = _("Trash");
icon_name = "user-trash";
position = Position::END;
SetQuirk(Quirk::VISIBLE, true);
SkipQuirkAnimation(Quirk::VISIBLE);
-
- SetQuirk(Quirk::RUNNING, file_manager_->IsTrashOpened());
SetShortcut('t');
glib::Object<GFile> location(g_file_new_for_uri(TRASH_URI.c_str()));
@@ -67,20 +67,27 @@ TrashLauncherIcon::TrashLauncherIcon(FileManager::Ptr const& fmo)
}
else
{
- trash_changed_signal_.Connect(trash_monitor_, "changed",
+ glib_signals_.Add<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent>(trash_monitor_, "changed",
[this] (GFileMonitor*, GFile*, GFile*, GFileMonitorEvent) {
UpdateTrashIcon();
});
}
- file_manager_->locations_changed.connect(sigc::mem_fun(this, &TrashLauncherIcon::OnOpenedLocationsChanged));
-
UpdateTrashIcon();
+ UpdateStorageWindows();
+}
+
+WindowList TrashLauncherIcon::GetStorageWindows() const
+{
+ auto windows = file_manager_->WindowsForLocation(TRASH_URI);
+ auto const& path_wins = file_manager_->WindowsForLocation(TRASH_PATH);
+ windows.insert(end(windows), begin(path_wins), end(path_wins));
+ return windows;
}
-void TrashLauncherIcon::OnOpenedLocationsChanged()
+void TrashLauncherIcon::OpenInstanceLauncherIcon(Time timestamp)
{
- SetQuirk(Quirk::RUNNING, file_manager_->IsTrashOpened());
+ file_manager_->OpenTrash(timestamp);
}
AbstractLauncherIcon::MenuItemsVector TrashLauncherIcon::GetMenus()
@@ -92,20 +99,41 @@ AbstractLauncherIcon::MenuItemsVector TrashLauncherIcon::GetMenus()
dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Empty Trash…"));
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, !empty_);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- empty_activated_signal_.Connect(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ glib_signals_.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
[this] (DbusmenuMenuitem*, unsigned timestamp) {
file_manager_->EmptyTrash(timestamp);
});
result.push_back(menu_item);
- return result;
-}
+ if (IsRunning())
+ {
+ auto const& windows_items = GetWindowsMenuItems();
+ if (!windows_items.empty())
+ {
+ menu_item = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ result.push_back(menu_item);
-void TrashLauncherIcon::ActivateLauncherIcon(ActionArg arg)
-{
- SimpleLauncherIcon::ActivateLauncherIcon(arg);
- file_manager_->OpenTrash(arg.timestamp);
+ result.insert(end(result), begin(windows_items), end(windows_items));
+ }
+
+ menu_item = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ result.push_back(menu_item);
+
+ menu_item = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Quit"));
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
+ result.push_back(menu_item);
+
+ glib_signals_.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ Quit();
+ });
+ }
+
+ return result;
}
void TrashLauncherIcon::UpdateTrashIcon()
diff --git a/launcher/TrashLauncherIcon.h b/launcher/TrashLauncherIcon.h
index 24a2622e3..3b32cd572 100644
--- a/launcher/TrashLauncherIcon.h
+++ b/launcher/TrashLauncherIcon.h
@@ -23,9 +23,10 @@
#include <gio/gio.h>
#include <UnityCore/GLibWrapper.h>
#include <UnityCore/GLibSignal.h>
+#include <UnityCore/ConnectionManager.h>
#include "DndData.h"
-#include "SimpleLauncherIcon.h"
+#include "StorageLauncherIcon.h"
#include "unity-shared/FileManager.h"
namespace unity
@@ -33,7 +34,7 @@ namespace unity
namespace launcher
{
-class TrashLauncherIcon : public SimpleLauncherIcon
+class TrashLauncherIcon : public StorageLauncherIcon
{
public:
TrashLauncherIcon(FileManager::Ptr const& = nullptr);
@@ -45,21 +46,18 @@ protected:
bool OnShouldHighlightOnDrag(DndData const& dnd_data);
void OnAcceptDrop(DndData const& dnd_data);
+ WindowList GetStorageWindows() const override;
std::string GetName() const;
private:
- void ActivateLauncherIcon(ActionArg arg);
- void OnOpenedLocationsChanged();
+ void OpenInstanceLauncherIcon(Time timestamp) override;
MenuItemsVector GetMenus();
static void UpdateTrashIconCb(GObject* source, GAsyncResult* res, gpointer data);
bool empty_;
- FileManager::Ptr file_manager_;
glib::Cancellable cancellable_;
glib::Object<GFileMonitor> trash_monitor_;
- glib::Signal<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent> trash_changed_signal_;
- glib::Signal<void, DbusmenuMenuitem*, unsigned> empty_activated_signal_;
};
}
diff --git a/launcher/VolumeLauncherIcon.cpp b/launcher/VolumeLauncherIcon.cpp
index 8f09be7c7..85eee27fc 100644
--- a/launcher/VolumeLauncherIcon.cpp
+++ b/launcher/VolumeLauncherIcon.cpp
@@ -49,7 +49,7 @@ public:
, volume_(volume)
, devices_settings_(devices_settings)
, notification_(notification)
- , file_manager_(fm)
+ , file_manager_(parent_->file_manager_)
{
UpdateIcon();
UpdateVisibility();
@@ -60,48 +60,41 @@ public:
{
parent_->tooltip_text = volume_->GetName();
parent_->icon_name = volume_->GetIconName();
- parent_->SetQuirk(Quirk::RUNNING, file_manager_->IsPrefixOpened(volume_->GetUri()));
}
void UpdateVisibility()
{
- UpdateKeepInLauncher();
- parent_->SetQuirk(Quirk::VISIBLE, keep_in_launcher_);
+ parent_->SetQuirk(Quirk::VISIBLE, IsVisible());
}
- void UpdateKeepInLauncher()
+ bool IsBlackListed()
{
- auto const& identifier = volume_->GetIdentifier();
- keep_in_launcher_ = !devices_settings_->IsABlacklistedDevice(identifier);
+ return devices_settings_->IsABlacklistedDevice(volume_->GetIdentifier());
}
- void ConnectSignals()
+ bool IsVisible()
{
- connections_.Add(volume_->changed.connect(sigc::mem_fun(this, &Impl::OnVolumeChanged)));
- connections_.Add(volume_->removed.connect(sigc::mem_fun(this, &Impl::OnVolumeRemoved)));
- connections_.Add(devices_settings_->changed.connect(sigc::mem_fun(this, &Impl::OnSettingsChanged)));
- connections_.Add(file_manager_->locations_changed.connect(sigc::mem_fun(this, &Impl::UpdateIcon)));
+ if (IsBlackListed() && parent_->GetManagedWindows().empty())
+ return false;
+
+ return true;
}
- void OnVolumeChanged()
+ void ConnectSignals()
{
- UpdateIcon();
+ connections_.Add(volume_->changed.connect([this] { UpdateIcon(); }));
+ connections_.Add(volume_->removed.connect(sigc::mem_fun(this, &Impl::OnVolumeRemoved)));
+ connections_.Add(devices_settings_->changed.connect([this] { UpdateVisibility(); }));
+ connections_.Add(parent_->windows_changed.connect([this] (int) { UpdateVisibility(); }));
}
void OnVolumeRemoved()
{
- if (devices_settings_->IsABlacklistedDevice(volume_->GetIdentifier()))
- devices_settings_->TryToUnblacklist(volume_->GetIdentifier());
-
+ devices_settings_->TryToUnblacklist(volume_->GetIdentifier());
parent_->UnStick();
parent_->Remove();
}
- void OnSettingsChanged()
- {
- UpdateVisibility();
- }
-
bool CanEject() const
{
return volume_->CanBeEjected();
@@ -152,7 +145,7 @@ public:
void OpenInFileManager(uint64_t timestamp)
{
DoActionWhenMounted([this, timestamp] {
- file_manager_->OpenActiveChild(volume_->GetUri(), timestamp);
+ file_manager_->Open(volume_->GetUri(), timestamp);
});
}
@@ -171,29 +164,38 @@ public:
AppendSeparatorItem(result);
AppendNameItem(result);
AppendSeparatorItem(result);
- AppendUnlockFromLauncherItem(result);
+ AppendWindowsItems(result);
+ AppendToggleLockFromLauncherItem(result);
AppendEjectItem(result);
AppendSafelyRemoveItem(result);
AppendUnmountItem(result);
+ AppendQuitItem(result);
return result;
}
- void AppendUnlockFromLauncherItem(MenuItemsVector& menu)
+ void AppendToggleLockFromLauncherItem(MenuItemsVector& menu)
{
if (volume_->GetIdentifier().empty())
return;
glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Unlock from Launcher"));
+ const char* label = IsBlackListed() ? _("Lock to Launcher") : _("Unlock from Launcher");
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, label);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
- auto const& identifier = volume_->GetIdentifier();
- parent_->UnStick();
- devices_settings_->TryToBlacklist(identifier);
+ parent_->glib_signals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ if (!IsBlackListed())
+ {
+ parent_->UnStick();
+ devices_settings_->TryToBlacklist(volume_->GetIdentifier());
+ }
+ else
+ {
+ devices_settings_->TryToUnblacklist(volume_->GetIdentifier());
+ }
}));
menu.push_back(menu_item);
@@ -220,13 +222,26 @@ public:
dbusmenu_menuitem_property_set_bool(menu_item, QuicklistMenuItem::MARKUP_ENABLED_PROPERTY, true);
dbusmenu_menuitem_property_set_bool(menu_item, QuicklistMenuItem::MARKUP_ACCEL_DISABLED_PROPERTY, true);
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, unsigned timestamp) {
+ parent_->glib_signals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, unsigned timestamp) {
OpenInFileManager(timestamp);
}));
menu.push_back(menu_item);
}
+ void AppendWindowsItems(MenuItemsVector& menu)
+ {
+ if (!parent_->IsRunning())
+ return;
+
+ auto const& windows_items = parent_->GetWindowsMenuItems();
+ if (!windows_items.empty())
+ {
+ menu.insert(end(menu), begin(windows_items), end(windows_items));
+ AppendSeparatorItem(menu);
+ }
+ }
+
void AppendOpenItem(MenuItemsVector& menu)
{
glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
@@ -235,7 +250,7 @@ public:
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, unsigned timestamp) {
+ parent_->glib_signals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, unsigned timestamp) {
OpenInFileManager(timestamp);
}));
@@ -253,7 +268,8 @@ public:
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ parent_->glib_signals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ parent_->Quit();
EjectAndShowNotification();
}));
@@ -271,8 +287,9 @@ public:
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
- volume_->StopDrive();
+ parent_->glib_signals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ parent_->Quit();
+ volume_->StopDrive();
}));
menu.push_back(menu_item);
@@ -289,8 +306,29 @@ public:
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
- volume_->Unmount();
+ parent_->glib_signals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ volume_->Unmount();
+ }));
+
+ menu.push_back(menu_item);
+ }
+
+ void AppendQuitItem(MenuItemsVector& menu)
+ {
+ if (!parent_->IsRunning())
+ return;
+
+ if (!menu.empty())
+ AppendSeparatorItem(menu);
+
+ glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
+
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Quit"));
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
+
+ parent_->glib_signals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ parent_->Quit();
}));
menu.push_back(menu_item);
@@ -307,13 +345,10 @@ public:
}
VolumeLauncherIcon* parent_;
- bool keep_in_launcher_;
Volume::Ptr volume_;
DevicesSettings::Ptr devices_settings_;
DeviceNotificationDisplay::Ptr notification_;
FileManager::Ptr file_manager_;
-
- glib::SignalManager gsignals_;
connection::Manager connections_;
};
@@ -325,15 +360,20 @@ VolumeLauncherIcon::VolumeLauncherIcon(Volume::Ptr const& volume,
DevicesSettings::Ptr const& devices_settings,
DeviceNotificationDisplay::Ptr const& notification,
FileManager::Ptr const& fm)
- : SimpleLauncherIcon(IconType::DEVICE)
+ : WindowedLauncherIcon(IconType::DEVICE)
+ , StorageLauncherIcon(GetIconType(), fm)
, pimpl_(new Impl(volume, devices_settings, notification, fm, this))
-{}
+{
+ UpdateStorageWindows();
+}
VolumeLauncherIcon::~VolumeLauncherIcon()
{}
void VolumeLauncherIcon::AboutToRemove()
{
+ StorageLauncherIcon::AboutToRemove();
+
if (CanEject())
EjectAndShowNotification();
else if (CanStop())
@@ -360,12 +400,6 @@ void VolumeLauncherIcon::StopDrive()
return pimpl_->StopDrive();
}
-void VolumeLauncherIcon::ActivateLauncherIcon(ActionArg arg)
-{
- SimpleLauncherIcon::ActivateLauncherIcon(arg);
- pimpl_->OpenInFileManager(arg.timestamp);
-}
-
AbstractLauncherIcon::MenuItemsVector VolumeLauncherIcon::GetMenus()
{
return pimpl_->GetMenus();
@@ -388,17 +422,6 @@ void VolumeLauncherIcon::UnStick()
SetQuirk(Quirk::VISIBLE, true);
}
-bool VolumeLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data)
-{
- for (auto const& uri : dnd_data.Uris())
- {
- if (uri.find("file://") == 0)
- return true;
- }
-
- return false;
-}
-
nux::DndAction VolumeLauncherIcon::OnQueryAcceptDrop(DndData const& dnd_data)
{
return dnd_data.Uris().empty() ? nux::DNDACTION_NONE : nux::DNDACTION_COPY;
@@ -412,6 +435,21 @@ void VolumeLauncherIcon::OnAcceptDrop(DndData const& dnd_data)
FullyAnimateQuirkDelayed(100, LauncherIcon::Quirk::SHIMMER);
}
+std::string VolumeLauncherIcon::GetVolumeUri() const
+{
+ return pimpl_->volume_->GetUri();
+}
+
+WindowList VolumeLauncherIcon::GetStorageWindows() const
+{
+ return file_manager_->WindowsForLocation(GetVolumeUri());
+}
+
+void VolumeLauncherIcon::OpenInstanceLauncherIcon(Time timestamp)
+{
+ pimpl_->OpenInFileManager(timestamp);
+}
+
//
// Introspection
//
diff --git a/launcher/VolumeLauncherIcon.h b/launcher/VolumeLauncherIcon.h
index a78e2199c..3322db26c 100644
--- a/launcher/VolumeLauncherIcon.h
+++ b/launcher/VolumeLauncherIcon.h
@@ -24,7 +24,7 @@
#include "Volume.h"
#include "DevicesSettings.h"
#include "DeviceNotificationDisplay.h"
-#include "SimpleLauncherIcon.h"
+#include "StorageLauncherIcon.h"
#include "unity-shared/FileManager.h"
namespace unity
@@ -32,7 +32,7 @@ namespace unity
namespace launcher
{
-class VolumeLauncherIcon : public SimpleLauncherIcon
+class VolumeLauncherIcon : public StorageLauncherIcon
{
public:
typedef nux::ObjectPtr<VolumeLauncherIcon> Ptr;
@@ -41,7 +41,7 @@ public:
DeviceNotificationDisplay::Ptr const&, FileManager::Ptr const&);
virtual ~VolumeLauncherIcon();
- virtual void AboutToRemove();
+ void AboutToRemove() override;
bool CanEject() const; // TODO: rename to public virtual bool IsTrashable();
void EjectAndShowNotification(); // TODO: rename to private virtual void DoDropToTrash();
@@ -49,14 +49,16 @@ public:
void StopDrive();
void Stick(bool save = true);
void UnStick();
+
MenuItemsVector GetMenus();
std::string GetRemoteUri() const;
+ std::string GetVolumeUri() const;
protected:
- void ActivateLauncherIcon(ActionArg arg);
- bool OnShouldHighlightOnDrag(DndData const&);
void OnAcceptDrop(DndData const&);
nux::DndAction OnQueryAcceptDrop(DndData const&);
+ WindowList GetStorageWindows() const override;
+ void OpenInstanceLauncherIcon(Time timestamp) override;
// Introspection
virtual std::string GetName() const;
diff --git a/launcher/WindowedLauncherIcon.cpp b/launcher/WindowedLauncherIcon.cpp
new file mode 100644
index 000000000..efffb81ac
--- /dev/null
+++ b/launcher/WindowedLauncherIcon.cpp
@@ -0,0 +1,618 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 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: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#include <Nux/Nux.h>
+
+#include "WindowedLauncherIcon.h"
+#include "MultiMonitor.h"
+#include "unity-shared/UBusWrapper.h"
+#include "unity-shared/UBusMessages.h"
+#include "unity-shared/UScreen.h"
+
+namespace unity
+{
+namespace launcher
+{
+namespace
+{
+const std::string ICON_DND_OVER_TIMEOUT = "windowed-icon-dnd-over";
+const int COMPIZ_SCALE_DND_SPREAD = 1 << 7;
+const int MAXIMUM_QUICKLIST_WIDTH = 300;
+}
+
+NUX_IMPLEMENT_OBJECT_TYPE(WindowedLauncherIcon);
+
+WindowedLauncherIcon::WindowedLauncherIcon(AbstractLauncherIcon::IconType icon_type)
+ : SimpleLauncherIcon(icon_type)
+ , last_scroll_timestamp_(0)
+ , progressive_scroll_(0)
+{
+ WindowManager& wm = WindowManager::Default();
+ wm.window_minimized.connect(sigc::mem_fun(this, &WindowedLauncherIcon::OnWindowMinimized));
+ wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &WindowedLauncherIcon::EnsureWindowState));
+ wm.terminate_expo.connect(sigc::mem_fun(this, &WindowedLauncherIcon::EnsureWindowState));
+ UScreen::GetDefault()->changed.connect(sigc::hide(sigc::hide(sigc::mem_fun(this, &WindowedLauncherIcon::EnsureWindowsLocation))));
+
+ windows_changed.connect([this] (int) {
+ if (WindowManager::Default().IsScaleActiveForGroup() && IsActive())
+ Spread(true, 0, false);
+ });
+}
+
+bool WindowedLauncherIcon::IsActive() const
+{
+ return GetQuirk(Quirk::ACTIVE);
+}
+
+bool WindowedLauncherIcon::IsRunning() const
+{
+ return GetQuirk(Quirk::RUNNING);
+}
+
+bool WindowedLauncherIcon::IsUrgent() const
+{
+ return GetQuirk(Quirk::URGENT);
+}
+
+bool WindowedLauncherIcon::IsUserVisible() const
+{
+ return IsRunning();
+}
+
+void WindowedLauncherIcon::ActivateLauncherIcon(ActionArg arg)
+{
+ SimpleLauncherIcon::ActivateLauncherIcon(arg);
+ WindowManager& wm = WindowManager::Default();
+
+ // This is a little awkward as the target is only set from the switcher.
+ if (arg.target)
+ {
+ // thumper: should we Raise too? should the WM raise?
+ wm.Activate(arg.target);
+ return;
+ }
+
+ bool scale_was_active = wm.IsScaleActive();
+ bool active = IsActive();
+ bool user_visible = IsRunning();
+ /* We should check each child to see if there is
+ * an unmapped (!= minimized) window around and
+ * if so force "Focus" behaviour */
+
+ if (arg.source != ActionArg::Source::SWITCHER)
+ {
+ user_visible = IsUserVisible();
+
+ if (active)
+ {
+ bool any_visible = false;
+ bool any_mapped = false;
+ bool any_on_top = false;
+ bool any_on_monitor = (arg.monitor < 0);
+ int active_monitor = arg.monitor;
+
+ for (auto const& window : GetManagedWindows())
+ {
+ Window xid = window->window_id();
+
+ if (!any_visible && wm.IsWindowOnCurrentDesktop(xid))
+ {
+ any_visible = true;
+ }
+
+ if (!any_mapped && wm.IsWindowMapped(xid))
+ {
+ any_mapped = true;
+ }
+
+ if (!any_on_top && wm.IsWindowOnTop(xid))
+ {
+ any_on_top = true;
+ }
+
+ if (!any_on_monitor && window->monitor() == arg.monitor &&
+ wm.IsWindowMapped(xid) && wm.IsWindowVisible(xid))
+ {
+ any_on_monitor = true;
+ }
+
+ if (window->active())
+ {
+ active_monitor = window->monitor();
+ }
+ }
+
+ if (!any_visible || !any_mapped || !any_on_top)
+ active = false;
+
+ if (any_on_monitor && arg.monitor >= 0 && active_monitor != arg.monitor)
+ active = false;
+ }
+ }
+
+ /* Behaviour:
+ * 1) Nothing running, or nothing visible -> launch application
+ * 2) Running and active -> spread application
+ * 3) Running and not active -> focus application
+ * 4) Spread is active and different icon pressed -> change spread
+ * 5) Spread is active -> Spread de-activated, and fall through
+ */
+
+ if (!IsRunning() || (IsRunning() && !user_visible)) // #1 above
+ {
+ if (GetQuirk(Quirk::STARTING, arg.monitor))
+ return;
+
+ wm.TerminateScale();
+ SetQuirk(Quirk::STARTING, true, arg.monitor);
+ OpenInstanceLauncherIcon(arg.timestamp);
+ }
+ else // container is running
+ {
+ if (active)
+ {
+ if (scale_was_active) // #5 above
+ {
+ wm.TerminateScale();
+
+ if (minimize_window_on_click())
+ {
+ for (auto const& win : GetWindows(WindowFilter::ON_CURRENT_DESKTOP))
+ wm.Minimize(win->window_id());
+ }
+ else
+ {
+ Focus(arg);
+ }
+ }
+ else // #2 above
+ {
+ if (arg.source != ActionArg::Source::SWITCHER)
+ {
+ bool minimized = false;
+
+ if (minimize_window_on_click())
+ {
+ WindowList const& windows = GetWindows(WindowFilter::ON_CURRENT_DESKTOP);
+
+ if (windows.size() == 1)
+ {
+ wm.Minimize(windows[0]->window_id());
+ minimized = true;
+ }
+ }
+
+ if (!minimized)
+ {
+ Spread(true, 0, false);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (scale_was_active) // #4 above
+ {
+ if (GetWindows(WindowFilter::ON_CURRENT_DESKTOP).size() <= 1)
+ wm.TerminateScale();
+
+ Focus(arg);
+
+ if (arg.source != ActionArg::Source::SWITCHER)
+ Spread(true, 0, false);
+ }
+ else // #3 above
+ {
+ Focus(arg);
+ }
+ }
+ }
+}
+
+WindowList WindowedLauncherIcon::GetWindows(WindowFilterMask filter, int monitor)
+{
+ if ((!filter && monitor < 0) || (filter == WindowFilter::ON_ALL_MONITORS))
+ return GetManagedWindows();
+
+ WindowManager& wm = WindowManager::Default();
+ WindowList results;
+
+ monitor = (filter & WindowFilter::ON_ALL_MONITORS) ? -1 : monitor;
+ bool mapped = (filter & WindowFilter::MAPPED);
+ bool user_visible = (filter & WindowFilter::USER_VISIBLE);
+ bool current_desktop = (filter & WindowFilter::ON_CURRENT_DESKTOP);
+
+ for (auto& window : GetManagedWindows())
+ {
+ if ((monitor >= 0 && window->monitor() == monitor) || monitor < 0)
+ {
+ if ((user_visible && window->visible()) || !user_visible)
+ {
+ Window xid = window->window_id();
+
+ if ((mapped && wm.IsWindowMapped(xid)) || !mapped)
+ {
+ if ((current_desktop && wm.IsWindowOnCurrentDesktop(xid)) || !current_desktop)
+ {
+ results.push_back(window);
+ }
+ }
+ }
+ }
+ }
+
+ return results;
+}
+
+WindowList WindowedLauncherIcon::Windows()
+{
+ return GetWindows(WindowFilter::MAPPED|WindowFilter::ON_ALL_MONITORS);
+}
+
+WindowList WindowedLauncherIcon::WindowsOnViewport()
+{
+ WindowFilterMask filter = 0;
+ filter |= WindowFilter::MAPPED;
+ filter |= WindowFilter::USER_VISIBLE;
+ filter |= WindowFilter::ON_CURRENT_DESKTOP;
+ filter |= WindowFilter::ON_ALL_MONITORS;
+
+ return GetWindows(filter);
+}
+
+WindowList WindowedLauncherIcon::WindowsForMonitor(int monitor)
+{
+ WindowFilterMask filter = 0;
+ filter |= WindowFilter::MAPPED;
+ filter |= WindowFilter::USER_VISIBLE;
+ filter |= WindowFilter::ON_CURRENT_DESKTOP;
+
+ return GetWindows(filter, monitor);
+}
+
+void WindowedLauncherIcon::OnWindowMinimized(Window xid)
+{
+ for (auto const& window : GetManagedWindows())
+ {
+ if (xid == window->window_id())
+ {
+ int monitor = GetCenterForMonitor(window->monitor()).first;
+
+ if (monitor >= 0)
+ {
+ Present(0.5f, 600, monitor);
+ FullyAnimateQuirkDelayed(300, Quirk::SHIMMER, monitor);
+ }
+
+ break;
+ }
+ }
+}
+
+void WindowedLauncherIcon::Focus(ActionArg arg)
+{
+ bool show_only_visible = (arg.source == ActionArg::Source::SWITCHER);
+ ApplicationManager::Default().FocusWindowGroup(GetManagedWindows(), show_only_visible, arg.monitor);
+}
+
+bool WindowedLauncherIcon::Spread(bool current_desktop, int state, bool force)
+{
+ std::vector<Window> windows;
+ for (auto& window : GetWindows(current_desktop ? WindowFilter::ON_CURRENT_DESKTOP : 0))
+ windows.push_back(window->window_id());
+
+ return WindowManager::Default().ScaleWindowGroup(windows, state, force);
+}
+
+void WindowedLauncherIcon::EnsureWindowState()
+{
+ std::vector<int> number_of_windows_on_monitor(monitors::MAX);
+
+ for (auto const& window : WindowsOnViewport())
+ {
+ int monitor = window->monitor();
+
+ // If monitor is -1 (or negative), show on all monitors.
+ if (monitor < 0)
+ {
+ for (unsigned j; j < monitors::MAX; ++j)
+ ++number_of_windows_on_monitor[j];
+ }
+ else
+ {
+ ++number_of_windows_on_monitor[monitor];
+ }
+ }
+
+ for (unsigned i = 0; i < monitors::MAX; ++i)
+ SetNumberOfWindowsVisibleOnMonitor(number_of_windows_on_monitor[i], i);
+}
+
+void WindowedLauncherIcon::EnsureWindowsLocation()
+{
+ EnsureWindowState();
+ UpdateIconGeometries(GetCenters());
+}
+
+void WindowedLauncherIcon::UpdateIconGeometries(std::vector<nux::Point3> const& centers)
+{
+ nux::Geometry geo(0, 0, icon_size, icon_size);
+
+ for (auto& window : GetManagedWindows())
+ {
+ Window xid = window->window_id();
+ int monitor = GetCenterForMonitor(window->monitor()).first;
+
+ if (monitor < 0)
+ {
+ WindowManager::Default().SetWindowIconGeometry(xid, nux::Geometry());
+ continue;
+ }
+
+ geo.x = centers[monitor].x - icon_size / 2;
+ geo.y = centers[monitor].y - icon_size / 2;
+ WindowManager::Default().SetWindowIconGeometry(xid, geo);
+ }
+}
+
+void WindowedLauncherIcon::OnCenterStabilized(std::vector<nux::Point3> const& centers)
+{
+ UpdateIconGeometries(centers);
+}
+
+void WindowedLauncherIcon::OnDndEnter()
+{
+ auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
+
+ _source_manager.AddTimeout(1000, [this, timestamp] {
+ bool to_spread = GetWindows(WindowFilter::ON_CURRENT_DESKTOP).size() > 1;
+
+ if (!to_spread)
+ WindowManager::Default().TerminateScale();
+
+ if (!IsRunning())
+ return false;
+
+ UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
+ Focus(ActionArg(ActionArg::Source::LAUNCHER, 1, timestamp));
+
+ if (to_spread)
+ Spread(true, COMPIZ_SCALE_DND_SPREAD, false);
+
+ return false;
+ }, ICON_DND_OVER_TIMEOUT);
+}
+
+void WindowedLauncherIcon::OnDndLeave()
+{
+ _source_manager.Remove(ICON_DND_OVER_TIMEOUT);
+}
+
+bool WindowedLauncherIcon::HandlesSpread()
+{
+ return true;
+}
+
+bool WindowedLauncherIcon::ShowInSwitcher(bool current)
+{
+ if (!removed() && IsRunning() && IsVisible())
+ {
+ // If current is true, we only want to show the current workspace.
+ if (!current)
+ {
+ return true;
+ }
+ else
+ {
+ for (unsigned i = 0; i < monitors::MAX; ++i)
+ {
+ if (WindowVisibleOnMonitor(i))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool WindowedLauncherIcon::AllowDetailViewInSwitcher() const
+{
+ return true;
+}
+
+uint64_t WindowedLauncherIcon::SwitcherPriority()
+{
+ uint64_t result = 0;
+
+ for (auto& window : GetManagedWindows())
+ {
+ Window xid = window->window_id();
+ result = std::max(result, WindowManager::Default().GetWindowActiveNumber(xid));
+ }
+
+ return result;
+}
+
+void PerformScrollUp(WindowList const& windows, unsigned int progressive_scroll)
+{
+ if (progressive_scroll == windows.size() - 1)
+ {
+ //RestackAbove to preserve Global Stacking Order
+ WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(1)->window_id());
+ WindowManager::Default().RestackBelow(windows.at(1)->window_id(), windows.at(0)->window_id());
+ windows.back()->Focus();
+ return;
+ }
+
+ WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(progressive_scroll + 1)->window_id());
+ windows.at(progressive_scroll + 1)->Focus();
+}
+
+void PerformScrollDown(WindowList const& windows, unsigned int progressive_scroll)
+{
+ if (!progressive_scroll)
+ {
+ WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.back()->window_id());
+ windows.at(1)->Focus();
+ return;
+ }
+
+ WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(progressive_scroll)->window_id());
+ windows.at(progressive_scroll)->Focus();
+}
+
+void WindowedLauncherIcon::PerformScroll(ScrollDirection direction, Time timestamp)
+{
+ if (timestamp - last_scroll_timestamp_ < 150)
+ return;
+ else if (timestamp - last_scroll_timestamp_ > 1500)
+ progressive_scroll_ = 0;
+
+ last_scroll_timestamp_ = timestamp;
+
+ auto const& windows = GetWindowsOnCurrentDesktopInStackingOrder();
+
+ if (windows.empty())
+ return;
+
+ if (scroll_inactive_icons && !IsActive())
+ {
+ windows.at(0)->Focus();
+ return;
+ }
+
+ if (!scroll_inactive_icons && !IsActive())
+ return;
+
+ if (windows.size() <= 1)
+ return;
+
+ if (direction == ScrollDirection::DOWN)
+ ++progressive_scroll_;
+ else
+ //--progressive_scroll_; but roll to the top of windows
+ progressive_scroll_ += windows.size() - 1;
+ progressive_scroll_ %= windows.size();
+
+ switch(direction)
+ {
+ case ScrollDirection::UP:
+ PerformScrollUp(windows, progressive_scroll_);
+ break;
+ case ScrollDirection::DOWN:
+ PerformScrollDown(windows, progressive_scroll_);
+ break;
+ }
+}
+
+WindowList WindowedLauncherIcon::GetWindowsOnCurrentDesktopInStackingOrder()
+{
+ auto windows = GetWindows(WindowFilter::ON_CURRENT_DESKTOP | WindowFilter::ON_ALL_MONITORS);
+ auto sorted_windows = WindowManager::Default().GetWindowsInStackingOrder();
+
+ // Order the windows
+ std::sort(windows.begin(), windows.end(), [&sorted_windows] (ApplicationWindowPtr const& win1, ApplicationWindowPtr const& win2) {
+ for (auto const& window : sorted_windows)
+ {
+ if (window == win1->window_id())
+ return false;
+ else if (window == win2->window_id())
+ return true;
+ }
+
+ return true;
+ });
+
+ return windows;
+}
+
+void WindowedLauncherIcon::Quit() const
+{
+ for (auto& window : GetManagedWindows())
+ window->Quit();
+}
+
+void WindowedLauncherIcon::AboutToRemove()
+{
+ Quit();
+}
+
+AbstractLauncherIcon::MenuItemsVector WindowedLauncherIcon::GetWindowsMenuItems()
+{
+ auto const& windows = Windows();
+ MenuItemsVector menu_items;
+
+ // We only add quicklist menu-items for windows if we have more than one window
+ if (windows.size() < 2)
+ return menu_items;
+
+ // add menu items for all open windows
+ for (auto const& w : windows)
+ {
+ auto const& title = w->title();
+
+ if (title.empty())
+ continue;
+
+ glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, title.c_str());
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, QuicklistMenuItem::MARKUP_ACCEL_DISABLED_PROPERTY, true);
+ dbusmenu_menuitem_property_set_int(menu_item, QuicklistMenuItem::MAXIMUM_LABEL_WIDTH_PROPERTY, MAXIMUM_QUICKLIST_WIDTH);
+
+ Window xid = w->window_id();
+ glib_signals_.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ [xid] (DbusmenuMenuitem*, unsigned) {
+ WindowManager& wm = WindowManager::Default();
+ wm.Activate(xid);
+ wm.Raise(xid);
+ });
+
+ if (w->active())
+ {
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_RADIO);
+ dbusmenu_menuitem_property_set_int(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED);
+ }
+
+ menu_items.push_back(menu_item);
+ }
+
+ return menu_items;
+}
+
+std::string WindowedLauncherIcon::GetName() const
+{
+ return "WindowedLauncherIcon";
+}
+
+void WindowedLauncherIcon::AddProperties(debug::IntrospectionData& introspection)
+{
+ SimpleLauncherIcon::AddProperties(introspection);
+
+ std::vector<Window> xids;
+ for (auto const& window : GetManagedWindows())
+ xids.push_back(window->window_id());
+
+ introspection.add("xids", glib::Variant::FromVector(xids))
+ .add("sticky", IsSticky());
+}
+
+} // namespace launcher
+} // namespace unity
diff --git a/launcher/WindowedLauncherIcon.h b/launcher/WindowedLauncherIcon.h
new file mode 100644
index 000000000..83ecbdb78
--- /dev/null
+++ b/launcher/WindowedLauncherIcon.h
@@ -0,0 +1,100 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2015 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: Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#ifndef WINDOWED_LAUNCHER_ICON_H
+#define WINDOWED_LAUNCHER_ICON_H
+
+#include <UnityCore/GLibSignal.h>
+
+#include "SimpleLauncherIcon.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class WindowedLauncherIcon : public SimpleLauncherIcon
+{
+ NUX_DECLARE_OBJECT_TYPE(WindowedLauncherIcon, SimpleLauncherIcon);
+public:
+ WindowedLauncherIcon(AbstractLauncherIcon::IconType);
+
+ WindowList Windows() override;
+ WindowList WindowsOnViewport() override;
+ WindowList WindowsForMonitor(int monitor) override;
+
+ virtual bool IsActive() const;
+ virtual bool IsRunning() const;
+ virtual bool IsUrgent() const;
+ virtual bool IsUserVisible() const;
+
+ virtual void Quit() const;
+
+protected:
+ virtual WindowList GetManagedWindows() const = 0;
+ void EnsureWindowState();
+ void EnsureWindowsLocation();
+
+ virtual void UpdateIconGeometries(std::vector<nux::Point3> const& centers);
+
+ std::string GetName() const override;
+ void AddProperties(debug::IntrospectionData&) override;
+
+ bool HandlesSpread() override;
+ bool ShowInSwitcher(bool current) override;
+ bool AllowDetailViewInSwitcher() const override;
+ uint64_t SwitcherPriority() override;
+ void AboutToRemove() override;
+
+ void ActivateLauncherIcon(ActionArg arg) override;
+ void PerformScroll(ScrollDirection direction, Time timestamp) override;
+ virtual void Focus(ActionArg arg);
+ virtual bool Spread(bool current_desktop, int state, bool force);
+
+ typedef unsigned long int WindowFilterMask;
+ enum WindowFilter
+ {
+ MAPPED = (1 << 0),
+ USER_VISIBLE = (1 << 1),
+ ON_CURRENT_DESKTOP = (1 << 2),
+ ON_ALL_MONITORS = (1 << 3),
+ };
+
+ WindowList GetWindows(WindowFilterMask filter = 0, int monitor = -1);
+ WindowList GetWindowsOnCurrentDesktopInStackingOrder();
+
+ MenuItemsVector GetWindowsMenuItems();
+
+private:
+ void OnCenterStabilized(std::vector<nux::Point3> const& centers) override;
+ void OnWindowMinimized(Window);
+ void OnDndEnter();
+ void OnDndLeave();
+
+ Time last_scroll_timestamp_;
+ unsigned int progressive_scroll_;
+
+protected:
+ glib::SignalManager glib_signals_;
+};
+
+} // namespace launcher
+} // namespace unity
+
+#endif // WINDOWED_LAUNCHER_ICON_H
diff --git a/plugins/unityshell/src/inputremover.cpp b/plugins/unityshell/src/inputremover.cpp
index b28e7a1e2..ec09f9eeb 100644
--- a/plugins/unityshell/src/inputremover.cpp
+++ b/plugins/unityshell/src/inputremover.cpp
@@ -19,12 +19,12 @@
* Sam Spilsbury <sam.spilsbury@canonical.com>
*/
-#include <cstdlib>
-#include <boost/scoped_array.hpp>
#include "inputremover.h"
+#include <cstdlib>
#include <X11/Xregion.h>
#include <cstdio>
#include <cstring>
+#include <vector>
namespace
{
@@ -347,8 +347,7 @@ compiz::WindowInputRemover::writeProperty (XRectangle *input,
*/
const size_t dataSize = headerSize + (nInput * 4);
- boost::scoped_array<unsigned long> data(new unsigned long[dataSize]);
-
+ std::vector<unsigned long> data(dataSize);
data[0] = propVersion;
data[1] = nInput;
data[2] = inputOrdering;
@@ -370,7 +369,7 @@ compiz::WindowInputRemover::writeProperty (XRectangle *input,
type,
fmt,
PropModeReplace,
- reinterpret_cast<unsigned char*>(data.get()),
+ reinterpret_cast<unsigned char*>(data.data()),
dataSize);
return true;
diff --git a/services/panel-indicator-entry-accessible.c b/services/panel-indicator-entry-accessible.c
index 459812dff..55f45d297 100644
--- a/services/panel-indicator-entry-accessible.c
+++ b/services/panel-indicator-entry-accessible.c
@@ -293,7 +293,7 @@ panel_indicator_entry_accessible_ref_child (AtkObject *accessible, gint i)
g_return_val_if_fail (PANEL_IS_INDICATOR_ENTRY_ACCESSIBLE (accessible), NULL);
piea = PANEL_INDICATOR_ENTRY_ACCESSIBLE (accessible);
- if (piea->priv->entry->parent_object && GTK_IS_MENU (piea->priv->entry->menu))
+ if (piea->priv->entry && piea->priv->entry->parent_object && GTK_IS_MENU (piea->priv->entry->menu))
{
child = gtk_widget_get_accessible (GTK_WIDGET (piea->priv->entry->menu));
atk_object_set_parent (child, accessible);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 9bcf0a582..17ea9b758 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -80,6 +80,7 @@ if (GMOCK_LIB AND
set (GTEST_SLOW_SOURCES
test_main.cpp
logger_helper.cpp
+ mock-application.cpp
test_switcher_controller_slow.cpp
test_switcher_controller_class.cpp
test_tooltip_manager.cpp
diff --git a/tests/mock-application.h b/tests/mock-application.h
index 312168854..0ee200f9d 100644
--- a/tests/mock-application.h
+++ b/tests/mock-application.h
@@ -91,7 +91,7 @@ struct MockApplicationWindow : unity::ApplicationWindow
return;
title_ = new_title;
- title.changed(title_);
+ title.changed.emit(title_);
}
void SetIcon(std::string const& new_icon)
@@ -100,7 +100,16 @@ struct MockApplicationWindow : unity::ApplicationWindow
return;
icon_ = new_icon;
- icon.changed(icon_);
+ icon.changed.emit(icon_);
+ }
+
+ void SetMonitor(int new_monitor)
+ {
+ if (monitor_ == new_monitor)
+ return;
+
+ monitor_ = new_monitor;
+ monitor.changed.emit(monitor_);
}
};
@@ -329,6 +338,7 @@ struct MockApplicationManager : public unity::ApplicationManager
MOCK_CONST_METHOD0(GetActiveApplication, unity::ApplicationPtr());
MOCK_CONST_METHOD1(GetWindowsForMonitor, unity::WindowList(int));
MOCK_CONST_METHOD1(GetWindowForId, unity::ApplicationWindowPtr(Window));
+ MOCK_CONST_METHOD3(FocusWindowGroup, void(unity::WindowList const&, bool, int));
unity::ApplicationPtr LocalGetApplicationForDesktopFile(std::string const& desktop_file)
{
diff --git a/tests/test_application_launcher_icon.cpp b/tests/test_application_launcher_icon.cpp
index 41688d36d..c34c39b6c 100644
--- a/tests/test_application_launcher_icon.cpp
+++ b/tests/test_application_launcher_icon.cpp
@@ -50,7 +50,8 @@ struct MockApplicationLauncherIcon : ApplicationLauncherIcon
typedef nux::ObjectPtr<MockApplicationLauncherIcon> Ptr;
MockApplicationLauncherIcon(ApplicationPtr const& app)
- : ApplicationLauncherIcon(app)
+ : WindowedLauncherIcon(IconType::APPLICATION)
+ , ApplicationLauncherIcon(app)
{
ON_CALL(*this, Stick(_)).WillByDefault(Invoke([this] (bool save) { ApplicationLauncherIcon::Stick(save); }));
ON_CALL(*this, Stick()).WillByDefault(Invoke([this] { ApplicationLauncherIcon::Stick(); }));
@@ -67,11 +68,14 @@ struct MockApplicationLauncherIcon : ApplicationLauncherIcon
bool LauncherIconIsSticky() const { return LauncherIcon::IsSticky(); }
void LocalActivate(ActionArg a) { ApplicationLauncherIcon::ActivateLauncherIcon(a); }
- using ApplicationLauncherIcon::IsFileManager;
using ApplicationLauncherIcon::LogUnityEvent;
using ApplicationLauncherIcon::Remove;
using ApplicationLauncherIcon::SetApplication;
using ApplicationLauncherIcon::GetApplication;
+ using ApplicationLauncherIcon::PerformScroll;
+ using LauncherIcon::BackgroundColor;
+ using LauncherIcon::GetRemoteUri;
+ using LauncherIcon::AllowDetailViewInSwitcher;
};
MATCHER_P(AreArgsEqual, a, "")
@@ -90,15 +94,15 @@ struct TestApplicationLauncherIcon : testmocks::TestUnityAppBase
virtual void SetUp() override
{
usc_app = std::make_shared<MockApplication::Nice>(USC_DESKTOP, "softwarecenter");
- usc_icon = new NiceMock<MockApplicationLauncherIcon>(usc_app);
+ usc_icon = new MockApplicationLauncherIcon(usc_app);
ASSERT_EQ(usc_icon->DesktopFile(), USC_DESKTOP);
empty_app = std::make_shared<MockApplication::Nice>(NO_ICON_DESKTOP);
- empty_icon = new NiceMock<MockApplicationLauncherIcon>(empty_app);
+ empty_icon = new MockApplicationLauncherIcon(empty_app);
ASSERT_EQ(empty_icon->DesktopFile(), NO_ICON_DESKTOP);
mock_app = std::make_shared<MockApplication::Nice>();
- mock_icon = new NiceMock<MockApplicationLauncherIcon>(mock_app);
+ mock_icon = new MockApplicationLauncherIcon(mock_app);
ASSERT_TRUE(mock_icon->DesktopFile().empty());
}
@@ -173,7 +177,7 @@ TEST_F(TestApplicationLauncherIcon, ApplicationSignalDisconnection)
{
std::shared_ptr<MockApplication> app = std::make_shared<MockApplication::Nice>(USC_DESKTOP);
{
- MockApplicationLauncherIcon::Ptr icon(new NiceMock<MockApplicationLauncherIcon>(app));
+ MockApplicationLauncherIcon::Ptr icon(new MockApplicationLauncherIcon(app));
EXPECT_FALSE(app->closed.empty());
}
@@ -266,7 +270,7 @@ TEST_F(TestApplicationLauncherIcon, StickStickedDesktopApp)
auto app = std::make_shared<MockApplication::Nice>(USC_DESKTOP);
app->sticky = true;
app->desktop_file_ = UM_DESKTOP;
- MockApplicationLauncherIcon::Ptr icon(new NiceMock<MockApplicationLauncherIcon>(app));
+ MockApplicationLauncherIcon::Ptr icon(new MockApplicationLauncherIcon(app));
ASSERT_TRUE(icon->IsSticky());
EXPECT_TRUE(icon->LauncherIconIsSticky());
}
@@ -275,7 +279,7 @@ TEST_F(TestApplicationLauncherIcon, StickStickedDesktopLessApp)
{
auto app = std::make_shared<MockApplication::Nice>();
app->sticky = true;
- MockApplicationLauncherIcon::Ptr icon(new NiceMock<MockApplicationLauncherIcon>(app));
+ MockApplicationLauncherIcon::Ptr icon(new MockApplicationLauncherIcon(app));
ASSERT_FALSE(icon->IsSticky());
EXPECT_FALSE(icon->LauncherIconIsSticky());
}
@@ -291,7 +295,7 @@ TEST_F(TestApplicationLauncherIcon, StickAndSaveDesktopAppDontCreateNewDesktop)
TEST_F(TestApplicationLauncherIcon, StickAndSaveDesktopLessAppCreatesNewDesktop)
{
auto app = std::make_shared<MockApplication::Nice>();
- MockApplicationLauncherIcon::Ptr icon(new NiceMock<MockApplicationLauncherIcon>(app));
+ MockApplicationLauncherIcon::Ptr icon(new MockApplicationLauncherIcon(app));
EXPECT_CALL(*app, CreateLocalDesktopFile());
icon->Stick(true);
@@ -354,7 +358,7 @@ TEST_F(TestApplicationLauncherIcon, UnstickDesktopAppLogEvents)
TEST_F(TestApplicationLauncherIcon, UnstickDesktopLessAppLogEvent)
{
auto app = std::make_shared<MockApplication::Nice>();
- MockApplicationLauncherIcon::Ptr icon(new NiceMock<MockApplicationLauncherIcon>(app));
+ MockApplicationLauncherIcon::Ptr icon(new MockApplicationLauncherIcon(app));
EXPECT_CALL(*unity_app_, LogEvent(ApplicationEventType::ACCESS, _)).Times(0);
icon->UnStick();
@@ -1103,25 +1107,6 @@ TEST_F(TestApplicationLauncherIcon, QuicklistMenuItemRemoteOverridesQuitByProper
dbusmenu_menuitem_handle_event(item, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
}
-TEST_F(TestApplicationLauncherIcon, IsFileManager)
-{
- EXPECT_FALSE(usc_icon->IsFileManager());
- EXPECT_FALSE(empty_icon->IsFileManager());
- EXPECT_FALSE(mock_icon->IsFileManager());
-
- auto app = std::make_shared<MockApplication::Nice>("/any/path/org.gnome.Nautilus.desktop", "Nautilus");
- MockApplicationLauncherIcon::Ptr icon(new NiceMock<MockApplicationLauncherIcon>(app));
- EXPECT_TRUE(icon->IsFileManager());
-
- app = std::make_shared<MockApplication::Nice>("/any/path/nautilus-folder-handler.desktop", "Nautilus");
- icon = new NiceMock<MockApplicationLauncherIcon>(app);
- EXPECT_TRUE(icon->IsFileManager());
-
- app = std::make_shared<MockApplication::Nice>("/any/path/nautilus-home.desktop", "Nautilus");
- icon = new NiceMock<MockApplicationLauncherIcon>(app);
- EXPECT_TRUE(icon->IsFileManager());
-}
-
TEST_F(TestApplicationLauncherIcon, AllowDetailViewInSwitcher)
{
mock_app->type_ = AppType::NORMAL;
@@ -1232,7 +1217,7 @@ TEST_F(TestApplicationLauncherIcon, DestructionDontUnsetsAppSeenIfReplaced)
mock_icon->Remove();
ASSERT_FALSE(mock_app->seen);
- MockApplicationLauncherIcon::Ptr new_icon(new NiceMock<MockApplicationLauncherIcon>(mock_app));
+ MockApplicationLauncherIcon::Ptr new_icon(new MockApplicationLauncherIcon(mock_app));
mock_icon = nullptr;
EXPECT_TRUE(mock_app->seen);
diff --git a/tests/test_launcher_controller.cpp b/tests/test_launcher_controller.cpp
index fefc6d15e..7758b1830 100644
--- a/tests/test_launcher_controller.cpp
+++ b/tests/test_launcher_controller.cpp
@@ -136,8 +136,10 @@ private:
struct MockApplicationLauncherIcon : ApplicationLauncherIcon
{
- typedef NiceMock<MockApplicationLauncherIcon> Nice;
- typedef nux::ObjectPtr<MockApplicationLauncherIcon::Nice> Ptr;
+ // NiceMock doesn't work well with Virtual Inheritance, so we need to disable it
+ //typedef NiceMock<MockApplicationLauncherIcon> Nice;
+ typedef MockApplicationLauncherIcon Nice;
+ typedef nux::ObjectPtr<MockApplicationLauncherIcon> Ptr;
typedef bool Fake;
MockApplicationLauncherIcon(Fake = true, std::string const& remote_uri = "")
@@ -154,7 +156,8 @@ struct MockApplicationLauncherIcon : ApplicationLauncherIcon
}
explicit MockApplicationLauncherIcon(ApplicationPtr const& app)
- : ApplicationLauncherIcon(app)
+ : WindowedLauncherIcon(IconType::APPLICATION)
+ , ApplicationLauncherIcon(app)
{
ON_CALL(*this, Stick(_)).WillByDefault(Invoke([this] (bool save) { ApplicationLauncherIcon::Stick(save); }));
ON_CALL(*this, UnStick()).WillByDefault(Invoke([this] { ApplicationLauncherIcon::UnStick(); }));
@@ -170,15 +173,18 @@ struct MockApplicationLauncherIcon : ApplicationLauncherIcon
MOCK_CONST_METHOD0(GetRemoteUri, std::string());
MOCK_METHOD1(Stick, void(bool));
MOCK_METHOD0(UnStick, void());
- MOCK_METHOD0(Quit, void());
+ MOCK_CONST_METHOD0(Quit, void());
};
struct MockVolumeLauncherIcon : public VolumeLauncherIcon
{
typedef nux::ObjectPtr<MockVolumeLauncherIcon> Ptr;
+ // typedef NiceMock<MockVolumeLauncherIcon> Nice;
+ typedef MockVolumeLauncherIcon Nice;
MockVolumeLauncherIcon()
- : VolumeLauncherIcon(Volume::Ptr(volume_ = new NiceMock<MockVolume>()),
+ : WindowedLauncherIcon(IconType::DEVICE)
+ , VolumeLauncherIcon(Volume::Ptr(volume_ = new NiceMock<MockVolume>()),
std::make_shared<MockDevicesSettings::Nice>(),
std::make_shared<MockDeviceNotificationDisplay::Nice>(),
std::make_shared<MockFileManager::Nice>())
@@ -269,7 +275,7 @@ protected:
void DisconnectSignals()
{
ApplicationManager::Default().application_started.clear();
- Impl()->device_section_.icon_added.clear();
+ Impl()->device_section_->icon_added.clear();
Impl()->model_->icon_removed.clear();
Impl()->model_->saved.clear();
Impl()->model_->order_changed.clear();
@@ -640,8 +646,8 @@ TEST_F(TestLauncherController, CreateFavoriteInvalidDesktopFile)
TEST_F(TestLauncherController, CreateFavoriteDevice)
{
- lc.Impl()->device_section_ = MockDeviceLauncherSection();
- auto const& icons = lc.Impl()->device_section_.GetIcons();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>();
+ auto const& icons = lc.Impl()->device_section_->GetIcons();
auto const& device_icon = icons.front();
ASSERT_TRUE(device_icon.IsValid());
@@ -903,8 +909,8 @@ TEST_F(TestLauncherController, AddDevices)
{
lc.ClearModel();
lc.DisconnectSignals();
- lc.Impl()->device_section_ = MockDeviceLauncherSection();
- auto const& icons = lc.Impl()->device_section_.GetIcons();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>();
+ auto const& icons = lc.Impl()->device_section_->GetIcons();
auto const& device_icon1 = icons.front();
auto const& device_icon2 = *(std::next(icons.begin()));
@@ -949,7 +955,7 @@ TEST_F(TestLauncherController, MigrateFavoritesUnneeded)
TEST_F(TestLauncherController, SetupIcons)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>();
lc.Impl()->expo_icon_->UnStick();
lc.Impl()->desktop_icon_->UnStick();
auto const& model = lc.Impl()->model_;
@@ -970,7 +976,7 @@ TEST_F(TestLauncherController, SetupIcons)
fav = lc.Impl()->GetIconByUri(FavoriteStore::URI_PREFIX_APP + app::SW_CENTER);
EXPECT_EQ(model->IconIndex(fav), ++icon_index);
- for (auto const& device : lc.Impl()->device_section_.GetIcons())
+ for (auto const& device : lc.Impl()->device_section_->GetIcons())
ASSERT_EQ(model->IconIndex(device), ++icon_index);
fav = lc.Impl()->GetIconByUri(FavoriteStore::URI_PREFIX_APP + app::UPDATE_MANAGER);
@@ -995,7 +1001,7 @@ TEST_F(TestLauncherController, SetupIcons)
TEST_F(TestLauncherController, ResetIconPriorities)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>();
auto const& model = lc.Impl()->model_;
favorite_store.AddFavorite(places::APPS_URI, -1);
@@ -1012,7 +1018,7 @@ TEST_F(TestLauncherController, ResetIconPriorities)
int icon_index = -1;
- for (auto const& device : lc.Impl()->device_section_.GetIcons())
+ for (auto const& device : lc.Impl()->device_section_->GetIcons())
ASSERT_EQ(model->IconIndex(device), ++icon_index);
auto fav = lc.Impl()->GetIconByUri(FavoriteStore::URI_PREFIX_APP + app::SW_CENTER);
@@ -1043,8 +1049,8 @@ TEST_F(TestLauncherController, ResetIconPriorities)
TEST_F(TestLauncherController, GetLastIconPriorityUnSticky)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(3);
- auto const& device_icons = lc.Impl()->device_section_.GetIcons();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(3);
+ auto const& device_icons = lc.Impl()->device_section_->GetIcons();
auto const& last_device = device_icons.back();
favorite_store.SetFavorites({ places::DEVICES_URI,
@@ -1060,8 +1066,8 @@ TEST_F(TestLauncherController, GetLastIconPriorityUnSticky)
TEST_F(TestLauncherController, GetLastIconPriorityUnStickyWithAllStickyIcons)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(3);
- auto const& device_icons = lc.Impl()->device_section_.GetIcons();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(3);
+ auto const& device_icons = lc.Impl()->device_section_->GetIcons();
auto const& last_device = device_icons.back();
favorite_store.SetFavorites({ places::DEVICES_URI,
@@ -1080,8 +1086,8 @@ TEST_F(TestLauncherController, GetLastIconPriorityUnStickyWithAllStickyIcons)
TEST_F(TestLauncherController, GetLastIconPriorityUnStickyWithSomeStickyIcons)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(3);
- auto const& device_icons = lc.Impl()->device_section_.GetIcons();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(3);
+ auto const& device_icons = lc.Impl()->device_section_->GetIcons();
auto const& first_device = *(std::next(device_icons.rbegin()));
auto const& last_device = device_icons.back();
@@ -1100,7 +1106,7 @@ TEST_F(TestLauncherController, GetLastIconPriorityUnStickyWithSomeStickyIcons)
TEST_F(TestLauncherController, GetLastIconPriorityUnStickyWithNoIcons)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(0);
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(0);
lc.Impl()->SetupIcons();
lc.DisconnectSignals();
@@ -1111,7 +1117,7 @@ TEST_F(TestLauncherController, GetLastIconPriorityUnStickyWithNoIcons)
TEST_F(TestLauncherController, GetLastIconPriorityUnStickyWithNoIconsAndUri)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(0);
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(0);
favorite_store.SetFavorites({ places::DEVICES_URI,
FavoriteStore::URI_PREFIX_APP + app::SW_CENTER });
@@ -1136,11 +1142,11 @@ TEST_F(TestLauncherController, GetLastIconPriorityUnStickyWithNoIconsAndUri)
TEST_F(TestLauncherController, GetLastIconPrioritySticky)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(3);
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(3);
lc.Impl()->SetupIcons();
lc.DisconnectSignals();
- auto const& device_icons = lc.Impl()->device_section_.GetIcons();
+ auto const& device_icons = lc.Impl()->device_section_->GetIcons();
auto const& first_device = device_icons.front();
int last_priority = lc.Impl()->GetLastIconPriority<VolumeLauncherIcon>("", true);
@@ -1150,8 +1156,8 @@ TEST_F(TestLauncherController, GetLastIconPrioritySticky)
TEST_F(TestLauncherController, GetLastIconPriorityStickyWithAllStickyIcons)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(3);
- auto const& device_icons = lc.Impl()->device_section_.GetIcons();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(3);
+ auto const& device_icons = lc.Impl()->device_section_->GetIcons();
auto const& last_device = device_icons.back();
favorite_store.SetFavorites({ places::DEVICES_URI,
@@ -1170,8 +1176,8 @@ TEST_F(TestLauncherController, GetLastIconPriorityStickyWithAllStickyIcons)
TEST_F(TestLauncherController, GetLastIconPriorityStickyWithSomeStickyIcons)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(3);
- auto const& device_icons = lc.Impl()->device_section_.GetIcons();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(3);
+ auto const& device_icons = lc.Impl()->device_section_->GetIcons();
auto const& first_device = *(std::next(device_icons.rbegin()));
favorite_store.SetFavorites({ places::DEVICES_URI,
@@ -1189,7 +1195,7 @@ TEST_F(TestLauncherController, GetLastIconPriorityStickyWithSomeStickyIcons)
TEST_F(TestLauncherController, GetLastIconPriorityStickyWithNoIcons)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection(0);
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>(0);
lc.Impl()->SetupIcons();
lc.DisconnectSignals();
@@ -1240,8 +1246,8 @@ TEST_F(TestLauncherController, LauncherAddRequestApplicationStick)
TEST_F(TestLauncherController, LauncherAddRequestDeviceAdd)
{
auto const& model = lc.Impl()->model_;
- lc.Impl()->device_section_ = MockDeviceLauncherSection();
- auto const& icons = lc.Impl()->device_section_.GetIcons();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>();
+ auto const& icons = lc.Impl()->device_section_->GetIcons();
auto const& device_icon = icons.front();
auto const& icon_uri = device_icon->RemoteUri();
@@ -1262,7 +1268,7 @@ TEST_F(TestLauncherController, LauncherAddRequestDeviceAdd)
TEST_F(TestLauncherController, LauncherAddRequestDeviceStick)
{
auto const& model = lc.Impl()->model_;
- MockVolumeLauncherIcon::Ptr device_icon(new NiceMock<MockVolumeLauncherIcon>());
+ MockVolumeLauncherIcon::Ptr device_icon(new MockVolumeLauncherIcon::Nice());
lc.Impl()->RegisterIcon(device_icon, std::numeric_limits<int>::max());
auto app_icons = model->GetSublist<ApplicationLauncherIcon>();
@@ -1287,7 +1293,7 @@ TEST_F(TestLauncherController, LauncherRemoveRequestApplicationUnStickAndQuit)
TEST_F(TestLauncherController, LauncherRemoveRequestDeviceEjects)
{
- MockVolumeLauncherIcon::Ptr device_icon(new NiceMock<MockVolumeLauncherIcon>());
+ MockVolumeLauncherIcon::Ptr device_icon(new MockVolumeLauncherIcon::Nice());
EXPECT_CALL(*(device_icon->volume_), CanBeEjected())
.WillRepeatedly(Return(true));
@@ -1302,7 +1308,7 @@ TEST_F(TestLauncherController, LauncherRemoveRequestDeviceEjects)
TEST_F(TestLauncherController, LauncherRemoveRequestDeviceStops)
{
- MockVolumeLauncherIcon::Ptr device_icon(new NiceMock<MockVolumeLauncherIcon>());
+ MockVolumeLauncherIcon::Ptr device_icon(new MockVolumeLauncherIcon::Nice());
EXPECT_CALL(*(device_icon->volume_), CanBeEjected())
.WillRepeatedly(Return(false));
@@ -1362,7 +1368,7 @@ TEST_F(TestLauncherController, SaveIconsOrder)
invisible_app->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
lc.Impl()->RegisterIcon(invisible_app, ++priority);
- MockVolumeLauncherIcon::Ptr sticky_device(new NiceMock<MockVolumeLauncherIcon>());
+ MockVolumeLauncherIcon::Ptr sticky_device(new MockVolumeLauncherIcon::Nice());
sticky_device->Stick(false);
lc.Impl()->RegisterIcon(sticky_device, ++priority);
@@ -1393,7 +1399,7 @@ TEST_F(TestLauncherController, SaveIconsOrderWithOnlyStickyIcons)
sticky_app->Stick(false);
lc.Impl()->RegisterIcon(sticky_app, ++priority);
- MockVolumeLauncherIcon::Ptr sticky_device(new NiceMock<MockVolumeLauncherIcon>());
+ MockVolumeLauncherIcon::Ptr sticky_device(new MockVolumeLauncherIcon::Nice());
sticky_device->Stick(false);
lc.Impl()->RegisterIcon(sticky_device, ++priority);
@@ -1422,7 +1428,7 @@ TEST_F(TestLauncherController, SaveIconsOrderTriesToKeepIconProvidersOrder)
sticky_app->Stick(false);
lc.Impl()->RegisterIcon(sticky_app, ++priority);
- MockVolumeLauncherIcon::Ptr sticky_device(new NiceMock<MockVolumeLauncherIcon>());
+ MockVolumeLauncherIcon::Ptr sticky_device(new MockVolumeLauncherIcon::Nice());
sticky_device->Stick(false);
lc.Impl()->RegisterIcon(sticky_device, ++priority);
@@ -1447,7 +1453,7 @@ TEST_F(TestLauncherController, SaveIconsOrderTriesToKeepIconProvidersOrder2)
sticky_app->Stick(false);
lc.Impl()->RegisterIcon(sticky_app, ++priority);
- MockVolumeLauncherIcon::Ptr sticky_device(new NiceMock<MockVolumeLauncherIcon>());
+ MockVolumeLauncherIcon::Ptr sticky_device(new MockVolumeLauncherIcon::Nice());
sticky_device->Stick(false);
lc.Impl()->RegisterIcon(sticky_device, ++priority);
@@ -1597,9 +1603,9 @@ TEST_F(TestLauncherController, OnFavoriteStoreFavoriteAddedStickAfter)
TEST_F(TestLauncherController, OnFavoriteStoreFavoriteAddedDeviceSection)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>();
auto const& model = lc.Impl()->model_;
- auto const& icons = lc.Impl()->device_section_.GetIcons();
+ auto const& icons = lc.Impl()->device_section_->GetIcons();
auto const& device_icon1(icons.front());
auto const& device_icon2(*(std::next(icons.begin())));
@@ -1634,10 +1640,10 @@ TEST_F(TestLauncherController, OnFavoriteStoreFavoriteRemovedApplication)
TEST_F(TestLauncherController, OnFavoriteStoreFavoriteRemovedDevice)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>();
auto const& model = lc.Impl()->model_;
- auto const& icons = lc.Impl()->device_section_.GetIcons();
+ auto const& icons = lc.Impl()->device_section_->GetIcons();
auto const& device_icon(icons.front());
favorite_store.SetFavorites({ lc.Impl()->expo_icon_->RemoteUri(),
@@ -1660,10 +1666,10 @@ TEST_F(TestLauncherController, OnFavoriteStoreFavoriteRemovedDevice)
TEST_F(TestLauncherController, OnFavoriteStoreFavoriteRemovedDeviceSection)
{
lc.ClearModel();
- lc.Impl()->device_section_ = MockDeviceLauncherSection();
+ lc.Impl()->device_section_ = std::make_shared<MockDeviceLauncherSection>();
auto const& model = lc.Impl()->model_;
- auto const& icons = lc.Impl()->device_section_.GetIcons();
+ auto const& icons = lc.Impl()->device_section_->GetIcons();
auto const& device_icon1(icons.front());
auto const& device_icon2(*(std::next(icons.begin())));
@@ -1958,10 +1964,9 @@ TEST_F(TestLauncherController, IconShowsOnQuickApplicationReopen)
unity::glib::Object<BamfMockApplication> bamf_mock_application(bamf_mock_application_new());
ApplicationPtr app(new unity::bamf::Application(mock_manager, unity::glib::object_cast<BamfApplication>(bamf_mock_application)));
- MockApplicationLauncherIcon::Ptr our_icon;
-
+ AbstractLauncherIcon::Ptr our_icon;
mock_manager.Default().application_started.emit(app);
-
+
app->title.changed.emit("Hello");
auto app_icons = lc.Impl()->model_->GetSublist<ApplicationLauncherIcon>();
@@ -1971,7 +1976,7 @@ TEST_F(TestLauncherController, IconShowsOnQuickApplicationReopen)
{
our_icon = icon;
break;
- }
+ }
}
ASSERT_TRUE(our_icon);
EXPECT_FALSE(our_icon->removed);
diff --git a/tests/test_mock_filemanager.h b/tests/test_mock_filemanager.h
index 231c0074e..1e541ebfd 100644
--- a/tests/test_mock_filemanager.h
+++ b/tests/test_mock_filemanager.h
@@ -32,15 +32,18 @@ struct MockFileManager : FileManager
typedef testing::NiceMock<MockFileManager> Nice;
MOCK_METHOD2(Open, void(std::string const& uri, uint64_t time));
- MOCK_METHOD2(OpenActiveChild, void(std::string const& uri, uint64_t time));
MOCK_METHOD1(OpenTrash, void(uint64_t time));
MOCK_METHOD1(TrashFile, bool(std::string const& uri));
MOCK_METHOD1(EmptyTrash, void(uint64_t time));
MOCK_METHOD3(CopyFiles, void(std::set<std::string> const& files, std::string const& dest, uint64_t time));
- MOCK_CONST_METHOD0(OpenedLocations, std::vector<std::string>());
- MOCK_CONST_METHOD1(IsPrefixOpened, bool(std::string const& uri));
- MOCK_CONST_METHOD0(IsTrashOpened, bool());
- MOCK_CONST_METHOD0(IsDeviceOpened, bool());
+ MOCK_CONST_METHOD1(WindowsForLocation, WindowList(std::string const&));
+ MOCK_CONST_METHOD1(LocationForWindow, std::string(ApplicationWindowPtr const&));
+
+ MockFileManager()
+ {
+ using namespace testing;
+ ON_CALL(*this, WindowsForLocation(_)).WillByDefault(Return(WindowList()));
+ }
};
}
diff --git a/tests/test_software_center_launcher_icon.cpp b/tests/test_software_center_launcher_icon.cpp
index abf65d09f..6ee4d8d12 100644
--- a/tests/test_software_center_launcher_icon.cpp
+++ b/tests/test_software_center_launcher_icon.cpp
@@ -62,16 +62,17 @@ struct TestSoftwareCenterLauncherIcon : testmocks::TestUnityAppBase
MockSoftwareCenterLauncherIcon(ApplicationPtr const& app,
std::string const& aptdaemon_trans_id,
std::string const& icon_path)
- : SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path)
+ : WindowedLauncherIcon(IconType::APPLICATION)
+ , SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path)
{}
void LauncherIconUnstick() { LauncherIcon::UnStick(); }
using SoftwareCenterLauncherIcon::GetActualDesktopFileAfterInstall;
- using SoftwareCenterLauncherIcon::GetRemoteUri;
using SoftwareCenterLauncherIcon::OnFinished;
using SoftwareCenterLauncherIcon::OnPropertyChanged;
using SoftwareCenterLauncherIcon::drag_window_;
+ using LauncherIcon::GetRemoteUri;
};
nux::ObjectPtr<Launcher> CreateLauncher()
diff --git a/tests/test_switcher_controller.h b/tests/test_switcher_controller.h
index bc0118df4..5e35b2e59 100644
--- a/tests/test_switcher_controller.h
+++ b/tests/test_switcher_controller.h
@@ -27,10 +27,11 @@
#include "test_utils.h"
#include "DesktopLauncherIcon.h"
-#include "SimpleLauncherIcon.h"
+#include "WindowedLauncherIcon.h"
#include "SwitcherController.h"
#include "SwitcherView.h"
#include "TimeUtil.h"
+#include "mock-application.h"
#include "mock-base-window.h"
#include "test_standalone_wm.h"
@@ -48,35 +49,24 @@ const unsigned TICK_DURATION = 10 * 1000;
/**
* A fake ApplicationWindow for verifying selection of the switcher.
*/
-class FakeApplicationWindow : public unity::ApplicationWindow
+struct FakeApplicationWindow : public ::testmocks::MockApplicationWindow::Nice
{
-public:
+ typedef NiceMock<FakeApplicationWindow> Nice;
FakeApplicationWindow(Window xid, uint64_t active_number = 0);
~FakeApplicationWindow();
-
- virtual WindowType type() const;
-
- virtual Window window_id() const;
- virtual int monitor() const;
- virtual unity::ApplicationPtr application() const;
- virtual bool Focus() const;
- virtual void Quit() const;
-
-private:
- Window xid_;
};
/**
* A fake LauncherIcon for verifying selection operations of the switcher.
*/
-struct FakeLauncherIcon : unity::launcher::SimpleLauncherIcon
+struct FakeLauncherIcon : unity::launcher::WindowedLauncherIcon
{
FakeLauncherIcon(std::string const& app_name, bool allow_detail_view, uint64_t priority);
- unity::WindowList Windows() override;
bool AllowDetailViewInSwitcher() const override;
bool ShowInSwitcher(bool) override;
uint64_t SwitcherPriority() override;
+ WindowList GetManagedWindows() const override;
bool allow_detail_view_;
uint64_t priority_;
diff --git a/tests/test_switcher_controller_class.cpp b/tests/test_switcher_controller_class.cpp
index 749359f54..807a239bc 100644
--- a/tests/test_switcher_controller_class.cpp
+++ b/tests/test_switcher_controller_class.cpp
@@ -26,14 +26,13 @@ using namespace unity::switcher;
using namespace std::chrono;
FakeApplicationWindow::FakeApplicationWindow(Window xid, uint64_t active_number)
- : xid_(xid)
+ : MockApplicationWindow::Nice(xid)
{
- auto standalone_window = std::make_shared<StandaloneWindow>(xid_);
+ SetMonitor(-1);
+ auto standalone_window = std::make_shared<StandaloneWindow>(window_id());
standalone_window->active_number = active_number;
testwrapper::StandaloneWM::Get()->AddStandaloneWindow(standalone_window);
-
- title.SetGetterFunction([this] { return "FakeApplicationWindow"; });
- icon.SetGetterFunction([this] { return ""; });
+ ON_CALL(*this, Quit()).WillByDefault(Invoke([this] { WindowManager::Default().Close(window_id()); }));
}
FakeApplicationWindow::~FakeApplicationWindow()
@@ -41,25 +40,17 @@ FakeApplicationWindow::~FakeApplicationWindow()
testwrapper::StandaloneWM::Get()->Close(xid_);
}
-WindowType FakeApplicationWindow::type() const { return WindowType::MOCK; }
-
-Window FakeApplicationWindow::window_id() const { return xid_; }
-int FakeApplicationWindow::monitor() const { return -1; }
-ApplicationPtr FakeApplicationWindow::application() const { return ApplicationPtr(); }
-bool FakeApplicationWindow::Focus() const { return false; }
-void FakeApplicationWindow::Quit() const { WindowManager::Default().Close(xid_); }
-
FakeLauncherIcon::FakeLauncherIcon(std::string const& app_name, bool allow_detail_view, uint64_t priority)
- : launcher::SimpleLauncherIcon(IconType::APPLICATION)
+ : launcher::WindowedLauncherIcon(IconType::APPLICATION)
, allow_detail_view_(allow_detail_view)
, priority_(priority)
- , window_list{ std::make_shared<FakeApplicationWindow>(priority_ | 0x0001, SwitcherPriority()),
- std::make_shared<FakeApplicationWindow>(priority_ | 0x0002, priority_) }
+ , window_list{ std::make_shared<FakeApplicationWindow::Nice>(priority_ | 0x0001, SwitcherPriority()),
+ std::make_shared<FakeApplicationWindow::Nice>(priority_ | 0x0002, priority_) }
{
tooltip_text = app_name;
}
-WindowList FakeLauncherIcon::Windows()
+WindowList FakeLauncherIcon::GetManagedWindows() const
{
return window_list;
}
@@ -85,7 +76,7 @@ uint64_t FakeLauncherIcon::SwitcherPriority()
//class TestSwitcherController : public testing::Test
TestSwitcherController::TestSwitcherController()
: animation_controller_(tick_source_)
- , mock_window_(new NiceMock<testmocks::MockBaseWindow>())
+ , mock_window_(new NiceMock<unity::testmocks::MockBaseWindow>())
, controller_(std::make_shared<Controller>([this] { return mock_window_; }))
{
controller_->timeout_length = 0;
diff --git a/tests/test_trash_launcher_icon.cpp b/tests/test_trash_launcher_icon.cpp
index 839c70ff4..d8a5b6162 100644
--- a/tests/test_trash_launcher_icon.cpp
+++ b/tests/test_trash_launcher_icon.cpp
@@ -27,9 +27,11 @@
using namespace unity;
using namespace unity::launcher;
using namespace testing;
+using namespace testmocks;
namespace
{
+const std::string TRASH_URI = "trash:";
struct TestTrashLauncherIcon : testmocks::TestUnityAppBase
{
@@ -42,6 +44,12 @@ struct TestTrashLauncherIcon : testmocks::TestUnityAppBase
TrashLauncherIcon icon;
};
+TEST_F(TestTrashLauncherIcon, InitState)
+{
+ EXPECT_FALSE(icon.GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
+ EXPECT_FALSE(icon.GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE));
+}
+
TEST_F(TestTrashLauncherIcon, Position)
{
EXPECT_EQ(icon.position(), AbstractLauncherIcon::Position::END);
@@ -74,15 +82,77 @@ TEST_F(TestTrashLauncherIcon, QuicklistEmptyTrash)
TEST_F(TestTrashLauncherIcon, RunningState)
{
- EXPECT_CALL(*fm_, IsTrashOpened()).WillRepeatedly(Return(true));
+ auto win1 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ auto win2 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+
+ ON_CALL(*fm_, WindowsForLocation(TRASH_URI)).WillByDefault(Return(WindowList({win1, win2})));
fm_->locations_changed.emit();
EXPECT_TRUE(icon.GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
- EXPECT_CALL(*fm_, IsTrashOpened()).WillRepeatedly(Return(false));
+ ON_CALL(*fm_, WindowsForLocation(TRASH_URI)).WillByDefault(Return(WindowList()));
fm_->locations_changed.emit();
EXPECT_FALSE(icon.GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
}
+TEST_F(TestTrashLauncherIcon, ActiveState)
+{
+ auto win1 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ auto win2 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+
+ ON_CALL(*fm_, WindowsForLocation(TRASH_URI)).WillByDefault(Return(WindowList({win1, win2})));
+ fm_->locations_changed.emit();
+ ASSERT_FALSE(icon.GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE));
+
+ win2->LocalFocus();
+ EXPECT_TRUE(icon.GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE));
+
+ ON_CALL(*fm_, WindowsForLocation(TRASH_URI)).WillByDefault(Return(WindowList()));
+ fm_->locations_changed.emit();
+ EXPECT_FALSE(icon.GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE));
+}
+
+TEST_F(TestTrashLauncherIcon, WindowsCount)
+{
+ WindowList windows((g_random_int() % 10) + 5);
+ for (unsigned i = 0; i < windows.capacity(); ++i)
+ windows[i] = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+
+ ON_CALL(*fm_, WindowsForLocation(TRASH_URI)).WillByDefault(Return(windows));
+ fm_->locations_changed.emit();
+ EXPECT_EQ(icon.Windows().size(), windows.size());
+}
+
+TEST_F(TestTrashLauncherIcon, WindowsPerMonitor)
+{
+ WindowList windows((g_random_int() % 10) + 5);
+ for (unsigned i = 0; i < windows.capacity(); ++i)
+ {
+ auto win = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ win->monitor_ = i % 2;
+ windows[i] = win;
+ }
+
+ ON_CALL(*fm_, WindowsForLocation(TRASH_URI)).WillByDefault(Return(windows));
+ fm_->locations_changed.emit();
+
+ EXPECT_EQ(icon.WindowsVisibleOnMonitor(0), (windows.size() / 2) + (windows.size() % 2));
+ EXPECT_EQ(icon.WindowsVisibleOnMonitor(1), windows.size() / 2);
+}
+
+TEST_F(TestTrashLauncherIcon, WindowsOnMonitorChanges)
+{
+ auto win = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ ON_CALL(*fm_, WindowsForLocation(TRASH_URI)).WillByDefault(Return(WindowList({win})));
+ fm_->locations_changed.emit();
+
+ EXPECT_EQ(icon.WindowsVisibleOnMonitor(0), 1);
+ EXPECT_EQ(icon.WindowsVisibleOnMonitor(1), 0);
+
+ win->SetMonitor(1);
+ EXPECT_EQ(icon.WindowsVisibleOnMonitor(0), 0);
+ EXPECT_EQ(icon.WindowsVisibleOnMonitor(1), 1);
+}
+
TEST_F(TestTrashLauncherIcon, FilemanagerSignalDisconnection)
{
auto file_manager = std::make_shared<NiceMock<MockFileManager>>();
diff --git a/tests/test_volume_launcher_icon.cpp b/tests/test_volume_launcher_icon.cpp
index 8d6bc48c2..41b794bae 100644
--- a/tests/test_volume_launcher_icon.cpp
+++ b/tests/test_volume_launcher_icon.cpp
@@ -27,8 +27,11 @@ using namespace testing;
#include "test_utils.h"
#include "test_mock_devices.h"
#include "test_mock_filemanager.h"
+#include "mock-application.h"
+
using namespace unity;
using namespace unity::launcher;
+using namespace testmocks;
namespace
{
@@ -43,7 +46,7 @@ struct TestVolumeLauncherIcon : public Test
{
SetupVolumeDefaultBehavior();
SetupSettingsDefaultBehavior();
- icon_ = new NiceMock<VolumeLauncherIcon>(volume_, settings_, notifications_, file_manager_);
+ icon_ = new VolumeLauncherIcon(volume_, settings_, notifications_, file_manager_);
}
void SetupSettingsDefaultBehavior()
@@ -94,7 +97,7 @@ struct TestVolumeLauncherIconDelayedConstruction : TestVolumeLauncherIcon
void CreateIcon()
{
- icon_ = new NiceMock<VolumeLauncherIcon>(volume_, settings_, notifications_, file_manager_);
+ icon_ = new VolumeLauncherIcon(volume_, settings_, notifications_, file_manager_);
}
};
@@ -105,7 +108,7 @@ TEST_F(TestVolumeLauncherIcon, TestIconType)
TEST_F(TestVolumeLauncherIconDelayedConstruction, TestRunningOnClosed)
{
- ON_CALL(*file_manager_, IsPrefixOpened(volume_->GetUri())).WillByDefault(Return(false));
+ ON_CALL(*file_manager_, WindowsForLocation(_)).WillByDefault(Return(WindowList()));
CreateIcon();
EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
@@ -113,7 +116,8 @@ TEST_F(TestVolumeLauncherIconDelayedConstruction, TestRunningOnClosed)
TEST_F(TestVolumeLauncherIconDelayedConstruction, TestRunningOnOpened)
{
- ON_CALL(*file_manager_, IsPrefixOpened(volume_->GetUri())).WillByDefault(Return(true));
+ auto win = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList({win})));
CreateIcon();
EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
@@ -128,16 +132,91 @@ TEST_F(TestVolumeLauncherIcon, FilemanagerSignalDisconnection)
TEST_F(TestVolumeLauncherIcon, TestRunningStateOnLocationChangedClosed)
{
- ON_CALL(*file_manager_, IsPrefixOpened(volume_->GetUri())).WillByDefault(Return(false));
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList()));
file_manager_->locations_changed.emit();
EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
}
TEST_F(TestVolumeLauncherIcon, TestRunningStateOnLocationChangedOpened)
{
- ON_CALL(*file_manager_, IsPrefixOpened(volume_->GetUri())).WillByDefault(Return(true));
+ auto win1 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ auto win2 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList({win1, win2})));
+ file_manager_->locations_changed.emit();
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
+}
+
+TEST_F(TestVolumeLauncherIcon, RunningState)
+{
+ auto win1 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ auto win2 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList({win1, win2})));
file_manager_->locations_changed.emit();
EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
+
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList()));
+ file_manager_->locations_changed.emit();
+ EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
+}
+
+TEST_F(TestVolumeLauncherIcon, ActiveState)
+{
+ auto win1 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ auto win2 = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList({win1, win2})));
+ file_manager_->locations_changed.emit();
+ ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE));
+
+ win2->LocalFocus();
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE));
+
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList()));
+ file_manager_->locations_changed.emit();
+ EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE));
+}
+
+TEST_F(TestVolumeLauncherIcon, WindowsCount)
+{
+ WindowList windows((g_random_int() % 10) + 5);
+ for (unsigned i = 0; i < windows.capacity(); ++i)
+ windows[i] = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(windows));
+ file_manager_->locations_changed.emit();
+ EXPECT_EQ(icon_->Windows().size(), windows.size());
+}
+
+TEST_F(TestVolumeLauncherIcon, WindowsPerMonitor)
+{
+ WindowList windows((g_random_int() % 10) + 5);
+ for (unsigned i = 0; i < windows.capacity(); ++i)
+ {
+ auto win = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ win->monitor_ = i % 2;
+ windows[i] = win;
+ }
+
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(windows));
+ file_manager_->locations_changed.emit();
+
+ EXPECT_EQ(icon_->WindowsVisibleOnMonitor(0), (windows.size() / 2) + (windows.size() % 2));
+ EXPECT_EQ(icon_->WindowsVisibleOnMonitor(1), windows.size() / 2);
+}
+
+TEST_F(TestVolumeLauncherIcon, WindowsOnMonitorChanges)
+{
+ auto win = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList({win})));
+ file_manager_->locations_changed.emit();
+
+ EXPECT_EQ(icon_->WindowsVisibleOnMonitor(0), 1);
+ EXPECT_EQ(icon_->WindowsVisibleOnMonitor(1), 0);
+
+ win->SetMonitor(1);
+ EXPECT_EQ(icon_->WindowsVisibleOnMonitor(0), 0);
+ EXPECT_EQ(icon_->WindowsVisibleOnMonitor(1), 1);
}
TEST_F(TestVolumeLauncherIcon, TestPosition)
@@ -240,6 +319,32 @@ TEST_F(TestVolumeLauncherIconDelayedConstruction, TestVisibilityAfterUnmount_Bla
EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
}
+TEST_F(TestVolumeLauncherIcon, TestVisibilityWithWindows)
+{
+ ON_CALL(*settings_, IsABlacklistedDevice(volume_->GetIdentifier())).WillByDefault(Return(false));
+ settings_->changed.emit();
+ ASSERT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+
+ auto win = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList({win})));
+ file_manager_->locations_changed.emit();
+
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestVisibilityWithWindows_Blacklisted)
+{
+ ON_CALL(*settings_, IsABlacklistedDevice(volume_->GetIdentifier())).WillByDefault(Return(true));
+ settings_->changed.emit();
+ ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+
+ auto win = std::make_shared<MockApplicationWindow::Nice>(g_random_int());
+ ON_CALL(*file_manager_, WindowsForLocation(volume_->GetUri())).WillByDefault(Return(WindowList({win})));
+ file_manager_->locations_changed.emit();
+
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_VolumeWithoutIdentifier)
{
EXPECT_CALL(*volume_, GetIdentifier())
@@ -251,22 +356,22 @@ TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_VolumeWithoutIdent
TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_Success)
{
+ ON_CALL(*settings_, IsABlacklistedDevice(volume_->GetIdentifier())).WillByDefault(Return(false));
+ settings_->changed.emit();
+ ASSERT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
auto menuitem = GetMenuItemAtIndex(4);
ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unlock from Launcher");
EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
- EXPECT_CALL(*settings_, TryToBlacklist(_))
- .Times(1);
-
- EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
- .WillRepeatedly(Return(true));
-
+ EXPECT_CALL(*settings_, TryToBlacklist(volume_->GetIdentifier())).Times(1);
dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(volume_->GetIdentifier())).WillRepeatedly(Return(true));
settings_->changed.emit(); // TryToBlacklist() works if DevicesSettings emits a changed signal.
- ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+ EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
}
TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_Failure)
@@ -277,12 +382,49 @@ TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_Failure)
EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
- EXPECT_CALL(*settings_, TryToBlacklist(_))
- .Times(1);
+ EXPECT_CALL(*settings_, TryToBlacklist(volume_->GetIdentifier())).Times(1);
+ dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestLockToLauncherMenuItem_Success)
+{
+ ON_CALL(*settings_, IsABlacklistedDevice(volume_->GetIdentifier())).WillByDefault(Return(true));
+ settings_->changed.emit();
+ ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+
+ auto menuitem = GetMenuItemAtIndex(4);
+ ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Lock to Launcher");
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
+
+ EXPECT_CALL(*settings_, TryToUnblacklist(volume_->GetIdentifier())).Times(1);
dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
- ASSERT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(_)).WillRepeatedly(Return(false));
+ settings_->changed.emit(); // TryToBlacklist() works if DevicesSettings emits a changed signal.
+
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestLockToLauncherMenuItem_Failure)
+{
+ ON_CALL(*settings_, IsABlacklistedDevice(volume_->GetIdentifier())).WillByDefault(Return(true));
+ settings_->changed.emit();
+ ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+
+ auto menuitem = GetMenuItemAtIndex(4);
+
+ ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Lock to Launcher");
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
+
+ EXPECT_CALL(*settings_, TryToUnblacklist(volume_->GetIdentifier())).Times(1);
+ dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+
+ EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
}
TEST_F(TestVolumeLauncherIcon, TestOpenMenuItem)
@@ -298,7 +440,7 @@ TEST_F(TestVolumeLauncherIcon, TestOpenMenuItem)
InSequence seq;
EXPECT_CALL(*volume_, Mount());
- EXPECT_CALL(*file_manager_, OpenActiveChild(volume_->GetUri(), time));
+ EXPECT_CALL(*file_manager_, Open(volume_->GetUri(), time));
dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, time);
}
@@ -318,7 +460,7 @@ TEST_F(TestVolumeLauncherIcon, TestNameMenuItem)
InSequence seq;
EXPECT_CALL(*volume_, Mount());
- EXPECT_CALL(*file_manager_, OpenActiveChild(volume_->GetUri(), time));
+ EXPECT_CALL(*file_manager_, Open(volume_->GetUri(), time));
dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, time);
}
@@ -438,7 +580,7 @@ TEST_F(TestVolumeLauncherIcon, OnRemoved)
EXPECT_CALL(*settings_, TryToBlacklist(_))
.Times(0);
EXPECT_CALL(*settings_, TryToUnblacklist(_))
- .Times(0);
+ .Times(1);
volume_->removed.emit();
}
@@ -451,7 +593,7 @@ TEST_F(TestVolumeLauncherIcon, OnRemoved_RemovabledVolume)
EXPECT_CALL(*settings_, TryToBlacklist(_))
.Times(0);
EXPECT_CALL(*settings_, TryToUnblacklist(_))
- .Times(0);
+ .Times(1);
volume_->removed.emit();
}
@@ -516,7 +658,7 @@ TEST_F(TestVolumeLauncherIcon, ActivateMounted)
uint64_t time = g_random_int();
InSequence seq;
EXPECT_CALL(*volume_, Mount()).Times(0);
- EXPECT_CALL(*file_manager_, OpenActiveChild(volume_->GetUri(), time));
+ EXPECT_CALL(*file_manager_, Open(volume_->GetUri(), time));
icon_->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, time));
}
@@ -526,7 +668,7 @@ TEST_F(TestVolumeLauncherIcon, ActivateUnmounted)
ON_CALL(*volume_, IsMounted()).WillByDefault(Return(false));
InSequence seq;
EXPECT_CALL(*volume_, Mount());
- EXPECT_CALL(*file_manager_, OpenActiveChild(volume_->GetUri(), time));
+ EXPECT_CALL(*file_manager_, Open(volume_->GetUri(), time));
icon_->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, time));
}
diff --git a/unity-shared/ApplicationManager.h b/unity-shared/ApplicationManager.h
index c0f681a5e..8a5e6270d 100644
--- a/unity-shared/ApplicationManager.h
+++ b/unity-shared/ApplicationManager.h
@@ -109,6 +109,8 @@ public:
nux::ROProperty<bool> active;
nux::ROProperty<bool> urgent;
nux::ROProperty<bool> maximized;
+
+ sigc::signal<void> closed;
};
@@ -219,6 +221,7 @@ public:
virtual WindowList GetWindowsForMonitor(int monitor = -1) const = 0;
virtual ApplicationPtr GetApplicationForWindow(Window xid) const = 0;
virtual ApplicationWindowPtr GetWindowForId(Window xid) const = 0;
+ virtual void FocusWindowGroup(WindowList const&, bool show_on_visible, int monitor) const = 0;
sigc::signal<void, ApplicationPtr const&> application_started;
sigc::signal<void, ApplicationPtr const&> application_stopped;
diff --git a/unity-shared/BamfApplicationManager.cpp b/unity-shared/BamfApplicationManager.cpp
index 9a76d2a08..8225ccc05 100644
--- a/unity-shared/BamfApplicationManager.cpp
+++ b/unity-shared/BamfApplicationManager.cpp
@@ -147,6 +147,7 @@ WindowBase::WindowBase(ApplicationManager const& manager,
});
signals_.Add<void, BamfView*>(bamf_view_, "closed",
[this] (BamfView* view) {
+ this->closed.emit();
pool::wins_.erase(view);
});
}
@@ -473,7 +474,7 @@ ApplicationWindowPtr Application::GetFocusableWindow() const
return pool::EnsureWindow(manager_, bamf_application_get_focusable_child(bamf_app_));
}
-void Application::Focus(bool show_only_visible, int monitor) const
+void Manager::FocusWindowGroup(WindowList const& wins, bool show_only_visible, int monitor) const
{
WindowManager& wm = WindowManager::Default();
std::vector<Window> urgent_windows;
@@ -481,7 +482,7 @@ void Application::Focus(bool show_only_visible, int monitor) const
std::vector<Window> non_visible_windows;
bool any_visible = false;
- for (auto& window : GetWindows())
+ for (auto& window : wins)
{
Window window_id = window->window_id();
if (window->urgent())
@@ -526,12 +527,15 @@ void Application::Focus(bool show_only_visible, int monitor) const
}
}
+void Application::Focus(bool show_only_visible, int monitor) const
+{
+ manager_.FocusWindowGroup(GetWindows(), show_only_visible, monitor);
+}
+
void Application::Quit() const
{
for (auto& window : GetWindows())
- {
window->Quit();
- }
}
bool Application::CreateLocalDesktopFile() const
diff --git a/unity-shared/BamfApplicationManager.h b/unity-shared/BamfApplicationManager.h
index 74503a9aa..30859025a 100644
--- a/unity-shared/BamfApplicationManager.h
+++ b/unity-shared/BamfApplicationManager.h
@@ -64,7 +64,7 @@ public:
bool operator==(unity::ApplicationWindow const& other) const override
{
- return static_cast<WindowBase const*>(this)->bamf_view_ == static_cast<WindowBase const&>(other).bamf_view_;
+ 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)); }
};
@@ -175,6 +175,8 @@ public:
ApplicationPtr EnsureApplication(BamfView*) const;
ApplicationWindowPtr EnsureWindow(BamfView*) const;
+ void FocusWindowGroup(WindowList const&, bool show_on_visible, int monitor) const;
+
private:
void OnViewOpened(BamfMatcher* matcher, BamfView* view);
void OnViewClosed(BamfMatcher* matcher, BamfView* view);
diff --git a/unity-shared/FileManager.h b/unity-shared/FileManager.h
index 55647d2c0..15dc1d966 100644
--- a/unity-shared/FileManager.h
+++ b/unity-shared/FileManager.h
@@ -27,6 +27,8 @@
#include <vector>
#include <set>
#include <sigc++/sigc++.h>
+#include "ApplicationManager.h"
+
namespace unity
{
@@ -40,15 +42,12 @@ public:
virtual ~FileManager() = default;
virtual void Open(std::string const& uri, uint64_t timestamp = 0) = 0;
- virtual void OpenActiveChild(std::string const& uri, uint64_t timestamp = 0) = 0;
virtual void OpenTrash(uint64_t timestamp) = 0;
- virtual std::vector<std::string> OpenedLocations() const = 0;
- virtual bool IsPrefixOpened(std::string const& uri) const = 0;
- virtual bool IsTrashOpened() const = 0;
- virtual bool IsDeviceOpened() const = 0;
virtual void CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp = 0) = 0;
virtual bool TrashFile(std::string const& uri) = 0;
virtual void EmptyTrash(uint64_t timestamp = 0) = 0;
+ virtual WindowList WindowsForLocation(std::string const& location) const = 0;
+ virtual std::string LocationForWindow(ApplicationWindowPtr const&) const = 0;
sigc::signal<void> locations_changed;
@@ -57,6 +56,6 @@ private:
FileManager& operator=(FileManager const&) = delete;
};
-}
+} // namespace unity
#endif
diff --git a/unity-shared/GnomeFileManager.cpp b/unity-shared/GnomeFileManager.cpp
index 2f142f836..e273ffd70 100644
--- a/unity-shared/GnomeFileManager.cpp
+++ b/unity-shared/GnomeFileManager.cpp
@@ -21,8 +21,9 @@
#include "GnomeFileManager.h"
#include <NuxCore/Logger.h>
#include <UnityCore/DesktopUtilities.h>
-#include <UnityCore/GLibWrapper.h>
+#include <UnityCore/GLibSource.h>
#include <UnityCore/GLibDBusProxy.h>
+#include <UnityCore/GLibWrapper.h>
#include <gdk/gdk.h>
#include <gio/gio.h>
@@ -33,10 +34,8 @@ namespace
{
DECLARE_LOGGER(logger, "unity.filemanager.gnome");
-const std::string TRASH_URI = "trash:";
+const std::string TRASH_URI = "trash:///";
const std::string FILE_SCHEMA = "file://";
-const std::string TRASH_PATH = FILE_SCHEMA + DesktopUtilities::GetUserDataDirectory() + "/Trash/files";
-const std::string DEVICES_PREFIX = FILE_SCHEMA + "/media/" + std::string(g_get_user_name());
const std::string NAUTILUS_NAME = "org.gnome.Nautilus";
const std::string NAUTILUS_PATH = "/org/gnome/Nautilus";
@@ -48,64 +47,83 @@ struct GnomeFileManager::Impl
: parent_(parent)
, filemanager_proxy_("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1", "org.freedesktop.FileManager1")
{
- auto callback = sigc::mem_fun(this, &Impl::OnOpenLocationsUpdated);
- filemanager_proxy_.GetProperty("OpenLocations", callback);
- filemanager_proxy_.ConnectProperty("OpenLocations", callback);
+ auto callback = sigc::mem_fun(this, &Impl::OnOpenLocationsXidsUpdated);
+ filemanager_proxy_.GetProperty("XUbuntuOpenLocationsXids", callback);
+ filemanager_proxy_.ConnectProperty("XUbuntuOpenLocationsXids", callback);
}
- void OnOpenLocationsUpdated(GVariant* value)
+ glib::DBusProxy::Ptr NautilusOperationsProxy() const
{
- if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY))
+ return std::make_shared<glib::DBusProxy>(NAUTILUS_NAME, NAUTILUS_PATH,
+ "org.gnome.Nautilus.FileOperations");
+ }
+
+ void OnOpenLocationsXidsUpdated(GVariant* value)
+ {
+ opened_location_for_xid_.clear();
+
+ if (!value)
{
- LOG_ERROR(logger) << "Locations value type is not matching the expected one!";
+ LOG_WARN(logger) << "Locations have been invalidated, maybe there's no filemanager around...";
+ parent_->locations_changed.emit();
return;
}
- opened_locations_.clear();
+ if (!g_variant_is_of_type(value, G_VARIANT_TYPE("a{uas}")))
+ {
+ LOG_ERROR(logger) << "Locations value type is not matching the expected one!";
+ parent_->locations_changed.emit();
+ return;
+ }
GVariantIter iter;
- const char *str;
+ GVariantIter *str_iter;
+ const char *loc;
+ guint32 xid;
g_variant_iter_init(&iter, value);
- while (g_variant_iter_loop(&iter, "s", &str))
+ while (g_variant_iter_loop(&iter, "{uas}", &xid, &str_iter))
{
- LOG_DEBUG(logger) << "Opened location " << str;
- opened_locations_.push_back(str);
+ while (g_variant_iter_loop(str_iter, "s", &loc))
+ {
+ /* We only care about the first mentioned location as per our "standard"
+ * it's the active one */
+ LOG_DEBUG(logger) << xid << ": Opened location " << loc;
+ opened_location_for_xid_[xid] = loc;
+ break;
+ }
}
- parent_->locations_changed.emit();
- }
-
- std::string GetOpenedPrefix(std::string const& uri, bool allow_equal = true)
- {
- glib::Object<GFile> uri_file(g_file_new_for_uri(uri.c_str()));
-
- for (auto const& loc : opened_locations_)
+ // We must ensure that we emit the locations_changed signal only when all
+ // the parent windows have been registered on the app-manager
+ auto app_manager_not_synced = [this]
{
- bool equal = false;
+ auto& app_manager = ApplicationManager::Default();
+ bool synced = true;
- glib::Object<GFile> loc_file(g_file_new_for_uri(loc.c_str()));
+ for (auto const& pair : opened_location_for_xid_)
+ {
+ synced = (app_manager.GetWindowForId(pair.first) != nullptr);
- if (allow_equal && g_file_equal(loc_file, uri_file))
- equal = true;
+ if (!synced)
+ break;
+ }
- if (equal || g_file_has_prefix(loc_file, uri_file))
- return loc;
- }
+ if (synced)
+ parent_->locations_changed.emit();
- return "";
- }
+ return !synced;
+ };
- glib::DBusProxy::Ptr NautilusOperationsProxy() const
- {
- return std::make_shared<glib::DBusProxy>(NAUTILUS_NAME, NAUTILUS_PATH,
- "org.gnome.Nautilus.FileOperations");
+ if (app_manager_not_synced())
+ idle_.reset(new glib::Idle(app_manager_not_synced));
}
GnomeFileManager* parent_;
glib::DBusProxy filemanager_proxy_;
- std::vector<std::string> opened_locations_;
+ glib::Source::UniquePtr idle_;
+ std::map<Window, std::string> opened_location_for_xid_;
};
@@ -146,23 +164,9 @@ void GnomeFileManager::Open(std::string const& uri, uint64_t timestamp)
}
}
-void GnomeFileManager::OpenActiveChild(std::string const& uri, uint64_t timestamp)
-{
- auto const& opened = impl_->GetOpenedPrefix(uri);
-
- Open(opened.empty() ? uri : opened, timestamp);
-}
-
void GnomeFileManager::OpenTrash(uint64_t timestamp)
{
- if (IsPrefixOpened(TRASH_PATH))
- {
- OpenActiveChild(TRASH_PATH, timestamp);
- }
- else
- {
- OpenActiveChild(TRASH_URI, timestamp);
- }
+ Open(TRASH_URI, timestamp);
}
void GnomeFileManager::Activate(uint64_t timestamp)
@@ -252,25 +256,48 @@ void GnomeFileManager::CopyFiles(std::set<std::string> const& uris, std::string
}
}
-std::vector<std::string> GnomeFileManager::OpenedLocations() const
+WindowList GnomeFileManager::WindowsForLocation(std::string const& location) const
{
- return impl_->opened_locations_;
-}
+ std::vector<ApplicationWindowPtr> windows;
+ auto& app_manager = ApplicationManager::Default();
-bool GnomeFileManager::IsPrefixOpened(std::string const& uri) const
-{
- return !impl_->GetOpenedPrefix(uri).empty();
-}
+ glib::Object<GFile> location_file(g_file_new_for_uri(location.c_str()));
-bool GnomeFileManager::IsTrashOpened() const
-{
- return (IsPrefixOpened(TRASH_URI) || IsPrefixOpened(TRASH_PATH));
+ for (auto const& pair : impl_->opened_location_for_xid_)
+ {
+ auto const& loc = pair.second;
+ bool matches = (loc == location);
+
+ if (!matches)
+ {
+ glib::Object<GFile> loc_file(g_file_new_for_uri(loc.c_str()));
+ glib::String relative(g_file_get_relative_path(location_file, loc_file));
+ matches = static_cast<bool>(relative);
+ }
+
+ if (matches)
+ {
+ auto const& win = app_manager.GetWindowForId(pair.first);
+
+ if (win && std::find(windows.rbegin(), windows.rend(), win) == windows.rend())
+ windows.push_back(win);
+ }
+ }
+
+ return windows;
}
-bool GnomeFileManager::IsDeviceOpened() const
+std::string GnomeFileManager::LocationForWindow(ApplicationWindowPtr const& win) const
{
- return !impl_->GetOpenedPrefix(DEVICES_PREFIX, false).empty();
-}
+ if (win)
+ {
+ auto it = impl_->opened_location_for_xid_.find(win->window_id());
+ if (it != end(impl_->opened_location_for_xid_))
+ return it->second;
+ }
+ return std::string();
}
+
+} // namespace unity
diff --git a/unity-shared/GnomeFileManager.h b/unity-shared/GnomeFileManager.h
index 5b9ac1203..b017ce0ea 100644
--- a/unity-shared/GnomeFileManager.h
+++ b/unity-shared/GnomeFileManager.h
@@ -33,17 +33,14 @@ public:
~GnomeFileManager();
void Open(std::string const& uri, uint64_t timestamp);
- void OpenActiveChild(std::string const& uri, uint64_t timestamp);
void OpenTrash(uint64_t timestamp);
void CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp);
bool TrashFile(std::string const& uri);
void EmptyTrash(uint64_t timestamp);
- std::vector<std::string> OpenedLocations() const;
- bool IsPrefixOpened(std::string const& uri) const;
- bool IsTrashOpened() const;
- bool IsDeviceOpened() const;
+ WindowList WindowsForLocation(std::string const& location) const;
+ std::string LocationForWindow(ApplicationWindowPtr const&) const;
private:
GnomeFileManager();