summaryrefslogtreecommitdiff
path: root/launcher
diff options
authorMarco Trevisan (Treviño) <mail@3v1n0.net>2013-03-07 17:43:06 +0100
committerMarco Trevisan (Treviño) <mail@3v1n0.net>2013-03-07 17:43:06 +0100
commitc5c588214074a38370c6c447ed1119dba7edc173 (patch)
tree9182b44221e322015bd1d0731e4d48314f9742ef /launcher
parent07391b49bd09666c23ab76629eb31968daffaf77 (diff)
parent45048fbb79c09b01561b1aa8c5f51053c0d8c03e (diff)
Merging with trunk
(bzr r3144.3.31)
Diffstat (limited to 'launcher')
-rw-r--r--launcher/AbstractLauncherIcon.h6
-rw-r--r--launcher/ApplicationLauncherIcon.cpp32
-rw-r--r--launcher/ApplicationLauncherIcon.h4
-rw-r--r--launcher/BFBLauncherIcon.cpp3
-rw-r--r--launcher/CMakeLists.txt1
-rw-r--r--launcher/EdgeBarrierController.cpp36
-rw-r--r--launcher/EdgeBarrierControllerPrivate.h2
-rw-r--r--launcher/ExpoLauncherIcon.cpp5
-rw-r--r--launcher/ExpoLauncherIcon.h1
-rw-r--r--launcher/HudLauncherIcon.cpp3
-rw-r--r--launcher/Launcher.cpp60
-rw-r--r--launcher/Launcher.h10
-rw-r--r--launcher/LauncherController.cpp212
-rw-r--r--launcher/LauncherController.h3
-rw-r--r--launcher/LauncherControllerPrivate.h17
-rw-r--r--launcher/LauncherIcon.cpp18
-rw-r--r--launcher/LauncherIcon.h2
-rw-r--r--launcher/LauncherModel.cpp5
-rw-r--r--launcher/MockLauncherIcon.h6
-rw-r--r--launcher/PointerBarrier.cpp39
-rw-r--r--launcher/PointerBarrier.h6
-rw-r--r--launcher/StandaloneLauncher.cpp1
-rw-r--r--launcher/SwitcherController.cpp13
-rw-r--r--launcher/SwitcherController.h1
-rw-r--r--launcher/SwitcherControllerImpl.h1
-rw-r--r--launcher/SwitcherModel.cpp9
-rw-r--r--launcher/TooltipManager.cpp126
-rw-r--r--launcher/TooltipManager.h57
-rw-r--r--launcher/XdndCollectionWindowImp.cpp19
29 files changed, 520 insertions, 178 deletions
diff --git a/launcher/AbstractLauncherIcon.h b/launcher/AbstractLauncherIcon.h
index db8f1492b..36d0eddaf 100644
--- a/launcher/AbstractLauncherIcon.h
+++ b/launcher/AbstractLauncherIcon.h
@@ -59,9 +59,10 @@ public:
{
}
- ActionArg(Source source, int button, Window target = 0, int monitor = -1)
+ ActionArg(Source source, int button, Time timestamp = -1, Window target = 0, int monitor = -1)
: source(source)
, button(button)
+ , timestamp(timestamp)
, target(target)
, monitor(monitor)
{
@@ -69,6 +70,7 @@ public:
Source source;
int button;
+ Time timestamp;
Window target;
int monitor;
};
@@ -131,7 +133,9 @@ public:
nux::Property<std::string> tooltip_text;
nux::Property<bool> tooltip_enabled;
nux::Property<Position> position;
+ nux::Property<bool> removed;
+ virtual void ShowTooltip() = 0;
virtual void HideTooltip() = 0;
virtual void SetShortcut(guint64 shortcut) = 0;
diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp
index 6ff39832c..ade59aacc 100644
--- a/launcher/ApplicationLauncherIcon.cpp
+++ b/launcher/ApplicationLauncherIcon.cpp
@@ -324,7 +324,7 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg)
return;
SetQuirk(Quirk::STARTING, true);
- OpenInstanceLauncherIcon();
+ OpenInstanceLauncherIcon(arg.timestamp);
}
else // app is running
{
@@ -468,12 +468,19 @@ void ApplicationLauncherIcon::UpdateDesktopFile()
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*, GFile*, GFileMonitorEvent event_type) {
+ [&] (GFileMonitor*, GFile* f, GFile*, GFileMonitorEvent event_type) {
switch (event_type)
{
case G_FILE_MONITOR_EVENT_DELETED:
- UnStick();
+ {
+ 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();
@@ -510,7 +517,7 @@ void ApplicationLauncherIcon::AddProperties(GVariantBuilder* builder)
.add("startup_notification_timestamp", _startup_notification_timestamp);
}
-void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const& uris)
+void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const& uris, Time timestamp)
{
glib::Error error;
glib::Object<GDesktopAppInfo> desktopInfo(g_desktop_app_info_new_from_filename(DesktopFile().c_str()));
@@ -519,8 +526,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 = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
- 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))
{
@@ -558,10 +566,10 @@ void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const&
UpdateQuirkTime(Quirk::STARTING);
}
-void ApplicationLauncherIcon::OpenInstanceLauncherIcon()
+void ApplicationLauncherIcon::OpenInstanceLauncherIcon(Time timestamp)
{
std::set<std::string> empty;
- OpenInstanceWithUris(empty);
+ OpenInstanceWithUris(empty, timestamp);
}
void ApplicationLauncherIcon::Focus(ActionArg arg)
@@ -576,7 +584,7 @@ void ApplicationLauncherIcon::Focus(ActionArg arg)
else if (app_->type() == "webapp")
{
// Webapps are again special.
- OpenInstanceLauncherIcon();
+ OpenInstanceLauncherIcon(arg.timestamp);
return;
}
@@ -779,7 +787,10 @@ void ApplicationLauncherIcon::UnStick()
if (!IsSticky())
return;
+ SetQuirk(Quirk::VISIBLE, app_->running());
+
app_->sticky = false;
+
if (!app_->running())
Remove();
}
@@ -1143,7 +1154,8 @@ nux::DndAction ApplicationLauncherIcon::OnQueryAcceptDrop(DndData const& dnd_dat
void ApplicationLauncherIcon::OnAcceptDrop(DndData const& dnd_data)
{
- OpenInstanceWithUris(ValidateUrisForLaunch(dnd_data));
+ auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
+ OpenInstanceWithUris(ValidateUrisForLaunch(dnd_data), timestamp);
}
bool ApplicationLauncherIcon::ShowInSwitcher(bool current)
diff --git a/launcher/ApplicationLauncherIcon.h b/launcher/ApplicationLauncherIcon.h
index 7bee592c5..04594aa48 100644
--- a/launcher/ApplicationLauncherIcon.h
+++ b/launcher/ApplicationLauncherIcon.h
@@ -77,7 +77,7 @@ protected:
void OnDndEnter();
void OnDndHovered();
void OnDndLeave();
- void OpenInstanceLauncherIcon();
+ void OpenInstanceLauncherIcon(Time timestamp) override;
void ToggleSticky();
bool OnShouldHighlightOnDrag(DndData const& dnd_data);
@@ -114,7 +114,7 @@ private:
void UpdateMenus();
void UpdateDesktopQuickList();
- void OpenInstanceWithUris(std::set<std::string> const& uris);
+ void OpenInstanceWithUris(std::set<std::string> const& uris, Time timestamp);
void Focus(ActionArg arg);
bool Spread(bool current_desktop, int state, bool force);
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/EdgeBarrierController.cpp b/launcher/EdgeBarrierController.cpp
index c1d1ad8da..46514431d 100644
--- a/launcher/EdgeBarrierController.cpp
+++ b/launcher/EdgeBarrierController.cpp
@@ -24,8 +24,15 @@
#include "unity-shared/UScreen.h"
#include "UnityCore/GLibSource.h"
-namespace unity {
-namespace ui {
+namespace unity
+{
+namespace ui
+{
+
+namespace
+{
+ int const Y_BREAK_BUFFER = 20;
+}
EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent)
@@ -119,7 +126,14 @@ void EdgeBarrierController::Impl::BarrierReset()
void EdgeBarrierController::Impl::BarrierPush(PointerBarrierWrapper* owner, BarrierEvent::Ptr const& event)
{
- decaymulator_.value = decaymulator_.value + event->velocity;
+ if (EventIsInsideYBreakZone(event))
+ {
+ decaymulator_.value = decaymulator_.value + event->velocity;
+ }
+ else
+ {
+ BarrierReset();
+ }
if (decaymulator_.value > edge_overcome_pressure_)
{
@@ -127,6 +141,22 @@ void EdgeBarrierController::Impl::BarrierPush(PointerBarrierWrapper* owner, Barr
}
}
+bool EdgeBarrierController::Impl::EventIsInsideYBreakZone(BarrierEvent::Ptr const& event)
+{
+ static int y_break_zone = event->y;
+
+ if (decaymulator_.value <= 0)
+ y_break_zone = event->y;
+
+ if (event->y <= y_break_zone + Y_BREAK_BUFFER &&
+ event->y >= y_break_zone - Y_BREAK_BUFFER)
+ {
+ return true;
+ }
+
+ return false;
+}
+
void EdgeBarrierController::Impl::OnPointerBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr const& event)
{
if (owner->released)
diff --git a/launcher/EdgeBarrierControllerPrivate.h b/launcher/EdgeBarrierControllerPrivate.h
index c7cef24b8..eb4199d19 100644
--- a/launcher/EdgeBarrierControllerPrivate.h
+++ b/launcher/EdgeBarrierControllerPrivate.h
@@ -42,6 +42,8 @@ struct EdgeBarrierController::Impl
void BarrierRelease(PointerBarrierWrapper* owner, int event);
void BarrierReset();
+ bool EventIsInsideYBreakZone(BarrierEvent::Ptr const& event);
+
std::vector<PointerBarrierWrapper::Ptr> barriers_;
std::vector<EdgeBarrierSubscriber*> subscribers_;
Decaymulator decaymulator_;
diff --git a/launcher/ExpoLauncherIcon.cpp b/launcher/ExpoLauncherIcon.cpp
index 17c2d64d7..8e2adc3a8 100644
--- a/launcher/ExpoLauncherIcon.cpp
+++ b/launcher/ExpoLauncherIcon.cpp
@@ -66,6 +66,11 @@ void ExpoLauncherIcon::OnViewportLayoutChanged(int hsize, int vsize)
}
}
+void ExpoLauncherIcon::AboutToRemove()
+{
+ WindowManager::Default().SetViewportSize(1, 1);
+}
+
void ExpoLauncherIcon::UpdateIcon()
{
auto const& vp = WindowManager::Default().GetCurrentViewport();
diff --git a/launcher/ExpoLauncherIcon.h b/launcher/ExpoLauncherIcon.h
index af1ba244e..f660cdcaa 100644
--- a/launcher/ExpoLauncherIcon.h
+++ b/launcher/ExpoLauncherIcon.h
@@ -32,6 +32,7 @@ class ExpoLauncherIcon : public SimpleLauncherIcon
public:
ExpoLauncherIcon();
void Stick(bool save);
+ void AboutToRemove();
protected:
void ActivateLauncherIcon(ActionArg arg);
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 7565dd182..79c8f472f 100644
--- a/launcher/Launcher.cpp
+++ b/launcher/Launcher.cpp
@@ -101,7 +101,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 +286,21 @@ 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;
+ tooltip_manager_.SetIcon(icon);
}
bool Launcher::MouseBeyondDragThreshold() const
@@ -1210,8 +1225,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 +1267,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 +1333,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();
@@ -1600,8 +1618,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 +1937,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 +2176,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 +2228,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();
if (!_hidden)
UpdateChangeInMousePosition(dx, dy);
@@ -2297,7 +2307,9 @@ ui::EdgeBarrierSubscriber::Result Launcher::HandleBarrierEvent(ui::PointerBarrie
if (!apply_to_reveal)
return ui::EdgeBarrierSubscriber::Result::IGNORED;
- _hide_machine.AddRevealPressure(event->velocity);
+ if (!owner->IsFirstEvent())
+ _hide_machine.AddRevealPressure(event->velocity);
+
return ui::EdgeBarrierSubscriber::Result::HANDLED;
}
@@ -2365,18 +2377,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)
@@ -2391,6 +2392,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();
}
}
diff --git a/launcher/Launcher.h b/launcher/Launcher.h
index 338fa1ab8..ac61275d6 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);
@@ -334,7 +337,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 +391,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 f62ecc2be..25da39a3a 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)
@@ -216,7 +221,7 @@ void Controller::Impl::EnsureLaunchers(int primary, std::vector<nux::Geometry> c
launchers[i] = nux::ObjectPtr<Launcher>(CreateLauncher());
}
- int monitor = (num_launchers == 1) ? primary : i;
+ int monitor = (num_launchers == 1 && num_monitors > 1) ? primary : i;
if (launchers[i]->monitor() != monitor)
{
@@ -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,
@@ -525,7 +589,7 @@ void Controller::Impl::OnLauncherEntryRemoteRemoved(LauncherEntryRemote::Ptr con
void Controller::Impl::OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before)
{
- if (entry == local::RUNNING_APPS_URI || entry == local::DEVICES_URI || entry == expo_icon_->RemoteUri())
+ if (entry == local::RUNNING_APPS_URI || entry == local::DEVICES_URI)
{
// Since the running apps and the devices are always shown, when added to
// the model, we only have to re-order them
@@ -570,11 +634,12 @@ void Controller::Impl::OnFavoriteStoreFavoriteAdded(std::string const& entry, st
void Controller::Impl::OnFavoriteStoreFavoriteRemoved(std::string const& entry)
{
- if (entry == local::RUNNING_APPS_URI || entry == local::DEVICES_URI || entry == expo_icon_->RemoteUri())
+ if (entry == local::RUNNING_APPS_URI || entry == local::DEVICES_URI)
{
// Since the running apps and the devices are always shown, when added to
// the model, we only have to re-order them
ResetIconPriorities();
+ SaveIconsOrder();
return;
}
@@ -595,7 +660,6 @@ void Controller::Impl::ResetIconPriorities()
auto const& apps_icons = model_->GetSublist<ApplicationLauncherIcon>();
auto const& volumes_icons = model_->GetSublist<VolumeLauncherIcon>();
bool running_apps_found = false;
- bool expo_icon_found = false;
bool volumes_found = false;
for (auto const& fav : favs)
@@ -622,10 +686,6 @@ void Controller::Impl::ResetIconPriorities()
volumes_found = true;
continue;
}
- else if (fav == expo_icon_->RemoteUri())
- {
- expo_icon_found = true;
- }
auto const& icon = GetIconByUri(fav);
@@ -642,9 +702,6 @@ void Controller::Impl::ResetIconPriorities()
}
}
- if (!expo_icon_found)
- expo_icon_->SetSortPriority(++sort_priority_);
-
if (!volumes_found)
{
for (auto const& ico : volumes_icons)
@@ -655,9 +712,6 @@ void Controller::Impl::ResetIconPriorities()
}
model_->Sort();
-
- if (!expo_icon_found)
- SaveIconsOrder();
}
void Controller::Impl::UpdateNumWorkspaces(int workspaces)
@@ -825,8 +879,6 @@ AbstractLauncherIcon::Ptr Controller::Impl::CreateFavoriteIcon(std::string const
if (!app || app->seen())
return result;
- // Sticky apps are those that are in the launcher when not running.
- app->sticky = true;
result = AbstractLauncherIcon::Ptr(new ApplicationLauncherIcon(app));
}
else if (icon_uri.find(FavoriteStore::URI_PREFIX_DEVICE) == 0)
@@ -923,12 +975,33 @@ void Controller::Impl::AddDevices()
}
}
+void Controller::Impl::MigrateFavorites()
+{
+ // This migrates favorites to new format, ensuring that upgrades won't lose anything
+ auto& favorites = FavoriteStore::Instance();
+ auto const& favs = favorites.GetFavorites();
+
+ auto fav_it = std::find_if(begin(favs), end(favs), [](std::string const& fav) {
+ return (fav.find(FavoriteStore::URI_PREFIX_UNITY) != std::string::npos);
+ });
+
+ if (fav_it == end(favs))
+ {
+ favorites.AddFavorite(local::RUNNING_APPS_URI, -1);
+ favorites.AddFavorite(expo_icon_->RemoteUri(), -1);
+ favorites.AddFavorite(local::DEVICES_URI, -1);
+ }
+}
+
void Controller::Impl::SetupIcons()
{
+ MigrateFavorites();
+
auto& favorite_store = FavoriteStore::Instance();
FavoriteList const& favs = favorite_store.GetFavorites();
bool running_apps_added = false;
bool devices_added = false;
+
for (auto const& fav_uri : favs)
{
if (fav_uri == local::RUNNING_APPS_URI)
@@ -956,23 +1029,15 @@ void Controller::Impl::SetupIcons()
AddRunningApps();
}
- if (model_->IconIndex(expo_icon_) < 0)
- {
- LOG_INFO(logger) << "Adding expo icon";
- RegisterIcon(CreateFavoriteIcon(expo_icon_->RemoteUri()), ++sort_priority_);
- }
-
if (!devices_added)
{
LOG_INFO(logger) << "Adding devices";
AddDevices();
}
- if (std::find(favs.begin(), favs.end(), expo_icon_->RemoteUri()) == favs.end())
- SaveIconsOrder();
-
ApplicationManager::Default().application_started
.connect(sigc::mem_fun(this, &Impl::OnApplicationStarted));
+
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));
@@ -1181,7 +1246,7 @@ void Controller::HandleLauncherKeyRelease(bool was_tap, int when)
}
}
-bool Controller::HandleLauncherKeyEvent(Display *display, unsigned int key_sym, unsigned long key_code, unsigned long key_state, char* key_string)
+bool Controller::HandleLauncherKeyEvent(Display *display, unsigned int key_sym, unsigned long key_code, unsigned long key_state, char* key_string, Time timestamp)
{
LauncherModel::iterator it;
@@ -1197,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));
+ (*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0, timestamp));
else
- (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0));
+ (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0, timestamp));
}
// disable the "tap on super" check
@@ -1319,8 +1384,10 @@ void Controller::KeyNavTerminate(bool activate)
if (activate)
{
- pimpl->sources_.AddIdle([this] {
- pimpl->model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0));
+ auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
+
+ pimpl->sources_.AddIdle([this, timestamp] {
+ pimpl->model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0, timestamp));
return false;
});
}
@@ -1420,10 +1487,12 @@ void Controller::Impl::ReceiveLauncherKeyPress(unsigned long eventType,
// <SPACE> (open a new instance)
case NUX_VK_SPACE:
- model_->Selection()->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0));
+ {
+ auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
+ model_->Selection()->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0, timestamp));
parent_->KeyNavTerminate(false);
break;
-
+ }
// <RETURN> (start/activate currently selected icon)
case NUX_VK_ENTER:
case NUX_KP_ENTER:
@@ -1450,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/LauncherController.h b/launcher/LauncherController.h
index 04504ebc8..d4c0c7744 100644
--- a/launcher/LauncherController.h
+++ b/launcher/LauncherController.h
@@ -70,7 +70,8 @@ public:
unsigned int key_sym,
unsigned long key_code,
unsigned long key_state,
- char* key_string);
+ char* key_string,
+ Time timestamp);
void KeyNavActivate();
void KeyNavGrab();
diff --git a/launcher/LauncherControllerPrivate.h b/launcher/LauncherControllerPrivate.h
index b275ae0de..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);
@@ -91,6 +93,7 @@ public:
SoftwareCenterLauncherIcon::Ptr CreateSCLauncherIcon(std::string const& file_path, std::string const& aptdaemon_trans_id, std::string const& icon_path);
void SetupIcons();
+ void MigrateFavorites();
void AddRunningApps();
void AddDevices();
@@ -115,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_;
@@ -151,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 f34d7fd65..b0a9a9425 100644
--- a/launcher/LauncherIcon.cpp
+++ b/launcher/LauncherIcon.cpp
@@ -106,6 +106,7 @@ LauncherIcon::LauncherIcon(IconType type)
tooltip_text = "blank";
position = Position::FLOATING;
+ removed = false;
// FIXME: the abstraction is already broken, should be fixed for O
// right now, hooking the dynamic quicklist the less ugly possible way
@@ -230,7 +231,7 @@ LauncherIcon::OpenInstance(ActionArg arg)
if (wm.IsScaleActive())
wm.TerminateScale();
- OpenInstanceLauncherIcon();
+ OpenInstanceLauncherIcon(arg.timestamp);
UpdateQuirkTime(Quirk::LAST_ACTION);
}
@@ -527,23 +528,12 @@ 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)
@@ -661,7 +651,9 @@ void LauncherIcon::RecvMouseUp(int button, int monitor, unsigned long key_flags)
void LauncherIcon::RecvMouseClick(int button, int monitor, unsigned long key_flags)
{
- ActionArg arg(ActionArg::LAUNCHER, button);
+ auto timestamp = nux::GetWindowThread()->GetGraphicsDisplay().GetCurrentEvent().x11_timestamp;
+
+ ActionArg arg(ActionArg::LAUNCHER, button, timestamp);
arg.monitor = monitor;
bool shift_pressed = nux::GetKeyModifierState(key_flags, nux::NUX_STATE_SHIFT);
diff --git a/launcher/LauncherIcon.h b/launcher/LauncherIcon.h
index b6712796c..af3f0bed1 100644
--- a/launcher/LauncherIcon.h
+++ b/launcher/LauncherIcon.h
@@ -250,7 +250,7 @@ protected:
virtual void ActivateLauncherIcon(ActionArg arg) {}
- virtual void OpenInstanceLauncherIcon() {}
+ virtual void OpenInstanceLauncherIcon(Time timestamp) {}
virtual bool HandlesSpread () { return false; }
diff --git a/launcher/LauncherModel.cpp b/launcher/LauncherModel.cpp
index 202235d9b..a9e694924 100644
--- a/launcher/LauncherModel.cpp
+++ b/launcher/LauncherModel.cpp
@@ -49,7 +49,8 @@ unity::debug::Introspectable::IntrospectableList LauncherModel::GetIntrospectabl
introspection_results_.clear();
for (auto icon : _inner)
- introspection_results_.push_back(icon.GetPointer());
+ if (!icon->removed)
+ introspection_results_.push_back(icon.GetPointer());
return introspection_results_;
}
@@ -139,6 +140,8 @@ void LauncherModel::RemoveIcon(AbstractLauncherIcon::Ptr const& icon)
void LauncherModel::OnIconRemove(AbstractLauncherIcon::Ptr const& icon)
{
+ icon->removed = true;
+
timeouts_.AddTimeout(1000, [this, icon] {
RemoveIcon(icon);
return false;
diff --git a/launcher/MockLauncherIcon.h b/launcher/MockLauncherIcon.h
index 147b34564..b6d512aa7 100644
--- a/launcher/MockLauncherIcon.h
+++ b/launcher/MockLauncherIcon.h
@@ -68,6 +68,7 @@ public:
, type_(type)
, sort_priority_(DefaultPriority(type))
, remote_uri_("fake")
+ , is_tooltip_visible_(false)
{
tooltip_text = "Mock Icon";
position = Position::FLOATING;
@@ -80,7 +81,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) {}
@@ -366,6 +369,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/PointerBarrier.cpp b/launcher/PointerBarrier.cpp
index 1e3876c16..5d513c5b3 100644
--- a/launcher/PointerBarrier.cpp
+++ b/launcher/PointerBarrier.cpp
@@ -43,6 +43,8 @@ PointerBarrierWrapper::PointerBarrierWrapper()
, max_velocity_multiplier(1.0f)
, direction(BOTH)
, event_base_(0)
+ , last_event_(0)
+ , first_event_(false)
, barrier(0)
, smoothing_count_(0)
, smoothing_accum_(0)
@@ -114,12 +116,22 @@ void PointerBarrierWrapper::EmitCurrentData(int event_id, int x, int y)
return;
int velocity = std::min<int>(600 * max_velocity_multiplier, smoothing_accum_ / smoothing_count_);
+ SendBarrierEvent(x, y, velocity, event_id);
+
+ smoothing_accum_ = 0;
+ smoothing_count_ = 0;
+}
+
+void PointerBarrierWrapper::SendBarrierEvent(int x, int y, int velocity, int event_id)
+{
auto event = std::make_shared<BarrierEvent>(x, y, velocity, event_id);
barrier_event.emit(this, event);
+}
- smoothing_accum_ = 0;
- smoothing_count_ = 0;
+bool PointerBarrierWrapper::IsFirstEvent() const
+{
+ return first_event_;
}
bool PointerBarrierWrapper::HandleEvent(XEvent xevent)
@@ -138,9 +150,9 @@ bool PointerBarrierWrapper::HandleEvent(XEvent xevent)
/* If the barrier is released, just emit the current event without
* waiting, so there won't be any delay on releasing the barrier. */
smoothing_timeout_.reset();
- auto event = std::make_shared<BarrierEvent>(notify_event->x, notify_event->y,
- notify_event->velocity, notify_event->event_id);
- barrier_event.emit(this, event);
+
+ SendBarrierEvent(notify_event->x, notify_event->y,
+ notify_event->velocity, notify_event->event_id);
}
else if (!smoothing_timeout_)
{
@@ -148,15 +160,24 @@ bool PointerBarrierWrapper::HandleEvent(XEvent xevent)
int y = notify_event->y;
int event = notify_event->event_id;
- auto smoothing_cb = [&, event, x, y] ()
+ // If we are a new event, don't delay sending the first event
+ if (last_event_ != event)
{
+ first_event_ = true;
+ last_event_ = event;
+
+ SendBarrierEvent(notify_event->x, notify_event->y,
+ notify_event->velocity, notify_event->event_id);
+
+ first_event_ = false;
+ }
+
+ smoothing_timeout_.reset(new glib::Timeout(smoothing, [this, event, x, y] () {
EmitCurrentData(event, x, y);
smoothing_timeout_.reset();
return false;
- };
-
- smoothing_timeout_.reset(new glib::Timeout(smoothing, smoothing_cb));
+ }));
}
}
diff --git a/launcher/PointerBarrier.h b/launcher/PointerBarrier.h
index 7a796950d..6576c090e 100644
--- a/launcher/PointerBarrier.h
+++ b/launcher/PointerBarrier.h
@@ -86,6 +86,8 @@ public:
sigc::signal<void, PointerBarrierWrapper*, BarrierEvent::Ptr> barrier_event;
+ bool IsFirstEvent() const;
+
protected:
void EmitCurrentData(int event_id, int x, int y);
bool HandleEvent(XEvent event);
@@ -93,7 +95,11 @@ protected:
private:
static bool HandleEventWrapper(XEvent event, void* data);
+ void SendBarrierEvent(int x, int y, int velocity, int event_id);
+
int event_base_;
+ int last_event_;
+ bool first_event_;
PointerBarrier barrier;
int smoothing_count_;
diff --git a/launcher/StandaloneLauncher.cpp b/launcher/StandaloneLauncher.cpp
index ccc5e11e4..777951f6f 100644
--- a/launcher/StandaloneLauncher.cpp
+++ b/launcher/StandaloneLauncher.cpp
@@ -64,7 +64,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)});
diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp
index 684918cef..89922e006 100644
--- a/launcher/SwitcherController.cpp
+++ b/launcher/SwitcherController.cpp
@@ -139,6 +139,11 @@ SwitcherView::Ptr Controller::GetView() const
return impl_->GetView();
}
+bool Controller::IsDetailViewShown()
+{
+ return impl_->IsDetailViewShown();
+}
+
void Controller::SetDetail(bool value, unsigned int min_windows)
{
impl_->SetDetail(value, min_windows);
@@ -421,8 +426,9 @@ void Controller::Impl::Hide(bool accept_state)
Selection selection = GetCurrentSelection();
if (selection.application_)
{
+ Time timestamp = -1;
selection.application_->Activate(ActionArg(ActionArg::SWITCHER, 0,
- selection.window_));
+ timestamp, selection.window_));
}
}
@@ -520,6 +526,11 @@ SwitcherView::Ptr Controller::Impl::GetView() const
return view_;
}
+bool Controller::Impl::IsDetailViewShown()
+{
+ return model_ && model_->detail_selection();
+}
+
void Controller::Impl::SetDetail(bool value, unsigned int min_windows)
{
if (value && model_->DetailXids().size() >= min_windows)
diff --git a/launcher/SwitcherController.h b/launcher/SwitcherController.h
index 29c5b7e7c..f291b7182 100644
--- a/launcher/SwitcherController.h
+++ b/launcher/SwitcherController.h
@@ -98,6 +98,7 @@ public:
void Select(int index);
+ bool IsDetailViewShown();
void SetDetail(bool detail,
unsigned int min_windows = 1);
diff --git a/launcher/SwitcherControllerImpl.h b/launcher/SwitcherControllerImpl.h
index 5734f1b05..9a877e5d0 100644
--- a/launcher/SwitcherControllerImpl.h
+++ b/launcher/SwitcherControllerImpl.h
@@ -56,6 +56,7 @@ struct Controller::Impl
void NextDetail();
void PrevDetail();
+ bool IsDetailViewShown();
void SetDetail(bool detail, unsigned int min_windows = 1);
void SelectFirstItem();
diff --git a/launcher/SwitcherModel.cpp b/launcher/SwitcherModel.cpp
index afaec75fb..cb2d41a73 100644
--- a/launcher/SwitcherModel.cpp
+++ b/launcher/SwitcherModel.cpp
@@ -39,11 +39,18 @@ SwitcherModel::SwitcherModel(std::vector<AbstractLauncherIcon::Ptr> const& icons
, index_(0)
, last_index_(0)
{
+ // When using Webapps, there are more than one active icon, so let's just pick
+ // up the first one found which is the web browser.
+ bool found = false;
+
for (auto const& application : applications_)
{
AddChild(application.GetPointer());
- if (application->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE))
+ if (application->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE) && !found)
+ {
last_active_application_ = application;
+ found = true;
+ }
}
}
diff --git a/launcher/TooltipManager.cpp b/launcher/TooltipManager.cpp
new file mode 100644
index 000000000..c34783233
--- /dev/null
+++ b/launcher/TooltipManager.cpp
@@ -0,0 +1,126 @@
+// -*- 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>
+ */
+
+#include "TooltipManager.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+namespace
+{
+const unsigned int TOOLTIPS_SHOW_TIMEOUT_LENGTH = 1000;
+}
+
+TooltipManager::TooltipManager()
+ : show_tooltips_(false)
+ , hovered_(false)
+ , timer_locked_(false)
+{}
+
+void TooltipManager::SetIcon(AbstractLauncherIcon::Ptr const& newIcon)
+{
+ if (icon_ == newIcon)
+ return;
+
+ // Unlock hover timer, in case the previous icon had no valid tooltip
+ timer_locked_ = false;
+
+ if (show_tooltips_)
+ {
+ // Show new tooltip, get rid of the old olne
+ if (icon_)
+ icon_->HideTooltip();
+ if (newIcon)
+ newIcon->ShowTooltip();
+ }
+ else if (!newIcon)
+ {
+ // Stop the hover timer for null launcher space
+ StopTimer();
+ }
+ else
+ {
+ AbstractLauncherIcon::IconType type = newIcon->GetIconType();
+ if ((type == AbstractLauncherIcon::IconType::HOME ||
+ type == AbstractLauncherIcon::IconType::HUD) &&
+ newIcon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE))
+ {
+ // Lock the hover timer for no valid tooltip cases
+ timer_locked_ = true;
+ StopTimer();
+ }
+ }
+
+ icon_ = newIcon;
+}
+
+void TooltipManager::SetHover(bool on_launcher)
+{
+ if (hovered_ == on_launcher)
+ return;
+ hovered_ = on_launcher;
+
+ if (show_tooltips_ && !hovered_)
+ {
+ show_tooltips_ = false;
+ if (icon_)
+ icon_->HideTooltip();
+ }
+}
+
+void TooltipManager::MouseMoved()
+{
+ if (!icon_ || show_tooltips_)
+ return;
+
+ ResetTimer();
+}
+
+void TooltipManager::IconClicked()
+{
+ StopTimer();
+ if (show_tooltips_ && icon_)
+ icon_->HideTooltip();
+
+ show_tooltips_ = false;
+ timer_locked_ = true;
+}
+
+void TooltipManager::ResetTimer()
+{
+ if (timer_locked_)
+ return;
+
+ hover_timer_.reset(new glib::Timeout(TOOLTIPS_SHOW_TIMEOUT_LENGTH));
+ hover_timer_->Run([&] () {
+ show_tooltips_ = true;
+ icon_->ShowTooltip();
+ return false;
+ });
+}
+
+void TooltipManager::StopTimer()
+{
+ hover_timer_.reset();
+}
+
+} // namespace launcher
+} // namespace unity
diff --git a/launcher/TooltipManager.h b/launcher/TooltipManager.h
new file mode 100644
index 000000000..f61fc199f
--- /dev/null
+++ b/launcher/TooltipManager.h
@@ -0,0 +1,57 @@
+// -*- 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>
+ */
+
+#ifndef TOOLTIPMANAGER
+#define TOOLTIPMANAGER
+
+#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 on_launcher);
+ void SetIcon(AbstractLauncherIcon::Ptr const& newIcon);
+ void MouseMoved();
+ void IconClicked();
+
+private:
+ void ResetTimer();
+ void StopTimer();
+
+ bool show_tooltips_;
+ bool hovered_;
+ AbstractLauncherIcon::Ptr icon_;
+ glib::Source::UniquePtr hover_timer_;
+ bool timer_locked_;
+};
+
+} // namespace launcher
+} // namespace unity
+
+#endif
diff --git a/launcher/XdndCollectionWindowImp.cpp b/launcher/XdndCollectionWindowImp.cpp
index e39f373a7..b98075187 100644
--- a/launcher/XdndCollectionWindowImp.cpp
+++ b/launcher/XdndCollectionWindowImp.cpp
@@ -40,9 +40,14 @@ public:
ShowWindow(true);
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));
@@ -100,13 +105,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");
}
}