summaryrefslogtreecommitdiff
path: root/launcher
diff options
authorSam Spilsbury <sam.spilsbury@canonical.com>2013-03-22 11:33:00 +0800
committerSam Spilsbury <sam.spilsbury@canonical.com>2013-03-22 11:33:00 +0800
commitfee726045ee0fdfd265b657fab792bfcab5809cc (patch)
tree676e82804f443eb1f6856a7117d3611e58c031f0 /launcher
parent8f7ba0c05f948efdcf21c28bd19bb23e51fd9849 (diff)
parente9e3a104f7fbe33c9d7fa15cca5707fec75ff07a (diff)
Merge lp:unity and use the old fbo api
(bzr r3139.1.11)
Diffstat (limited to 'launcher')
-rw-r--r--launcher/AbstractLauncherIcon.h27
-rw-r--r--launcher/ApplicationLauncherIcon.cpp320
-rw-r--r--launcher/ApplicationLauncherIcon.h6
-rw-r--r--launcher/BFBLauncherIcon.cpp3
-rw-r--r--launcher/CMakeLists.txt1
-rw-r--r--launcher/DeviceLauncherSection.cpp4
-rw-r--r--launcher/FileManagerOpener.h9
-rw-r--r--launcher/FileManagerOpenerImp.cpp33
-rw-r--r--launcher/FileManagerOpenerImp.h2
-rw-r--r--launcher/HudLauncherIcon.cpp3
-rw-r--r--launcher/Launcher.cpp98
-rw-r--r--launcher/Launcher.h12
-rw-r--r--launcher/LauncherController.cpp155
-rw-r--r--launcher/LauncherControllerPrivate.h16
-rw-r--r--launcher/LauncherIcon.cpp48
-rw-r--r--launcher/LauncherIcon.h9
-rw-r--r--launcher/MockLauncherIcon.h9
-rw-r--r--launcher/QuicklistMenuItem.cpp5
-rw-r--r--launcher/SimpleLauncherIcon.cpp2
-rw-r--r--launcher/StandaloneLauncher.cpp8
-rw-r--r--launcher/SwitcherController.cpp9
-rw-r--r--launcher/SwitcherView.cpp6
-rw-r--r--launcher/SwitcherView.h2
-rw-r--r--launcher/TooltipManager.cpp92
-rw-r--r--launcher/TooltipManager.h56
-rw-r--r--launcher/TrashLauncherIcon.cpp46
-rw-r--r--launcher/TrashLauncherIcon.h10
-rw-r--r--launcher/Volume.h12
-rw-r--r--launcher/VolumeImp.cpp12
-rw-r--r--launcher/VolumeImp.h2
-rw-r--r--launcher/VolumeLauncherIcon.cpp12
-rw-r--r--launcher/XdndCollectionWindowImp.cpp19
32 files changed, 707 insertions, 341 deletions
diff --git a/launcher/AbstractLauncherIcon.h b/launcher/AbstractLauncherIcon.h
index be9f65589..859ab56ba 100644
--- a/launcher/AbstractLauncherIcon.h
+++ b/launcher/AbstractLauncherIcon.h
@@ -41,10 +41,9 @@ namespace unity
namespace launcher
{
-class ActionArg
+struct ActionArg
{
-public:
- enum Source
+ enum class Source
{
LAUNCHER,
SWITCHER,
@@ -52,25 +51,24 @@ public:
};
ActionArg()
- : source(OTHER)
+ : source(Source::OTHER)
, button(0)
+ , timestamp(0)
, target(0)
, monitor(-1)
- {
- }
+ {}
- ActionArg(Source source, int button, Time timestamp = -1, Window target = 0, int monitor = -1)
+ ActionArg(Source source, int button, unsigned long timestamp = 0, Window target = 0, int monitor = -1)
: source(source)
, button(button)
, timestamp(timestamp)
, target(target)
, monitor(monitor)
- {
- }
+ {}
Source source;
int button;
- Time timestamp;
+ unsigned long timestamp;
Window target;
int monitor;
};
@@ -128,6 +126,12 @@ public:
END
};
+ enum class ScrollDirection
+ {
+ UP,
+ DOWN
+ };
+
virtual ~AbstractLauncherIcon() {}
nux::Property<std::string> tooltip_text;
@@ -135,6 +139,7 @@ public:
nux::Property<Position> position;
nux::Property<bool> removed;
+ virtual void ShowTooltip() = 0;
virtual void HideTooltip() = 0;
virtual void SetShortcut(guint64 shortcut) = 0;
@@ -226,6 +231,8 @@ public:
return static_cast<int>(type) * 1000;
}
+ virtual void PerformScroll(ScrollDirection direction, Time timestamp) = 0;
+
sigc::signal<void, int, int, unsigned long> mouse_down;
sigc::signal<void, int, int, unsigned long> mouse_up;
sigc::signal<void, int, int, unsigned long> mouse_click;
diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp
index ade59aacc..2e0e70691 100644
--- a/launcher/ApplicationLauncherIcon.cpp
+++ b/launcher/ApplicationLauncherIcon.cpp
@@ -60,6 +60,9 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app)
: SimpleLauncherIcon(IconType::APPLICATION)
, app_(app)
, _startup_notification_timestamp(0)
+ , _last_scroll_timestamp(0)
+ , _last_scroll_direction(ScrollDirection::DOWN)
+ , _progressive_scroll(0)
, use_custom_bg_color_(false)
, bg_color_(nux::color::White)
{
@@ -87,68 +90,68 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app)
// Lambda functions should be fine here because when the application the icon
// is only ever removed when the application is closed.
app->window_opened.connect([this](ApplicationWindow const&) {
- EnsureWindowState();
- UpdateMenus();
- UpdateIconGeometries(GetCenters());
- });
- app->window_closed.connect([this]() { EnsureWindowState(); });
- app->window_moved.connect([this](ApplicationWindow const&) { EnsureWindowState(); });
+ EnsureWindowState();
+ UpdateMenus();
+ UpdateIconGeometries(GetCenters());
+ });
+ app->window_closed.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState));
+ app->window_moved.connect(sigc::hide(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState)));
app->urgent.changed.connect([this](bool const& urgent) {
- LOG_DEBUG(logger) << tooltip_text() << " urgent now " << (urgent ? "true" : "false");
- SetQuirk(Quirk::URGENT, urgent);
- });
+ LOG_DEBUG(logger) << tooltip_text() << " urgent now " << (urgent ? "true" : "false");
+ SetQuirk(Quirk::URGENT, urgent);
+ });
app->active.changed.connect([this](bool const& active) {
- LOG_DEBUG(logger) << tooltip_text() << " active now " << (active ? "true" : "false");
- SetQuirk(Quirk::ACTIVE, active);
- });
+ LOG_DEBUG(logger) << tooltip_text() << " active now " << (active ? "true" : "false");
+ SetQuirk(Quirk::ACTIVE, active);
+ });
app->running.changed.connect([this](bool const& running) {
- LOG_DEBUG(logger) << tooltip_text() << " running now " << (running ? "true" : "false");
- SetQuirk(Quirk::RUNNING, running);
-
- if (running)
- {
- _source_manager.Remove(ICON_REMOVE_TIMEOUT);
-
- /* It can happen that these values are not set
- * during initialization if the view is closed
- * very early, so we need to make sure that they
- * are updated as soon as the view is re-opened. */
- if (tooltip_text().empty())
- tooltip_text = app_->title();
-
- if (icon_name == DEFAULT_ICON)
- {
- std::string icon = app_->icon();
- icon_name = (icon.empty() ? DEFAULT_ICON : icon);
- }
-
- EnsureWindowState();
- UpdateIconGeometries(GetCenters());
- }
- });
+ LOG_DEBUG(logger) << tooltip_text() << " running now " << (running ? "true" : "false");
+ SetQuirk(Quirk::RUNNING, running);
+
+ if (running)
+ {
+ _source_manager.Remove(ICON_REMOVE_TIMEOUT);
+
+ /* It can happen that these values are not set
+ * during initialization if the view is closed
+ * very early, so we need to make sure that they
+ * are updated as soon as the view is re-opened. */
+ if (tooltip_text().empty())
+ tooltip_text = app_->title();
+
+ if (icon_name == DEFAULT_ICON)
+ {
+ std::string icon = app_->icon();
+ icon_name = (icon.empty() ? DEFAULT_ICON : icon);
+ }
+
+ EnsureWindowState();
+ UpdateIconGeometries(GetCenters());
+ }
+ });
app->visible.changed.connect([this](bool const& visible) {
- if (!IsSticky())
- SetQuirk(Quirk::VISIBLE, visible);
- });
+ if (!IsSticky())
+ SetQuirk(Quirk::VISIBLE, visible);
+ });
app->closed.connect([this]() {
- if (!IsSticky())
- {
- SetQuirk(Quirk::VISIBLE, false);
-
- /* 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, [&] {
- Remove();
- return false;
- }, ICON_REMOVE_TIMEOUT);
- }
- });
+ if (!IsSticky())
+ {
+ SetQuirk(Quirk::VISIBLE, false);
+
+ /* 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);
+ }
+ });
WindowManager& wm = WindowManager::Default();
wm.window_minimized.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::OnWindowMinimized));
@@ -259,7 +262,7 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
* an unmapped (!= minimized) window around and
* if so force "Focus" behaviour */
- if (arg.source != ActionArg::SWITCHER)
+ if (arg.source != ActionArg::Source::SWITCHER)
{
user_visible = app_->visible();
@@ -336,7 +339,7 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
}
else // #2 above
{
- if (arg.source != ActionArg::SWITCHER)
+ if (arg.source != ActionArg::Source::SWITCHER)
{
Spread(true, 0, false);
}
@@ -347,7 +350,7 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
if (scaleWasActive) // #4 above
{
Focus(arg);
- if (arg.source != ActionArg::SWITCHER)
+ if (arg.source != ActionArg::Source::SWITCHER)
Spread(true, 0, false);
}
else // #3 above
@@ -440,7 +443,7 @@ void ApplicationLauncherIcon::OnWindowMoved(guint32 moved_win)
if (!app_->OwnsWindow(moved_win))
return;
- _source_manager.AddTimeout(250, [&] {
+ _source_manager.AddTimeout(250, [this] {
EnsureWindowState();
UpdateIconGeometries(GetCenters());
@@ -465,31 +468,32 @@ void ApplicationLauncherIcon::UpdateDesktopFile()
glib::Object<GFile> desktop_file(g_file_new_for_path(_desktop_file.c_str()));
_desktop_file_monitor = g_file_monitor_file(desktop_file, G_FILE_MONITOR_NONE,
nullptr, nullptr);
- g_file_monitor_set_rate_limit(_desktop_file_monitor, 1000);
-
- auto sig = new glib::Signal<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent>(_desktop_file_monitor, "changed",
- [&] (GFileMonitor*, GFile* f, GFile*, GFileMonitorEvent event_type) {
- switch (event_type)
- {
- case G_FILE_MONITOR_EVENT_DELETED:
- {
- glib::Object<GFile> file(f, glib::AddRef());
- _source_manager.AddTimeoutSeconds(1, [this, file] {
- if (!g_file_query_exists (file, nullptr))
- UnStick();
- return false;
- });
- break;
- }
- case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
- UpdateDesktopQuickList();
- UpdateBackgroundColor();
- break;
- default:
- break;
- }
- });
- _gsignals.Add(sig);
+ g_file_monitor_set_rate_limit(_desktop_file_monitor, 2000);
+
+ _gsignals.Add<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent>(_desktop_file_monitor, "changed",
+ [this] (GFileMonitor*, GFile* f, GFile*, GFileMonitorEvent event_type) {
+ switch (event_type)
+ {
+ case G_FILE_MONITOR_EVENT_DELETED:
+ {
+ glib::Object<GFile> file(f, glib::AddRef());
+ _source_manager.AddTimeoutSeconds(1, [this, file] {
+ if (!g_file_query_exists (file, nullptr))
+ UnStick();
+ return false;
+ });
+ break;
+ }
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ {
+ UpdateDesktopQuickList();
+ UpdateBackgroundColor();
+ break;
+ }
+ default:
+ break;
+ }
+ });
}
}
@@ -527,7 +531,7 @@ void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const&
glib::Object<GdkAppLaunchContext> app_launch_context(gdk_display_get_app_launch_context(display));
_startup_notification_timestamp = timestamp;
- if (_startup_notification_timestamp >= 0)
+ if (_startup_notification_timestamp > 0)
gdk_app_launch_context_set_timestamp(app_launch_context, _startup_notification_timestamp);
if (g_app_info_supports_uris(appInfo))
@@ -588,7 +592,7 @@ void ApplicationLauncherIcon::Focus(ActionArg arg)
return;
}
- bool show_only_visible = arg.source == ActionArg::SWITCHER;
+ bool show_only_visible = arg.source == ActionArg::Source::SWITCHER;
app_->Focus(show_only_visible, arg.monitor);
}
@@ -642,7 +646,7 @@ void ApplicationLauncherIcon::UpdateDesktopQuickList()
{
for (GList *l = dbusmenu_menuitem_get_children(_menu_desktop_shortcuts); l; l = l->next)
{
- _gsignals.Disconnect(l->data, "item-activated");
+ _gsignals.Disconnect(l->data, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED);
}
}
@@ -669,15 +673,12 @@ void ApplicationLauncherIcon::UpdateDesktopQuickList()
dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, name);
dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- dbusmenu_menuitem_property_set(item, "shortcut-nick", nicks[index]);
+ std::string nick(nicks[index]);
- auto sig = new glib::Signal<void, DbusmenuMenuitem*, gint>(item, "item-activated",
- [&] (DbusmenuMenuitem* item, gint) {
- const gchar *nick;
- nick = dbusmenu_menuitem_property_get(item, "shortcut-nick");
- indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick);
- });
- _gsignals.Add(sig);
+ _gsignals.Add<void, DbusmenuMenuitem*, gint>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ [this, nick] (DbusmenuMenuitem* item, unsigned) {
+ indicator_desktop_shortcuts_nick_exec(_desktop_shortcuts, nick.c_str());
+ });
dbusmenu_menuitem_child_append(_menu_desktop_shortcuts, item);
index++;
@@ -726,8 +727,8 @@ void ApplicationLauncherIcon::EnsureMenuItemsWindowsReady()
dbusmenu_menuitem_property_set_int(menu_item, QuicklistMenuItem::MAXIMUM_LABEL_WIDTH_PROPERTY, MAXIMUM_QUICKLIST_WIDTH);
Window xid = w->window_id();
- _gsignals.Add<void, DbusmenuMenuitem*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- [xid] (DbusmenuMenuitem*, int) {
+ _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);
@@ -818,8 +819,8 @@ void ApplicationLauncherIcon::EnsureMenuItemsReady()
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*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- [&] (DbusmenuMenuitem*, int) {
+ _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ [this] (DbusmenuMenuitem*, unsigned) {
ToggleSticky();
});
@@ -839,8 +840,8 @@ void ApplicationLauncherIcon::EnsureMenuItemsReady()
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*, int>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- [&] (DbusmenuMenuitem*, int) {
+ _gsignals.Add<void, DbusmenuMenuitem*, unsigned>(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ [this] (DbusmenuMenuitem*, unsigned) {
Quit();
});
@@ -933,24 +934,19 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus()
else
{
glib::String app_name(g_markup_escape_text(app_->title().c_str(), -1));
- std::ostringstream bold_app_name;
- bold_app_name << "<b>" << app_name << "</b>";
+ std::string bold_app_name("<b>"+app_name.Str()+"</b>");
item = dbusmenu_menuitem_new();
dbusmenu_menuitem_property_set(item,
DBUSMENU_MENUITEM_PROP_LABEL,
- bold_app_name.str().c_str());
- 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*, int>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- [&] (DbusmenuMenuitem*, int) {
- _source_manager.AddIdle([&] {
- ActivateLauncherIcon(ActionArg());
+ bold_app_name.c_str());
+ 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,
+ [this] (DbusmenuMenuitem*, unsigned timestamp) {
+ _source_manager.AddIdle([this, timestamp] {
+ ActivateLauncherIcon(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp));
return false;
});
});
@@ -1104,7 +1100,7 @@ void ApplicationLauncherIcon::OnDndHovered()
void ApplicationLauncherIcon::OnDndEnter()
{
/* Disabled, since the DND code is currently disabled as well.
- _source_manager.AddTimeout(1000, [&] {
+ _source_manager.AddTimeout(1000, [this] {
OnDndHovered();
return false;
}, ICON_DND_OVER_TIMEOUT);
@@ -1154,7 +1150,7 @@ nux::DndAction ApplicationLauncherIcon::OnQueryAcceptDrop(DndData const& dnd_dat
void ApplicationLauncherIcon::OnAcceptDrop(DndData const& dnd_data)
{
- auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
+ auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
OpenInstanceWithUris(ValidateUrisForLaunch(dnd_data), timestamp);
}
@@ -1171,7 +1167,7 @@ bool ApplicationLauncherIcon::ShowInSwitcher(bool current)
}
else
{
- for (int i = 0; i < max_num_monitors; i++)
+ for (int i = 0; i < max_num_monitors; ++i)
{
if (WindowVisibleOnMonitor(i))
{
@@ -1222,6 +1218,94 @@ const std::set<std::string> ApplicationLauncherIcon::GetSupportedTypes()
return supported_types;
}
+void PerformScrollUp(WindowList const& windows, unsigned int progressive_scroll)
+{
+ if (!progressive_scroll)
+ {
+ windows.at(1)->Focus();
+ return;
+ }
+ else if (progressive_scroll == 1)
+ {
+ windows.back()->Focus();
+ return;
+ }
+
+ WindowManager::Default().RestackBelow(windows.at(0)->window_id(), windows.at(windows.size() - progressive_scroll + 1)->window_id());
+ windows.at(windows.size() - 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)
+{
+ if (timestamp - _last_scroll_timestamp < 150)
+ return;
+ else if (timestamp - _last_scroll_timestamp > 1500 || direction != _last_scroll_direction)
+ _progressive_scroll = 0;
+
+ _last_scroll_timestamp = timestamp;
+ _last_scroll_direction = direction;
+
+ auto const& windows = GetWindowsOnCurrentDesktopInStackingOrder();
+ if (windows.empty())
+ return;
+
+ if (!IsActive())
+ {
+ windows.at(0)->Focus();
+ return;
+ }
+
+ if (windows.size() <= 1)
+ return;
+
+ ++_progressive_scroll;
+ _progressive_scroll %= windows.size();
+
+ switch(direction)
+ {
+ case ScrollDirection::UP:
+ PerformScrollUp(windows, _progressive_scroll);
+ break;
+ case ScrollDirection::DOWN:
+ PerformScrollDown(windows, _progressive_scroll);
+ break;
+ }
+}
+
+WindowList ApplicationLauncherIcon::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;
+}
+
std::string ApplicationLauncherIcon::GetName() const
{
return "ApplicationLauncherIcon";
diff --git a/launcher/ApplicationLauncherIcon.h b/launcher/ApplicationLauncherIcon.h
index 04594aa48..8a604a6f7 100644
--- a/launcher/ApplicationLauncherIcon.h
+++ b/launcher/ApplicationLauncherIcon.h
@@ -68,6 +68,8 @@ public:
std::vector<Window> WindowsOnViewport();
std::vector<Window> WindowsForMonitor(int monitor);
+ void PerformScroll(ScrollDirection direction, Time timestamp) override;
+
protected:
void Remove();
void UpdateIconGeometries(std::vector<nux::Point3> center);
@@ -124,9 +126,13 @@ private:
WindowList GetWindows(WindowFilterMask filter = 0, int monitor = -1);
const std::set<std::string> GetSupportedTypes();
std::string GetDesktopID();
+ WindowList GetWindowsOnCurrentDesktopInStackingOrder();
std::string _remote_uri;
Time _startup_notification_timestamp;
+ Time _last_scroll_timestamp;
+ ScrollDirection _last_scroll_direction;
+ unsigned int _progressive_scroll;
std::set<std::string> _supported_types;
std::map<std::string, glib::Object<DbusmenuClient>> _menu_clients;
std::map<std::string, glib::Object<DbusmenuMenuitem>> _menu_items;
diff --git a/launcher/BFBLauncherIcon.cpp b/launcher/BFBLauncherIcon.cpp
index a84d71f7b..f7d701020 100644
--- a/launcher/BFBLauncherIcon.cpp
+++ b/launcher/BFBLauncherIcon.cpp
@@ -58,8 +58,9 @@ void BFBLauncherIcon::OnOverlayShown(GVariant *data, bool visible)
unity::glib::String overlay_identity;
gboolean can_maximise = FALSE;
gint32 overlay_monitor = 0;
+ int width, height;
g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
- &overlay_identity, &can_maximise, &overlay_monitor);
+ &overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
if (overlay_identity.Str() == "dash" && IsVisibleOnMonitor(overlay_monitor))
{
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 3987c69cf..b32d93953 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -57,6 +57,7 @@ set (LAUNCHER_SOURCES
SoftwareCenterLauncherIcon.cpp
SpacerLauncherIcon.cpp
Tooltip.cpp
+ TooltipManager.cpp
TrashLauncherIcon.cpp
VolumeImp.cpp
VolumeLauncherIcon.cpp
diff --git a/launcher/DeviceLauncherSection.cpp b/launcher/DeviceLauncherSection.cpp
index b46e34f7c..41443eca7 100644
--- a/launcher/DeviceLauncherSection.cpp
+++ b/launcher/DeviceLauncherSection.cpp
@@ -32,8 +32,8 @@ DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr v
DevicesSettings::Ptr devices_settings)
: monitor_(volume_monitor)
, devices_settings_(devices_settings)
- , file_manager_opener_(new FileManagerOpenerImp)
- , device_notification_display_(new DeviceNotificationDisplayImp)
+ , file_manager_opener_(std::make_shared<FileManagerOpenerImp>())
+ , device_notification_display_(std::make_shared<DeviceNotificationDisplayImp>())
{
monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded));
monitor_->volume_removed.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeRemoved));
diff --git a/launcher/FileManagerOpener.h b/launcher/FileManagerOpener.h
index a318930bc..b96d495fd 100644
--- a/launcher/FileManagerOpener.h
+++ b/launcher/FileManagerOpener.h
@@ -20,7 +20,6 @@
#ifndef UNITYSHELL_FILEMANAGER_OPENER_H
#define UNITYSHELL_FILEMANAGER_OPENER_H
-#include <boost/noncopyable.hpp>
#include <memory>
#include <string>
@@ -29,14 +28,18 @@ namespace unity
namespace launcher
{
-class FileManagerOpener : private boost::noncopyable
+class FileManagerOpener
{
public:
typedef std::shared_ptr<FileManagerOpener> Ptr;
+ FileManagerOpener() = default;
virtual ~FileManagerOpener() {}
+ virtual void Open(std::string const& uri, unsigned long long timestamp = 0) = 0;
- virtual void Open(std::string const& uri) = 0;
+private:
+ FileManagerOpener(FileManagerOpener const&) = delete;
+ FileManagerOpener& operator=(FileManagerOpener const&) = delete;
};
}
diff --git a/launcher/FileManagerOpenerImp.cpp b/launcher/FileManagerOpenerImp.cpp
index 8fb2cd964..4d5068c26 100644
--- a/launcher/FileManagerOpenerImp.cpp
+++ b/launcher/FileManagerOpenerImp.cpp
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2012 Canonical Ltd
+ * Copyright (C) 2012-2013 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
@@ -15,20 +15,43 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
-#include <gio/gio.h>
-
#include "FileManagerOpenerImp.h"
+#include <NuxCore/Logger.h>
+#include <UnityCore/GLibWrapper.h>
+#include <gdk/gdk.h>
namespace unity
{
namespace launcher
{
-void FileManagerOpenerImp::Open(std::string const& uri)
+DECLARE_LOGGER(logger, "unity.launcher.filemanager.opener.imp");
+
+void FileManagerOpenerImp::Open(std::string const& uri, unsigned long long timestamp)
{
- g_app_info_launch_default_for_uri(uri. c_str(), nullptr, nullptr);
+ if (uri.empty())
+ {
+ LOG_ERROR(logger) << "Impossible to open an empty location";
+ return;
+ }
+
+ glib::Error error;
+ GdkDisplay* display = gdk_display_get_default();
+ glib::Object<GdkAppLaunchContext> context(gdk_display_get_app_launch_context(display));
+
+ if (timestamp > 0)
+ gdk_app_launch_context_set_timestamp(context, timestamp);
+
+ auto const& gcontext = glib::object_cast<GAppLaunchContext>(context);
+ g_app_info_launch_default_for_uri(uri.c_str(), gcontext, &error);
+
+ if (error)
+ {
+ LOG_ERROR(logger) << "Impossible to open the location: " << error.Message();
+ }
}
}
diff --git a/launcher/FileManagerOpenerImp.h b/launcher/FileManagerOpenerImp.h
index 6a4d62562..09785ed5b 100644
--- a/launcher/FileManagerOpenerImp.h
+++ b/launcher/FileManagerOpenerImp.h
@@ -30,7 +30,7 @@ namespace launcher
class FileManagerOpenerImp : public FileManagerOpener
{
public:
- virtual void Open(std::string const& uri);
+ virtual void Open(std::string const& uri, unsigned long long timestamp);
};
}
diff --git a/launcher/HudLauncherIcon.cpp b/launcher/HudLauncherIcon.cpp
index 7fea6c4f7..39fa01a0d 100644
--- a/launcher/HudLauncherIcon.cpp
+++ b/launcher/HudLauncherIcon.cpp
@@ -89,8 +89,9 @@ void HudLauncherIcon::OnOverlayShown(GVariant* data, bool visible)
unity::glib::String overlay_identity;
gboolean can_maximise = FALSE;
gint32 overlay_monitor = 0;
+ int width, height;
g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
- &overlay_identity, &can_maximise, &overlay_monitor);
+ &overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
// If the hud is open, we show the HUD button if we have a locked launcher
if (overlay_identity.Str() == "hud" &&
diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp
index 81eedd501..49e694f22 100644
--- a/launcher/Launcher.cpp
+++ b/launcher/Launcher.cpp
@@ -91,6 +91,9 @@ const int START_DRAGICON_DURATION = 250;
const int MOUSE_DEADZONE = 15;
const float DRAG_OUT_PIXELS = 300.0f;
+const int SCROLL_AREA_HEIGHT = 24;
+const int SCROLL_FPS = 30;
+
const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout";
const std::string SCROLL_TIMEOUT = "scroll-timeout";
const std::string ANIMATION_IDLE = "animation-idle";
@@ -101,7 +104,7 @@ NUX_IMPLEMENT_OBJECT_TYPE(Launcher);
const int Launcher::Launcher::ANIM_DURATION_SHORT = 125;
-Launcher::Launcher(nux::BaseWindow* parent,
+Launcher::Launcher(MockableBaseWindow* parent,
NUX_FILE_LINE_DECL)
: View(NUX_FILE_LINE_PARAM)
#ifdef USE_X11
@@ -286,6 +289,20 @@ void Launcher::SetStateMouseOverLauncher(bool over_launcher)
_hide_machine.SetQuirk(LauncherHideMachine::MOUSE_OVER_LAUNCHER, over_launcher);
_hide_machine.SetQuirk(LauncherHideMachine::REVEAL_PRESSURE_PASS, false);
_hover_machine.SetQuirk(LauncherHoverMachine::MOUSE_OVER_LAUNCHER, over_launcher);
+ tooltip_manager_.SetHover(over_launcher);
+}
+
+void Launcher::SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon)
+{
+ if (_icon_under_mouse == icon)
+ return;
+
+ if (_icon_under_mouse)
+ _icon_under_mouse->mouse_leave.emit(monitor);
+ if (icon)
+ icon->mouse_enter.emit(monitor);
+
+ _icon_under_mouse = icon;
}
bool Launcher::MouseBeyondDragThreshold() const
@@ -1210,8 +1227,9 @@ void Launcher::OnOverlayShown(GVariant* data)
unity::glib::String overlay_identity;
gboolean can_maximise = FALSE;
gint32 overlay_monitor = 0;
+ int width, height;
g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
- &overlay_identity, &can_maximise, &overlay_monitor);
+ &overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
std::string identity(overlay_identity.Str());
LOG_DEBUG(logger) << "Overlay shown: " << identity
@@ -1251,8 +1269,9 @@ void Launcher::OnOverlayHidden(GVariant* data)
unity::glib::String overlay_identity;
gboolean can_maximise = FALSE;
gint32 overlay_monitor = 0;
+ int width, height;
g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
- &overlay_identity, &can_maximise, &overlay_monitor);
+ &overlay_identity, &can_maximise, &overlay_monitor, &width, &height);
std::string identity = overlay_identity.Str();
@@ -1316,7 +1335,8 @@ void Launcher::SetHidden(bool hide_launcher)
TimeUtil::SetTimeStruct(&_times[TIME_AUTOHIDE], &_times[TIME_AUTOHIDE], ANIM_DURATION_SHORT);
- _parent->EnableInputWindow(!hide_launcher, launcher::window_title, false, false);
+ if (nux::GetWindowThread()->IsEmbeddedWindow())
+ _parent->EnableInputWindow(!hide_launcher, launcher::window_title, false, false);
if (!hide_launcher && GetActionState() == ACTION_DRAG_EXTERNAL)
DndReset();
@@ -1485,27 +1505,18 @@ void Launcher::SetHover(bool hovered)
bool Launcher::MouseOverTopScrollArea()
{
- return _mouse_position.y < panel::Style::Instance().panel_height;
-}
-
-bool Launcher::MouseOverTopScrollExtrema()
-{
- return _mouse_position.y == 0;
+ return _mouse_position.y < SCROLL_AREA_HEIGHT;
}
bool Launcher::MouseOverBottomScrollArea()
{
- return _mouse_position.y > GetGeometry().height - panel::Style::Instance().panel_height;
-}
-
-bool Launcher::MouseOverBottomScrollExtrema()
-{
- return _mouse_position.y == GetGeometry().height - 1;
+ return _mouse_position.y >= GetGeometry().height - SCROLL_AREA_HEIGHT;
}
bool Launcher::OnScrollTimeout()
{
bool continue_animation = true;
+ int speed = 0;
if (IsInKeyNavMode() || !_hovered ||
GetActionState() == ACTION_DRAG_LAUNCHER)
@@ -1516,19 +1527,21 @@ bool Launcher::OnScrollTimeout()
{
if (_launcher_drag_delta >= _launcher_drag_delta_max)
continue_animation = false;
- else if (MouseOverTopScrollExtrema())
- _launcher_drag_delta += 6;
else
- _launcher_drag_delta += 3;
+ {
+ speed = (SCROLL_AREA_HEIGHT - _mouse_position.y) / SCROLL_AREA_HEIGHT * SCROLL_FPS;
+ _launcher_drag_delta += speed;
+ }
}
else if (MouseOverBottomScrollArea())
{
if (_launcher_drag_delta <= _launcher_drag_delta_min)
continue_animation = false;
- else if (MouseOverBottomScrollExtrema())
- _launcher_drag_delta -= 6;
else
- _launcher_drag_delta -= 3;
+ {
+ speed = ((_mouse_position.y + 1) - (GetGeometry().height - SCROLL_AREA_HEIGHT)) / SCROLL_AREA_HEIGHT * SCROLL_FPS;
+ _launcher_drag_delta -= speed;
+ }
}
else
{
@@ -1600,8 +1613,7 @@ void Launcher::OnIconRemoved(AbstractLauncherIcon::Ptr const& icon)
if (icon->needs_redraw_connection.connected())
icon->needs_redraw_connection.disconnect();
- if (icon == _icon_under_mouse)
- _icon_under_mouse = nullptr;
+ SetIconUnderMouse(AbstractLauncherIcon::Ptr());
if (icon == _icon_mouse_down)
_icon_mouse_down = nullptr;
if (icon == _drag_icon)
@@ -1920,11 +1932,7 @@ bool Launcher::StartIconDragTimeout(int x, int y)
// if we are still waiting…
if (GetActionState() == ACTION_NONE)
{
- if (_icon_under_mouse)
- {
- _icon_under_mouse->mouse_leave.emit(monitor);
- _icon_under_mouse = nullptr;
- }
+ SetIconUnderMouse(AbstractLauncherIcon::Ptr());
_initial_drag_animation = true;
StartIconDragRequest(x, y);
}
@@ -2163,11 +2171,7 @@ void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_
GetActionState() == ACTION_NONE)
return;
- if (_icon_under_mouse)
- {
- _icon_under_mouse->mouse_leave.emit(monitor);
- _icon_under_mouse = nullptr;
- }
+ SetIconUnderMouse(AbstractLauncherIcon::Ptr());
if (GetActionState() == ACTION_NONE)
{
@@ -2219,6 +2223,7 @@ void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned
void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
{
SetMousePosition(x, y);
+ tooltip_manager_.MouseMoved(_icon_under_mouse);
if (!_hidden)
UpdateChangeInMousePosition(dx, dy);
@@ -2233,9 +2238,16 @@ void Launcher::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned lo
return;
bool alt_pressed = nux::GetKeyModifierState(key_flags, nux::NUX_STATE_ALT);
-
if (alt_pressed)
+ {
ScrollLauncher(wheel_delta);
+ }
+ else if (_icon_under_mouse)
+ {
+ auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
+ auto scroll_direction = (wheel_delta < 0) ? AbstractLauncherIcon::ScrollDirection::DOWN : AbstractLauncherIcon::ScrollDirection::UP;
+ _icon_under_mouse->PerformScroll(scroll_direction, timestamp);
+ }
}
void Launcher::ScrollLauncher(int wheel_delta)
@@ -2367,18 +2379,7 @@ void Launcher::EventLogic()
launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
}
-
- if (_icon_under_mouse && (_icon_under_mouse != launcher_icon))
- {
- _icon_under_mouse->mouse_leave.emit(monitor);
- _icon_under_mouse = nullptr;
- }
-
- if (launcher_icon && (_icon_under_mouse != launcher_icon))
- {
- launcher_icon->mouse_enter.emit(monitor);
- _icon_under_mouse = launcher_icon;
- }
+ SetIconUnderMouse(launcher_icon);
}
void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags)
@@ -2393,6 +2394,7 @@ void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned
sources_.AddTimeout(START_DRAGICON_DURATION, cb_func, START_DRAGICON_TIMEOUT);
launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags), monitor, key_flags);
+ tooltip_manager_.IconClicked();
}
}
@@ -2734,7 +2736,7 @@ void Launcher::ProcessDndDrop(int x, int y)
else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)
{
if (IsOverlayOpen())
- ubus_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
+ ubus_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
_dnd_hovered_icon->AcceptDrop(_dnd_data);
}
diff --git a/launcher/Launcher.h b/launcher/Launcher.h
index 338fa1ab8..d04f0ca9c 100644
--- a/launcher/Launcher.h
+++ b/launcher/Launcher.h
@@ -39,8 +39,10 @@
#include "LauncherDragWindow.h"
#include "LauncherHideMachine.h"
#include "LauncherHoverMachine.h"
+#include "unity-shared/MockableBaseWindow.h"
#include "unity-shared/UBusWrapper.h"
#include "SoftwareCenterLauncherIcon.h"
+#include "TooltipManager.h"
#ifdef USE_X11
# include "PointerBarrier.h"
@@ -65,7 +67,7 @@ class Launcher : public unity::debug::Introspectable,
NUX_DECLARE_OBJECT_TYPE(Launcher, nux::View);
public:
- Launcher(nux::BaseWindow* parent, NUX_FILE_LINE_PROTO);
+ Launcher(MockableBaseWindow* parent, NUX_FILE_LINE_PROTO);
nux::Property<Display*> display;
nux::Property<int> monitor;
@@ -99,7 +101,7 @@ public:
BacklightMode GetBacklightMode() const;
bool IsBackLightModeToggles() const;
- nux::BaseWindow* GetParent() const
+ MockableBaseWindow* GetParent() const
{
return _parent;
};
@@ -222,6 +224,7 @@ private:
bool OnScrollTimeout();
void SetMousePosition(int x, int y);
+ void SetIconUnderMouse(AbstractLauncherIcon::Ptr const& icon);
void SetStateMouseOverLauncher(bool over_launcher);
@@ -240,10 +243,8 @@ private:
void EnsureScrollTimer();
bool MouseOverTopScrollArea();
- bool MouseOverTopScrollExtrema();
bool MouseOverBottomScrollArea();
- bool MouseOverBottomScrollExtrema();
float DnDStartProgress(struct timespec const& current) const;
float DnDExitProgress(struct timespec const& current) const;
@@ -334,7 +335,7 @@ private:
bool DndIsSpecialRequest(std::string const& uri) const;
LauncherModel::Ptr _model;
- nux::BaseWindow* _parent;
+ MockableBaseWindow* _parent;
nux::ObjectPtr<nux::View> _active_tooltip;
QuicklistView* _active_quicklist;
@@ -388,6 +389,7 @@ private:
nux::ObjectPtr<LauncherDragWindow> _drag_window;
LauncherHideMachine _hide_machine;
LauncherHoverMachine _hover_machine;
+ TooltipManager tooltip_manager_;
unity::DndData _dnd_data;
nux::DndAction _drag_action;
diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp
index a9cd3fba8..eef602458 100644
--- a/launcher/LauncherController.cpp
+++ b/launcher/LauncherController.cpp
@@ -24,7 +24,6 @@
#include <Nux/Nux.h>
#include <Nux/HLayout.h>
-#include <Nux/BaseWindow.h>
#include <NuxCore/Logger.h>
#include <UnityCore/DesktopUtilities.h>
@@ -68,6 +67,11 @@ const std::string DBUS_INTROSPECTION =
" <arg type='s' name='aptdaemon_task' direction='in'/>"
" </method>"
""
+ " <method name='UpdateLauncherIconFavoriteState'>"
+ " <arg type='s' name='icon_uri' direction='in'/>"
+ " <arg type='b' name='is_sticky' direction='in'/>"
+ " </method>"
+ ""
" </interface>"
"</node>";
}
@@ -89,11 +93,16 @@ namespace
const std::string RUNNING_APPS_URI = FavoriteStore::URI_PREFIX_UNITY + "running-apps";
const std::string DEVICES_URI = FavoriteStore::URI_PREFIX_UNITY + "devices";
}
-}
-GDBusInterfaceVTable Controller::Impl::interface_vtable =
- { Controller::Impl::OnDBusMethodCall, NULL, NULL};
+std::string CreateAppUriNameFromDesktopPath(const std::string &desktop_path)
+{
+ if (desktop_path.empty())
+ return "";
+ return FavoriteStore::URI_PREFIX_APP + DesktopUtilities::GetDesktopID(desktop_path);
+}
+
+}
Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager)
: parent_(parent)
@@ -111,10 +120,7 @@ Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager)
, launcher_key_press_time_(0)
, last_dnd_monitor_(-1)
, super_tap_duration_(0)
- , dbus_owner_(g_bus_own_name(G_BUS_TYPE_SESSION, DBUS_NAME.c_str(), G_BUS_NAME_OWNER_FLAGS_NONE,
- OnBusAcquired, nullptr, nullptr, this, nullptr))
- , gdbus_connection_(nullptr)
- , reg_id_(0)
+ , dbus_server_(DBUS_NAME)
{
#ifdef USE_X11
edge_barriers_.options = parent_->options();
@@ -179,6 +185,10 @@ Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager)
xdnd_manager_->dnd_started.connect(sigc::mem_fun(this, &Impl::OnDndStarted));
xdnd_manager_->dnd_finished.connect(sigc::mem_fun(this, &Impl::OnDndFinished));
xdnd_manager_->monitor_changed.connect(sigc::mem_fun(this, &Impl::OnDndMonitorChanged));
+
+ dbus_server_.AddObjects(DBUS_INTROSPECTION, DBUS_PATH);
+ for (auto const& obj : dbus_server_.GetObjects())
+ obj->SetMethodsCallsHandler(sigc::mem_fun(this, &Impl::OnDBusMethodCall));
}
Controller::Impl::~Impl()
@@ -191,11 +201,6 @@ Controller::Impl::~Impl()
if (launcher_ptr)
launcher_ptr->GetParent()->UnReference();
}
-
- if (gdbus_connection_ && reg_id_)
- g_dbus_connection_unregister_object(gdbus_connection_, reg_id_);
-
- g_bus_unown_name(dbus_owner_);
}
void Controller::Impl::EnsureLaunchers(int primary, std::vector<nux::Geometry> const& monitors)
@@ -314,7 +319,7 @@ void Controller::Impl::OnDndMonitorChanged(int monitor)
Launcher* Controller::Impl::CreateLauncher()
{
- nux::BaseWindow* launcher_window = new nux::BaseWindow(TEXT("LauncherWindow"));
+ auto* launcher_window = new MockableBaseWindow(TEXT("LauncherWindow"));
Launcher* launcher = new Launcher(launcher_window);
launcher->options = parent_->options();
@@ -329,7 +334,10 @@ Launcher* Controller::Impl::CreateLauncher()
launcher_window->SetLayout(layout);
launcher_window->SetBackgroundColor(nux::color::Transparent);
launcher_window->ShowWindow(true);
- launcher_window->EnableInputWindow(true, launcher::window_title, false, false);
+
+ if (nux::GetWindowThread()->IsEmbeddedWindow())
+ launcher_window->EnableInputWindow(true, launcher::window_title, false, false);
+
launcher_window->InputWindowEnableStruts(parent_->options()->hide_mode == LAUNCHER_HIDE_NEVER);
launcher_window->SetEnterFocusInputArea(launcher);
@@ -348,7 +356,7 @@ void Controller::Impl::OnLauncherAddRequest(std::string const& icon_uri, Abstrac
if (icon_uri.find(FavoriteStore::URI_PREFIX_FILE) == 0)
{
auto const& desktop_path = icon_uri.substr(FavoriteStore::URI_PREFIX_FILE.length());
- app_uri = FavoriteStore::URI_PREFIX_APP + DesktopUtilities::GetDesktopID(desktop_path);
+ app_uri = local::CreateAppUriNameFromDesktopPath(desktop_path);
}
auto const& icon = GetIconByUri(app_uri.empty() ? icon_uri : app_uri);
@@ -433,6 +441,62 @@ void Controller::Impl::SaveIconsOrder()
}
void
+Controller::Impl::OnLauncherUpdateIconStickyState(std::string const& icon_uri, bool sticky)
+{
+ if (icon_uri.empty())
+ return;
+
+ std::string target_uri = icon_uri;
+ if (icon_uri.find(FavoriteStore::URI_PREFIX_FILE) == 0)
+ {
+ auto const& desktop_path =
+ icon_uri.substr(FavoriteStore::URI_PREFIX_FILE.length());
+
+ // app uri instead
+ target_uri = local::CreateAppUriNameFromDesktopPath(desktop_path);
+ }
+ auto const& existing_icon_entry =
+ GetIconByUri(target_uri);
+
+ if (existing_icon_entry)
+ {
+ // use the backgroung mechanism of model updates & propagation
+ bool should_update = (existing_icon_entry->IsSticky() != sticky);
+ if (should_update)
+ {
+ if (sticky)
+ {
+ existing_icon_entry->Stick(true);
+ }
+ else
+ {
+ existing_icon_entry->UnStick();
+ }
+
+ SortAndUpdate();
+ }
+ }
+ else
+ {
+ FavoriteStore& favorite_store = FavoriteStore::Instance();
+
+ bool should_update = (favorite_store.IsFavorite(target_uri) != sticky);
+ if (should_update)
+ {
+ if (sticky)
+ {
+ favorite_store.AddFavorite(target_uri, -1);
+ RegisterIcon(CreateFavoriteIcon(target_uri));
+ }
+ else
+ {
+ favorite_store.RemoveFavorite(target_uri);
+ }
+ }
+ }
+}
+
+void
Controller::Impl::OnLauncherAddRequestSpecial(std::string const& path,
std::string const& aptdaemon_trans_id,
std::string const& icon_path,
@@ -1198,9 +1262,9 @@ bool Controller::HandleLauncherKeyEvent(Display *display, unsigned int key_sym,
if (TimeUtil::TimeDelta(&current, &last_action_time) > local::ignore_repeat_shortcut_duration)
{
if (g_ascii_isdigit((gchar)(*it)->GetShortcut()) && (key_state & ShiftMask))
- (*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0, timestamp));
+ (*it)->OpenInstance(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp));
else
- (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0, timestamp));
+ (*it)->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp));
}
// disable the "tap on super" check
@@ -1320,10 +1384,10 @@ void Controller::KeyNavTerminate(bool activate)
if (activate)
{
- auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
+ auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
pimpl->sources_.AddIdle([this, timestamp] {
- pimpl->model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0, timestamp));
+ pimpl->model_->Selection()->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp));
return false;
});
}
@@ -1424,8 +1488,8 @@ void Controller::Impl::ReceiveLauncherKeyPress(unsigned long eventType,
// <SPACE> (open a new instance)
case NUX_VK_SPACE:
{
- auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
- model_->Selection()->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0, timestamp));
+ auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
+ model_->Selection()->OpenInstance(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp));
parent_->KeyNavTerminate(false);
break;
}
@@ -1455,50 +1519,29 @@ void Controller::Impl::OpenQuicklist()
}
}
-void Controller::Impl::OnBusAcquired(GDBusConnection* connection, const gchar* name, gpointer user_data)
-{
- GDBusNodeInfo* introspection_data = g_dbus_node_info_new_for_xml(DBUS_INTROSPECTION.c_str(), nullptr);
-
- if (!introspection_data)
- {
- LOG_WARNING(logger) << "No introspection data loaded. Won't get dynamic launcher addition.";
- return;
- }
-
- auto self = static_cast<Controller::Impl*>(user_data);
-
- self->gdbus_connection_ = connection;
- self->reg_id_ = g_dbus_connection_register_object(connection, DBUS_PATH.c_str(),
- introspection_data->interfaces[0],
- &interface_vtable, user_data,
- nullptr, nullptr);
- if (!self->reg_id_)
- {
- LOG_WARNING(logger) << "Object registration failed. Won't get dynamic launcher addition.";
- }
-
- g_dbus_node_info_unref(introspection_data);
-}
-
-void Controller::Impl::OnDBusMethodCall(GDBusConnection* connection, const gchar* sender,
- const gchar* object_path, const gchar* interface_name,
- const gchar* method_name, GVariant* parameters,
- GDBusMethodInvocation* invocation, gpointer user_data)
+GVariant* Controller::Impl::OnDBusMethodCall(std::string const& method, GVariant *parameters)
{
- if (g_strcmp0(method_name, "AddLauncherItemFromPosition") == 0)
+ if (method == "AddLauncherItemFromPosition")
{
- auto self = static_cast<Controller::Impl*>(user_data);
glib::String icon, icon_title, desktop_file, aptdaemon_task;
gint icon_x, icon_y, icon_size;
g_variant_get(parameters, "(ssiiiss)", &icon_title, &icon, &icon_x, &icon_y,
&icon_size, &desktop_file, &aptdaemon_task);
- self->OnLauncherAddRequestSpecial(desktop_file.Str(), aptdaemon_task.Str(),
- icon.Str(), icon_x, icon_y, icon_size);
+ OnLauncherAddRequestSpecial(desktop_file.Str(), aptdaemon_task.Str(),
+ icon.Str(), icon_x, icon_y, icon_size);
+ }
+ else if (method == "UpdateLauncherIconFavoriteState")
+ {
+ gboolean is_sticky;
+ glib::String icon_uri;
+ g_variant_get(parameters, "(sb)", &icon_uri, &is_sticky);
- g_dbus_method_invocation_return_value(invocation, nullptr);
+ OnLauncherUpdateIconStickyState(icon_uri.Str(), is_sticky);
}
+
+ return nullptr;
}
} // namespace launcher
diff --git a/launcher/LauncherControllerPrivate.h b/launcher/LauncherControllerPrivate.h
index 8b9449505..af2ced337 100644
--- a/launcher/LauncherControllerPrivate.h
+++ b/launcher/LauncherControllerPrivate.h
@@ -24,6 +24,7 @@
#define LAUNCHER_CONTROLLER_PRIVATE_H
#include <Nux/Nux.h>
+#include <UnityCore/GLibDBusServer.h>
#include "AbstractLauncherIcon.h"
#include "DeviceLauncherSection.h"
@@ -71,6 +72,7 @@ public:
void OnLauncherAddRequest(std::string const& icon_uri, AbstractLauncherIcon::Ptr const& before);
void OnLauncherAddRequestSpecial(std::string const& path, std::string const& aptdaemon_trans_id,
std::string const& icon_path, int icon_x, int icon_y, int icon_size);
+ void OnLauncherUpdateIconStickyState(std::string const& desktop_file, bool sticky);
void OnLauncherRemoveRequest(AbstractLauncherIcon::Ptr const& icon);
void OnLauncherEntryRemoteAdded(LauncherEntryRemote::Ptr const& entry);
@@ -116,14 +118,7 @@ public:
void OnDndStarted(std::string const& data, int monitor);
void OnDndFinished();
void OnDndMonitorChanged(int monitor);
-
- static void OnBusAcquired(GDBusConnection* connection, const gchar* name, gpointer user_data);
- static void OnDBusMethodCall(GDBusConnection* connection, const gchar* sender, const gchar* object_path,
- const gchar* interface_name, const gchar* method_name,
- GVariant* parameters, GDBusMethodInvocation* invocation,
- gpointer user_data);
-
- static GDBusInterfaceVTable interface_vtable;
+ GVariant* OnDBusMethodCall(std::string const& method, GVariant *parameters);
Controller* parent_;
LauncherModel::Ptr model_;
@@ -152,10 +147,7 @@ public:
int last_dnd_monitor_;
int super_tap_duration_;
- unsigned dbus_owner_;
- GDBusConnection* gdbus_connection_;
- unsigned reg_id_;
-
+ glib::DBusServer dbus_server_;
glib::SourceManager sources_;
UBusManager ubus;
diff --git a/launcher/LauncherIcon.cpp b/launcher/LauncherIcon.cpp
index 895612f70..7efe4b458 100644
--- a/launcher/LauncherIcon.cpp
+++ b/launcher/LauncherIcon.cpp
@@ -62,6 +62,8 @@ const std::string UNITY_THEME_NAME = "unity-icon-theme";
const std::string CENTER_STABILIZE_TIMEOUT = "center-stabilize-timeout";
const std::string PRESENT_TIMEOUT = "present-timeout";
const std::string QUIRK_DELAY_TIMEOUT = "quirk-delay-timeout";
+
+const unsigned TOOLTIP_FADE_DURATION = 80;
}
NUX_IMPLEMENT_OBJECT_TYPE(LauncherIcon);
@@ -86,6 +88,7 @@ LauncherIcon::LauncherIcon(IconType type)
, _parent_geo(max_num_monitors)
, _saved_center(max_num_monitors)
, _allow_quicklist_to_show(true)
+ , _tooltip_fade_animator(TOOLTIP_FADE_DURATION)
{
for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i)
{
@@ -115,6 +118,19 @@ LauncherIcon::LauncherIcon(IconType type)
mouse_down.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseDown));
mouse_up.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseUp));
mouse_click.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseClick));
+
+ _tooltip_fade_animator.updated.connect([this] (double opacity) {
+ if (_tooltip)
+ {
+ _tooltip->SetOpacity(opacity);
+
+ if (opacity == 0.0f && _tooltip_fade_animator.GetStartValue() > _tooltip_fade_animator.GetFinishValue())
+ {
+ _tooltip->ShowWindow(false);
+ _tooltip->SetOpacity(0.0f);
+ }
+ }
+ });
}
LauncherIcon::~LauncherIcon()
@@ -143,6 +159,7 @@ LauncherIcon::~LauncherIcon()
void LauncherIcon::LoadTooltip()
{
_tooltip = new Tooltip();
+ _tooltip->SetOpacity(0.0f);
AddChild(_tooltip.GetPointer());
_tooltip->text = tooltip_text();
@@ -522,29 +539,23 @@ LauncherIcon::ShowTooltip()
_tooltip->ShowTooltipWithTipAt(tip_x, tip_y);
_tooltip->ShowWindow(!tooltip_text().empty());
tooltip_visible.emit(_tooltip);
+
+ if (_tooltip_fade_animator.CurrentState() == nux::animation::Animation::State::Running)
+ _tooltip_fade_animator.Reverse();
+ else
+ _tooltip_fade_animator.SetStartValue(0.0f).SetFinishValue(1.0f).Start();
}
void
LauncherIcon::RecvMouseEnter(int monitor)
{
_last_monitor = monitor;
- if (QuicklistManager::Default()->Current())
- {
- // A quicklist is active
- return;
- }
-
- ShowTooltip();
}
void LauncherIcon::RecvMouseLeave(int monitor)
{
_last_monitor = -1;
_allow_quicklist_to_show = true;
-
- if (_tooltip)
- _tooltip->ShowWindow(false);
- tooltip_visible.emit(nux::ObjectPtr<nux::View>(nullptr));
}
bool LauncherIcon::OpenQuicklist(bool select_first_item, int monitor)
@@ -662,9 +673,9 @@ void LauncherIcon::RecvMouseUp(int button, int monitor, unsigned long key_flags)
void LauncherIcon::RecvMouseClick(int button, int monitor, unsigned long key_flags)
{
- auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
+ auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
- ActionArg arg(ActionArg::LAUNCHER, button, timestamp);
+ ActionArg arg(ActionArg::Source::LAUNCHER, button, timestamp);
arg.monitor = monitor;
bool shift_pressed = nux::GetKeyModifierState(key_flags, nux::NUX_STATE_SHIFT);
@@ -680,7 +691,13 @@ void LauncherIcon::RecvMouseClick(int button, int monitor, unsigned long key_fla
void LauncherIcon::HideTooltip()
{
if (_tooltip)
- _tooltip->ShowWindow(false);
+ {
+ if (_tooltip_fade_animator.CurrentState() == nux::animation::Animation::State::Running)
+ _tooltip_fade_animator.Reverse();
+ else
+ _tooltip_fade_animator.SetStartValue(1.0f).SetFinishValue(0.0f).Start();
+ }
+
tooltip_visible.emit(nux::ObjectPtr<nux::View>(nullptr));
}
@@ -1217,6 +1234,9 @@ void LauncherIcon::UnStick()
SetQuirk(Quirk::VISIBLE, false);
}
+void LauncherIcon::PerformScroll(ScrollDirection direction, Time timestamp)
+{}
+
} // namespace launcher
} // namespace unity
diff --git a/launcher/LauncherIcon.h b/launcher/LauncherIcon.h
index af3f0bed1..68a783b60 100644
--- a/launcher/LauncherIcon.h
+++ b/launcher/LauncherIcon.h
@@ -21,12 +21,9 @@
#ifndef LAUNCHERICON_H
#define LAUNCHERICON_H
-#include <set>
-#include <boost/unordered_map.hpp>
-
#include <Nux/Nux.h>
#include <Nux/BaseWindow.h>
-#include <NuxCore/Math/MathInc.h>
+#include <NuxCore/Animation.h>
#include <gtk/gtk.h>
#include <libdbusmenu-glib/client.h>
@@ -196,6 +193,8 @@ public:
virtual void UnStick();
+ void PerformScroll(ScrollDirection direction, Time timestamp) override;
+
protected:
std::vector<nux::Point3> GetCenters();
@@ -336,6 +335,8 @@ private:
std::list<LauncherEntryRemote::Ptr> _entry_list;
+ nux::animation::AnimateValue<double> _tooltip_fade_animator;
+
protected:
glib::SourceManager _source_manager;
};
diff --git a/launcher/MockLauncherIcon.h b/launcher/MockLauncherIcon.h
index 147b34564..e1057515c 100644
--- a/launcher/MockLauncherIcon.h
+++ b/launcher/MockLauncherIcon.h
@@ -22,7 +22,6 @@
#define MOCKLAUNCHERICON_H
#include <Nux/Nux.h>
-#include <NuxCore/Math/MathInc.h>
#include <Nux/BaseWindow.h>
#include <Nux/View.h>
@@ -68,6 +67,7 @@ public:
, type_(type)
, sort_priority_(DefaultPriority(type))
, remote_uri_("fake")
+ , is_tooltip_visible_(false)
{
tooltip_text = "Mock Icon";
position = Position::FLOATING;
@@ -80,7 +80,9 @@ public:
void AddProperties(GVariantBuilder* builder) {}
- void HideTooltip() {}
+ void ShowTooltip() { is_tooltip_visible_ = true; }
+ void HideTooltip() { is_tooltip_visible_ = false; }
+ bool IsTooltipVisible() { return is_tooltip_visible_; }
void SetShortcut(guint64 shortcut) {}
@@ -311,6 +313,8 @@ public:
void UnStick() {}
+ void PerformScroll(ScrollDirection /*direction*/, Time /*timestamp*/) override {}
+
private:
nux::BaseTexture* TextureFromGtkTheme(const char* icon_name, int size)
{
@@ -366,6 +370,7 @@ private:
timespec quirk_times_[unsigned(Quirk::LAST)];
std::map<int, nux::Point3> center_;
std::string remote_uri_;
+ bool is_tooltip_visible_;
};
}
diff --git a/launcher/QuicklistMenuItem.cpp b/launcher/QuicklistMenuItem.cpp
index f24cf0fab..9d3d9bac0 100644
--- a/launcher/QuicklistMenuItem.cpp
+++ b/launcher/QuicklistMenuItem.cpp
@@ -134,12 +134,13 @@ void QuicklistMenuItem::Activate() const
if (!_menu_item || !GetSelectable())
return;
- dbusmenu_menuitem_handle_event(_menu_item, "clicked", nullptr, 0);
+ auto event_time = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
+ dbusmenu_menuitem_handle_event(_menu_item, "clicked", nullptr, event_time);
if (!IsOverlayQuicklist())
{
UBusManager manager;
- manager.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
+ manager.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
}
}
diff --git a/launcher/SimpleLauncherIcon.cpp b/launcher/SimpleLauncherIcon.cpp
index 7138a0bf7..8cf1d97b0 100644
--- a/launcher/SimpleLauncherIcon.cpp
+++ b/launcher/SimpleLauncherIcon.cpp
@@ -88,7 +88,7 @@ void SimpleLauncherIcon::OnMouseLeave(int monitor)
void SimpleLauncherIcon::ActivateLauncherIcon(ActionArg arg)
{
activate.emit();
- UBusManager::SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST,
+ UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST,
g_variant_new_boolean(FALSE));
}
diff --git a/launcher/StandaloneLauncher.cpp b/launcher/StandaloneLauncher.cpp
index ccc5e11e4..cec0cd82d 100644
--- a/launcher/StandaloneLauncher.cpp
+++ b/launcher/StandaloneLauncher.cpp
@@ -18,7 +18,9 @@
*
*/
-#include "Nux/Nux.h"
+#include <Nux/Nux.h>
+#include <Nux/NuxTimerTickSource.h>
+#include <NuxCore/AnimationController.h>
#include <gtk/gtk.h>
#include "unity-shared/BackgroundEffectHelper.h"
@@ -43,6 +45,7 @@ struct LauncherWindow
{
LauncherWindow()
: wt(nux::CreateGUIThread("Unity Launcher", win_size.width, win_size.height, 0, &LauncherWindow::ThreadWidgetInit, this))
+ , animation_controller(tick_source)
{}
void Show()
@@ -64,7 +67,6 @@ private:
{
SetupBackground();
controller.reset(new launcher::Controller(std::make_shared<XdndManager>()));
- controller->launcher().GetParent()->EnableInputWindow(false);
UScreen* uscreen = UScreen::GetDefault();
std::vector<nux::Geometry> fake_monitor({nux::Geometry(0, 0, win_size.width, win_size.height)});
@@ -86,6 +88,8 @@ private:
unity::Settings settings;
panel::Style panel_style;
std::shared_ptr<nux::WindowThread> wt;
+ nux::NuxTimerTickSource tick_source;
+ nux::animation::AnimationController animation_controller;
launcher::Controller::Ptr controller;
};
diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp
index 28bbc0c4f..58b3850b9 100644
--- a/launcher/SwitcherController.cpp
+++ b/launcher/SwitcherController.cpp
@@ -316,7 +316,7 @@ void Controller::Impl::Show(ShowMode show, SortMode sort, std::vector<AbstractLa
sources_.AddTimeout(obj_->initial_detail_timeout_length, cb_func, DETAIL_TIMEOUT);
}
- ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
+ ubus_manager_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
ubus_manager_.SendMessage(UBUS_SWITCHER_SHOWN,
g_variant_new("(bi)", true, obj_->monitor_));
}
@@ -365,6 +365,7 @@ void Controller::Impl::ShowView()
if (view_window_)
{
+ view_->live_background = true;
view_window_->ShowWindow(true);
view_window_->PushToFront();
@@ -409,7 +410,6 @@ void Controller::Impl::ConstructView()
view_->SetModel(model_);
view_->background_color = bg_color_;
view_->monitor = obj_->monitor_;
- view_->SetupBackground();
ConstructWindow();
main_layout_->AddView(view_.GetPointer(), 1);
@@ -426,8 +426,8 @@ void Controller::Impl::Hide(bool accept_state)
Selection selection = GetCurrentSelection();
if (selection.application_)
{
- Time timestamp = -1;
- selection.application_->Activate(ActionArg(ActionArg::SWITCHER, 0,
+ Time timestamp = 0;
+ selection.application_->Activate(ActionArg(ActionArg::Source::SWITCHER, 0,
timestamp, selection.window_));
}
}
@@ -458,7 +458,6 @@ void Controller::Impl::HideWindow()
view_window_->SetOpacity(0.0f);
view_window_->ShowWindow(false);
view_window_->PushToBack();
- view_window_->EnableInputWindow(false);
model_.reset();
view_.Release();
diff --git a/launcher/SwitcherView.cpp b/launcher/SwitcherView.cpp
index 2453b786f..b75063899 100644
--- a/launcher/SwitcherView.cpp
+++ b/launcher/SwitcherView.cpp
@@ -564,12 +564,14 @@ nux::Geometry SwitcherView::GetBackgroundGeometry()
return last_background_;
}
-void SwitcherView::DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry internal_clip)
+void SwitcherView::DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry const& clip)
{
- nux::Geometry base = GetGeometry();
+ nux::Geometry const& base = GetGeometry();
+ nux::Geometry internal_clip = clip;
GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
+
for (auto const& arg : last_args_)
{
if (text_view_->IsVisible() && model_->Selection() == arg.icon)
diff --git a/launcher/SwitcherView.h b/launcher/SwitcherView.h
index 85d3e1336..a690d9b73 100644
--- a/launcher/SwitcherView.h
+++ b/launcher/SwitcherView.h
@@ -79,7 +79,7 @@ protected:
void AddProperties(GVariantBuilder* builder);
void PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw);
- void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry clip);
+ void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry const& clip);
nux::Geometry GetBackgroundGeometry();
ui::RenderArg InterpolateRenderArgs(ui::RenderArg const& start, ui::RenderArg const& end, float progress);
diff --git a/launcher/TooltipManager.cpp b/launcher/TooltipManager.cpp
new file mode 100644
index 000000000..dee8a5103
--- /dev/null
+++ b/launcher/TooltipManager.cpp
@@ -0,0 +1,92 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2013 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: Jacob Edwards <j.johan.edwards@gmail.com>
+ * Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#include "TooltipManager.h"
+
+namespace unity
+{
+namespace launcher
+{
+namespace
+{
+const unsigned int TOOLTIPS_SHOW_TIMEOUT_LENGTH = 500;
+}
+
+TooltipManager::TooltipManager()
+ : skip_timeout_(false)
+{}
+
+void TooltipManager::MouseMoved(AbstractLauncherIcon::Ptr const& icon_under_mouse)
+{
+ if (icon_ == icon_under_mouse)
+ return;
+
+ StopTimer();
+ if (icon_)
+ icon_->HideTooltip();
+
+ icon_ = icon_under_mouse;
+
+ if (icon_ && !skip_timeout_)
+ ResetTimer(icon_);
+ else if (icon_ && skip_timeout_)
+ icon_->ShowTooltip();
+}
+
+void TooltipManager::IconClicked()
+{
+ if (icon_)
+ icon_->HideTooltip();
+}
+
+void TooltipManager::SetHover(bool hovered)
+{
+ if (!hovered)
+ Reset();
+}
+
+void TooltipManager::Reset()
+{
+ StopTimer();
+
+ if (icon_)
+ icon_->HideTooltip();
+
+ icon_ = AbstractLauncherIcon::Ptr();
+ skip_timeout_ = false;
+}
+
+void TooltipManager::ResetTimer(AbstractLauncherIcon::Ptr const& icon_under_mouse)
+{
+ hover_timer_.reset(new glib::Timeout(TOOLTIPS_SHOW_TIMEOUT_LENGTH));
+ hover_timer_->Run([&] () {
+ skip_timeout_ = true;
+ icon_under_mouse->ShowTooltip();
+ return false;
+ });
+ }
+
+void TooltipManager::StopTimer()
+{
+ hover_timer_.reset();
+}
+
+}
+}
diff --git a/launcher/TooltipManager.h b/launcher/TooltipManager.h
new file mode 100644
index 000000000..817239d26
--- /dev/null
+++ b/launcher/TooltipManager.h
@@ -0,0 +1,56 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2013 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: Jacob Edwards <j.johan.edwards@gmail.com>
+ * Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef LAUNCHER_TOOLTIP_MANAGER_H
+#define LAUNCHER_TOOLTIP_MANAGER_H
+
+#include <boost/noncopyable.hpp>
+#include <UnityCore/GLibSource.h>
+
+#include "AbstractLauncherIcon.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class TooltipManager : public boost::noncopyable
+{
+public:
+ TooltipManager();
+
+ void SetHover(bool hovered);
+ void MouseMoved(AbstractLauncherIcon::Ptr const& icon_under_mouse);
+ void IconClicked();
+
+private:
+ void Reset();
+ void ResetTimer(AbstractLauncherIcon::Ptr const& icon_under_mouse);
+ void StopTimer();
+
+ bool skip_timeout_;
+ AbstractLauncherIcon::Ptr icon_;
+ glib::Source::UniquePtr hover_timer_;
+};
+
+}
+}
+
+#endif
diff --git a/launcher/TrashLauncherIcon.cpp b/launcher/TrashLauncherIcon.cpp
index 2ec4563dd..f16c6f8b1 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 Canonical Ltd
+ * Copyright (C) 2010-2013 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
@@ -16,6 +16,7 @@
*
* Authored by: Jason Smith <jason.smith@canonical.com>
* Andrea Azzarone <azzaronea@gmail.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
#include "TrashLauncherIcon.h"
@@ -24,11 +25,13 @@
#include <glib/gi18n-lib.h>
#include <Nux/WindowCompositor.h>
#include <NuxCore/Logger.h>
+#include <UnityCore/GLibDBusProxy.h>
#include <zeitgeist.h>
#include "Launcher.h"
#include "QuicklistManager.h"
#include "QuicklistMenuItemLabel.h"
+#include "FileManagerOpenerImp.h"
namespace unity
{
@@ -38,11 +41,12 @@ DECLARE_LOGGER(logger, "unity.launcher.icon");
namespace
{
const std::string ZEITGEIST_UNITY_ACTOR = "application://compiz.desktop";
+ const std::string TRASH_URI = "trash:///";
}
-TrashLauncherIcon::TrashLauncherIcon()
+TrashLauncherIcon::TrashLauncherIcon(FileManagerOpener::Ptr const& fmo)
: SimpleLauncherIcon(IconType::TRASH)
- , proxy_("org.gnome.Nautilus", "/org/gnome/Nautilus", "org.gnome.Nautilus.FileOperations")
+ , file_manager_(fmo ? fmo : std::make_shared<FileManagerOpenerImp>())
, cancellable_(g_cancellable_new())
{
tooltip_text = _("Trash");
@@ -52,10 +56,11 @@ TrashLauncherIcon::TrashLauncherIcon()
SetQuirk(Quirk::RUNNING, false);
SetShortcut('t');
- glib::Object<GFile> location(g_file_new_for_uri("trash:///"));
+ glib::Object<GFile> location(g_file_new_for_uri(TRASH_URI.c_str()));
glib::Error err;
trash_monitor_ = g_file_monitor_directory(location, G_FILE_MONITOR_NONE, nullptr, &err);
+ g_file_monitor_set_rate_limit(trash_monitor_, 1000);
if (err)
{
@@ -83,12 +88,16 @@ AbstractLauncherIcon::MenuItemsVector TrashLauncherIcon::GetMenus()
/* Empty Trash */
glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Empty Trash..."));
+ 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,
- [this] (DbusmenuMenuitem*, int) {
- proxy_.Call("EmptyTrash");
+ [this] (DbusmenuMenuitem*, unsigned) {
+ auto proxy = std::make_shared<glib::DBusProxy>("org.gnome.Nautilus", "/org/gnome/Nautilus",
+ "org.gnome.Nautilus.FileOperations");
+
+ // Passing the proxy to the lambda we ensure that it will be destroyed when needed
+ proxy->CallBegin("EmptyTrash", nullptr, [proxy] (GVariant*, glib::Error const&) {});
});
result.push_back(menu_item);
@@ -100,13 +109,12 @@ void TrashLauncherIcon::ActivateLauncherIcon(ActionArg arg)
{
SimpleLauncherIcon::ActivateLauncherIcon(arg);
- glib::Error error;
- g_spawn_command_line_async("xdg-open trash://", &error);
+ file_manager_->Open(TRASH_URI.c_str(), arg.timestamp);
}
void TrashLauncherIcon::UpdateTrashIcon()
{
- glib::Object<GFile> location(g_file_new_for_uri("trash:///"));
+ glib::Object<GFile> location(g_file_new_for_uri(TRASH_URI.c_str()));
g_file_query_info_async(location,
G_FILE_ATTRIBUTE_STANDARD_ICON,
@@ -117,14 +125,12 @@ void TrashLauncherIcon::UpdateTrashIcon()
this);
}
-void TrashLauncherIcon::UpdateTrashIconCb(GObject* source,
- GAsyncResult* res,
- gpointer data)
+void TrashLauncherIcon::UpdateTrashIconCb(GObject* source, GAsyncResult* res, gpointer data)
{
- TrashLauncherIcon* self = (TrashLauncherIcon*) data;
+ auto self = static_cast<TrashLauncherIcon*>(data);
// FIXME: should use the generic LoadIcon function (not taking from the unity theme)
- glib::Object<GFileInfo> info(g_file_query_info_finish(G_FILE(source), res, NULL));
+ glib::Object<GFileInfo> info(g_file_query_info_finish(G_FILE(source), res, nullptr));
if (info)
{
@@ -132,7 +138,6 @@ void TrashLauncherIcon::UpdateTrashIconCb(GObject* source,
glib::String icon_string(g_icon_to_string(icon));
self->icon_name = icon_string.Str();
-
self->empty_ = (self->icon_name == "user-trash");
}
}
@@ -152,23 +157,22 @@ bool TrashLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data)
return true;
}
-
void TrashLauncherIcon::OnAcceptDrop(DndData const& dnd_data)
{
- for (auto it : dnd_data.Uris())
+ for (auto const& uri : dnd_data.Uris())
{
- glib::Object<GFile> file(g_file_new_for_uri(it.c_str()));
+ glib::Object<GFile> file(g_file_new_for_uri(uri.c_str()));
/* Log ZG event when moving file to trash; this is requred by File Lens.
See https://bugs.launchpad.net/unity/+bug/870150 */
if (g_file_trash(file, NULL, NULL))
{
// based on nautilus zg event logging code
- glib::String origin(g_path_get_dirname(it.c_str()));
+ glib::String origin(g_path_get_dirname(uri.c_str()));
glib::String parse_name(g_file_get_parse_name(file));
glib::String display_name(g_path_get_basename(parse_name));
- ZeitgeistSubject *subject = zeitgeist_subject_new_full(it.c_str(),
+ ZeitgeistSubject *subject = zeitgeist_subject_new_full(uri.c_str(),
NULL, // subject interpretation
NULL, // suject manifestation
NULL, // mime-type
diff --git a/launcher/TrashLauncherIcon.h b/launcher/TrashLauncherIcon.h
index 8f9df0966..640886bf0 100644
--- a/launcher/TrashLauncherIcon.h
+++ b/launcher/TrashLauncherIcon.h
@@ -21,12 +21,12 @@
#define TRASHLAUNCHERICON_H
#include <gio/gio.h>
-#include <UnityCore/GLibDBusProxy.h>
#include <UnityCore/GLibWrapper.h>
#include <UnityCore/GLibSignal.h>
#include "DndData.h"
#include "SimpleLauncherIcon.h"
+#include "FileManagerOpener.h"
namespace unity
{
@@ -37,7 +37,7 @@ class TrashLauncherIcon : public SimpleLauncherIcon
{
public:
- TrashLauncherIcon();
+ TrashLauncherIcon(FileManagerOpener::Ptr const& = nullptr);
~TrashLauncherIcon();
protected:
@@ -55,12 +55,12 @@ private:
static void UpdateTrashIconCb(GObject* source, GAsyncResult* res, gpointer data);
- gboolean empty_;
- glib::DBusProxy proxy_;
+ bool empty_;
+ FileManagerOpener::Ptr file_manager_;
glib::Object<GCancellable> cancellable_;
glib::Object<GFileMonitor> trash_monitor_;
glib::Signal<void, GFileMonitor*, GFile*, GFile*, GFileMonitorEvent> trash_changed_signal_;
- glib::Signal<void, DbusmenuMenuitem*, int> empty_activated_signal_;
+ glib::Signal<void, DbusmenuMenuitem*, unsigned> empty_activated_signal_;
};
}
diff --git a/launcher/Volume.h b/launcher/Volume.h
index 0675a14f7..1248027c9 100644
--- a/launcher/Volume.h
+++ b/launcher/Volume.h
@@ -20,7 +20,6 @@
#ifndef UNITYSHELL_VOLUME_H
#define UNITYSHELL_VOLUME_H
-#include <boost/noncopyable.hpp>
#include <memory>
#include <sigc++/signal.h>
#include <sigc++/trackable.h>
@@ -31,12 +30,13 @@ namespace unity
namespace launcher
{
-class Volume : private boost::noncopyable, public sigc::trackable
+class Volume : public sigc::trackable
{
public:
typedef std::shared_ptr<Volume> Ptr;
- virtual ~Volume() {}
+ Volume() = default;
+ virtual ~Volume() = default;
virtual bool CanBeEjected() const = 0;
virtual bool CanBeRemoved() const = 0;
@@ -48,12 +48,16 @@ public:
virtual bool IsMounted() const = 0;
virtual void EjectAndShowNotification() = 0;
- virtual void MountAndOpenInFileManager() = 0;
+ virtual void MountAndOpenInFileManager(unsigned long long timestamp = 0) = 0;
virtual void StopDrive() = 0;
virtual void Unmount() = 0;
sigc::signal<void> changed;
sigc::signal<void> removed;
+
+private:
+ Volume(Volume const&) = delete;
+ Volume& operator=(Volume const&) = delete;
};
}
diff --git a/launcher/VolumeImp.cpp b/launcher/VolumeImp.cpp
index c63d4d1a0..b00ccd965 100644
--- a/launcher/VolumeImp.cpp
+++ b/launcher/VolumeImp.cpp
@@ -40,6 +40,7 @@ public:
DeviceNotificationDisplay::Ptr const& device_notification_display,
VolumeImp* parent)
: parent_(parent)
+ , open_timestamp_(0)
, cancellable_(g_cancellable_new())
, volume_(volume)
, file_manager_opener_(file_manager_opener)
@@ -140,8 +141,10 @@ public:
}
}
- void MountAndOpenInFileManager()
+ void MountAndOpenInFileManager(unsigned long long timestamp)
{
+ open_timestamp_ = timestamp;
+
if (!IsMounted())
MountAndOnFinishOpenInFileManager();
else
@@ -170,7 +173,7 @@ public:
void OpenInFileManager()
{
- file_manager_opener_->Open(GetUri());
+ file_manager_opener_->Open(GetUri(), open_timestamp_);
}
std::string GetUri()
@@ -216,6 +219,7 @@ public:
}
VolumeImp* parent_;
+ unsigned long long open_timestamp_;
glib::Object<GCancellable> cancellable_;
glib::Object<GVolume> volume_;
FileManagerOpener::Ptr file_manager_opener_;
@@ -278,9 +282,9 @@ bool VolumeImp::IsMounted() const
return pimpl->IsMounted();
}
-void VolumeImp::MountAndOpenInFileManager()
+void VolumeImp::MountAndOpenInFileManager(unsigned long long timestamp)
{
- pimpl->MountAndOpenInFileManager();
+ pimpl->MountAndOpenInFileManager(timestamp);
}
void VolumeImp::EjectAndShowNotification()
diff --git a/launcher/VolumeImp.h b/launcher/VolumeImp.h
index 0d8cc2112..cea1768de 100644
--- a/launcher/VolumeImp.h
+++ b/launcher/VolumeImp.h
@@ -53,7 +53,7 @@ public:
virtual bool IsMounted() const;
virtual void EjectAndShowNotification();
- virtual void MountAndOpenInFileManager();
+ virtual void MountAndOpenInFileManager(unsigned long long timestamp);
virtual void StopDrive();
virtual void Unmount();
diff --git a/launcher/VolumeLauncherIcon.cpp b/launcher/VolumeLauncherIcon.cpp
index 4f1342435..471f98631 100644
--- a/launcher/VolumeLauncherIcon.cpp
+++ b/launcher/VolumeLauncherIcon.cpp
@@ -46,7 +46,7 @@ const unsigned int volume_changed_timeout = 500;
class VolumeLauncherIcon::Impl
{
public:
- typedef glib::Signal<void, DbusmenuMenuitem*, int> ItemSignal;
+ typedef glib::Signal<void, DbusmenuMenuitem*, unsigned> ItemSignal;
Impl(Volume::Ptr const& volume,
DevicesSettings::Ptr const& devices_settings,
@@ -136,7 +136,7 @@ public:
void ActivateLauncherIcon(ActionArg arg)
{
parent_->SimpleLauncherIcon::ActivateLauncherIcon(arg);
- volume_->MountAndOpenInFileManager();
+ volume_->MountAndOpenInFileManager(arg.timestamp);
}
MenuItemsVector GetMenus()
@@ -194,8 +194,8 @@ public:
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
dbusmenu_menuitem_property_set_bool(menu_item, QuicklistMenuItem::MARKUP_ENABLED_PROPERTY, true);
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
- volume_->MountAndOpenInFileManager();
+ gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, unsigned timestamp) {
+ volume_->MountAndOpenInFileManager(timestamp);
}));
menu.push_back(menu_item);
@@ -209,8 +209,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) {
- volume_->MountAndOpenInFileManager();
+ gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, unsigned timestamp) {
+ volume_->MountAndOpenInFileManager(timestamp);
}));
menu.push_back(menu_item);
diff --git a/launcher/XdndCollectionWindowImp.cpp b/launcher/XdndCollectionWindowImp.cpp
index 102580be9..1976db13c 100644
--- a/launcher/XdndCollectionWindowImp.cpp
+++ b/launcher/XdndCollectionWindowImp.cpp
@@ -41,9 +41,14 @@ public:
// We are not calling ShowWindow () as this window
// isn't really visible
PushToBack();
- // Hack to create the X Window as soon as possible.
- EnableInputWindow(true, "XdndCollectionWindowImp");
- EnableInputWindow(false, "XdndCollectionWindowImp");
+
+ if (nux::GetWindowThread()->IsEmbeddedWindow())
+ {
+ // Hack to create the X Window as soon as possible.
+ EnableInputWindow(true, "XdndCollectionWindowImp");
+ EnableInputWindow(false, "XdndCollectionWindowImp");
+ }
+
SetDndEnabled(false, true);
uscreen->changed.connect(sigc::mem_fun(this, &PrivateWindow::OnScreenChanged));
@@ -101,13 +106,17 @@ void XdndCollectionWindowImp::Collect()
// the launcher window and the dash window. Don't forget to call PushToBack as
// soon as possible.
window_->PushToFront();
- window_->EnableInputWindow(true, "XdndCollectionWindowImp");
+
+ if (nux::GetWindowThread()->IsEmbeddedWindow())
+ window_->EnableInputWindow(true, "XdndCollectionWindowImp");
}
void XdndCollectionWindowImp::Deactivate()
{
window_->PushToBack();
- window_->EnableInputWindow(false, "XdndCollectionWindowImp");
+
+ if (nux::GetWindowThread()->IsEmbeddedWindow())
+ window_->EnableInputWindow(false, "XdndCollectionWindowImp");
}
}