diff options
| author | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2013-11-14 19:50:58 +0100 |
|---|---|---|
| committer | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2013-11-14 19:50:58 +0100 |
| commit | 3ae2655c7dfd44b22f8b4319e0aa6baeaace2554 (patch) | |
| tree | aff915dd9d171e111f98cce09f18a66dae116857 /launcher | |
| parent | eaa4e9347d032bc2347a2d228ad85e411735453f (diff) | |
| parent | 1fd5b35de006d9881b744ecd25dbf18d3d44b303 (diff) | |
Merging with lp:~3v1n0/unity/gl-bottleneck-fix
(bzr r3347.5.8)
Diffstat (limited to 'launcher')
68 files changed, 2941 insertions, 2459 deletions
diff --git a/launcher/AbstractLauncherIcon.cpp b/launcher/AbstractLauncherIcon.cpp index 0c647ac54..ae3ebd042 100644 --- a/launcher/AbstractLauncherIcon.cpp +++ b/launcher/AbstractLauncherIcon.cpp @@ -21,6 +21,8 @@ namespace unity { namespace launcher { + nux::Property<unsigned> AbstractLauncherIcon::icon_size(48); + // needed for ungodly stupid reasons NUX_IMPLEMENT_OBJECT_TYPE(AbstractLauncherIcon); } diff --git a/launcher/AbstractLauncherIcon.h b/launcher/AbstractLauncherIcon.h index 0166bc52f..0b586ec90 100644 --- a/launcher/AbstractLauncherIcon.h +++ b/launcher/AbstractLauncherIcon.h @@ -47,6 +47,7 @@ struct ActionArg enum class Source { LAUNCHER, + LAUNCHER_KEYBINDING, SWITCHER, OTHER, }; @@ -111,11 +112,8 @@ public: SHIMMER, CENTER_SAVED, PROGRESS, - DROP_PRELIGHT, - DROP_DIM, DESAT, PULSE_ONCE, - LAST_ACTION, LAST }; @@ -133,8 +131,9 @@ public: DOWN }; - virtual ~AbstractLauncherIcon() {} + virtual ~AbstractLauncherIcon() = default; + static nux::Property<unsigned> icon_size; nux::Property<std::string> tooltip_text; nux::Property<bool> tooltip_enabled; nux::Property<Position> position; @@ -152,7 +151,9 @@ public: virtual bool OpenQuicklist(bool select_first_item = false, int monitor = -1) = 0; virtual void CloseQuicklist() = 0; - virtual void SetCenter(nux::Point3 const& center, int monitor, nux::Geometry const& parent_geo) = 0; + virtual void SetCenter(nux::Point3 const& center, int monitor) = 0; + + virtual void ResetCenters(int monitor = -1) = 0; virtual nux::Point3 GetCenter(int monitor) = 0; @@ -185,17 +186,19 @@ public: virtual uint64_t SwitcherPriority() = 0; - virtual bool GetQuirk(Quirk quirk) const = 0; + virtual bool GetQuirk(Quirk quirk, int monitor = -1) const = 0; + + virtual void SetQuirk(Quirk quirk, bool value, int monitor = -1) = 0; - virtual void SetQuirk(Quirk quirk, bool value) = 0; + virtual float GetQuirkProgress(Quirk quirk, int monitor) const = 0; - virtual struct timespec GetQuirkTime(Quirk quirk) = 0; + virtual void SetQuirkDuration(Quirk quirk, unsigned duration, int monitor = -1) = 0; - virtual void ResetQuirkTime(Quirk quirk) = 0; + virtual void SkipQuirkAnimation(Quirk quirk, int monitor = -1) = 0; virtual IconType GetIconType() const = 0; - virtual std::string RemoteUri() = 0; + virtual std::string RemoteUri() const = 0; virtual MenuItemsVector Menus() = 0; @@ -212,7 +215,7 @@ public: virtual void InsertEntryRemote(LauncherEntryRemote::Ptr const& remote) = 0; virtual void RemoveEntryRemote(LauncherEntryRemote::Ptr const& remote) = 0; - virtual std::string DesktopFile() = 0; + virtual std::string DesktopFile() const = 0; virtual bool IsSticky() const = 0; @@ -241,12 +244,13 @@ public: sigc::signal<void, int> mouse_enter; sigc::signal<void, int> mouse_leave; - sigc::signal<void, AbstractLauncherIcon::Ptr const&> needs_redraw; + sigc::signal<void, AbstractLauncherIcon::Ptr const&, int> needs_redraw; sigc::signal<void, AbstractLauncherIcon::Ptr const&> remove; sigc::signal<void, nux::ObjectPtr<nux::View>> tooltip_visible; - sigc::signal<void> visibility_changed; + sigc::signal<void, int> visibility_changed; sigc::signal<void> position_saved; sigc::signal<void> position_forgot; + sigc::signal<void, std::string const&> uri_changed; connection::Wrapper on_icon_removed_connection; }; diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp index 0a6ed3761..b5b5c8836 100644 --- a/launcher/ApplicationLauncherIcon.cpp +++ b/launcher/ApplicationLauncherIcon.cpp @@ -18,6 +18,7 @@ * Marco Trevisan (Treviño) <3v1n0@ubuntu.com> */ +#include "config.h" #include <boost/algorithm/string.hpp> #include <Nux/Nux.h> @@ -30,16 +31,14 @@ #include "ApplicationLauncherIcon.h" #include "FavoriteStore.h" -#include "Launcher.h" #include "MultiMonitor.h" +#include "unity-shared/DesktopApplicationManager.h" #include "unity-shared/GnomeFileManager.h" #include "unity-shared/UBusMessages.h" #include <glib/gi18n-lib.h> #include <gio/gdesktopappinfo.h> -#include <libbamf/bamf-tab.h> - namespace unity { namespace launcher @@ -75,19 +74,6 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app) , use_custom_bg_color_(false) , bg_color_(nux::color::White) { - app->seen = true; - - tooltip_text = app->title(); - std::string const& icon = app->icon(); - icon_name = (icon.empty() ? DEFAULT_ICON : icon); - - SetQuirk(Quirk::VISIBLE, app->visible()); - SetQuirk(Quirk::ACTIVE, app->active()); - SetQuirk(Quirk::RUNNING, app->running()); - // Make sure we set the LauncherIcon stick bit too... - if (app->sticky()) - SimpleLauncherIcon::Stick(false); // don't emit the signal - LOG_INFO(logger) << "Created ApplicationLauncherIcon: " << tooltip_text() << ", icon: " << icon_name() @@ -105,21 +91,16 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app) wm.terminate_expo.connect(sigc::mem_fun(this, &ApplicationLauncherIcon::EnsureWindowState)); EnsureWindowState(); - UpdateMenus(); - UpdateDesktopFile(); - UpdateBackgroundColor(); - - // hack - SetProgress(0.0f); } ApplicationLauncherIcon::~ApplicationLauncherIcon() { - if (app_) - { - app_->sticky = false; - app_->seen = false; - } + UnsetApplication(); +} + +ApplicationPtr ApplicationLauncherIcon::GetApplication() const +{ + return app_; } void ApplicationLauncherIcon::SetApplication(ApplicationPtr const& app) @@ -127,9 +108,46 @@ void ApplicationLauncherIcon::SetApplication(ApplicationPtr const& app) if (app_ == app) return; + if (!app) + { + Remove(); + return; + } + + bool was_sticky = IsSticky(); + UnsetApplication(); + app_ = app; - signals_conn_.Clear(); + app_->seen = true; SetupApplicationSignalsConnections(); + + // Let's update the icon properties to match the new application ones + app_->title.changed.emit(app_->title()); + app_->icon.changed.emit(app_->icon()); + app_->visible.changed.emit(app_->visible()); + app_->active.changed.emit(app_->active()); + app_->running.changed.emit(app_->running()); + app_->desktop_file.changed.emit(app_->desktop_file()); + + // Make sure we set the LauncherIcon stick bit too... + if (app_->sticky() || was_sticky) + Stick(false); // don't emit the signal +} + +void ApplicationLauncherIcon::UnsetApplication() +{ + if (!app_ || removed()) + return; + + /* Removing the unity-seen flag to the wrapped bamf application, on remove + * request we make sure that if the application is re-opened while the + * removal process is still ongoing, the application will be shown on the + * launcher. Disconnecting from signals we make sure that this icon won't be + * updated or will change visibility (no duplicated icon). */ + + signals_conn_.Clear(); + app_->sticky = false; + app_->seen = false; } void ApplicationLauncherIcon::SetupApplicationSignalsConnections() @@ -138,7 +156,6 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections() // is only ever removed when the application is closed. signals_conn_.Add(app_->window_opened.connect([this](ApplicationWindow const&) { EnsureWindowState(); - UpdateMenus(); UpdateIconGeometries(GetCenters()); })); @@ -155,6 +172,11 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections() SetQuirk(Quirk::ACTIVE, active); })); + signals_conn_.Add(app_->desktop_file.changed.connect([this](std::string const& desktop_file) { + LOG_DEBUG(logger) << tooltip_text() << " desktop_file now " << desktop_file; + UpdateDesktopFile(); + })); + signals_conn_.Add(app_->title.changed.connect([this](std::string const& name) { LOG_DEBUG(logger) << tooltip_text() << " name now " << name; if (_menu_items.size() == MenuItemType::SIZE) @@ -181,14 +203,14 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections() })); signals_conn_.Add(app_->visible.changed.connect([this](bool const& visible) { - if (!IsSticky()) - SetQuirk(Quirk::VISIBLE, visible); + SetQuirk(Quirk::VISIBLE, IsSticky() ? true : visible); })); signals_conn_.Add(app_->closed.connect([this]() { if (!IsSticky()) { SetQuirk(Quirk::VISIBLE, false); + HideTooltip(); /* Use a timeout to remove the icon, this avoids * that we remove an application that is going @@ -204,11 +226,11 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections() })); } -bool ApplicationLauncherIcon::GetQuirk(AbstractLauncherIcon::Quirk quirk) const +bool ApplicationLauncherIcon::GetQuirk(AbstractLauncherIcon::Quirk quirk, int monitor) const { if (quirk == Quirk::ACTIVE) { - if (!SimpleLauncherIcon::GetQuirk(Quirk::ACTIVE)) + if (!SimpleLauncherIcon::GetQuirk(Quirk::ACTIVE, monitor)) return false; if (app_->type() == "webapp") @@ -217,35 +239,24 @@ bool ApplicationLauncherIcon::GetQuirk(AbstractLauncherIcon::Quirk quirk) const // Sometimes BAMF is not fast enough to update the active application // while quickly switching between apps, so we double check that the // real active window is part of the selection (see bug #1111620) - Window active = WindowManager::Default().GetActiveWindow(); - - for (auto& window : app_->GetWindows()) - if (window->window_id() == active) - return true; - - return false; + return app_->OwnsWindow(WindowManager::Default().GetActiveWindow()); } - return SimpleLauncherIcon::GetQuirk(quirk); + return SimpleLauncherIcon::GetQuirk(quirk, monitor); } void ApplicationLauncherIcon::Remove() { - /* Removing the unity-seen flag to the wrapped bamf application, on remove - * request we make sure that if the application is re-opened while the - * removal process is still ongoing, the application will be shown on the - * launcher. Disconnecting from signals we make sure that this icon won't be - * reused (no duplicated icon). */ - app_->seen = false; - // Disconnect all our callbacks. - notify_callbacks(); // This is from sigc++::trackable + LogUnityEvent(ApplicationEventType::LEAVE); + UnsetApplication(); SimpleLauncherIcon::Remove(); } bool ApplicationLauncherIcon::IsSticky() const { if (app_) - return app_->sticky(); + return app_->sticky() && SimpleLauncherIcon::IsSticky(); + return false; } @@ -301,7 +312,7 @@ void ApplicationLauncherIcon::ActivateLauncherIcon(ActionArg arg) bool any_on_monitor = (arg.monitor < 0); int active_monitor = arg.monitor; - for (auto& window : app_->GetWindows()) + for (auto const& window : app_->GetWindows()) { Window xid = window->window_id(); @@ -480,11 +491,21 @@ std::vector<Window> ApplicationLauncherIcon::WindowsForMonitor(int monitor) void ApplicationLauncherIcon::OnWindowMinimized(guint32 xid) { - if (!app_->OwnsWindow(xid)) - return; + for (auto const& window: app_->GetWindows()) + { + if (xid == window->window_id()) + { + int monitor = GetCenterForMonitor(window->monitor()).first; + + if (monitor >= 0) + { + Present(0.5f, 600, monitor); + FullyAnimateQuirkDelayed(300, Quirk::SHIMMER, monitor); + } - Present(0.5f, 600); - UpdateQuirkTimeDelayed(300, Quirk::SHIMMER); + break; + } + } } void ApplicationLauncherIcon::OnWindowMoved(guint32 moved_win) @@ -504,17 +525,21 @@ void ApplicationLauncherIcon::UpdateDesktopFile() { std::string const& filename = app_->desktop_file(); - if (!filename.empty() && _desktop_file != filename) - { - _desktop_file = filename; + if (_desktop_file_monitor) + _gsignals.Disconnect(_desktop_file_monitor, "changed"); + auto old_uri = RemoteUri(); + UpdateRemoteUri(); + UpdateDesktopQuickList(); + UpdateBackgroundColor(); + auto const& new_uri = RemoteUri(); + + if (!filename.empty()) + { // add a file watch to the desktop file so that if/when the app is removed // we can remove ourself from the launcher and when it's changed // we can update the quicklist. - if (_desktop_file_monitor) - _gsignals.Disconnect(_desktop_file_monitor, "changed"); - - glib::Object<GFile> desktop_file(g_file_new_for_path(_desktop_file.c_str())); + glib::Object<GFile> desktop_file(g_file_new_for_path(filename.c_str())); _desktop_file_monitor = g_file_monitor_file(desktop_file, G_FILE_MONITOR_NONE, nullptr, nullptr); g_file_monitor_set_rate_limit(_desktop_file_monitor, 2000); @@ -527,8 +552,11 @@ void ApplicationLauncherIcon::UpdateDesktopFile() { glib::Object<GFile> file(f, glib::AddRef()); _source_manager.AddTimeoutSeconds(1, [this, file] { - if (!g_file_query_exists (file, nullptr)) + if (!g_file_query_exists(file, nullptr)) + { UnStick(); + LogUnityEvent(ApplicationEventType::DELETE); + } return false; }); break; @@ -544,12 +572,28 @@ void ApplicationLauncherIcon::UpdateDesktopFile() } }); } + else if (app_->sticky()) + { + UnStick(); + } + + if (old_uri != new_uri) + { + bool update_saved_uri = (!filename.empty() && app_->sticky()); + + if (update_saved_uri) + SimpleLauncherIcon::UnStick(); + + uri_changed.emit(new_uri); + + if (update_saved_uri) + Stick(); + } } -std::string ApplicationLauncherIcon::DesktopFile() +std::string ApplicationLauncherIcon::DesktopFile() const { - UpdateDesktopFile(); - return _desktop_file; + return app_->desktop_file(); } void ApplicationLauncherIcon::AddProperties(GVariantBuilder* builder) @@ -559,12 +603,12 @@ void ApplicationLauncherIcon::AddProperties(GVariantBuilder* builder) GVariantBuilder xids_builder; g_variant_builder_init(&xids_builder, G_VARIANT_TYPE ("au")); - for (auto& window : GetWindows()) + for (auto const& window : GetWindows()) g_variant_builder_add(&xids_builder, "u", window->window_id()); variant::BuilderWrapper(builder) .add("desktop_file", DesktopFile()) - .add("desktop_id", GetDesktopID()) + .add("desktop_id", app_->desktop_id()) .add("xids", g_variant_builder_end(&xids_builder)) .add("sticky", IsSticky()) .add("startup_notification_timestamp", (uint64_t)_startup_notification_timestamp); @@ -616,7 +660,7 @@ void ApplicationLauncherIcon::OpenInstanceWithUris(std::set<std::string> const& LOG_WARN(logger) << error; } - UpdateQuirkTime(Quirk::STARTING); + FullyAnimateQuirk(Quirk::STARTING); } void ApplicationLauncherIcon::OpenInstanceLauncherIcon(Time timestamp) @@ -657,8 +701,7 @@ bool ApplicationLauncherIcon::Spread(bool current_desktop, int state, bool force void ApplicationLauncherIcon::EnsureWindowState() { - std::vector<bool> monitors; - monitors.resize(max_num_monitors); + std::bitset<monitors::MAX> monitors; for (auto& window: app_->GetWindows()) { @@ -670,35 +713,37 @@ void ApplicationLauncherIcon::EnsureWindowState() // If monitor is -1 (or negative), show on all monitors. if (monitor < 0) { - for (int j = 0; j < max_num_monitors; j++) - monitors[j] = true; + monitors.set(); + break; } else + { monitors[monitor] = true; + } } } - for (int i = 0; i < max_num_monitors; i++) + for (unsigned i = 0; i < monitors::MAX; i++) SetWindowVisibleOnMonitor(monitors[i], i); - - EmitNeedsRedraw(); } void ApplicationLauncherIcon::UpdateDesktopQuickList() { std::string const& desktop_file = DesktopFile(); - if (desktop_file.empty()) - return; - if (_menu_desktop_shortcuts) { for (GList *l = dbusmenu_menuitem_get_children(_menu_desktop_shortcuts); l; l = l->next) { _gsignals.Disconnect(l->data, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED); } + + _menu_desktop_shortcuts = nullptr; } + if (desktop_file.empty()) + return; + _menu_desktop_shortcuts = dbusmenu_menuitem_new(); dbusmenu_menuitem_set_root(_menu_desktop_shortcuts, TRUE); @@ -710,8 +755,7 @@ void ApplicationLauncherIcon::UpdateDesktopQuickList() // any or they're filtered for the environment we're in const gchar** nicks = indicator_desktop_shortcuts_get_nicks(_desktop_shortcuts); - int index = 0; - while (nicks[index]) + for (int index = 0; nicks[index]; ++index) { // Build a dbusmenu item for each nick that is the desktop // file that is built from it's name and includes a callback @@ -722,7 +766,7 @@ 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); - std::string nick(nicks[index]); + auto nick = glib::gchar_to_string(nicks[index]); _gsignals.Add<void, DbusmenuMenuitem*, gint>(item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this, nick] (DbusmenuMenuitem* item, unsigned timestamp) { @@ -734,7 +778,6 @@ void ApplicationLauncherIcon::UpdateDesktopQuickList() }); dbusmenu_menuitem_child_append(_menu_desktop_shortcuts, item); - index++; } } @@ -752,7 +795,9 @@ void ApplicationLauncherIcon::UpdateBackgroundColor() if (last_use_custom_bg_color != use_custom_bg_color_ || last_bg_color != bg_color_) + { EmitNeedsRedraw(); + } } void ApplicationLauncherIcon::EnsureMenuItemsWindowsReady() @@ -765,17 +810,19 @@ void ApplicationLauncherIcon::EnsureMenuItemsWindowsReady() // We only add quicklist menu-items for windows if we have more than one window if (windows.size() < 2) return; - + Window active = WindowManager::Default().GetActiveWindow(); // add menu items for all open windows for (auto const& w : windows) { - if (w->title().empty()) + auto const& title = w->title(); + + if (title.empty()) continue; glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new()); - dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, w->title().c_str()); + dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, title.c_str()); dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true); dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); dbusmenu_menuitem_property_set_bool(menu_item, QuicklistMenuItem::MARKUP_ACCEL_DISABLED_PROPERTY, true); @@ -788,7 +835,7 @@ void ApplicationLauncherIcon::EnsureMenuItemsWindowsReady() wm.Activate(xid); wm.Raise(xid); }); - + if (xid == active) { dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_RADIO); @@ -799,7 +846,7 @@ void ApplicationLauncherIcon::EnsureMenuItemsWindowsReady() } } -void ApplicationLauncherIcon::UpdateMenus() +void ApplicationLauncherIcon::EnsureMenuItemsStaticQuicklist() { // make a client for desktop file actions if (!_menu_desktop_shortcuts.IsType(DBUSMENU_TYPE_MENUITEM)) @@ -821,22 +868,33 @@ void ApplicationLauncherIcon::AboutToRemove() void ApplicationLauncherIcon::Stick(bool save) { - if (IsSticky()) + if (IsSticky() && !save) return; app_->sticky = true; - SimpleLauncherIcon::Stick(save); + + if (RemoteUri().empty()) + { + if (save) + app_->CreateLocalDesktopFile(); + } + else + { + SimpleLauncherIcon::Stick(save); + + if (save) + LogUnityEvent(ApplicationEventType::ACCESS); + } } void ApplicationLauncherIcon::UnStick() { - SimpleLauncherIcon::UnStick(); - if (!IsSticky()) return; - SetQuirk(Quirk::VISIBLE, app_->running()); - + LogUnityEvent(ApplicationEventType::ACCESS); + SimpleLauncherIcon::UnStick(); + SetQuirk(Quirk::VISIBLE, app_->visible()); app_->sticky = false; if (!app_->running()) @@ -855,6 +913,28 @@ void ApplicationLauncherIcon::ToggleSticky() } } +void ApplicationLauncherIcon::LogUnityEvent(ApplicationEventType type) +{ + if (RemoteUri().empty()) + return; + + auto const& unity_app = ApplicationManager::Default().GetUnityApplication(); + unity_app->LogEvent(type, GetSubject()); +} + +ApplicationSubjectPtr ApplicationLauncherIcon::GetSubject() +{ + auto subject = std::make_shared<desktop::ApplicationSubject>(); + subject->uri = RemoteUri(); + subject->current_uri = subject->uri(); + subject->interpretation = ZEITGEIST_NFO_SOFTWARE; + subject->manifestation = ZEITGEIST_NFO_SOFTWARE_ITEM; + subject->mimetype = "application/x-desktop"; + subject->text = tooltip_text(); + + return subject; +} + void ApplicationLauncherIcon::EnsureMenuItemsDefaultReady() { if (_menu_items.size() == MenuItemType::SIZE) @@ -902,7 +982,7 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus() bool separator_needed = false; EnsureMenuItemsDefaultReady(); - UpdateMenus(); + EnsureMenuItemsStaticQuicklist(); for (auto const& menus : {GetRemoteMenus(), _menu_desktop_shortcuts}) { @@ -1004,70 +1084,52 @@ AbstractLauncherIcon::MenuItemsVector ApplicationLauncherIcon::GetMenus() return result; } -void ApplicationLauncherIcon::UpdateIconGeometries(std::vector<nux::Point3> center) +void ApplicationLauncherIcon::UpdateIconGeometries(std::vector<nux::Point3> const& centers) { if (app_->type() == "webapp") return; - nux::Geometry geo; - - // TODO: replace 48 with icon_size; - geo.width = 48; - geo.height = 48; + nux::Geometry geo(0, 0, icon_size, icon_size); for (auto& window : app_->GetWindows()) { Window xid = window->window_id(); - int monitor = window->monitor(); - monitor = std::max<int>(0, std::min<int>(center.size() - 1, monitor)); + int monitor = GetCenterForMonitor(window->monitor()).first; - // TODO: replace 24 with icon_size / 2; - geo.x = center[monitor].x - 24; - geo.y = center[monitor].y - 24; + if (monitor < 0) + { + WindowManager::Default().SetWindowIconGeometry(xid, nux::Geometry()); + continue; + } + + geo.x = centers[monitor].x - icon_size / 2; + geo.y = centers[monitor].y - icon_size / 2; WindowManager::Default().SetWindowIconGeometry(xid, geo); } } -void ApplicationLauncherIcon::OnCenterStabilized(std::vector<nux::Point3> center) +void ApplicationLauncherIcon::OnCenterStabilized(std::vector<nux::Point3> const& centers) { - UpdateIconGeometries(center); -} - -std::string ApplicationLauncherIcon::GetDesktopID() -{ - std::string const& desktop_file = DesktopFile(); - - return DesktopUtilities::GetDesktopID(desktop_file); + UpdateIconGeometries(centers); } void ApplicationLauncherIcon::UpdateRemoteUri() { - std::string const& desktop_id = GetDesktopID(); - - if (!desktop_id.empty()) - { - _remote_uri = FavoriteStore::URI_PREFIX_APP + desktop_id; - } -} + std::string const& desktop_id = app_->desktop_id(); -std::string ApplicationLauncherIcon::GetRemoteUri() -{ - if (_remote_uri.empty()) + if (!desktop_id.empty()) { - UpdateRemoteUri(); + _remote_uri = FavoriteStore::URI_PREFIX_APP + desktop_id; + } + else + { + _remote_uri.clear(); } - - return _remote_uri; } -std::set<std::string> ApplicationLauncherIcon::ValidateUrisForLaunch(DndData const& uris) +std::string ApplicationLauncherIcon::GetRemoteUri() const { - std::set<std::string> result; - - for (auto uri : uris.Uris()) - result.insert(uri); - - return result; + return _remote_uri; } void ApplicationLauncherIcon::OnDndHovered() @@ -1107,7 +1169,7 @@ bool ApplicationLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data) { if (IsFileManager()) { - for (auto uri : dnd_data.Uris()) + for (auto const& uri : dnd_data.Uris()) { if (boost::algorithm::starts_with(uri, "file://")) return true; @@ -1133,7 +1195,7 @@ bool ApplicationLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data) nux::DndAction ApplicationLauncherIcon::OnQueryAcceptDrop(DndData const& dnd_data) { #ifdef USE_X11 - return ValidateUrisForLaunch(dnd_data).empty() ? nux::DNDACTION_NONE : nux::DNDACTION_COPY; + return dnd_data.Uris().empty() ? nux::DNDACTION_NONE : nux::DNDACTION_COPY; #else return nux::DNDACTION_NONE; #endif @@ -1142,7 +1204,7 @@ nux::DndAction ApplicationLauncherIcon::OnQueryAcceptDrop(DndData const& dnd_dat void ApplicationLauncherIcon::OnAcceptDrop(DndData const& dnd_data) { auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; - OpenInstanceWithUris(ValidateUrisForLaunch(dnd_data), timestamp); + OpenInstanceWithUris(dnd_data.Uris(), timestamp); } bool ApplicationLauncherIcon::ShowInSwitcher(bool current) @@ -1158,7 +1220,7 @@ bool ApplicationLauncherIcon::ShowInSwitcher(bool current) } else { - for (int i = 0; i < max_num_monitors; ++i) + for (unsigned i = 0; i < monitors::MAX; ++i) { if (WindowVisibleOnMonitor(i)) { @@ -1265,7 +1327,7 @@ void ApplicationLauncherIcon::PerformScroll(ScrollDirection direction, Time time } if (windows.size() <= 1) - return; + return; ++_progressive_scroll; _progressive_scroll %= windows.size(); diff --git a/launcher/ApplicationLauncherIcon.h b/launcher/ApplicationLauncherIcon.h index eb788ffd7..4aed11e48 100644 --- a/launcher/ApplicationLauncherIcon.h +++ b/launcher/ApplicationLauncherIcon.h @@ -45,14 +45,14 @@ public: virtual void ActivateLauncherIcon(ActionArg arg); - std::string DesktopFile(); + std::string DesktopFile() const; bool IsSticky() const; bool IsActive() const; bool IsRunning() const; bool IsUrgent() const; - virtual bool GetQuirk(Quirk quirk) const; + virtual bool GetQuirk(Quirk quirk, int monitor = 0) const override; virtual void Quit(); virtual void AboutToRemove(); @@ -74,9 +74,11 @@ public: protected: void SetApplication(ApplicationPtr const& app); + ApplicationPtr GetApplication() const; + void Remove(); - void UpdateIconGeometries(std::vector<nux::Point3> center); - void OnCenterStabilized(std::vector<nux::Point3> center); + void UpdateIconGeometries(std::vector<nux::Point3> const& centers); + void OnCenterStabilized(std::vector<nux::Point3> const& centers); void AddProperties(GVariantBuilder* builder); void OnAcceptDrop(DndData const& dnd_data); void OnDndEnter(); @@ -84,15 +86,15 @@ protected: void OnDndLeave(); void OpenInstanceLauncherIcon(Time timestamp) override; void ToggleSticky(); + void LogUnityEvent(ApplicationEventType); bool IsFileManager(); bool OnShouldHighlightOnDrag(DndData const& dnd_data); nux::DndAction OnQueryAcceptDrop(DndData const& dnd_data); MenuItemsVector GetMenus(); - std::set<std::string> ValidateUrisForLaunch(DndData const& dnd_data); - std::string GetRemoteUri(); + std::string GetRemoteUri() const; bool HandlesSpread() { return true; } std::string GetName() const; @@ -111,12 +113,13 @@ private: ON_ALL_MONITORS = (1 << 3), }; + void UnsetApplication(); void SetupApplicationSignalsConnections(); void EnsureWindowState(); void EnsureMenuItemsWindowsReady(); void EnsureMenuItemsDefaultReady(); + void EnsureMenuItemsStaticQuicklist(); void UpdateBackgroundColor(); - void UpdateMenus(); void UpdateDesktopQuickList(); void OpenInstanceWithUris(std::set<std::string> const& uris, Time timestamp); @@ -128,8 +131,8 @@ private: WindowList GetWindows(WindowFilterMask filter = 0, int monitor = -1); const std::set<std::string> GetSupportedTypes(); - std::string GetDesktopID(); WindowList GetWindowsOnCurrentDesktopInStackingOrder(); + ApplicationSubjectPtr GetSubject(); ApplicationPtr app_; std::string _remote_uri; diff --git a/launcher/BFBLauncherIcon.cpp b/launcher/BFBLauncherIcon.cpp index 4480abede..15fe55cd3 100644 --- a/launcher/BFBLauncherIcon.cpp +++ b/launcher/BFBLauncherIcon.cpp @@ -23,7 +23,6 @@ #include "unity-shared/UBusMessages.h" #include "BFBLauncherIcon.h" -#include "Launcher.h" namespace unity { @@ -39,7 +38,7 @@ BFBLauncherIcon::BFBLauncherIcon(LauncherHideMode hide_mode) icon_name = PKGDATADIR"/launcher_bfb.png"; position = Position::BEGIN; SetQuirk(Quirk::VISIBLE, true); - SetQuirk(Quirk::RUNNING, false); + SkipQuirkAnimation(Quirk::VISIBLE); background_color_ = nux::color::White; @@ -65,8 +64,7 @@ void BFBLauncherIcon::OnOverlayShown(GVariant *data, bool visible) if (overlay_identity.Str() == "dash" && IsVisibleOnMonitor(overlay_monitor)) { tooltip_enabled = !visible; - SetQuirk(Quirk::ACTIVE, visible); - EmitNeedsRedraw(); + SetQuirk(Quirk::ACTIVE, visible, overlay_monitor); } // If the hud is open, we hide the BFB if we have a locked launcher else if (overlay_identity.Str() == "hud") @@ -74,7 +72,7 @@ void BFBLauncherIcon::OnOverlayShown(GVariant *data, bool visible) if (launcher_hide_mode_ == LAUNCHER_HIDE_NEVER) { SetVisibleOnMonitor(overlay_monitor, !visible); - EmitNeedsRedraw(); + SkipQuirkAnimation(Quirk::VISIBLE, overlay_monitor); } } } diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 86b774269..f832a23e9 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -81,6 +81,7 @@ target_link_libraries (launcher-lib unity-shared) add_pch(pch/launcher_pch.hh launcher-lib) set (SWITCHER_SOURCES + DeltaTracker.cpp SwitcherController.cpp SwitcherModel.cpp SwitcherView.cpp diff --git a/launcher/CairoBaseWindow.cpp b/launcher/CairoBaseWindow.cpp index cb86414c7..d26ce8706 100644 --- a/launcher/CairoBaseWindow.cpp +++ b/launcher/CairoBaseWindow.cpp @@ -21,6 +21,7 @@ #include <Nux/Nux.h> #include <Nux/WindowCompositor.h> +#include "unity-shared/AnimationUtils.h" #include "unity-shared/CairoTexture.h" #include "unity-shared/UnitySettings.h" #include "CairoBaseWindow.h" @@ -36,21 +37,41 @@ namespace const int TEXT_PADDING = 8; const int MINIMUM_TEXT_WIDTH = 100; const int TOP_SIZE = 0; + const int FADE_DURATION = 80; } NUX_IMPLEMENT_OBJECT_TYPE(CairoBaseWindow); -CairoBaseWindow::CairoBaseWindow() : - use_blur_(!Settings::Instance().GetLowGfxMode()), - _use_blurred_background(use_blur_), - _compute_blur_bkg(use_blur_) +CairoBaseWindow::CairoBaseWindow() + : use_blurred_background_(!Settings::Instance().GetLowGfxMode()) + , compute_blur_bkg_(use_blurred_background_) + , fade_animator_(FADE_DURATION) { SetWindowSizeMatchLayout(true); + sigVisible.connect([this] (BaseWindow*) { compute_blur_bkg_ = true; }); + + fade_animator_.updated.connect(sigc::mem_fun(this, &BaseWindow::SetOpacity)); + fade_animator_.finished.connect([this] { + if (animation::GetDirection(fade_animator_) == animation::Direction::BACKWARD) + ShowWindow(false); + }); } -CairoBaseWindow::~CairoBaseWindow() +void CairoBaseWindow::Show() { - // nothing to do + animation::StartOrReverse(fade_animator_, animation::Direction::FORWARD); + ShowWindow(true); + PushToFront(); +} + +void CairoBaseWindow::Hide() +{ + animation::StartOrReverse(fade_animator_, animation::Direction::BACKWARD); +} + +bool CairoBaseWindow::HasBlurredBackground() const +{ + return use_blurred_background_; } void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) @@ -58,7 +79,7 @@ void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) nux::Geometry base(GetGeometry()); // Get the background and apply some blur - if (_use_blurred_background && _compute_blur_bkg) + if (use_blurred_background_ && compute_blur_bkg_) { auto current_fbo = nux::GetGraphicsDisplay()->GetGpuDevice()->GetCurrentFrameBufferObject(); nux::GetWindowCompositor ().RestoreMainFramebuffer(); @@ -83,7 +104,7 @@ void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) gfxContext.Push2DWindow(gfxContext.GetWindowWidth(), gfxContext.GetWindowHeight()); gfxContext.ApplyClippingRectangle(); } - _compute_blur_bkg = false; + compute_blur_bkg_ = false; } // the elements position inside the window are referenced to top-left window @@ -96,11 +117,11 @@ void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) /*"Clear" out the background. Blending is disabled if blur is disabled. This might need to change, but for the moment both classes * which are children of CairoBaseWindow don't have any alpha blending when not using the blurred texture.*/ nux::ROPConfig rop; - rop.Blend = use_blur_; + rop.Blend = use_blurred_background_; rop.SrcBlend = GL_ONE; rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; - nux::ColorLayer layer(nux::Color(0x00000000), use_blur_, rop); + nux::ColorLayer layer(nux::Color(0x00000000), use_blurred_background_, rop); nux::GetPainter().PushDrawLayer(gfxContext, base, &layer); nux::TexCoordXForm texxform_bg; @@ -110,7 +131,7 @@ void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) nux::TexCoordXForm texxform_mask; texxform_mask.SetWrap(nux::TEXWRAP_CLAMP, nux::TEXWRAP_CLAMP); texxform_mask.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); - + nux::GetWindowThread()->GetGraphicsEngine().GetRenderStates().SetBlend(true); nux::GetWindowThread()->GetGraphicsEngine().GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER); @@ -150,7 +171,7 @@ void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) nux::TexCoordXForm texxform; texxform.SetWrap(nux::TEXWRAP_CLAMP, nux::TEXWRAP_CLAMP); texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); - + gfxContext.QRP_1Tex(base.x, base.y, base.width, diff --git a/launcher/CairoBaseWindow.h b/launcher/CairoBaseWindow.h index d99006d30..029e4e0f9 100644 --- a/launcher/CairoBaseWindow.h +++ b/launcher/CairoBaseWindow.h @@ -22,6 +22,7 @@ #include <Nux/Nux.h> #include <Nux/BaseWindow.h> +#include <NuxCore/Animation.h> namespace unity { @@ -30,7 +31,12 @@ class CairoBaseWindow : public nux::BaseWindow NUX_DECLARE_OBJECT_TYPE(CairoBaseWindow, nux::BaseWindow); public: CairoBaseWindow(); - virtual ~CairoBaseWindow(); + virtual ~CairoBaseWindow() = default; + + virtual void Show(); + virtual void Hide(); + + bool HasBlurredBackground() const; protected: void Draw(nux::GraphicsEngine& gfxContext, bool forceDraw); @@ -39,12 +45,11 @@ protected: nux::ObjectPtr<nux::BaseTexture> texture_mask_; nux::ObjectPtr<nux::BaseTexture> texture_outline_; - bool use_blur_; - bool _use_blurred_background; - bool _compute_blur_bkg; - private: + bool use_blurred_background_; + bool compute_blur_bkg_; nux::ObjectPtr<nux::IOpenGLBaseTexture> bg_blur_texture_; + nux::animation::AnimateValue<double> fade_animator_; }; } diff --git a/launcher/DeltaTracker.cpp b/launcher/DeltaTracker.cpp new file mode 100644 index 000000000..7718a5d51 --- /dev/null +++ b/launcher/DeltaTracker.cpp @@ -0,0 +1,80 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2011 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: Brandon Schaefer <brandon.schaefer@canonical.com> + */ + +#include "DeltaTracker.h" + +namespace unity +{ + +DeltaTracker::DeltaTracker() + : delta_state_(DeltaState::NONE) +{ +} + +void DeltaTracker::HandleNewMouseDelta(int dx, int dy) +{ + if (dx > 0) + { + delta_state_ |= DeltaState::RIGHT; + } + else if (dx < 0) + { + delta_state_ |= DeltaState::LEFT; + } + + if (dy > 0) + { + delta_state_ |= DeltaState::DOWN; + } + else if (dy < 0) + { + delta_state_ |= DeltaState::UP; + } +} + +void DeltaTracker::ResetState() +{ + delta_state_ = DeltaState::NONE; +} + +unsigned int DeltaTracker::AmountOfDirectionsChanged() const +{ + unsigned int directions_changed = 0; + + if (HasState(DeltaState::RIGHT)) + directions_changed++; + + if (HasState(DeltaState::LEFT)) + directions_changed++; + + if (HasState(DeltaState::UP)) + directions_changed++; + + if (HasState(DeltaState::DOWN)) + directions_changed++; + + return directions_changed; +} + +bool DeltaTracker::HasState(DeltaState const& state) const +{ + return (delta_state_ & state); +} + +} diff --git a/launcher/DeltaTracker.h b/launcher/DeltaTracker.h new file mode 100644 index 000000000..7db121c96 --- /dev/null +++ b/launcher/DeltaTracker.h @@ -0,0 +1,53 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2011 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: Brandon Schaefer <brandon.schaefer@canonical.com> + */ + +#ifndef DELTA_TRACKER_H +#define DELTA_TRACKER_H + +namespace unity +{ + +class DeltaTracker +{ +public: + DeltaTracker(); + + void HandleNewMouseDelta(int dx, int dy); + void ResetState(); + + unsigned int AmountOfDirectionsChanged() const; + +private: + enum DeltaState + { + NONE = 1 << 0, + RIGHT = 1 << 1, + DOWN = 1 << 2, + LEFT = 1 << 3, + UP = 1 << 4 + }; + + bool HasState(DeltaState const& state) const; + + unsigned int delta_state_; +}; + +} + +#endif // DELTA_TRACKER_H diff --git a/launcher/DesktopLauncherIcon.cpp b/launcher/DesktopLauncherIcon.cpp index 8b3791317..2fc752b2f 100644 --- a/launcher/DesktopLauncherIcon.cpp +++ b/launcher/DesktopLauncherIcon.cpp @@ -36,7 +36,6 @@ DesktopLauncherIcon::DesktopLauncherIcon() tooltip_text = _("Show Desktop"); icon_name = "desktop"; SetQuirk(Quirk::VISIBLE, true); - SetQuirk(Quirk::RUNNING, false); SetShortcut('d'); } @@ -51,7 +50,7 @@ std::string DesktopLauncherIcon::GetName() const return "DesktopLauncherIcon"; } -std::string DesktopLauncherIcon::GetRemoteUri() +std::string DesktopLauncherIcon::GetRemoteUri() const { return FavoriteStore::URI_PREFIX_UNITY + "desktop-icon"; } diff --git a/launcher/DesktopLauncherIcon.h b/launcher/DesktopLauncherIcon.h index 987ca3df9..41eaa8a10 100644 --- a/launcher/DesktopLauncherIcon.h +++ b/launcher/DesktopLauncherIcon.h @@ -38,7 +38,7 @@ public: protected: void ActivateLauncherIcon(ActionArg arg); std::string GetName() const; - std::string GetRemoteUri(); + std::string GetRemoteUri() const; private: bool show_in_switcher_; diff --git a/launcher/DeviceLauncherSection.cpp b/launcher/DeviceLauncherSection.cpp index 5eea0cdc7..bfc922dd4 100644 --- a/launcher/DeviceLauncherSection.cpp +++ b/launcher/DeviceLauncherSection.cpp @@ -19,8 +19,9 @@ #include "DeviceLauncherSection.h" #include "DeviceNotificationDisplayImp.h" -#include "DevicesSettings.h" +#include "DevicesSettingsImp.h" #include "VolumeImp.h" +#include "VolumeMonitorWrapper.h" #include "unity-shared/GnomeFileManager.h" namespace unity @@ -28,12 +29,13 @@ namespace unity namespace launcher { -DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor, - DevicesSettings::Ptr devices_settings) - : monitor_(volume_monitor) - , devices_settings_(devices_settings) +DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr const& vm, + DevicesSettings::Ptr const& ds, + DeviceNotificationDisplay::Ptr const& notify) + : monitor_(vm ? vm : std::make_shared<VolumeMonitorWrapper>()) + , devices_settings_(ds ? ds : std::make_shared<DevicesSettingsImp>()) , file_manager_(GnomeFileManager::Get()) - , device_notification_display_(std::make_shared<DeviceNotificationDisplayImp>()) + , device_notification_display_(notify ? notify : std::make_shared<DeviceNotificationDisplayImp>()) { monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded)); monitor_->volume_removed.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeRemoved)); @@ -43,7 +45,7 @@ DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr v void DeviceLauncherSection::PopulateEntries() { - for (auto volume : monitor_->GetVolumes()) + for (auto const& volume : monitor_->GetVolumes()) TryToCreateAndAddIcon(volume); } @@ -57,8 +59,8 @@ void DeviceLauncherSection::TryToCreateAndAddIcon(glib::Object<GVolume> volume) if (map_.find(volume) != map_.end()) return; - auto vol = std::make_shared<VolumeImp>(volume, file_manager_, device_notification_display_); - VolumeLauncherIcon::Ptr icon(new VolumeLauncherIcon(vol, devices_settings_)); + auto vol = std::make_shared<VolumeImp>(volume); + VolumeLauncherIcon::Ptr icon(new VolumeLauncherIcon(vol, devices_settings_, device_notification_display_, file_manager_)); map_[volume] = icon; icon_added.emit(icon); diff --git a/launcher/DeviceLauncherSection.h b/launcher/DeviceLauncherSection.h index e86172e0b..358b405c4 100644 --- a/launcher/DeviceLauncherSection.h +++ b/launcher/DeviceLauncherSection.h @@ -37,8 +37,9 @@ namespace launcher class DeviceLauncherSection : public sigc::trackable { public: - DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor, - DevicesSettings::Ptr devices_settings); + DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr const& volume_monitor = nullptr, + DevicesSettings::Ptr const& devices_settings = nullptr, + DeviceNotificationDisplay::Ptr const& notifications = nullptr); std::vector<VolumeLauncherIcon::Ptr> GetIcons() const; diff --git a/launcher/DeviceNotificationDisplayImp.cpp b/launcher/DeviceNotificationDisplayImp.cpp index 70f8c1960..62f2e5584 100644 --- a/launcher/DeviceNotificationDisplayImp.cpp +++ b/launcher/DeviceNotificationDisplayImp.cpp @@ -32,6 +32,11 @@ namespace unity namespace launcher { +namespace +{ +const unsigned icon_size = 48; +} + // // Start private implementation // @@ -40,7 +45,6 @@ class DeviceNotificationDisplayImp::Impl public: void Show(std::string const& icon_name, std::string const& volume_name) { - int icon_size = 48; IconLoader::GetDefault().LoadFromGIconString(icon_name, -1, icon_size, sigc::bind(sigc::mem_fun(this, &Impl::ShowNotificationWhenIconIsReady), volume_name)); } diff --git a/launcher/DndData.h b/launcher/DndData.h index 48c5014bc..3a0f8aebc 100644 --- a/launcher/DndData.h +++ b/launcher/DndData.h @@ -42,22 +42,22 @@ public: /** * Returns a std::set<std::string> with all the uris. **/ - std::set<std::string> const& Uris() const { return uris_; } + std::set<std::string> Uris() const { return uris_; } /** * Returns a std::set<std::string> with all the types. **/ - std::set<std::string> const& Types() const { return types_; } + std::set<std::string> Types() const { return types_; } /** * Returns a std::set<std::string> with all uris of a given type. **/ - std::set<std::string> const& UrisByType(const std::string& type) const { return types_to_uris_.find(type)->second; } + std::set<std::string> UrisByType(const std::string& type) const { return types_to_uris_.find(type)->second; } /** * Returns a std::set<std::string> with all types of a given uri. **/ - std::string const& TypeByUri(const std::string& uris) { return uris_to_types_.find(uris)->second; } + std::string TypeByUri(const std::string& uris) { return uris_to_types_.find(uris)->second; } private: std::set<std::string> uris_; diff --git a/launcher/EdgeBarrierController.cpp b/launcher/EdgeBarrierController.cpp index c50f8bc9b..f310b24de 100644 --- a/launcher/EdgeBarrierController.cpp +++ b/launcher/EdgeBarrierController.cpp @@ -16,6 +16,7 @@ * * Authored by: Jason Smith <jason.smith@canonical.com> * Marco Trevisan <marco.trevisan@canonical.com> + * Andrea Azzarone <andrea.azzarone@canonical.com> */ #include "EdgeBarrierController.h" @@ -33,6 +34,7 @@ namespace ui namespace { int const Y_BREAK_BUFFER = 20; + int const X_BREAK_BUFFER = 20; int const MAJOR = 2; int const MINOR = 3; } @@ -84,10 +86,12 @@ EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent) auto monitors = uscreen->GetMonitors(); ResizeBarrierList(monitors); - uscreen->changed.connect([&](int primary, std::vector<nux::Geometry>& layout) { + /* FIXME: Back to c++11 lambda once we get sigc::track_obj. + uscreen->changed.connect(sigc::track_obj(([&](int primary, std::vector<nux::Geometry>& layout) { ResizeBarrierList(layout); SetupBarriers(layout); - }); + }));*/ + uscreen->changed.connect(sigc::mem_fun(this, &EdgeBarrierController::Impl::OnUScreenChanged)); parent_->sticky_edges.SetGetterFunction([this] { return parent_->options() ? parent_->options()->edge_resist() : false; @@ -103,9 +107,11 @@ EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent) }); parent_->options.changed.connect([&](launcher::Options::Ptr options) { + /* FIXME: Back to c++11 lambda once we get sigc::track_obj. options->option_changed.connect([&]() { SetupBarriers(UScreen::GetDefault()->GetMonitors()); - }); + });*/ + options->option_changed.connect(sigc::mem_fun(this, &EdgeBarrierController::Impl::OnOptionsChanged)); SetupBarriers(UScreen::GetDefault()->GetMonitors()); }); @@ -117,19 +123,63 @@ EdgeBarrierController::Impl::~Impl() nux::GetGraphicsDisplay()->RemoveEventFilter(this); } +void EdgeBarrierController::Impl::OnUScreenChanged(int primary, std::vector<nux::Geometry>& layout) +{ + ResizeBarrierList(layout); + SetupBarriers(layout); +} + +void EdgeBarrierController::Impl::OnOptionsChanged() +{ + SetupBarriers(UScreen::GetDefault()->GetMonitors()); +} + +void EdgeBarrierController::Impl::AddSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor, std::vector<EdgeBarrierSubscriber*>& subscribers) +{ + if (monitor >= subscribers.size()) + subscribers.resize(monitor + 1); + + auto const& monitors = UScreen::GetDefault()->GetMonitors(); + subscribers[monitor] = subscriber; + ResizeBarrierList(monitors); + SetupBarriers(monitors); +} + +void EdgeBarrierController::Impl::RemoveSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor, std::vector<EdgeBarrierSubscriber*>& subscribers) +{ + if (monitor >= subscribers.size() || subscribers[monitor] != subscriber) + return; + + auto const& monitors = UScreen::GetDefault()->GetMonitors(); + subscribers[monitor] = nullptr; + ResizeBarrierList(monitors); + SetupBarriers(monitors); +} + void EdgeBarrierController::Impl::ResizeBarrierList(std::vector<nux::Geometry> const& layout) { auto num_monitors = layout.size(); - if (barriers_.size() > num_monitors) + + if (vertical_barriers_.size() > num_monitors) + vertical_barriers_.resize(num_monitors); + + if (horizontal_barriers_.size() > num_monitors) + horizontal_barriers_.resize(num_monitors); + + while (vertical_barriers_.size() < num_monitors) { - barriers_.resize(num_monitors); + auto barrier = std::make_shared<PointerBarrierWrapper>(); + barrier->orientation = VERTICAL; + barrier->barrier_event.connect(sigc::mem_fun(this, &EdgeBarrierController::Impl::OnPointerBarrierEvent)); + vertical_barriers_.push_back(barrier); } - while (barriers_.size() < num_monitors) + while (horizontal_barriers_.size() < num_monitors) { auto barrier = std::make_shared<PointerBarrierWrapper>(); + barrier->orientation = HORIZONTAL; barrier->barrier_event.connect(sigc::mem_fun(this, &EdgeBarrierController::Impl::OnPointerBarrierEvent)); - barriers_.push_back(barrier); + horizontal_barriers_.push_back(barrier); } } @@ -151,24 +201,41 @@ void EdgeBarrierController::Impl::SetupBarriers(std::vector<nux::Geometry> const for (unsigned i = 0; i < layout.size(); i++) { - auto barrier = barriers_[i]; + auto vertical_barrier = vertical_barriers_[i]; + auto horizontal_barrier = horizontal_barriers_[i]; auto monitor = layout[i]; - barrier->DestroyBarrier(); + vertical_barrier->DestroyBarrier(); + horizontal_barrier->DestroyBarrier(); + + if (edge_resist) + { + horizontal_barrier->x1 = monitor.x; + horizontal_barrier->x2 = monitor.x + monitor.width; + horizontal_barrier->y1 = monitor.y; + horizontal_barrier->y2 = monitor.y; + horizontal_barrier->index = i; + horizontal_barrier->direction = UP; + + horizontal_barrier->threshold = parent_->options()->edge_stop_velocity(); + horizontal_barrier->max_velocity_multiplier = parent_->options()->edge_responsiveness(); + + horizontal_barrier->ConstructBarrier(); + } if (!edge_resist && parent_->options()->hide_mode() == launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER) continue; - barrier->x1 = monitor.x; - barrier->x2 = monitor.x; - barrier->y1 = monitor.y; - barrier->y2 = monitor.y + monitor.height; - barrier->index = i; + vertical_barrier->x1 = monitor.x; + vertical_barrier->x2 = monitor.x; + vertical_barrier->y1 = monitor.y; + vertical_barrier->y2 = monitor.y + monitor.height; + vertical_barrier->index = i; - barrier->threshold = parent_->options()->edge_stop_velocity(); - barrier->max_velocity_multiplier = parent_->options()->edge_responsiveness(); + vertical_barrier->threshold = parent_->options()->edge_stop_velocity(); + vertical_barrier->max_velocity_multiplier = parent_->options()->edge_responsiveness(); - barrier->ConstructBarrier(); + vertical_barrier->ConstructBarrier(); } SetupXI2Events(); @@ -235,7 +302,11 @@ bool EdgeBarrierController::Impl::HandleEventCB(XEvent xevent, void* data) PointerBarrierWrapper::Ptr EdgeBarrierController::Impl::FindBarrierEventOwner(XIBarrierEvent* barrier_event) { - for (auto barrier : barriers_) + for (auto barrier : vertical_barriers_) + if (barrier->OwnsBarrierEvent(barrier_event->barrier)) + return barrier; + + for (auto barrier : horizontal_barriers_) if (barrier->OwnsBarrierEvent(barrier_event->barrier)) return barrier; @@ -249,7 +320,8 @@ void EdgeBarrierController::Impl::BarrierReset() void EdgeBarrierController::Impl::BarrierPush(PointerBarrierWrapper* owner, BarrierEvent::Ptr const& event) { - if (EventIsInsideYBreakZone(event)) + if ((owner->orientation == VERTICAL and EventIsInsideYBreakZone(event)) or + (owner->orientation == HORIZONTAL and EventIsInsideXBreakZone(event))) { decaymulator_.value = decaymulator_.value + event->velocity; } @@ -280,6 +352,22 @@ bool EdgeBarrierController::Impl::EventIsInsideYBreakZone(BarrierEvent::Ptr cons return false; } +bool EdgeBarrierController::Impl::EventIsInsideXBreakZone(BarrierEvent::Ptr const& event) +{ + static int x_break_zone = event->y; + + if (decaymulator_.value <= 0) + x_break_zone = event->x; + + if (event->x <= x_break_zone + X_BREAK_BUFFER && + event->x >= x_break_zone - X_BREAK_BUFFER) + { + return true; + } + + return false; +} + void EdgeBarrierController::Impl::OnPointerBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr const& event) { if (owner->released) @@ -289,11 +377,14 @@ void EdgeBarrierController::Impl::OnPointerBarrierEvent(PointerBarrierWrapper* o } unsigned int monitor = owner->index; + auto orientation = owner->orientation(); auto result = EdgeBarrierSubscriber::Result::NEEDS_RELEASE; - if (monitor < subscribers_.size()) + auto subscribers = orientation == VERTICAL ? vertical_subscribers_ : horizontal_subscribers_ ; + + if (monitor < subscribers.size()) { - auto subscriber = subscribers_[monitor]; + auto subscriber = subscribers[monitor]; if (subscriber) result = subscriber->HandleBarrierEvent(owner, event); @@ -352,34 +443,40 @@ EdgeBarrierController::EdgeBarrierController() EdgeBarrierController::~EdgeBarrierController() {} -void EdgeBarrierController::Subscribe(EdgeBarrierSubscriber* subscriber, unsigned int monitor) +void EdgeBarrierController::AddVerticalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor) { - if (monitor >= pimpl->subscribers_.size()) - pimpl->subscribers_.resize(monitor + 1); + pimpl->AddSubscriber(subscriber, monitor, pimpl->vertical_subscribers_); +} - auto const& monitors = UScreen::GetDefault()->GetMonitors(); - pimpl->subscribers_[monitor] = subscriber; - pimpl->ResizeBarrierList(monitors); - pimpl->SetupBarriers(monitors); +void EdgeBarrierController::RemoveVerticalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor) +{ + pimpl->RemoveSubscriber(subscriber, monitor, pimpl->vertical_subscribers_); } -void EdgeBarrierController::Unsubscribe(EdgeBarrierSubscriber* subscriber, unsigned int monitor) +void EdgeBarrierController::AddHorizontalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor) { - if (monitor >= pimpl->subscribers_.size() || pimpl->subscribers_[monitor] != subscriber) - return; + pimpl->AddSubscriber(subscriber, monitor, pimpl->horizontal_subscribers_); +} - auto const& monitors = UScreen::GetDefault()->GetMonitors(); - pimpl->subscribers_[monitor] = nullptr; - pimpl->ResizeBarrierList(monitors); - pimpl->SetupBarriers(monitors); +void EdgeBarrierController::RemoveHorizontalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor) +{ + pimpl->RemoveSubscriber(subscriber, monitor, pimpl->horizontal_subscribers_); +} + +EdgeBarrierSubscriber* EdgeBarrierController::GetVerticalSubscriber(unsigned int monitor) +{ + if (monitor >= pimpl->vertical_subscribers_.size()) + return nullptr; + + return pimpl->vertical_subscribers_[monitor]; } -EdgeBarrierSubscriber* EdgeBarrierController::GetSubscriber(unsigned int monitor) +EdgeBarrierSubscriber* EdgeBarrierController::GetHorizontalSubscriber(unsigned int monitor) { - if (monitor >= pimpl->subscribers_.size()) + if (monitor >= pimpl->horizontal_subscribers_.size()) return nullptr; - return pimpl->subscribers_[monitor]; + return pimpl->horizontal_subscribers_[monitor]; } } diff --git a/launcher/EdgeBarrierController.h b/launcher/EdgeBarrierController.h index 4942827e0..d55ffb49d 100644 --- a/launcher/EdgeBarrierController.h +++ b/launcher/EdgeBarrierController.h @@ -42,15 +42,22 @@ struct EdgeBarrierSubscriber class EdgeBarrierController : public sigc::trackable { public: + typedef std::shared_ptr<EdgeBarrierController> Ptr; + EdgeBarrierController(); ~EdgeBarrierController(); nux::RWProperty<bool> sticky_edges; nux::Property<launcher::Options::Ptr> options; - void Subscribe(EdgeBarrierSubscriber* subscriber, unsigned int monitor); - void Unsubscribe(EdgeBarrierSubscriber* subscriber, unsigned int monitor); - EdgeBarrierSubscriber* GetSubscriber(unsigned int monitor); + void AddHorizontalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor); + void RemoveHorizontalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor); + + void AddVerticalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor); + void RemoveVerticalSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor); + + EdgeBarrierSubscriber* GetHorizontalSubscriber(unsigned int monitor); + EdgeBarrierSubscriber* GetVerticalSubscriber(unsigned int monitor); private: struct Impl; diff --git a/launcher/EdgeBarrierControllerPrivate.h b/launcher/EdgeBarrierControllerPrivate.h index 063c193a8..9a31d4155 100644 --- a/launcher/EdgeBarrierControllerPrivate.h +++ b/launcher/EdgeBarrierControllerPrivate.h @@ -30,20 +30,27 @@ namespace ui { // NOTE: This private header is not part of the public interface -struct EdgeBarrierController::Impl +struct EdgeBarrierController::Impl : public sigc::trackable { Impl(EdgeBarrierController *parent); ~Impl(); + void AddSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor, std::vector<EdgeBarrierSubscriber*>& subscribers); + void RemoveSubscriber(EdgeBarrierSubscriber* subscriber, unsigned int monitor, std::vector<EdgeBarrierSubscriber*>& subscribers); + void ResizeBarrierList(std::vector<nux::Geometry> const& layout); void SetupBarriers(std::vector<nux::Geometry> const& layout); + void OnUScreenChanged(int primary, std::vector<nux::Geometry>& layout); + void OnOptionsChanged(); + void OnPointerBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr const& event); void BarrierPush(PointerBarrierWrapper* owner, BarrierEvent::Ptr const& event); void BarrierRelease(PointerBarrierWrapper* owner, int event); void BarrierReset(); bool EventIsInsideYBreakZone(BarrierEvent::Ptr const& event); + bool EventIsInsideXBreakZone(BarrierEvent::Ptr const& event); void AddEventFilter(); @@ -52,8 +59,12 @@ struct EdgeBarrierController::Impl static bool HandleEventCB(XEvent event, void* data); bool HandleEvent(XEvent event); - std::vector<PointerBarrierWrapper::Ptr> barriers_; - std::vector<EdgeBarrierSubscriber*> subscribers_; + std::vector<PointerBarrierWrapper::Ptr> vertical_barriers_; + std::vector<PointerBarrierWrapper::Ptr> horizontal_barriers_; + + std::vector<EdgeBarrierSubscriber*> vertical_subscribers_; + std::vector<EdgeBarrierSubscriber*> horizontal_subscribers_; + Decaymulator decaymulator_; glib::Source::UniquePtr release_timeout_; int xi2_opcode_; diff --git a/launcher/ExpoLauncherIcon.cpp b/launcher/ExpoLauncherIcon.cpp index d7b5dfd31..f195c6701 100644 --- a/launcher/ExpoLauncherIcon.cpp +++ b/launcher/ExpoLauncherIcon.cpp @@ -34,8 +34,6 @@ ExpoLauncherIcon::ExpoLauncherIcon() { tooltip_text = _("Workspace Switcher"); icon_name = "workspace-switcher-top-left"; - SetQuirk(Quirk::VISIBLE, false); - SetQuirk(Quirk::RUNNING, false); SetShortcut('s'); auto& wm = WindowManager::Default(); @@ -106,7 +104,7 @@ std::string ExpoLauncherIcon::GetName() const return "ExpoLauncherIcon"; } -std::string ExpoLauncherIcon::GetRemoteUri() +std::string ExpoLauncherIcon::GetRemoteUri() const { return FavoriteStore::URI_PREFIX_UNITY + "expo-icon"; } diff --git a/launcher/ExpoLauncherIcon.h b/launcher/ExpoLauncherIcon.h index 6ca563c34..4e58e30f1 100644 --- a/launcher/ExpoLauncherIcon.h +++ b/launcher/ExpoLauncherIcon.h @@ -37,7 +37,7 @@ public: protected: void ActivateLauncherIcon(ActionArg arg); std::string GetName() const; - std::string GetRemoteUri(); + std::string GetRemoteUri() const; private: void OnViewportLayoutChanged(int hsize, int vsize); diff --git a/launcher/HudLauncherIcon.cpp b/launcher/HudLauncherIcon.cpp index 39fa01a0d..a4ba04997 100644 --- a/launcher/HudLauncherIcon.cpp +++ b/launcher/HudLauncherIcon.cpp @@ -18,13 +18,13 @@ */ #include "HudLauncherIcon.h" -#include "Launcher.h" #include "UnityCore/GLibWrapper.h" #include "UnityCore/Variant.h" #include <NuxCore/Logger.h> #include "unity-shared/UBusMessages.h" +#include "config.h" #include <glib/gi18n-lib.h> namespace unity @@ -34,14 +34,13 @@ namespace launcher DECLARE_LOGGER(logger, "unity.launcher.icon.hud"); HudLauncherIcon::HudLauncherIcon(LauncherHideMode hide_mode) - : SingleMonitorLauncherIcon(IconType::HUD, 0) + : SingleMonitorLauncherIcon(IconType::HUD) , launcher_hide_mode_(hide_mode) { tooltip_text = _("HUD"); + tooltip_enabled = false; icon_name = PKGDATADIR"/launcher_bfb.png"; position = Position::BEGIN; - SetQuirk(Quirk::VISIBLE, false); - SetQuirk(Quirk::RUNNING, false); SetQuirk(Quirk::ACTIVE, true); background_color_ = nux::color::White; @@ -55,7 +54,7 @@ HudLauncherIcon::HudLauncherIcon(LauncherHideMode hide_mode) sigc::bind(sigc::mem_fun(this, &HudLauncherIcon::OnOverlayShown), false)); - mouse_enter.connect([&](int m) { ubus_manager_.SendMessage(UBUS_DASH_ABOUT_TO_SHOW); }); + mouse_enter.connect([this](int m) { ubus_manager_.SendMessage(UBUS_DASH_ABOUT_TO_SHOW); }); } void HudLauncherIcon::OnHudIconChanged(GVariant *data) @@ -68,8 +67,6 @@ void HudLauncherIcon::OnHudIconChanged(GVariant *data) icon_name = PKGDATADIR"/launcher_bfb.png"; else icon_name = hud_icon_name; - - EmitNeedsRedraw(); } } @@ -97,11 +94,8 @@ void HudLauncherIcon::OnOverlayShown(GVariant* data, bool visible) if (overlay_identity.Str() == "hud" && launcher_hide_mode_ == LAUNCHER_HIDE_NEVER) { - SetMonitor(overlay_monitor); - SetQuirk(Quirk::VISIBLE, visible); - SetQuirk(Quirk::ACTIVE, visible); - tooltip_enabled = !visible; - EmitNeedsRedraw(); + SetMonitor(visible ? overlay_monitor : -1); + SkipQuirkAnimation(Quirk::VISIBLE, overlay_monitor); } } diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp index f96c5e5bf..226430f9f 100644 --- a/launcher/Launcher.cpp +++ b/launcher/Launcher.cpp @@ -19,51 +19,35 @@ */ #include "config.h" -#include <math.h> - -#include <functional> #include <Nux/Nux.h> -#include <Nux/VScrollBar.h> -#include <Nux/HLayout.h> -#include <Nux/VLayout.h> #include <NuxCore/Logger.h> -#include <NuxGraphics/NuxGraphics.h> -#include <NuxGraphics/GestureEvent.h> -#include <NuxGraphics/GpuDevice.h> -#include <NuxGraphics/GLTextureResourceManager.h> - -#include <Nux/BaseWindow.h> -#include <Nux/WindowCompositor.h> - #include "Launcher.h" #include "AbstractLauncherIcon.h" -#include "unity-shared/PanelStyle.h" #include "SpacerLauncherIcon.h" #include "LauncherModel.h" #include "QuicklistManager.h" #include "QuicklistView.h" +#include "unity-shared/AnimationUtils.h" #include "unity-shared/IconRenderer.h" -#include "unity-shared/TimeUtil.h" -#include "unity-shared/TextureCache.h" +#include "unity-shared/GraphicsUtils.h" #include "unity-shared/IconLoader.h" +#include "unity-shared/PanelStyle.h" +#include "unity-shared/TextureCache.h" +#include "unity-shared/TimeUtil.h" #include "unity-shared/UScreen.h" #include "unity-shared/UBusMessages.h" #include "unity-shared/UnitySettings.h" -#include "unity-shared/GraphicsUtils.h" - #include <UnityCore/GLibWrapper.h> #include <UnityCore/Variant.h> #include <boost/algorithm/string.hpp> -#include <sigc++/sigc++.h> namespace unity { using ui::RenderArg; -using ui::Decaymulator; namespace launcher { @@ -85,97 +69,94 @@ const float BACKLIGHT_STRENGTH = 0.9f; const int ICON_PADDING = 6; const int RIGHT_LINE_WIDTH = 1; +const int ANIM_DURATION_SHORT = 125; const int ANIM_DURATION_SHORT_SHORT = 100; const int ANIM_DURATION = 200; const int ANIM_DURATION_LONG = 350; const int START_DRAGICON_DURATION = 250; +const int DEFAULT_ICON_SIZE = 48; +const int DEFAULT_ICON_SIZE_DELTA = 6; +const int SPACE_BETWEEN_ICONS = 5; + const int MOUSE_DEADZONE = 15; + const float DRAG_OUT_PIXELS = 300.0f; +const float FOLDED_Z_DISTANCE = 10.f; +const float NEG_FOLDED_ANGLE = -1.0f; const int SCROLL_AREA_HEIGHT = 24; const int SCROLL_FPS = 30; -const int BASE_URGENT_WIGGLE_PERIOD = 60; // In seconds -const int MAX_URGENT_WIGGLE_DELTA = 960; // In seconds +const int BASE_URGENT_ANIMATION_PERIOD = 60; // In seconds +const int MAX_URGENT_ANIMATION_DELTA = 960; // In seconds const int DOUBLE_TIME = 2; const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout"; const std::string SCROLL_TIMEOUT = "scroll-timeout"; -const std::string ANIMATION_IDLE = "animation-idle"; +const std::string SCALE_DESATURATE_IDLE = "scale-desaturate-idle"; const std::string URGENT_TIMEOUT = "urgent-timeout"; +const std::string LAST_ANIMATION_URGENT_IDLE = "last-animation-urgent-idle"; } - NUX_IMPLEMENT_OBJECT_TYPE(Launcher); -const int Launcher::Launcher::ANIM_DURATION_SHORT = 125; - Launcher::Launcher(MockableBaseWindow* parent, NUX_FILE_LINE_DECL) : View(NUX_FILE_LINE_PARAM) -#ifdef USE_X11 - , display(nux::GetGraphicsDisplay()->GetX11Display()) -#else - , display(0) -#endif , monitor(0) - , _parent(parent) - , _active_quicklist(nullptr) - , _hovered(false) - , _hidden(false) - , _shortcuts_shown(false) - , _data_checked(false) - , _steal_drag(false) - , _drag_edge_touching(false) - , _initial_drag_animation(false) - , _dash_is_open(false) - , _hud_is_open(false) - , _folded_angle(1.0f) - , _neg_folded_angle(-1.0f) - , _folded_z_distance(10.0f) - , _edge_overcome_pressure(0.0f) - , _launcher_action_state(ACTION_NONE) - , _space_between_icons(5) - , _icon_image_size(48) - , _icon_image_size_delta(6) - , _icon_glow_size(62) - , _icon_size(_icon_image_size + _icon_image_size_delta) - , _dnd_delta_y(0) - , _dnd_delta_x(0) - , _postreveal_mousemove_delta_x(0) - , _postreveal_mousemove_delta_y(0) - , _launcher_drag_delta(0) - , _launcher_drag_delta_max(0) - , _launcher_drag_delta_min(0) - , _enter_y(0) - , _last_button_press(0) - , _urgent_wiggle_time(0) - , _urgent_acked(false) - , _urgent_timer_running(false) - , _urgent_ack_needed(false) - , _drag_out_delta_x(0.0f) - , _drag_gesture_ongoing(false) - , _last_reveal_progress(0.0f) - , _drag_action(nux::DNDACTION_NONE) - , _selection_atom(0) - , icon_renderer(std::make_shared<ui::IconRenderer>()) -{ - m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION); - icon_renderer->monitor = monitor(); + , parent_(parent) + , icon_renderer_(std::make_shared<ui::IconRenderer>()) + , hovered_(false) + , hidden_(false) + , folded_(true) + , shortcuts_shown_(false) + , data_checked_(false) + , steal_drag_(false) + , drag_edge_touching_(false) + , initial_drag_animation_(false) + , dash_is_open_(false) + , hud_is_open_(false) + , launcher_action_state_(ACTION_NONE) + , icon_size_(DEFAULT_ICON_SIZE + DEFAULT_ICON_SIZE_DELTA) + , dnd_delta_y_(0) + , dnd_delta_x_(0) + , postreveal_mousemove_delta_x_(0) + , postreveal_mousemove_delta_y_(0) + , launcher_drag_delta_(0) + , launcher_drag_delta_max_(0) + , launcher_drag_delta_min_(0) + , enter_y_(0) + , last_button_press_(0) + , urgent_animation_period_(0) + , urgent_ack_needed_(false) + , drag_out_delta_x_(0.0f) + , drag_gesture_ongoing_(false) + , last_reveal_progress_(0.0f) + , drag_action_(nux::DNDACTION_NONE) + , auto_hide_animation_(ANIM_DURATION_SHORT) + , hover_animation_(ANIM_DURATION) + , drag_over_animation_(ANIM_DURATION_LONG) + , drag_out_animation_(ANIM_DURATION_SHORT) + , drag_icon_animation_(ANIM_DURATION_SHORT) + , dnd_hide_animation_(ANIM_DURATION * 3) + , dash_showing_animation_(90) +{ + icon_renderer_->monitor = monitor(); + icon_renderer_->SetTargetSize(icon_size_, DEFAULT_ICON_SIZE, SPACE_BETWEEN_ICONS); bg_effect_helper_.owner = this; bg_effect_helper_.enabled = false; - SetCompositionLayout(m_Layout); CaptureMouseDownAnyWhereElse(true); SetAcceptKeyNavFocusOnMouseDown(false); SetAcceptMouseWheelEvent(true); SetDndEnabled(false, true); - _hide_machine.should_hide_changed.connect(sigc::mem_fun(this, &Launcher::SetHidden)); - _hide_machine.reveal_progress.changed.connect([&](float value) { EnsureAnimation(); }); - _hover_machine.should_hover_changed.connect(sigc::mem_fun(this, &Launcher::SetHover)); + auto const& redraw_cb = sigc::hide(sigc::mem_fun(this, &Launcher::QueueDraw)); + hide_machine_.should_hide_changed.connect(sigc::mem_fun(this, &Launcher::SetHidden)); + hide_machine_.reveal_progress.changed.connect(redraw_cb); + hover_machine_.should_hover_changed.connect(sigc::mem_fun(this, &Launcher::SetHover)); mouse_down.connect(sigc::mem_fun(this, &Launcher::RecvMouseDown)); mouse_up.connect(sigc::mem_fun(this, &Launcher::RecvMouseUp)); @@ -184,35 +165,22 @@ Launcher::Launcher(MockableBaseWindow* parent, mouse_leave.connect(sigc::mem_fun(this, &Launcher::RecvMouseLeave)); mouse_move.connect(sigc::mem_fun(this, &Launcher::RecvMouseMove)); mouse_wheel.connect(sigc::mem_fun(this, &Launcher::RecvMouseWheel)); - //OnEndFocus.connect (sigc::mem_fun (this, &Launcher::exitKeyNavMode)); QuicklistManager& ql_manager = *(QuicklistManager::Default()); ql_manager.quicklist_opened.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistOpened)); ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed)); WindowManager& wm = WindowManager::Default(); - wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); - wm.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); - wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); - wm.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); - wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::EnsureAnimation)); - - // 0 out timers to avoid wonky startups - for (int i = 0; i < TIME_LAST; ++i) - { - _times[i].tv_sec = 0; - _times[i].tv_nsec = 0; - } - - _urgent_finished_time.tv_sec = 0; - _urgent_finished_time.tv_nsec = 0; + wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnSpreadChanged)); + wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnSpreadChanged)); + wm.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnExpoChanged)); + wm.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnExpoChanged)); + wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::QueueDraw)); ubus_.RegisterInterest(UBUS_OVERLAY_SHOWN, sigc::mem_fun(this, &Launcher::OnOverlayShown)); ubus_.RegisterInterest(UBUS_OVERLAY_HIDDEN, sigc::mem_fun(this, &Launcher::OnOverlayHidden)); ubus_.RegisterInterest(UBUS_LAUNCHER_LOCK_HIDE, sigc::mem_fun(this, &Launcher::OnLockHideChanged)); - icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons); - TextureCache& cache = TextureCache::GetDefault(); launcher_sheen_ = cache.FindTexture("dash_sheen.png"); launcher_pressure_effect_ = cache.FindTexture("launcher_pressure_effect.png"); @@ -230,6 +198,14 @@ Launcher::Launcher(MockableBaseWindow* parent, parent->geometry_changed.connect(update_blur_geometry); update_blur_geometry(this, GetAbsoluteGeometry()); + + auto_hide_animation_.updated.connect(redraw_cb); + hover_animation_.updated.connect(redraw_cb); + drag_over_animation_.updated.connect(redraw_cb); + drag_out_animation_.updated.connect(redraw_cb); + drag_icon_animation_.updated.connect(redraw_cb); + dnd_hide_animation_.updated.connect(redraw_cb); + dash_showing_animation_.updated.connect(redraw_cb); } /* Introspection */ @@ -241,261 +217,105 @@ std::string Launcher::GetName() const #ifdef NUX_GESTURES_SUPPORT void Launcher::OnDragStart(const nux::GestureEvent &event) { - _drag_gesture_ongoing = true; - if (_hidden) + drag_gesture_ongoing_ = true; + if (hidden_) { - _drag_out_delta_x = 0.0f; + drag_out_delta_x_ = 0.0f; } else { - _drag_out_delta_x = DRAG_OUT_PIXELS; - _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false); + drag_out_delta_x_ = DRAG_OUT_PIXELS; + hide_machine_.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false); } } void Launcher::OnDragUpdate(const nux::GestureEvent &event) { - _drag_out_delta_x = - CLAMP(_drag_out_delta_x + event.GetDelta().x, 0.0f, DRAG_OUT_PIXELS); - EnsureAnimation(); + drag_out_delta_x_ = + CLAMP(drag_out_delta_x_ + event.GetDelta().x, 0.0f, DRAG_OUT_PIXELS); + QueueDraw(); } void Launcher::OnDragFinish(const nux::GestureEvent &event) { - if (_drag_out_delta_x >= DRAG_OUT_PIXELS - 90.0f) - _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, true); - TimeUtil::SetTimeStruct(&_times[TIME_DRAG_OUT], - &_times[TIME_DRAG_OUT], - ANIM_DURATION_SHORT); - EnsureAnimation(); - _drag_gesture_ongoing = false; + if (drag_out_delta_x_ >= DRAG_OUT_PIXELS - 90.0f) + hide_machine_.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, true); + + animation::StartOrReverse(drag_out_animation_, animation::Direction::BACKWARD); + drag_gesture_ongoing_ = false; } #endif void Launcher::AddProperties(GVariantBuilder* builder) { - timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - unity::variant::BuilderWrapper(builder) .add(GetAbsoluteGeometry()) - .add("hover-progress", GetHoverProgress(current)) - .add("dnd-exit-progress", DnDExitProgress(current)) - .add("autohide-progress", AutohideProgress(current)) - .add("dnd-delta", _dnd_delta_y) - .add("hovered", _hovered) + .add("hover-progress", hover_animation_.GetCurrentValue()) + .add("dnd-exit-progress", drag_over_animation_.GetCurrentValue()) + .add("autohide-progress", auto_hide_animation_.GetCurrentValue()) + .add("dnd-delta", dnd_delta_y_) + .add("hovered", hovered_) .add("hidemode", options()->hide_mode) - .add("hidden", _hidden) - .add("is_showing", ! _hidden) + .add("hidden", hidden_) + .add("is_showing", ! hidden_) .add("monitor", monitor()) - .add("quicklist-open", _hide_machine.GetQuirk(LauncherHideMachine::QUICKLIST_OPEN)) - .add("hide-quirks", _hide_machine.DebugHideQuirks()) - .add("hover-quirks", _hover_machine.DebugHoverQuirks()) - .add("icon-size", _icon_size) - .add("shortcuts_shown", _shortcuts_shown) - .add("tooltip-shown", _active_tooltip != nullptr); + .add("quicklist-open", hide_machine_.GetQuirk(LauncherHideMachine::QUICKLIST_OPEN)) + .add("hide-quirks", hide_machine_.DebugHideQuirks()) + .add("hover-quirks", hover_machine_.DebugHoverQuirks()) + .add("icon-size", icon_size_) + .add("shortcuts_shown", shortcuts_shown_) + .add("tooltip-shown", active_tooltip_ != nullptr); } void Launcher::SetMousePosition(int x, int y) { - bool beyond_drag_threshold = MouseBeyondDragThreshold(); - _mouse_position = nux::Point2(x, y); + bool was_beyond_drag_threshold = MouseBeyondDragThreshold(); + mouse_position_ = nux::Point(x, y); + bool is_beyond_drag_threshold = MouseBeyondDragThreshold(); - if (beyond_drag_threshold != MouseBeyondDragThreshold()) - TimeUtil::SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT); + if (was_beyond_drag_threshold != is_beyond_drag_threshold) + animation::StartOrReverseIf(drag_icon_animation_, !is_beyond_drag_threshold); EnsureScrollTimer(); } 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); + 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) + if (icon_under_mouse_ == icon) return; - if (_icon_under_mouse) - _icon_under_mouse->mouse_leave.emit(monitor); + if (icon_under_mouse_) + icon_under_mouse_->mouse_leave.emit(monitor); if (icon) icon->mouse_enter.emit(monitor); - _icon_under_mouse = icon; + icon_under_mouse_ = icon; } bool Launcher::MouseBeyondDragThreshold() const { if (GetActionState() == ACTION_DRAG_ICON) - return _mouse_position.x > GetGeometry().width + _icon_size / 2; + return mouse_position_.x > GetGeometry().width + icon_size_ / 2; return false; } /* Render Layout Logic */ -float Launcher::GetHoverProgress(struct timespec const& current) const +float Launcher::DragOutProgress() const { - if (_hovered) - return CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_ENTER])) / (float) ANIM_DURATION, 0.0f, 1.0f); - else - return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_LEAVE])) / (float) ANIM_DURATION, 0.0f, 1.0f); -} - -float Launcher::DnDExitProgress(struct timespec const& current) const -{ - return pow(1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_END])) / (float) ANIM_DURATION_LONG, 0.0f, 1.0f), 2); -} + float progress = drag_out_delta_x_ / DRAG_OUT_PIXELS; -float Launcher::DragOutProgress(struct timespec const& current) const -{ - float timeout = CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_OUT])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); - float progress = CLAMP(_drag_out_delta_x / DRAG_OUT_PIXELS, 0.0f, 1.0f); - - if (_drag_gesture_ongoing - || _hide_machine.GetQuirk(LauncherHideMachine::MT_DRAG_OUT)) + if (drag_gesture_ongoing_ || hide_machine_.GetQuirk(LauncherHideMachine::MT_DRAG_OUT)) return progress; else - return progress * (1.0f - timeout); -} - -float Launcher::AutohideProgress(struct timespec const& current) const -{ - // time-based progress (full scale or finish the TRIGGER_AUTOHIDE_MIN -> 0.00f on bfb) - float animation_progress; - animation_progress = CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_AUTOHIDE])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); - if (_hidden) - return animation_progress; - else - return 1.0f - animation_progress; -} - -float Launcher::DragHideProgress(struct timespec const& current) const -{ - if (_drag_edge_touching) - return CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f); - else - return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f); -} - -float Launcher::DragThresholdProgress(struct timespec const& current) const -{ - if (MouseBeyondDragThreshold()) - return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); - else - return CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); -} - -void Launcher::EnsureAnimation() -{ - QueueDraw(); -} - -bool Launcher::IconNeedsAnimation(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - struct timespec time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::RUNNING); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING); - if (unity::TimeUtil::TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2)) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT); - if (unity::TimeUtil::TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * URGENT_BLINKS * 2)) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PULSE_ONCE); - if (unity::TimeUtil::TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2)) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PRESENTED); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_LONG) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::CENTER_SAVED); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PROGRESS); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_DIM); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DESAT); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT_SHORT) - return true; - - time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_PRELIGHT); - if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) - return true; - - return false; -} - -bool Launcher::AnimationInProgress() const -{ - // performance here can be improved by caching the longer remaining animation found and short circuiting to that each time - // this way extra checks may be avoided - - if (_last_reveal_progress != _hide_machine.reveal_progress) - return true; - - // short circuit to avoid unneeded calculations - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - - // hover in animation - if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_ENTER]) < ANIM_DURATION) - return true; - - // hover out animation - if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_LEAVE]) < ANIM_DURATION) - return true; - - // drag end animation - if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_END]) < ANIM_DURATION_LONG) - return true; - - // hide animation (time only), position is trigger manually on the bfb - if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_AUTOHIDE]) < ANIM_DURATION_SHORT) - return true; - - // collapse animation on DND out of launcher space - if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD]) < ANIM_DURATION_SHORT) - return true; - - // hide animation for dnd - if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH]) < ANIM_DURATION * 6) - return true; - - // restore from drag_out animation - if (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_OUT]) < ANIM_DURATION_SHORT) - return true; - - // animations happening on specific icons - for (auto const &icon : *_model) - if (IconNeedsAnimation(icon, current)) - return true; - - return false; + return progress * drag_out_animation_.GetCurrentValue(); } /* Min is when you are on the trigger */ @@ -506,6 +326,7 @@ float Launcher::GetAutohidePositionMin() const else return 0.25f; } + /* Max is the initial state over the bfb */ float Launcher::GetAutohidePositionMax() const { @@ -515,214 +336,107 @@ float Launcher::GetAutohidePositionMax() const return 0.75f; } - -float Launcher::IconVisibleProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const +void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo) { - if (!icon->IsVisibleOnMonitor(monitor)) - return 0.0f; - - if (icon->GetIconType() == AbstractLauncherIcon::IconType::HUD) - { - return icon->IsVisible() ? 1.0f : 0.0f; - } - - if (icon->IsVisible()) - { - struct timespec icon_visible_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE); - DeltaTime enter_ms = unity::TimeUtil::TimeDelta(¤t, &icon_visible_time); - return CLAMP((float) enter_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); - } - else - { - struct timespec icon_hide_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE); - DeltaTime hide_ms = unity::TimeUtil::TimeDelta(¤t, &icon_hide_time); - return 1.0f - CLAMP((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); - } -} - -void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo, timespec const& current) -{ - AbstractLauncherIcon::Ptr const& anchor = MouseIconIntersection(x, _enter_y); + auto const& anchor = MouseIconIntersection(x, enter_y_); if (anchor) { float position = y; - for (AbstractLauncherIcon::Ptr const& model_icon : *_model) + for (AbstractLauncherIcon::Ptr const& model_icon : *model_) { if (model_icon == anchor) { - position += _icon_size / 2; - _launcher_drag_delta = _enter_y - position; + position += icon_size_ / 2; + launcher_drag_delta_ = enter_y_ - position; - if (position + _icon_size / 2 + _launcher_drag_delta > geo.height) - _launcher_drag_delta -= (position + _icon_size / 2 + _launcher_drag_delta) - geo.height; + if (position + icon_size_ / 2 + launcher_drag_delta_ > geo.height) + launcher_drag_delta_ -= (position + icon_size_ / 2 + launcher_drag_delta_) - geo.height; break; } - position += (_icon_size + _space_between_icons) * IconVisibleProgress(model_icon, current); + float visibility = model_icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::VISIBLE, monitor()); + position += (icon_size_ + SPACE_BETWEEN_ICONS) * visibility; } } } -float Launcher::IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - struct timespec icon_present_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PRESENTED); - DeltaTime ms = unity::TimeUtil::TimeDelta(¤t, &icon_present_time); - float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f); - - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PRESENTED)) - return result; - else - return 1.0f - result; -} - -float Launcher::IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const +float Launcher::IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon) const { - struct timespec icon_unfold_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED); - DeltaTime ms = unity::TimeUtil::TimeDelta(¤t, &icon_unfold_time); - float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f); - - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED)) - return result; - else - return 1.0f - result; -} - -float Launcher::IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT); - DeltaTime urgent_ms = unity::TimeUtil::TimeDelta(¤t, &urgent_time); - float result; - - if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE) - result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_SHORT * WIGGLE_CYCLES), 0.0f, 1.0f); - else - result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f); - - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT)) - return result; - else - return 1.0f - result; -} - -float Launcher::IconDropDimValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DROP_DIM); - DeltaTime dim_ms = unity::TimeUtil::TimeDelta(¤t, &dim_time); - float result = CLAMP((float) dim_ms / (float) ANIM_DURATION, 0.0f, 1.0f); - - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::DROP_DIM)) - return 1.0f - result; - else - return result; -} - -float Launcher::IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::DESAT); - DeltaTime ms = unity::TimeUtil::TimeDelta(¤t, &dim_time); - float result = CLAMP((float) ms / (float) ANIM_DURATION_SHORT_SHORT, 0.0f, 1.0f); - - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::DESAT)) - return 1.0f - result; - else - return result; -} - -float Launcher::IconShimmerProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - struct timespec shimmer_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER); - DeltaTime shimmer_ms = unity::TimeUtil::TimeDelta(¤t, &shimmer_time); - return CLAMP((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f); -} - -float Launcher::IconCenterTransitionProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - struct timespec save_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::CENTER_SAVED); - DeltaTime save_ms = unity::TimeUtil::TimeDelta(¤t, &save_time); - return CLAMP((float) save_ms / (float) ANIM_DURATION, 0.0f, 1.0f); -} - -float Launcher::IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT)) + if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor())) return 1.0f; // we are full on in a normal condition - double urgent_progress = (double) IconUrgentProgress(icon, current); + float urgent_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::URGENT, monitor()); return 0.5f + (float)(std::cos(M_PI * (float)(URGENT_BLINKS * 2) * urgent_progress)) * 0.5f; } -float Launcher::IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const ¤t) const +float Launcher::IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon) const { - struct timespec pulse_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PULSE_ONCE); - DeltaTime pulse_ms = unity::TimeUtil::TimeDelta(¤t, &pulse_time); - double pulse_progress = (double) CLAMP((float) pulse_ms / (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2), 0.0f, 1.0f); + float pulse_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::PULSE_ONCE, monitor()); if (pulse_progress == 1.0f) - icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, false); + { + icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, false, monitor()); + icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::PULSE_ONCE, monitor()); + } return 0.5f + (float) (std::cos(M_PI * 2.0 * pulse_progress)) * 0.5f; } -float Launcher::IconUrgentWiggleValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const +float Launcher::IconUrgentWiggleValue(AbstractLauncherIcon::Ptr const& icon) const { - if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT)) + if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor())) return 0.0f; // we are full on in a normal condition - double urgent_progress = (double) IconUrgentProgress(icon, current); + float urgent_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::URGENT, monitor()); return 0.3f * (float)(std::sin(M_PI * (float)(WIGGLE_CYCLES * 2) * urgent_progress)) * 0.5f; } -float Launcher::IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const +float Launcher::IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon) const { - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING)) + if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING, monitor())) return 1.0f; - if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING)) + if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING, monitor())) return 1.0f; - struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING); - DeltaTime starting_ms = unity::TimeUtil::TimeDelta(¤t, &starting_time); - double starting_progress = (double) CLAMP((float) starting_ms / (float)(ANIM_DURATION_LONG * STARTING_BLINK_LAMBDA), 0.0f, 1.0f); + float starting_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::STARTING, monitor()); + double val = IsBackLightModeToggles() ? 3.0f : 4.0f; return 1.0f-(0.5f + (float)(std::cos(M_PI * val * starting_progress)) * 0.5f); } -float Launcher::IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const +float Launcher::IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon) const { - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING)) + if (icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING, monitor())) return 1.0f; - if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING)) + if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING, monitor())) return 1.0f; - struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::STARTING); - DeltaTime starting_ms = unity::TimeUtil::TimeDelta(¤t, &starting_time); - double starting_progress = (double) CLAMP((float) starting_ms / (float)(ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), 0.0f, 1.0f); + float starting_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::STARTING, monitor()); - if (starting_progress == 1.0f && !icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING)) + if (starting_progress == 1.0f) { - icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false); - icon->ResetQuirkTime(AbstractLauncherIcon::Quirk::STARTING); + icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false, monitor()); + icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::STARTING, monitor()); + return starting_progress; } return 1.0f-(0.5f + (float)(std::cos(M_PI * (float)(MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f); } -float Launcher::IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const +float Launcher::IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon) const { float result = 0.0f; + float running_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::RUNNING, monitor()); - struct timespec running_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::RUNNING); - DeltaTime running_ms = unity::TimeUtil::TimeDelta(¤t, &running_time); - float running_progress = CLAMP((float) running_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); - - if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING)) - running_progress = 1.0f - running_progress; - - // After we finish a fade in from running, we can reset the quirk - if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING)) - icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false); + // After we finish the running animation running, we can restore the starting quirk. + if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::Quirk::STARTING, monitor())) + { + icon->SetQuirk(AbstractLauncherIcon::Quirk::STARTING, false, monitor()); + icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::STARTING, monitor()); + } float backlight_strength; if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON) @@ -739,53 +453,48 @@ float Launcher::IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon, s break; case LAUNCH_ANIMATION_BLINK: if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON) - result = IconStartingBlinkValue(icon, current); + result = IconStartingBlinkValue(icon); else if (options()->backlight_mode() == BACKLIGHT_ALWAYS_OFF) - result = 1.0f - IconStartingBlinkValue(icon, current); + result = 1.0f - IconStartingBlinkValue(icon); else result = backlight_strength; // The blink concept is a failure in this case (it just doesn't work right) break; case LAUNCH_ANIMATION_PULSE: - if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING)) - icon->ResetQuirkTime(AbstractLauncherIcon::Quirk::STARTING); - result = backlight_strength; if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON) - result *= CLAMP(running_progress + IconStartingPulseValue(icon, current), 0.0f, 1.0f); + result *= CLAMP(running_progress + IconStartingPulseValue(icon), 0.0f, 1.0f); else if (IsBackLightModeToggles()) - result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconStartingPulseValue(icon, current)); + result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconStartingPulseValue(icon)); else - result = 1.0f - CLAMP(running_progress + IconStartingPulseValue(icon, current), 0.0f, 1.0f); + result = 1.0f - CLAMP(running_progress + IconStartingPulseValue(icon), 0.0f, 1.0f); break; } - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE)) + if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, monitor())) { if (options()->backlight_mode() == BACKLIGHT_ALWAYS_ON) - result *= CLAMP(running_progress + IconPulseOnceValue(icon, current), 0.0f, 1.0f); + result *= CLAMP(running_progress + IconPulseOnceValue(icon), 0.0f, 1.0f); else if (options()->backlight_mode() == BACKLIGHT_NORMAL) - result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconPulseOnceValue(icon, current)); + result += (BACKLIGHT_STRENGTH - result) * (1.0f - IconPulseOnceValue(icon)); else - result = 1.0f - CLAMP(running_progress + IconPulseOnceValue(icon, current), 0.0f, 1.0f); + result = 1.0f - CLAMP(running_progress + IconPulseOnceValue(icon), 0.0f, 1.0f); } // urgent serves to bring the total down only - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT) && options()->urgent_animation() == URGENT_ANIMATION_PULSE) - result *= 0.2f + 0.8f * IconUrgentPulseValue(icon, current); + if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor()) && options()->urgent_animation() == URGENT_ANIMATION_PULSE) + result *= 0.2f + 0.8f * IconUrgentPulseValue(icon); return result; } -float Launcher::IconProgressBias(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const +float Launcher::IconProgressBias(AbstractLauncherIcon::Ptr const& icon) const { - struct timespec icon_progress_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::PROGRESS); - DeltaTime ms = unity::TimeUtil::TimeDelta(¤t, &icon_progress_time); - float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f); + float result = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::PROGRESS, monitor()); - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PROGRESS)) + if (icon->GetQuirk(AbstractLauncherIcon::Quirk::PROGRESS, monitor())) return -1.0f + result; else - return result; + return 1.0f - result; } bool Launcher::IconDrawEdgeOnly(AbstractLauncherIcon::Ptr const& icon) const @@ -799,23 +508,23 @@ bool Launcher::IconDrawEdgeOnly(AbstractLauncherIcon::Ptr const& icon) const return false; } -void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current, RenderArg& arg) +void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, RenderArg& arg) { - float desat_value = IconDesatValue(icon, current); + float stauration = 1.0f - icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::DESAT, monitor()); arg.icon = icon.GetPointer(); - arg.alpha = 0.2f + 0.8f * desat_value; - arg.saturation = desat_value; + arg.alpha = 0.2f + 0.8f * stauration; + arg.saturation = stauration; arg.colorify = nux::color::White; - arg.running_arrow = icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING); - arg.running_colored = icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT); + arg.running_arrow = icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING, monitor()); + arg.running_colored = icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor()); arg.draw_edge_only = IconDrawEdgeOnly(icon); arg.active_colored = false; arg.skip = false; arg.stick_thingy = false; arg.keyboard_nav_hl = false; - arg.progress_bias = IconProgressBias(icon, current); + arg.progress_bias = IconProgressBias(icon); arg.progress = CLAMP(icon->GetProgress(), 0.0f, 1.0f); - arg.draw_shortcut = _shortcuts_shown && !_hide_machine.GetQuirk(LauncherHideMachine::PLACES_VISIBLE); + arg.draw_shortcut = shortcuts_shown_ && !hide_machine_.GetQuirk(LauncherHideMachine::PLACES_VISIBLE); arg.system_item = icon->GetIconType() == AbstractLauncherIcon::IconType::HOME || icon->GetIconType() == AbstractLauncherIcon::IconType::HUD; arg.colorify_background = icon->GetIconType() == AbstractLauncherIcon::IconType::HOME || @@ -832,7 +541,7 @@ void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, struct time arg.saturation = 0.0; } - arg.active_arrow = icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE); + arg.active_arrow = icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, monitor()); /* BFB or HUD icons don't need the active arrow if the overaly is opened * in another monitor */ @@ -855,7 +564,7 @@ void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, struct time arg.shortcut_label = 0; // we dont need to show strays - if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING)) + if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING, monitor())) { arg.window_indicators = 0; } @@ -874,25 +583,26 @@ void Launcher::SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, struct time } } - arg.backlight_intensity = IconBackgroundIntensity(icon, current); - arg.shimmer_progress = IconShimmerProgress(icon, current); + arg.backlight_intensity = IconBackgroundIntensity(icon); + arg.shimmer_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::SHIMMER, monitor()); - float urgent_progress = IconUrgentProgress(icon, current); + float urgent_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::URGENT, monitor()); - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT)) + if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor())) urgent_progress = CLAMP(urgent_progress * 3.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle else urgent_progress = CLAMP(urgent_progress * 3.0f - 2.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle + arg.glow_intensity = urgent_progress; - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT) && options()->urgent_animation() == URGENT_ANIMATION_WIGGLE) + if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE) { - arg.rotation.z = IconUrgentWiggleValue(icon, current); + arg.rotation.z = IconUrgentWiggleValue(icon); } if (IsInKeyNavMode()) { - if (icon == _model->Selection()) + if (icon == model_->Selection()) arg.keyboard_nav_hl = true; } } @@ -906,22 +616,22 @@ void Launcher::FillRenderArg(AbstractLauncherIcon::Ptr const& icon, float folded_spacing, float autohide_offset, float folded_z_distance, - float animation_neg_rads, - struct timespec const& current) + float animation_neg_rads) { - SetupRenderArg(icon, current, arg); + SetupRenderArg(icon, arg); // reset z center.z = 0; - float size_modifier = IconVisibleProgress(icon, current); + float size_modifier = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::VISIBLE, monitor()); if (size_modifier < 1.0f) { arg.alpha *= size_modifier; center.z = 300.0f * (1.0f - size_modifier); } - float drop_dim_value = 0.2f + 0.8f * IconDropDimValue(icon, current); + const float icon_dim = 0.0f; // icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::DROP_DIM, monitor()); + float drop_dim_value = 0.2f + 0.8f * (1.0f - icon_dim); if (drop_dim_value < 1.0f) arg.alpha *= drop_dim_value; @@ -933,45 +643,50 @@ void Launcher::FillRenderArg(AbstractLauncherIcon::Ptr const& icon, arg.saturation = 0.0; } - if (icon == _drag_icon) + if (icon == drag_icon_) { - if (MouseBeyondDragThreshold()) + bool mouse_beyond_drag_threshold = MouseBeyondDragThreshold(); + + if (mouse_beyond_drag_threshold) arg.stick_thingy = true; if (GetActionState() == ACTION_DRAG_ICON || - (_drag_window && _drag_window->Animating()) || + (drag_window_ && drag_window_->Animating()) || icon->GetIconType() == AbstractLauncherIcon::IconType::SPACER) { arg.skip = true; } - size_modifier *= DragThresholdProgress(current); + if (drag_icon_animation_.CurrentState() == na::Animation::State::Running) + size_modifier *= drag_icon_animation_.GetCurrentValue(); + else if (mouse_beyond_drag_threshold) + size_modifier = 0.0f; } if (size_modifier <= 0.0f) arg.skip = true; // goes for 0.0f when fully unfolded, to 1.0f folded - float folding_progress = CLAMP((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f); - float unfold_progress = IconUnfoldProgress(icon, current); + float folding_progress = CLAMP((center.y + icon_size_ - folding_threshold) / (float) icon_size_, 0.0f, 1.0f); + float unfold_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::UNFOLDED, monitor()); folding_progress *= 1.0f - unfold_progress; - float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress); + float half_size = (folded_size / 2.0f) + (icon_size_ / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress); float icon_hide_offset = autohide_offset; - float present_progress = IconPresentProgress(icon, current); + float present_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::PRESENTED, monitor()); icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency()); // icon is crossing threshold, start folding center.z += folded_z_distance * folding_progress; arg.rotation.x = animation_neg_rads * folding_progress; - float spacing_overlap = CLAMP((float)(center.y + (2.0f * half_size * size_modifier) + (_space_between_icons * size_modifier) - folding_threshold) / (float) _icon_size, 0.0f, 1.0f); - float spacing = (_space_between_icons * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier; + float spacing_overlap = CLAMP((float)(center.y + (2.0f * half_size * size_modifier) + (SPACE_BETWEEN_ICONS * size_modifier) - folding_threshold) / (float) icon_size_, 0.0f, 1.0f); + float spacing = (SPACE_BETWEEN_ICONS * (1.0f - spacing_overlap) + folded_spacing * spacing_overlap) * size_modifier; nux::Point3 centerOffset; - float center_transit_progress = IconCenterTransitionProgress(icon, current); + float center_transit_progress = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::CENTER_SAVED, monitor()); if (center_transit_progress <= 1.0f) { int saved_center = icon->GetSavedCenter(monitor).y - parent_abs_geo.y; @@ -983,13 +698,13 @@ void Launcher::FillRenderArg(AbstractLauncherIcon::Ptr const& icon, arg.render_center = nux::Point3(roundf(center.x + icon_hide_offset), roundf(center.y + centerOffset.y), roundf(center.z)); arg.logical_center = nux::Point3(roundf(center.x + icon_hide_offset), roundf(center.y), roundf(center.z)); - icon->SetCenter(nux::Point3(roundf(center.x), roundf(center.y), roundf(center.z)), monitor, parent_abs_geo); + nux::Point3 icon_center(parent_abs_geo.x + roundf(center.x), parent_abs_geo.y + roundf(center.y), roundf(center.z)); + icon->SetCenter(icon_center, monitor); // FIXME: this is a hack, to avoid that we set the target to the end of the icon - if (!_initial_drag_animation && icon == _drag_icon && _drag_window && _drag_window->Animating()) + if (!initial_drag_animation_ && icon == drag_icon_ && drag_window_ && drag_window_->Animating()) { - auto const& icon_center = _drag_icon->GetCenter(monitor); - _drag_window->SetAnimationTarget(icon_center.x, icon_center.y); + drag_window_->SetAnimationTarget(icon_center.x, icon_center.y); } center.y += (half_size * size_modifier) + spacing; // move to end @@ -1004,9 +719,9 @@ float Launcher::DragLimiter(float x) return -result; } -nux::Color FullySaturateColor (nux::Color color) +nux::Color FullySaturateColor(nux::Color color) { - float max = std::max<float>(color.red, std::max<float>(color.green, color.blue)); + float max = std::max<float>({color.red, color.green, color.blue}); if (max > 0.0f) color = color * (1.0f / max); @@ -1020,52 +735,58 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, nux::Geometry const& geo = GetGeometry(); LauncherModel::iterator it; nux::Point3 center; - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); nux::Color const& colorify = FullySaturateColor(options()->background_color); - float hover_progress = GetHoverProgress(current); - float folded_z_distance = _folded_z_distance * (1.0f - hover_progress); - float animation_neg_rads = _neg_folded_angle * (1.0f - hover_progress); + float hover_progress = folded_ ? hover_animation_.GetCurrentValue() : 1.0f; + float folded_z_distance = FOLDED_Z_DISTANCE * (1.0f - hover_progress); + float animation_neg_rads = NEG_FOLDED_ANGLE * (1.0f - hover_progress); float folding_constant = 0.25f; float folding_not_constant = folding_constant + ((1.0f - folding_constant) * hover_progress); - float folded_size = _icon_size * folding_not_constant; - float folded_spacing = _space_between_icons * folding_not_constant; + float folded_size = icon_size_ * folding_not_constant; + float folded_spacing = SPACE_BETWEEN_ICONS * folding_not_constant; center.x = geo.width / 2; - center.y = _space_between_icons; + center.y = SPACE_BETWEEN_ICONS; center.z = 0; int launcher_height = geo.height; + folded_ = true; // compute required height of launcher AND folding threshold float sum = 0.0f + center.y; - float folding_threshold = launcher_height - _icon_size / 2.5f; - for (it = _model->begin(); it != _model->end(); ++it) + float folding_threshold = launcher_height - icon_size_ / 2.5f; + for (it = model_->begin(); it != model_->end(); ++it) { - float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current); + float visibility = (*it)->GetQuirkProgress(AbstractLauncherIcon::Quirk::VISIBLE, monitor()); + float height = (icon_size_ + SPACE_BETWEEN_ICONS) * visibility; sum += height; // magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching"; float magic_constant = 1.3f; - float unfold_progress = IconUnfoldProgress(*it, current); + float unfold_progress = (*it)->GetQuirkProgress(AbstractLauncherIcon::Quirk::UNFOLDED, monitor()); folding_threshold -= CLAMP(sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * unfold_progress); } - if (sum - _space_between_icons <= launcher_height) + if (sum - SPACE_BETWEEN_ICONS <= launcher_height) + { folding_threshold = launcher_height; + folded_ = false; + } float autohide_offset = 0.0f; *launcher_alpha = 1.0f; - if (options()->hide_mode != LAUNCHER_HIDE_NEVER || _hide_machine.GetQuirk(LauncherHideMachine::LOCK_HIDE)) + if (options()->hide_mode != LAUNCHER_HIDE_NEVER || hide_machine_.GetQuirk(LauncherHideMachine::LOCK_HIDE)) { - - float autohide_progress = AutohideProgress(current) * (1.0f - DragOutProgress(current)); - if (options()->auto_hide_animation() == FADE_ONLY) + float autohide_progress = auto_hide_animation_.GetCurrentValue() * (1.0f - DragOutProgress()); + if (dash_is_open_) + { + *launcher_alpha = dash_showing_animation_.GetCurrentValue(); + } + else if (options()->auto_hide_animation() == FADE_ONLY) { *launcher_alpha = 1.0f - autohide_progress; } @@ -1080,19 +801,19 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, } } - float drag_hide_progress = DragHideProgress(current); + float drag_hide_progress = dnd_hide_animation_.GetCurrentValue(); if (options()->hide_mode != LAUNCHER_HIDE_NEVER && drag_hide_progress > 0.0f) { autohide_offset -= geo.width * 0.25f * drag_hide_progress; if (drag_hide_progress >= 1.0f) - _hide_machine.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, true); + hide_machine_.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, true); } // Inform the painter where to paint the box box_geo = geo; - if (options()->hide_mode != LAUNCHER_HIDE_NEVER || _hide_machine.GetQuirk(LauncherHideMachine::LOCK_HIDE)) + if (options()->hide_mode != LAUNCHER_HIDE_NEVER || hide_machine_.GetQuirk(LauncherHideMachine::LOCK_HIDE)) box_geo.x += autohide_offset; /* Why we need last_geo? It stores the last box_geo (note: as it is a static variable, @@ -1104,39 +825,39 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, static nux::Geometry last_geo = box_geo; // this happens on hover, basically its a flag and a value in one, we translate this into a dnd offset - if (_enter_y != 0 && _enter_y + _icon_size / 2 > folding_threshold) - SetDndDelta(last_geo.x + last_geo.width / 2, center.y, geo, current); + if (enter_y_ != 0 && enter_y_ + icon_size_ / 2 > folding_threshold) + SetDndDelta(last_geo.x + last_geo.width / 2, center.y, geo); // Update the last_geo value. last_geo = box_geo; - _enter_y = 0; + enter_y_ = 0; - // logically dnd exit only restores to the clamped ranges // hover_progress restores to 0 - _launcher_drag_delta_max = 0.0f; - _launcher_drag_delta_min = MIN(0.0f, launcher_height - sum); + launcher_drag_delta_max_ = 0.0f; + launcher_drag_delta_min_ = MIN(0.0f, launcher_height - sum); - if (hover_progress > 0.0f && _launcher_drag_delta != 0) + if (hover_progress > 0.0f && launcher_drag_delta_ != 0) { - float delta_y = _launcher_drag_delta; + float delta_y = launcher_drag_delta_; - if (_launcher_drag_delta > _launcher_drag_delta_max) - delta_y = _launcher_drag_delta_max + DragLimiter(delta_y - _launcher_drag_delta_max); - else if (_launcher_drag_delta < _launcher_drag_delta_min) - delta_y = _launcher_drag_delta_min + DragLimiter(delta_y - _launcher_drag_delta_min); + if (launcher_drag_delta_ > launcher_drag_delta_max_) + delta_y = launcher_drag_delta_max_ + DragLimiter(delta_y - launcher_drag_delta_max_); + else if (launcher_drag_delta_ < launcher_drag_delta_min_) + delta_y = launcher_drag_delta_min_ + DragLimiter(delta_y - launcher_drag_delta_min_); if (GetActionState() != ACTION_DRAG_LAUNCHER) { - float dnd_progress = DnDExitProgress(current); + // XXX: nux::Animation should allow to define new kinds of easing curves + float dnd_progress = std::pow(drag_over_animation_.GetCurrentValue(), 2); - if (_launcher_drag_delta > _launcher_drag_delta_max) - delta_y = _launcher_drag_delta_max + (delta_y - _launcher_drag_delta_max) * dnd_progress; - else if (_launcher_drag_delta < _launcher_drag_delta_min) - delta_y = _launcher_drag_delta_min + (delta_y - _launcher_drag_delta_min) * dnd_progress; + if (launcher_drag_delta_ > launcher_drag_delta_max_) + delta_y = launcher_drag_delta_max_ + (delta_y - launcher_drag_delta_max_) * dnd_progress; + else if (launcher_drag_delta_ < launcher_drag_delta_min_) + delta_y = launcher_drag_delta_min_ + (delta_y - launcher_drag_delta_min_) * dnd_progress; if (dnd_progress == 0.0f) - _launcher_drag_delta = (int) delta_y; + launcher_drag_delta_ = (int) delta_y; } delta_y *= hover_progress; @@ -1145,7 +866,7 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, } else { - _launcher_drag_delta = 0; + launcher_drag_delta_ = 0; } // The functional position we wish to represent for these icons is not smooth. Rather than introducing @@ -1153,44 +874,44 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, // function is not smooth it is continuous, which is more important for our visual representation (icons // wont start jumping around). As a general rule ANY if () statements that modify center.y should be seen // as bugs. - for (it = _model->main_begin(); it != _model->main_end(); ++it) + for (it = model_->main_begin(); it != model_->main_end(); ++it) { RenderArg arg; AbstractLauncherIcon::Ptr const& icon = *it; - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT) && options()->hide_mode == LAUNCHER_HIDE_AUTOHIDE) - { - HandleUrgentIcon(icon, current); - } + if (options()->hide_mode == LAUNCHER_HIDE_AUTOHIDE) + HandleUrgentIcon(icon); + FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing, - autohide_offset, folded_z_distance, animation_neg_rads, current); + autohide_offset, folded_z_distance, animation_neg_rads); arg.colorify = colorify; launcher_args.push_back(arg); } // compute maximum height of shelf float shelf_sum = 0.0f; - for (it = _model->shelf_begin(); it != _model->shelf_end(); ++it) + for (it = model_->shelf_begin(); it != model_->shelf_end(); ++it) { - float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current); + float visibility = (*it)->GetQuirkProgress(AbstractLauncherIcon::Quirk::VISIBLE, monitor()); + float height = (icon_size_ + SPACE_BETWEEN_ICONS) * visibility; shelf_sum += height; } // add bottom padding if (shelf_sum > 0.0f) - shelf_sum += _space_between_icons; + shelf_sum += SPACE_BETWEEN_ICONS; - float shelf_delta = MAX(((launcher_height - shelf_sum) + _space_between_icons) - center.y, 0.0f); + float shelf_delta = MAX(((launcher_height - shelf_sum) + SPACE_BETWEEN_ICONS) - center.y, 0.0f); folding_threshold += shelf_delta; center.y += shelf_delta; - for (it = _model->shelf_begin(); it != _model->shelf_end(); ++it) + for (it = model_->shelf_begin(); it != model_->shelf_end(); ++it) { RenderArg arg; AbstractLauncherIcon::Ptr const& icon = *it; FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing, - autohide_offset, folded_z_distance, animation_neg_rads, current); + autohide_offset, folded_z_distance, animation_neg_rads); arg.colorify = colorify; launcher_args.push_back(arg); } @@ -1200,14 +921,14 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, void Launcher::ForceReveal(bool force_reveal) { - _hide_machine.SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, force_reveal); + hide_machine_.SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, force_reveal); } void Launcher::ShowShortcuts(bool show) { - _shortcuts_shown = show; - _hide_machine.SetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE, show); - EnsureAnimation(); + shortcuts_shown_ = show; + hide_machine_.SetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE, show); + QueueDraw(); } void Launcher::OnLockHideChanged(GVariant *data) @@ -1217,33 +938,38 @@ void Launcher::OnLockHideChanged(GVariant *data) if (enable_lock) { - _hide_machine.SetQuirk(LauncherHideMachine::LOCK_HIDE, true); + hide_machine_.SetQuirk(LauncherHideMachine::LOCK_HIDE, true); } else { - _hide_machine.SetQuirk(LauncherHideMachine::LOCK_HIDE, false); + hide_machine_.SetQuirk(LauncherHideMachine::LOCK_HIDE, false); } } void Launcher::DesaturateIcons() { - for (auto icon : *_model) + bool inactive_only = WindowManager::Default().IsScaleActiveForGroup(); + + for (auto const& icon : *model_) { + bool desaturate = false; + if (icon->GetIconType () != AbstractLauncherIcon::IconType::HOME && - icon->GetIconType () != AbstractLauncherIcon::IconType::HUD) + icon->GetIconType () != AbstractLauncherIcon::IconType::HUD && + (!inactive_only || !icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, monitor()))) { - icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true); + desaturate = true; } - icon->HideTooltip(); + icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, desaturate, monitor()); } } void Launcher::SaturateIcons() { - for (auto icon : *_model) + for (auto const& icon : *model_) { - icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false); + icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false, monitor()); } } @@ -1267,26 +993,30 @@ void Launcher::OnOverlayShown(GVariant* data) { if (identity == "dash") { - _dash_is_open = true; - _hide_machine.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, true); - _hover_machine.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, true); + dash_is_open_ = true; + hide_machine_.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, true); + hover_machine_.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, true); + + if (options()->hide_mode != LAUNCHER_HIDE_NEVER) + animation::StartOrReverse(dash_showing_animation_, animation::Direction::FORWARD); } if (identity == "hud") { - _hud_is_open = true; + hud_is_open_ = true; } + bg_effect_helper_.enabled = true; + // Don't desaturate icons if the mouse is over the launcher: - if (!_hovered) + if (!hovered_) { LOG_DEBUG(logger) << "Desaturate on monitor " << monitor(); DesaturateIcons(); } - if (_icon_under_mouse) - _icon_under_mouse->HideTooltip(); + if (icon_under_mouse_) + icon_under_mouse_->HideTooltip(); } - EnsureAnimation(); } void Launcher::OnOverlayHidden(GVariant* data) @@ -1310,13 +1040,14 @@ void Launcher::OnOverlayHidden(GVariant* data) { if (identity == "dash") { - _hide_machine.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, false); - _hover_machine.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, false); - _dash_is_open = false; + dash_is_open_ = false; + hide_machine_.SetQuirk(LauncherHideMachine::PLACES_VISIBLE, false); + hover_machine_.SetQuirk(LauncherHoverMachine::PLACES_VISIBLE, false); + dash_showing_animation_.Stop(); } else if (identity == "hud") { - _hud_is_open = false; + hud_is_open_ = false; } // If they are both now shut, then disable the effect helper and saturate the icons. @@ -1326,8 +1057,13 @@ void Launcher::OnOverlayHidden(GVariant* data) LOG_DEBUG(logger) << "Saturate on monitor " << monitor(); SaturateIcons(); } + else if (WindowManager::Default().IsExpoActive()) + { + // XXX: This is a workaround, we need to disable blur effect on expo to avoid + // a wrong blurred background. Expo should damage the Launcher. + bg_effect_helper_.enabled = false; + } } - EnsureAnimation(); // as the leave event is no more received when the place is opened // FIXME: remove when we change the mouse grab strategy in nux @@ -1337,70 +1073,109 @@ void Launcher::OnOverlayHidden(GVariant* data) bool Launcher::IsOverlayOpen() const { - return _dash_is_open || _hud_is_open; + auto& wm = WindowManager::Default(); + return dash_is_open_ || hud_is_open_ || wm.IsScaleActive() || wm.IsExpoActive(); } void Launcher::SetHidden(bool hide_launcher) { - if (hide_launcher == _hidden) + if (hide_launcher == hidden_) return; - _hidden = hide_launcher; - _hide_machine.SetQuirk(LauncherHideMachine::LAUNCHER_HIDDEN, hide_launcher); - _hover_machine.SetQuirk(LauncherHoverMachine::LAUNCHER_HIDDEN, hide_launcher); + hidden_ = hide_launcher; + hide_machine_.SetQuirk(LauncherHideMachine::LAUNCHER_HIDDEN, hide_launcher); + hover_machine_.SetQuirk(LauncherHoverMachine::LAUNCHER_HIDDEN, hide_launcher); if (hide_launcher) { - _hide_machine.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, false); - _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false); + hide_machine_.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, false); + hide_machine_.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false); SetStateMouseOverLauncher(false); } - _postreveal_mousemove_delta_x = 0; - _postreveal_mousemove_delta_y = 0; + animation::StartOrReverseIf(auto_hide_animation_, hide_launcher); - TimeUtil::SetTimeStruct(&_times[TIME_AUTOHIDE], &_times[TIME_AUTOHIDE], ANIM_DURATION_SHORT); + postreveal_mousemove_delta_x_ = 0; + postreveal_mousemove_delta_y_ = 0; if (nux::GetWindowThread()->IsEmbeddedWindow()) - _parent->EnableInputWindow(!hide_launcher, launcher::window_title, false, false); + parent_->EnableInputWindow(!hide_launcher, launcher::window_title, false, false); if (!hide_launcher && GetActionState() == ACTION_DRAG_EXTERNAL) DndReset(); - EnsureAnimation(); - hidden_changed.emit(); } void Launcher::UpdateChangeInMousePosition(int delta_x, int delta_y) { - _postreveal_mousemove_delta_x += delta_x; - _postreveal_mousemove_delta_y += delta_y; + postreveal_mousemove_delta_x_ += delta_x; + postreveal_mousemove_delta_y_ += delta_y; // check the state before changing it to avoid uneeded hide calls - if (!_hide_machine.GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL) && - (std::abs(_postreveal_mousemove_delta_x) > MOUSE_DEADZONE || - std::abs(_postreveal_mousemove_delta_y) > MOUSE_DEADZONE)) + if (!hide_machine_.GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL) && + (std::abs(postreveal_mousemove_delta_x_) > MOUSE_DEADZONE || + std::abs(postreveal_mousemove_delta_y_) > MOUSE_DEADZONE)) { - _hide_machine.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true); + hide_machine_.SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true); } } int Launcher::GetMouseX() const { - return _mouse_position.x; + return mouse_position_.x; } int Launcher::GetMouseY() const { - return _mouse_position.y; + return mouse_position_.y; } -void Launcher::OnPluginStateChanged() +void Launcher::OnExpoChanged() { WindowManager& wm = WindowManager::Default(); - _hide_machine.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, wm.IsExpoActive()); - _hide_machine.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, wm.IsScaleActive()); + bool expo_active = wm.IsExpoActive(); + hide_machine_.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, expo_active); + // XXX: We must make sure that we regenerate the blur when expo is fully active + // bg_effect_helper_.enabled = expo_active; + + if (expo_active) + { + if (!hovered_) + DesaturateIcons(); + + if (icon_under_mouse_) + icon_under_mouse_->HideTooltip(); + } + else if (!IsOverlayOpen()) + { + SaturateIcons(); + } +} + +void Launcher::OnSpreadChanged() +{ + WindowManager& wm = WindowManager::Default(); + bool active = wm.IsScaleActive(); + hide_machine_.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, active); + + bg_effect_helper_.enabled = active; + + if (active && icon_under_mouse_) + icon_under_mouse_->HideTooltip(); + + if (active && (!hovered_ || wm.IsScaleActiveForGroup())) + { + // The icons can take some ms to update their active state, this can protect us. + sources_.AddIdle([this] { DesaturateIcons(); return false; }, SCALE_DESATURATE_IDLE); + } + else + { + sources_.Remove(SCALE_DESATURATE_IDLE); + + if (!IsOverlayOpen()) + SaturateIcons(); + } } LauncherHideMode Launcher::GetHideMode() const @@ -1428,7 +1203,7 @@ void Launcher::OnMonitorChanged(int new_monitor) unity::panel::Style &panel_style = panel::Style::Instance(); Resize(nux::Point(monitor_geo.x, monitor_geo.y + panel_style.panel_height), monitor_geo.height - panel_style.panel_height); - icon_renderer->monitor = new_monitor; + icon_renderer_->monitor = new_monitor; } void Launcher::UpdateOptions(Options::Ptr options) @@ -1436,8 +1211,14 @@ void Launcher::UpdateOptions(Options::Ptr options) SetIconSize(options->tile_size, options->icon_size); SetHideMode(options->hide_mode); + if (model_) + { + for (auto const& icon : *model_) + SetupIconAnimations(icon); + } + ConfigureBarrier(); - EnsureAnimation(); + QueueDraw(); } void Launcher::ConfigureBarrier() @@ -1445,16 +1226,15 @@ void Launcher::ConfigureBarrier() float decay_responsiveness_mult = ((options()->edge_responsiveness() - 1) * .3f) + 1; float reveal_responsiveness_mult = ((options()->edge_responsiveness() - 1) * .025f) + 1; - _hide_machine.reveal_pressure = options()->edge_reveal_pressure() * reveal_responsiveness_mult; - _hide_machine.edge_decay_rate = options()->edge_decay_rate() * decay_responsiveness_mult; + hide_machine_.reveal_pressure = options()->edge_reveal_pressure() * reveal_responsiveness_mult; + hide_machine_.edge_decay_rate = options()->edge_decay_rate() * decay_responsiveness_mult; } void Launcher::SetHideMode(LauncherHideMode hidemode) { bool fixed_launcher = (hidemode == LAUNCHER_HIDE_NEVER); - _parent->InputWindowEnableStruts(fixed_launcher); - _hide_machine.SetMode(static_cast<LauncherHideMachine::HideMode>(hidemode)); - EnsureAnimation(); + parent_->InputWindowEnableStruts(fixed_launcher); + hide_machine_.SetMode(static_cast<LauncherHideMachine::HideMode>(hidemode)); } BacklightMode Launcher::GetBacklightMode() const @@ -1476,97 +1256,95 @@ bool Launcher::IsBackLightModeToggles() const nux::ObjectPtr<nux::View> const& Launcher::GetActiveTooltip() const { - return _active_tooltip; + return active_tooltip_; } nux::ObjectPtr<LauncherDragWindow> const& Launcher::GetDraggedIcon() const { - return _drag_window; + return drag_window_; } void Launcher::SetActionState(LauncherActionState actionstate) { - if (_launcher_action_state == actionstate) + if (launcher_action_state_ == actionstate) return; - _launcher_action_state = actionstate; + launcher_action_state_ = actionstate; - _hover_machine.SetQuirk(LauncherHoverMachine::LAUNCHER_IN_ACTION, (actionstate != ACTION_NONE)); + hover_machine_.SetQuirk(LauncherHoverMachine::LAUNCHER_IN_ACTION, (actionstate != ACTION_NONE)); } Launcher::LauncherActionState Launcher::GetActionState() const { - return _launcher_action_state; + return launcher_action_state_; } void Launcher::SetHover(bool hovered) { - if (hovered == _hovered) + if (hovered == hovered_) return; - _hovered = hovered; + hovered_ = hovered; - if (_hovered) - { - _enter_y = (int) _mouse_position.y; - TimeUtil::SetTimeStruct(&_times[TIME_ENTER], &_times[TIME_LEAVE], ANIM_DURATION); - } - else - { - TimeUtil::SetTimeStruct(&_times[TIME_LEAVE], &_times[TIME_ENTER], ANIM_DURATION); - } + if (!IsInKeyNavMode() && hovered_) + enter_y_ = mouse_position_.y; + + if (folded_) + animation::StartOrReverseIf(hover_animation_, hovered_); - if (IsOverlayOpen() && !_hide_machine.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE)) + if (IsOverlayOpen() && !hide_machine_.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE)) { - if (hovered && !_hide_machine.GetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE)) + if (hovered && !hide_machine_.GetQuirk(LauncherHideMachine::SHORTCUT_KEYS_VISIBLE)) SaturateIcons(); else DesaturateIcons(); } - - EnsureAnimation(); } bool Launcher::MouseOverTopScrollArea() { - return _mouse_position.y < SCROLL_AREA_HEIGHT; + return mouse_position_.y < SCROLL_AREA_HEIGHT; } bool Launcher::MouseOverBottomScrollArea() { - return _mouse_position.y >= GetGeometry().height - SCROLL_AREA_HEIGHT; + 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) + if (IsInKeyNavMode() || !hovered_ || GetActionState() == ACTION_DRAG_LAUNCHER) { continue_animation = false; } else if (MouseOverTopScrollArea()) { - if (_launcher_drag_delta >= _launcher_drag_delta_max) + if (launcher_drag_delta_ >= launcher_drag_delta_max_) + { continue_animation = false; + } else { - speed = (SCROLL_AREA_HEIGHT - _mouse_position.y) / SCROLL_AREA_HEIGHT * SCROLL_FPS; - _launcher_drag_delta += speed; + int mouse_distance = (SCROLL_AREA_HEIGHT - mouse_position_.y); + int speed = static_cast<float>(mouse_distance) / SCROLL_AREA_HEIGHT * SCROLL_FPS; + launcher_drag_delta_ += speed; } } else if (MouseOverBottomScrollArea()) { - if (_launcher_drag_delta <= _launcher_drag_delta_min) + if (launcher_drag_delta_ <= launcher_drag_delta_min_) + { continue_animation = false; + } else { - speed = ((_mouse_position.y + 1) - (GetGeometry().height - SCROLL_AREA_HEIGHT)) / SCROLL_AREA_HEIGHT * SCROLL_FPS; - _launcher_drag_delta -= speed; - } + int mouse_distance = (mouse_position_.y + 1) - (GetGeometry().height - SCROLL_AREA_HEIGHT); + int speed = static_cast<float>(mouse_distance) / SCROLL_AREA_HEIGHT * SCROLL_FPS; + launcher_drag_delta_ -= speed; + } } else { @@ -1575,7 +1353,7 @@ bool Launcher::OnScrollTimeout() if (continue_animation) { - EnsureAnimation(); + QueueDraw(); } return continue_animation; @@ -1595,182 +1373,221 @@ void Launcher::EnsureScrollTimer() } } -void Launcher::SetUrgentTimer(int urgent_wiggle_period) +void Launcher::SetUrgentTimer(int urgent_animate_period) { - sources_.AddTimeoutSeconds(urgent_wiggle_period, sigc::mem_fun(this, &Launcher::OnUrgentTimeout), URGENT_TIMEOUT); + sources_.AddTimeoutSeconds(urgent_animate_period, sigc::mem_fun(this, &Launcher::OnUrgentTimeout), URGENT_TIMEOUT); } -void Launcher::WiggleUrgentIcon(AbstractLauncherIcon::Ptr const& icon) +void Launcher::AnimateUrgentIcon(AbstractLauncherIcon::Ptr const& icon) { - icon->SetQuirk(AbstractLauncherIcon::Quirk::URGENT, false); - icon->SetQuirk(AbstractLauncherIcon::Quirk::URGENT, true); - - clock_gettime(CLOCK_MONOTONIC, &_urgent_finished_time); + icon->SetQuirk(AbstractLauncherIcon::Quirk::URGENT, false, monitor()); + icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::URGENT, monitor()); + icon->SetQuirk(AbstractLauncherIcon::Quirk::URGENT, true, monitor()); } -void Launcher::HandleUrgentIcon(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) +void Launcher::HandleUrgentIcon(AbstractLauncherIcon::Ptr const& icon) { - struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT); - DeltaTime urgent_delta = unity::TimeUtil::TimeDelta(&urgent_time, &_urgent_finished_time); - - // If the Launcher is hidden, then add a timer to wiggle the urgent icons at - // certain intervals (1m, 2m, 4m, 8m, 16m, & 32m). - if (_hidden && !_urgent_timer_running && urgent_delta > 0) - { - _urgent_timer_running = true; - _urgent_ack_needed = true; - SetUrgentTimer(BASE_URGENT_WIGGLE_PERIOD); - } - // If the Launcher is hidden, the timer is running, an urgent icon is newer than the last time - // icons were wiggled, and the timer did not just start, then reset the timer since a new - // urgent icon just showed up. - else if (_hidden && _urgent_timer_running && urgent_delta > 0 && _urgent_wiggle_time != 0) + if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor())) { - _urgent_wiggle_time = 0; - SetUrgentTimer(BASE_URGENT_WIGGLE_PERIOD); + if (animating_urgent_icons_.erase(icon) > 0) + { + if (animating_urgent_icons_.empty()) + { + sources_.Remove(URGENT_TIMEOUT); + sources_.Remove(LAST_ANIMATION_URGENT_IDLE); + } + } + + return; } - // If the Launcher is no longer hidden, then after the Launcher is fully revealed, wiggle the - // urgent icon and then stop the timer (if it's running). - else if (!_hidden && _urgent_ack_needed) + + bool animating = (animating_urgent_icons_.find(icon) != animating_urgent_icons_.end()); + + if (hidden_ && !animating) { - if (_last_reveal_progress > 0) + bool urgent_timer_running = sources_.GetSource(URGENT_TIMEOUT) != nullptr; + + // If the Launcher is hidden, then add a timer to wiggle the urgent icons at + // certain intervals (1m, 2m, 4m, 8m, 16m, & 32m). + if (!urgent_timer_running && !animating) { - _urgent_acked = false; + urgent_ack_needed_ = true; + SetUrgentTimer(BASE_URGENT_ANIMATION_PERIOD); } - else + // If the Launcher is hidden, the timer is running, an urgent icon is newer than the last time + // icons were wiggled, and the timer did not just start, then reset the timer since a new + // urgent icon just showed up. + else if (urgent_timer_running && urgent_animation_period_ != 0) { - if (!_urgent_acked && IconUrgentProgress(icon, current) == 1.0f) - { - WiggleUrgentIcon(icon); - } - else if (IconUrgentProgress(icon, current) < 1.0f) - { - if (_urgent_timer_running) - { - sources_.Remove(URGENT_TIMEOUT); - _urgent_timer_running = false; - } - _urgent_acked = true; - _urgent_ack_needed = false; - } + urgent_animation_period_ = 0; + SetUrgentTimer(BASE_URGENT_ANIMATION_PERIOD); } + + animating_urgent_icons_.insert(icon); + } + // If the Launcher is no longer hidden, then after the Launcher is fully revealed, wiggle the + // urgent icon and then stop the timer (if it's running). + else if (!hidden_ && urgent_ack_needed_) + { + sources_.AddIdle([this] { + if (hidden_ || hide_machine_.reveal_progress == 1.0f) + return false; + + if (hide_machine_.reveal_progress > 0) + return true; + + for (auto const& icon : animating_urgent_icons_) + AnimateUrgentIcon(icon); + + sources_.Remove(URGENT_TIMEOUT); + urgent_ack_needed_ = false; + return false; + }, LAST_ANIMATION_URGENT_IDLE); } } bool Launcher::OnUrgentTimeout() { - bool foundUrgent = false, - continue_urgent = true; + bool foundUrgent = false; - if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE && _hidden) + if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE && hidden_) { // Look for any icons that are still urgent and wiggle them - for (auto icon : *_model) + for (auto icon : *model_) { - if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT)) + if (icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor())) { - WiggleUrgentIcon(icon); + AnimateUrgentIcon(icon); foundUrgent = true; } } } // Update the time for when the next wiggle will occur. - if (_urgent_wiggle_time == 0) + if (urgent_animation_period_ == 0) { - _urgent_wiggle_time = BASE_URGENT_WIGGLE_PERIOD; + urgent_animation_period_ = BASE_URGENT_ANIMATION_PERIOD; } else { - _urgent_wiggle_time = _urgent_wiggle_time * DOUBLE_TIME; + urgent_animation_period_ = urgent_animation_period_ * DOUBLE_TIME; } // If no urgent icons were found or we have reached the time threshold, // then let's stop the timer. Otherwise, start a new timer with the // updated wiggle time. - if (!foundUrgent || (_urgent_wiggle_time > MAX_URGENT_WIGGLE_DELTA)) - { - continue_urgent = false; - _urgent_timer_running = false; - } - else + if (!foundUrgent || (urgent_animation_period_ > MAX_URGENT_ANIMATION_DELTA)) { - SetUrgentTimer(_urgent_wiggle_time); + return false; } - return continue_urgent; + SetUrgentTimer(urgent_animation_period_); + return false; } void Launcher::SetIconSize(int tile_size, int icon_size) { ui::IconRenderer::DestroyShortcutTextures(); - _icon_size = tile_size; - _icon_image_size = icon_size; - _icon_image_size_delta = tile_size - icon_size; - _icon_glow_size = icon_size + 14; - - icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons); + icon_size_ = tile_size; + icon_renderer_->SetTargetSize(icon_size_, icon_size, SPACE_BETWEEN_ICONS); + AbstractLauncherIcon::icon_size = icon_size_; - nux::Geometry const& parent_geo = _parent->GetGeometry(); + nux::Geometry const& parent_geo = parent_->GetGeometry(); Resize(nux::Point(parent_geo.x, parent_geo.y), parent_geo.height); } int Launcher::GetIconSize() const { - return _icon_size; + return icon_size_; } void Launcher::Resize(nux::Point const& offset, int height) { - unsigned width = _icon_size + ICON_PADDING * 2 + RIGHT_LINE_WIDTH - 2; + unsigned width = icon_size_ + ICON_PADDING * 2 + RIGHT_LINE_WIDTH - 2; SetMaximumHeight(height); SetGeometry(nux::Geometry(0, 0, width, height)); - _parent->SetGeometry(nux::Geometry(offset.x, offset.y, width, height)); + parent_->SetGeometry(nux::Geometry(offset.x, offset.y, width, height)); ConfigureBarrier(); } +void Launcher::OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon, int icon_monitor) +{ + if (icon_monitor < 0 || icon_monitor == monitor()) + QueueDraw(); +} + void Launcher::OnIconAdded(AbstractLauncherIcon::Ptr const& icon) { - EnsureAnimation(); + SetupIconAnimations(icon); icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw)); icon->tooltip_visible.connect(sigc::mem_fun(this, &Launcher::OnTooltipVisible)); + + if (IsOverlayOpen() && !hovered_) + { + icon->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true, monitor()); + icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::DESAT, monitor()); + } + + if (icon->IsVisibleOnMonitor(monitor())) + QueueDraw(); } void Launcher::OnIconRemoved(AbstractLauncherIcon::Ptr const& icon) { SetIconUnderMouse(AbstractLauncherIcon::Ptr()); - if (icon == _icon_mouse_down) - _icon_mouse_down = nullptr; - if (icon == _drag_icon) - _drag_icon = nullptr; + if (icon == icon_mouse_down_) + icon_mouse_down_ = nullptr; + if (icon == drag_icon_) + drag_icon_ = nullptr; + + animating_urgent_icons_.erase(icon); - EnsureAnimation(); + if (icon->IsVisibleOnMonitor(monitor())) + QueueDraw(); } -void Launcher::OnOrderChanged() +void Launcher::SetupIconAnimations(AbstractLauncherIcon::Ptr const& icon) { - EnsureAnimation(); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::VISIBLE, ANIM_DURATION_SHORT, monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::RUNNING, ANIM_DURATION_SHORT, monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::STARTING, (ANIM_DURATION_LONG * MAX_STARTING_BLINKS * STARTING_BLINK_LAMBDA * 2), monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::PULSE_ONCE, (ANIM_DURATION_LONG * PULSE_BLINK_LAMBDA * 2), monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::PRESENTED, ANIM_DURATION, monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::UNFOLDED, ANIM_DURATION, monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::SHIMMER, ANIM_DURATION_LONG, monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::CENTER_SAVED, ANIM_DURATION, monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::PROGRESS, ANIM_DURATION, monitor()); + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::DESAT, ANIM_DURATION_SHORT_SHORT, monitor()); + + if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE) + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::URGENT, (ANIM_DURATION_SHORT * WIGGLE_CYCLES), monitor()); + else + icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::URGENT, (ANIM_DURATION_LONG * URGENT_BLINKS * 2), monitor()); } void Launcher::SetModel(LauncherModel::Ptr model) { - _model = model; + model_ = model; + auto const& queue_draw_cb = sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw); - for (auto icon : *_model) - icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw)); + for (auto const& icon : *model_) + { + SetupIconAnimations(icon); + icon->needs_redraw.connect(queue_draw_cb); + } - _model->icon_added.connect(sigc::mem_fun(this, &Launcher::OnIconAdded)); - _model->icon_removed.connect(sigc::mem_fun(this, &Launcher::OnIconRemoved)); - _model->order_changed.connect(sigc::mem_fun(this, &Launcher::OnOrderChanged)); - _model->selection_changed.connect(sigc::mem_fun(this, &Launcher::OnSelectionChanged)); + model_->icon_added.connect(sigc::mem_fun(this, &Launcher::OnIconAdded)); + model_->icon_removed.connect(sigc::mem_fun(this, &Launcher::OnIconRemoved)); + model_->order_changed.connect(sigc::mem_fun(this, &Launcher::QueueDraw)); + model_->selection_changed.connect(sigc::mem_fun(this, &Launcher::OnSelectionChanged)); } LauncherModel::Ptr Launcher::GetModel() const { - return _model; + return model_; } void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr const& selection) @@ -1778,21 +1595,21 @@ void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr const& selection) nux::Geometry const& geo = GetGeometry(); int natural_y = 0; - for (auto icon : *_model) + for (auto icon : *model_) { - if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor)) + if (!icon->IsVisibleOnMonitor(monitor)) continue; if (icon == selection) break; - natural_y += _icon_size + _space_between_icons; + natural_y += icon_size_ + SPACE_BETWEEN_ICONS; } - int max_drag_delta = geo.height - (natural_y + _icon_size + (2 * _space_between_icons)); + int max_drag_delta = geo.height - (natural_y + icon_size_ + (2 * SPACE_BETWEEN_ICONS)); int min_drag_delta = -natural_y; - _launcher_drag_delta = std::max<int>(min_drag_delta, std::min<int>(max_drag_delta, _launcher_drag_delta)); + launcher_drag_delta_ = std::max<int>(min_drag_delta, std::min<int>(max_drag_delta, launcher_drag_delta_)); } void Launcher::OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection) @@ -1800,18 +1617,13 @@ void Launcher::OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection) if (IsInKeyNavMode()) { EnsureIconOnScreen(selection); - EnsureAnimation(); + QueueDraw(); } } -void Launcher::OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon) -{ - EnsureAnimation(); -} - void Launcher::OnTooltipVisible(nux::ObjectPtr<nux::View> view) { - _active_tooltip = view; + active_tooltip_ = view; } void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) @@ -1827,17 +1639,6 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) std::list<RenderArg>::reverse_iterator rev_it; float launcher_alpha = 1.0f; - // rely on the compiz event loop to come back to us in a nice throttling - if (AnimationInProgress()) - { - auto idle = std::make_shared<glib::Idle>(glib::Source::Priority::DEFAULT); - sources_.Add(idle, ANIMATION_IDLE); - idle->Run([&]() { - EnsureAnimation(); - return false; - }); - } - nux::ROPConfig ROP; ROP.Blend = false; ROP.SrcBlend = GL_ONE; @@ -1846,9 +1647,9 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) nux::Geometry const& geo_absolute = GetAbsoluteGeometry(); RenderArgs(args, bkg_box, &launcher_alpha, geo_absolute); bkg_box.width -= RIGHT_LINE_WIDTH; - + nux::Color clear_colour = nux::Color(0x00000000); - + if (Settings::Instance().GetLowGfxMode()) { clear_colour = options()->background_color; @@ -1871,21 +1672,21 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) // clip vertically but not horizontally GfxContext.PushClippingRectangle(nux::Geometry(base.x, bkg_box.y, base.width, bkg_box.height)); - float reveal_progress = _hide_machine.reveal_progress; - if ((reveal_progress > 0 || _last_reveal_progress > 0) && launcher_pressure_effect_.IsValid()) + float reveal_progress = hide_machine_.reveal_progress; + if ((reveal_progress > 0 || last_reveal_progress_ > 0) && launcher_pressure_effect_.IsValid()) { - if (std::abs(_last_reveal_progress - reveal_progress) <= .1f) + if (std::abs(last_reveal_progress_ - reveal_progress) <= .1f) { - _last_reveal_progress = reveal_progress; + last_reveal_progress_ = reveal_progress; } else { - if (_last_reveal_progress > reveal_progress) - _last_reveal_progress -= .1f; + if (last_reveal_progress_ > reveal_progress) + last_reveal_progress_ -= .1f; else - _last_reveal_progress += .1f; + last_reveal_progress_ += .1f; } - nux::Color pressure_color = nux::color::White * _last_reveal_progress; + nux::Color pressure_color = nux::color::White * last_reveal_progress_; nux::TexCoordXForm texxform_pressure; GfxContext.QRP_1Tex(base.x, base.y, launcher_pressure_effect_->GetWidth(), base.height, launcher_pressure_effect_->GetDeviceTexture(), @@ -1893,9 +1694,9 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) pressure_color); } - if (Settings::Instance().GetLowGfxMode() == false) + if (!Settings::Instance().GetLowGfxMode()) { - if (IsOverlayOpen()) + if (IsOverlayOpen() && bg_effect_helper_.enabled) { nux::ObjectPtr<nux::IOpenGLBaseTexture> blur_texture; @@ -1910,40 +1711,44 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) if (blur_texture.IsValid()) { - nux::TexCoordXForm texxform_blur_bg; - texxform_blur_bg.flip_v_coord = true; - texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); - texxform_blur_bg.uoffset = ((float) base.x) / geo_absolute.width; - texxform_blur_bg.voffset = ((float) base.y) / geo_absolute.height; + nux::TexCoordXForm texxform_blur_bg; + texxform_blur_bg.flip_v_coord = true; + texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); + texxform_blur_bg.uoffset = ((float) base.x) / geo_absolute.width; + texxform_blur_bg.voffset = ((float) base.y) / geo_absolute.height; - GfxContext.PushClippingRectangle(bkg_box); + GfxContext.PushClippingRectangle(bkg_box); #ifndef NUX_OPENGLES_20 - if (GfxContext.UsingGLSLCodePath()) - gPainter.PushDrawCompositionLayer(GfxContext, base, - blur_texture, - texxform_blur_bg, - nux::color::White, - options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY, - true, ROP); - else - gPainter.PushDrawTextureLayer(GfxContext, base, - blur_texture, - texxform_blur_bg, - nux::color::White, - true, - ROP); + if (GfxContext.UsingGLSLCodePath()) + { + gPainter.PushDrawCompositionLayer(GfxContext, base, + blur_texture, + texxform_blur_bg, + nux::color::White, + options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY, + true, ROP); + } + else + { + gPainter.PushDrawTextureLayer(GfxContext, base, + blur_texture, + texxform_blur_bg, + nux::color::White, + true, + ROP); + } #else - gPainter.PushDrawCompositionLayer(GfxContext, base, - blur_texture, - texxform_blur_bg, - nux::color::White, - options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY, - true, ROP); + gPainter.PushDrawCompositionLayer(GfxContext, base, + blur_texture, + texxform_blur_bg, + nux::color::White, + options()->background_color, nux::LAYER_BLEND_MODE_OVERLAY, + true, ROP); #endif - GfxContext.PopClippingRectangle(); + GfxContext.PopClippingRectangle(); - push_count++; + push_count++; } unsigned int alpha = 0, src = 0, dest = 0; @@ -1957,7 +1762,7 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) // apply the bg colour #ifndef NUX_OPENGLES_20 if (GfxContext.UsingGLSLCodePath() == false) - gPainter.Paint2DQuadColor(GfxContext, bkg_box, options()->background_color); + gPainter.Paint2DQuadColor(GfxContext, bkg_box, options()->background_color); #endif // apply the shine @@ -1968,9 +1773,9 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) texxform.uoffset = (1.0f / launcher_sheen_->GetWidth()); // TODO (gord) don't use absolute values here texxform.voffset = (1.0f / launcher_sheen_->GetHeight()) * panel::Style::Instance().panel_height; GfxContext.QRP_1Tex(base.x, base.y, base.width, base.height, - launcher_sheen_->GetDeviceTexture(), - texxform, - nux::color::White); + launcher_sheen_->GetDeviceTexture(), + texxform, + nux::color::White); //reset the blend state GfxContext.GetRenderStates().SetBlend (alpha, src, dest); @@ -1985,7 +1790,8 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER); - icon_renderer->PreprocessIcons(args, base); + // XXX: It would be very cool to move the Rendering part out of the drawing part + icon_renderer_->PreprocessIcons(args, base); EventLogic(); /* draw launcher */ @@ -1999,7 +1805,7 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) if ((*rev_it).skip) continue; - icon_renderer->RenderIcon(GfxContext, *rev_it, bkg_box, base); + icon_renderer_->RenderIcon(GfxContext, *rev_it, bkg_box, base); } if (!IsOverlayOpen()) @@ -2049,7 +1855,7 @@ long Launcher::PostLayoutManagement(long LayoutResult) void Launcher::OnDragWindowAnimCompleted() { HideDragWindow(); - EnsureAnimation(); + QueueDraw(); } bool Launcher::StartIconDragTimeout(int x, int y) @@ -2058,7 +1864,7 @@ bool Launcher::StartIconDragTimeout(int x, int y) if (GetActionState() == ACTION_NONE) { SetIconUnderMouse(AbstractLauncherIcon::Ptr()); - _initial_drag_animation = true; + initial_drag_animation_ = true; StartIconDragRequest(x, y); } @@ -2067,12 +1873,12 @@ bool Launcher::StartIconDragTimeout(int x, int y) void Launcher::StartIconDragRequest(int x, int y) { - nux::Geometry const& abs_geo = GetAbsoluteGeometry(); - AbstractLauncherIcon::Ptr const& drag_icon = MouseIconIntersection(abs_geo.width / 2.0f, y); + auto const& abs_geo = GetAbsoluteGeometry(); + auto const& drag_icon = MouseIconIntersection(abs_geo.width / 2.0f, y); // FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying // on an internal Launcher property then - if (drag_icon && _last_button_press == 1 && drag_icon->position() == AbstractLauncherIcon::Position::FLOATING) + if (drag_icon && last_button_press_ == 1 && drag_icon->position() == AbstractLauncherIcon::Position::FLOATING) { auto const& icon_center = drag_icon->GetCenter(monitor); x += abs_geo.x; @@ -2082,17 +1888,17 @@ void Launcher::StartIconDragRequest(int x, int y) StartIconDrag(drag_icon); UpdateDragWindowPosition(icon_center.x, icon_center.y); - if (_initial_drag_animation) + if (initial_drag_animation_) { - _drag_window->SetAnimationTarget(x, y); - _drag_window->StartQuickAnimation(); + drag_window_->SetAnimationTarget(x, y); + drag_window_->StartQuickAnimation(); } - EnsureAnimation(); + QueueDraw(); } else { - _drag_icon = nullptr; + drag_icon_ = nullptr; HideDragWindow(); } } @@ -2104,80 +1910,74 @@ void Launcher::StartIconDrag(AbstractLauncherIcon::Ptr const& icon) if (!icon) return; - _hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true); - _drag_icon = icon; - _drag_icon_position = _model->IconIndex(icon); + hide_machine_.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true); + drag_icon_ = icon; + drag_icon_position_ = model_->IconIndex(icon); HideDragWindow(); - _offscreen_drag_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(GetWidth(), GetWidth(), 1, nux::BITFMT_R8G8B8A8); - _drag_window = new LauncherDragWindow(_offscreen_drag_texture, - std::bind(&Launcher::RenderIconToTexture, this, - _1, - _drag_icon, _offscreen_drag_texture)); - ShowDragWindow(); - ubus_.SendMessage(UBUS_LAUNCHER_ICON_START_DND); + auto cb = std::bind(&Launcher::RenderIconToTexture, this, _1, _2, drag_icon_); + drag_window_ = new LauncherDragWindow(GetWidth(), cb); + ShowDragWindow(); } void Launcher::EndIconDrag() { - if (_drag_window) + if (drag_window_) { AbstractLauncherIcon::Ptr hovered_icon; - if (!_drag_window->Cancelled()) - hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); + if (!drag_window_->Cancelled()) + hovered_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y); if (hovered_icon && hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH) { - hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, true); + hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, true, monitor()); - remove_request.emit(_drag_icon); + remove_request.emit(drag_icon_); HideDragWindow(); - EnsureAnimation(); + QueueDraw(); } else { - if (!_drag_window->Cancelled() && _model->IconIndex(_drag_icon) != _drag_icon_position) + if (!drag_window_->Cancelled() && model_->IconIndex(drag_icon_) != drag_icon_position_) { - _drag_icon->Stick(false); - _model->Save(); + drag_icon_->Stick(true); } - _drag_window->on_anim_completed_conn_ = _drag_window->anim_completed.connect(sigc::mem_fun(this, &Launcher::OnDragWindowAnimCompleted)); - - auto const& icon_center = _drag_icon->GetCenter(monitor); - _drag_window->SetAnimationTarget(icon_center.x, icon_center.y), - _drag_window->StartQuickAnimation(); + auto const& icon_center = drag_icon_->GetCenter(monitor); + drag_window_->SetAnimationTarget(icon_center.x, icon_center.y); + drag_window_->anim_completed.connect(sigc::mem_fun(this, &Launcher::OnDragWindowAnimCompleted)); + drag_window_->StartQuickAnimation(); } } if (MouseBeyondDragThreshold()) - TimeUtil::SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT); + animation::StartOrReverse(drag_icon_animation_, animation::Direction::FORWARD); - _hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, false); - ubus_.SendMessage(UBUS_LAUNCHER_ICON_END_DND); + hide_machine_.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, false); } void Launcher::ShowDragWindow() { - if (!_drag_window || _drag_window->IsVisible()) + if (!drag_window_ || drag_window_->IsVisible()) return; - _drag_window->GrabKeyboard(); - _drag_window->ShowWindow(true); - _drag_window->PushToFront(); + drag_window_->GrabKeyboard(); + drag_window_->ShowWindow(true); + drag_window_->PushToFront(); bool is_before; - AbstractLauncherIcon::Ptr const& closer = _model->GetClosestIcon(_drag_icon, is_before); - _drag_window->drag_cancel_request.connect([this, closer, is_before] { + AbstractLauncherIcon::Ptr const& closer = model_->GetClosestIcon(drag_icon_, is_before); + drag_window_->drag_cancel_request.connect([this, closer, is_before] { if (is_before) - _model->ReorderAfter(_drag_icon, closer); + model_->ReorderAfter(drag_icon_, closer); else - _model->ReorderBefore(_drag_icon, closer, true); + model_->ReorderBefore(drag_icon_, closer, true); ResetMouseDragState(); + SetActionState(ACTION_DRAG_ICON_CANCELLED); }); } @@ -2189,55 +1989,53 @@ void Launcher::HideDragWindow() if (abs_geo.IsInside(mouse)) mouse_enter.emit(mouse.x - abs_geo.x, mouse.y - abs_geo.y, 0, 0); - if (!_drag_window) + if (!drag_window_) return; - _drag_window->UnGrabKeyboard(); - _drag_window->ShowWindow(false); - _drag_window = nullptr; + drag_window_->UnGrabKeyboard(); + drag_window_->ShowWindow(false); + drag_window_ = nullptr; } void Launcher::UpdateDragWindowPosition(int x, int y) { - if (!_drag_window) + if (!drag_window_) return; - auto const& icon_geo = _drag_window->GetGeometry(); - _drag_window->SetBaseXY(x - icon_geo.width / 2, y - icon_geo.height / 2); + auto const& icon_geo = drag_window_->GetGeometry(); + drag_window_->SetBaseXY(x - icon_geo.width / 2, y - icon_geo.height / 2); - if (!_drag_icon) + if (!drag_icon_) return; auto const& launcher_geo = GetGeometry(); auto const& hovered_icon = MouseIconIntersection((launcher_geo.x + launcher_geo.width) / 2.0, y - GetAbsoluteY()); - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - float progress = DragThresholdProgress(current); + bool mouse_beyond_drag_threshold = MouseBeyondDragThreshold(); - if (hovered_icon && _drag_icon != hovered_icon) + if (hovered_icon && drag_icon_ != hovered_icon) { - if (progress >= 1.0f) + if (!mouse_beyond_drag_threshold) { - _model->ReorderSmart(_drag_icon, hovered_icon, true); + model_->ReorderSmart(drag_icon_, hovered_icon, true); } - else if (progress == 0.0f) + else { - _model->ReorderBefore(_drag_icon, hovered_icon, false); + model_->ReorderBefore(drag_icon_, hovered_icon, false); } } - else if (!hovered_icon && progress == 0.0f) + else if (!hovered_icon && mouse_beyond_drag_threshold) { // If no icon is hovered, then we can add our icon to the bottom - for (auto it = _model->main_rbegin(); it != _model->main_rend(); ++it) + for (auto it = model_->main_rbegin(); it != model_->main_rend(); ++it) { auto const& icon = *it; - if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor)) + if (!icon->IsVisibleOnMonitor(monitor)) continue; if (y >= icon->GetCenter(monitor).y) { - _model->ReorderAfter(_drag_icon, icon); + model_->ReorderAfter(drag_icon_, icon); break; } } @@ -2250,22 +2048,20 @@ void Launcher::ResetMouseDragState() EndIconDrag(); if (GetActionState() == ACTION_DRAG_LAUNCHER) - _hide_machine.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, false); + hide_machine_.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, false); SetActionState(ACTION_NONE); - _dnd_delta_x = 0; - _dnd_delta_y = 0; - _last_button_press = 0; - EnsureAnimation(); + dnd_delta_x_ = 0; + dnd_delta_y_ = 0; + last_button_press_ = 0; } void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags) { - _last_button_press = nux::GetEventButton(button_flags); + last_button_press_ = nux::GetEventButton(button_flags); SetMousePosition(x, y); MouseDownLogic(x, y, button_flags, key_flags); - EnsureAnimation(); } void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags) @@ -2282,19 +2078,19 @@ void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_ * on an internal Launcher property then */ - if (_last_button_press != 1) + if (last_button_press_ != 1) return; SetMousePosition(x, y); // FIXME: hack (see SetupRenderArg) - _initial_drag_animation = false; + initial_drag_animation_ = false; - _dnd_delta_y += dy; - _dnd_delta_x += dx; + dnd_delta_y_ += dy; + dnd_delta_x_ += dx; - if (nux::Abs(_dnd_delta_y) < MOUSE_DEADZONE && - nux::Abs(_dnd_delta_x) < MOUSE_DEADZONE && + if (nux::Abs(dnd_delta_y_) < MOUSE_DEADZONE && + nux::Abs(dnd_delta_x_) < MOUSE_DEADZONE && GetActionState() == ACTION_NONE) return; @@ -2303,24 +2099,23 @@ void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_ if (GetActionState() == ACTION_NONE) { #ifdef USE_X11 - if (nux::Abs(_dnd_delta_y) >= nux::Abs(_dnd_delta_x)) + if (nux::Abs(dnd_delta_y_) >= nux::Abs(dnd_delta_x_)) { - _launcher_drag_delta += _dnd_delta_y; + launcher_drag_delta_ += dnd_delta_y_; SetActionState(ACTION_DRAG_LAUNCHER); - _hide_machine.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, true); + hide_machine_.SetQuirk(LauncherHideMachine::VERTICAL_SLIDE_ACTIVE, true); } else { // We we can safely start the icon drag, from the original mouse-down position sources_.Remove(START_DRAGICON_DURATION); - StartIconDragRequest(x - _dnd_delta_x, y - _dnd_delta_y); + StartIconDragRequest(x - dnd_delta_x_, y - dnd_delta_y_); } #endif } else if (GetActionState() == ACTION_DRAG_LAUNCHER) { - _launcher_drag_delta += dy; - ubus_.SendMessage(UBUS_LAUNCHER_END_DND); + launcher_drag_delta_ += dy; } else if (GetActionState() == ACTION_DRAG_ICON) { @@ -2328,40 +2123,44 @@ void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_ UpdateDragWindowPosition(geo.x + x, geo.y + y); } - EnsureAnimation(); + QueueDraw(); } void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags) { SetMousePosition(x, y); SetStateMouseOverLauncher(true); - EventLogic(); - EnsureAnimation(); } void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags) { SetStateMouseOverLauncher(false); EventLogic(); - EnsureAnimation(); } 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) + if (!hidden_) UpdateChangeInMousePosition(dx, dy); // Every time the mouse moves, we check if it is inside an icon... EventLogic(); + + if (icon_under_mouse_ && WindowManager::Default().IsScaleActiveForGroup()) + { + if (!icon_under_mouse_->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE, monitor())) + SaturateIcons(); + } + + tooltip_manager_.MouseMoved(icon_under_mouse_); } void Launcher::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned long /*button_flags*/, unsigned long key_flags) { - if (!_hovered) + if (!hovered_) return; bool alt_pressed = nux::GetKeyModifierState(key_flags, nux::NUX_STATE_ALT); @@ -2369,11 +2168,11 @@ void Launcher::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned lo { ScrollLauncher(wheel_delta); } - else if (_icon_under_mouse) + 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); + icon_under_mouse_->PerformScroll(scroll_direction, timestamp); } } @@ -2381,19 +2180,19 @@ void Launcher::ScrollLauncher(int wheel_delta) { if (wheel_delta < 0) // scroll down - _launcher_drag_delta -= 25; + launcher_drag_delta_ -= 25; else // scroll up - _launcher_drag_delta += 25; + launcher_drag_delta_ += 25; - EnsureAnimation(); + QueueDraw(); } #ifdef USE_X11 ui::EdgeBarrierSubscriber::Result Launcher::HandleBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event) { - if (_hide_machine.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE)) + if (hide_machine_.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE)) { return ui::EdgeBarrierSubscriber::Result::NEEDS_RELEASE; } @@ -2403,7 +2202,7 @@ ui::EdgeBarrierSubscriber::Result Launcher::HandleBarrierEvent(ui::PointerBarrie bool apply_to_reveal = false; if (event->x >= abs_geo.x && event->x <= abs_geo.x + abs_geo.width) { - if (!_hidden) + if (!hidden_) return ui::EdgeBarrierSubscriber::Result::ALREADY_HANDLED; if (options()->reveal_trigger == RevealTrigger::EDGE) @@ -2437,7 +2236,7 @@ ui::EdgeBarrierSubscriber::Result Launcher::HandleBarrierEvent(ui::PointerBarrie return ui::EdgeBarrierSubscriber::Result::IGNORED; if (!owner->IsFirstEvent()) - _hide_machine.AddRevealPressure(event->velocity); + hide_machine_.AddRevealPressure(event->velocity); return ui::EdgeBarrierSubscriber::Result::HANDLED; } @@ -2446,20 +2245,20 @@ ui::EdgeBarrierSubscriber::Result Launcher::HandleBarrierEvent(ui::PointerBarrie bool Launcher::IsInKeyNavMode() const { - return _hide_machine.GetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE); + return hide_machine_.GetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE); } void Launcher::EnterKeyNavMode() { - _hide_machine.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, true); - _hover_machine.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, true); + hide_machine_.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, true); + hover_machine_.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, true); SaturateIcons(); } void Launcher::ExitKeyNavMode() { - _hide_machine.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, false); - _hover_machine.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, false); + hide_machine_.SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, false); + hover_machine_.SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, false); } void Launcher::RecvQuicklistOpened(nux::ObjectPtr<QuicklistView> const& quicklist) @@ -2467,10 +2266,9 @@ void Launcher::RecvQuicklistOpened(nux::ObjectPtr<QuicklistView> const& quicklis UScreen* uscreen = UScreen::GetDefault(); if (uscreen->GetMonitorGeometry(monitor).IsInside(nux::Point(quicklist->GetGeometry().x, quicklist->GetGeometry().y))) { - _hide_machine.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, true); - _hover_machine.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, true); + hide_machine_.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, true); + hover_machine_.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, true); EventLogic(); - EnsureAnimation(); } } @@ -2486,11 +2284,10 @@ void Launcher::RecvQuicklistClosed(nux::ObjectPtr<QuicklistView> const& quicklis // Cancel any prior state that was set before the Quicklist appeared. SetActionState(ACTION_NONE); - _hide_machine.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, false); - _hover_machine.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, false); + hide_machine_.SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, false); + hover_machine_.SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, false); EventLogic(); - EnsureAnimation(); } void Launcher::EventLogic() @@ -2501,9 +2298,9 @@ void Launcher::EventLogic() AbstractLauncherIcon::Ptr launcher_icon; - if (!_hidden && !IsInKeyNavMode() && _hovered) + if (!hidden_ && !IsInKeyNavMode() && hovered_) { - launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); + launcher_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y); } SetIconUnderMouse(launcher_icon); @@ -2511,11 +2308,11 @@ void Launcher::EventLogic() void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags) { - AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); + AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y); if (launcher_icon) { - _icon_mouse_down = launcher_icon; + icon_mouse_down_ = launcher_icon; // if MouseUp after the time ended -> it's an icon drag, otherwise, it's starting an app auto cb_func = sigc::bind(sigc::mem_fun(this, &Launcher::StartIconDragTimeout), x, y); sources_.AddTimeout(START_DRAGICON_DURATION, cb_func, START_DRAGICON_TIMEOUT); @@ -2527,31 +2324,31 @@ void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned void Launcher::MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags) { - AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); + AbstractLauncherIcon::Ptr const& launcher_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y); sources_.Remove(START_DRAGICON_TIMEOUT); - if (_icon_mouse_down && (_icon_mouse_down == launcher_icon)) + if (icon_mouse_down_ && (icon_mouse_down_ == launcher_icon)) { - _icon_mouse_down->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags); + icon_mouse_down_->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags); if (GetActionState() == ACTION_NONE) { - _icon_mouse_down->mouse_click.emit(nux::GetEventButton(button_flags), monitor, key_flags); + icon_mouse_down_->mouse_click.emit(nux::GetEventButton(button_flags), monitor, key_flags); } } - if (launcher_icon && (_icon_mouse_down != launcher_icon)) + if (launcher_icon && (icon_mouse_down_ != launcher_icon)) { launcher_icon->mouse_up.emit(nux::GetEventButton(button_flags), monitor, key_flags); } if (GetActionState() == ACTION_DRAG_LAUNCHER) { - TimeUtil::SetTimeStruct(&_times[TIME_DRAG_END]); + animation::StartOrReverse(drag_over_animation_, animation::Direction::BACKWARD); } - _icon_mouse_down = nullptr; + icon_mouse_down_ = nullptr; } AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) const @@ -2561,9 +2358,9 @@ AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) const nux::Point2 mouse_position(x, y); int inside = 0; - for (it = _model->begin(); it != _model->end(); ++it) + for (it = model_->begin(); it != model_->end(); ++it) { - if (!(*it)->IsVisible() || !(*it)->IsVisibleOnMonitor(monitor)) + if (!(*it)->IsVisibleOnMonitor(monitor)) continue; nux::Point2 screen_coord [4]; @@ -2581,13 +2378,10 @@ AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) const return AbstractLauncherIcon::Ptr(); } -void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLauncherIcon::Ptr const& icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture) +void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, nux::ObjectPtr<nux::IOpenGLBaseTexture> const& texture, AbstractLauncherIcon::Ptr const& icon) { RenderArg arg; - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - - SetupRenderArg(icon, current, arg); + SetupRenderArg(icon, arg); arg.render_center = nux::Point3(roundf(texture->GetWidth() / 2.0f), roundf(texture->GetHeight() / 2.0f), 0.0f); arg.logical_center = arg.render_center; arg.rotation.x = 0.0f; @@ -2606,18 +2400,15 @@ void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLaun GfxContext.GetRenderStates().GetBlend(alpha, src, dest); GfxContext.GetRenderStates().SetBlend(false); - GfxContext.QRP_Color(0, - 0, - texture->GetWidth(), - texture->GetHeight(), - nux::Color(0.0f, 0.0f, 0.0f, 0.0f)); + GfxContext.QRP_Color(0, 0, texture->GetWidth(), texture->GetHeight(), + nux::color::Transparent); GfxContext.GetRenderStates().SetBlend(alpha, src, dest); nux::Geometry geo(0, 0, texture->GetWidth(), texture->GetWidth()); - icon_renderer->PreprocessIcons(drag_args, geo); - icon_renderer->RenderIcon(GfxContext, arg, geo, geo); + icon_renderer_->PreprocessIcons(drag_args, geo); + icon_renderer_->RenderIcon(GfxContext, arg, geo, geo); unity::graphics::PopOffscreenRenderTarget(); } @@ -2651,37 +2442,36 @@ void Launcher::ProcessDndEnter() #ifdef USE_X11 SetStateMouseOverLauncher(true); - _dnd_data.Reset(); - _drag_action = nux::DNDACTION_NONE; - _steal_drag = false; - _data_checked = false; - _drag_edge_touching = false; - _dnd_hovered_icon = nullptr; + dnd_data_.Reset(); + drag_action_ = nux::DNDACTION_NONE; + steal_drag_ = false; + data_checked_ = false; + dnd_hovered_icon_ = nullptr; + drag_edge_touching_ = false; + dnd_hide_animation_.Stop(); #endif } void Launcher::DndReset() { #ifdef USE_X11 - _dnd_data.Reset(); + dnd_data_.Reset(); bool is_overlay_open = IsOverlayOpen(); - for (auto it : *_model) + for (auto it : *model_) { auto icon_type = it->GetIconType(); + bool desaturate = false; - if (icon_type == AbstractLauncherIcon::IconType::HOME || - icon_type == AbstractLauncherIcon::IconType::HUD) - { - it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false); - } - else + if (icon_type != AbstractLauncherIcon::IconType::HOME && + icon_type != AbstractLauncherIcon::IconType::HUD) { - it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, is_overlay_open && !_hovered); + desaturate = is_overlay_open && !hovered_; } - it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false); + it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, desaturate, monitor()); + it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false, monitor()); } DndHoveredIconReset(); @@ -2691,20 +2481,20 @@ void Launcher::DndReset() void Launcher::DndHoveredIconReset() { #ifdef USE_X11 - _drag_edge_touching = false; SetActionState(ACTION_NONE); - if (_steal_drag && _dnd_hovered_icon) + if (steal_drag_ && dnd_hovered_icon_) { - _dnd_hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false); - _dnd_hovered_icon->remove.emit(_dnd_hovered_icon); + dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false, monitor()); + dnd_hovered_icon_->remove.emit(dnd_hovered_icon_); } - if (!_steal_drag && _dnd_hovered_icon) - _dnd_hovered_icon->SendDndLeave(); + if (!steal_drag_ && dnd_hovered_icon_) + dnd_hovered_icon_->SendDndLeave(); - _steal_drag = false; - _dnd_hovered_icon = nullptr; + steal_drag_ = false; + drag_edge_touching_ = false; + dnd_hovered_icon_ = nullptr; #endif } @@ -2720,11 +2510,11 @@ void Launcher::ProcessDndLeave() void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) { #ifdef USE_X11 - if (!_data_checked) + if (!data_checked_) { const std::string uri_list = "text/uri-list"; - _data_checked = true; - _dnd_data.Reset(); + data_checked_ = true; + dnd_data_.Reset(); auto& display = nux::GetWindowThread()->GetGraphicsDisplay(); // get the data @@ -2733,145 +2523,136 @@ void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) if (mime != uri_list) continue; - _dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str()))); + dnd_data_.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str()))); break; } // see if the launcher wants this one - auto const& uris = _dnd_data.Uris(); + auto const& uris = dnd_data_.Uris(); if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri) {return DndIsSpecialRequest(uri);}) != uris.end()) { - _steal_drag = true; + steal_drag_ = true; } // only set hover once we know our first x/y SetActionState(ACTION_DRAG_EXTERNAL); SetStateMouseOverLauncher(true); - - if (!_steal_drag && !_dnd_data.Uris().empty()) - { - for (auto const& it : *_model) - { - if (it->ShouldHighlightOnDrag(_dnd_data)) - it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false); - else - it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true); - } - } } - SetMousePosition(x - _parent->GetGeometry().x, y - _parent->GetGeometry().y); + SetMousePosition(x - parent_->GetGeometry().x, y - parent_->GetGeometry().y); - if (monitor() == 0 && !IsOverlayOpen() && _mouse_position.x == 0 && _mouse_position.y <= (_parent->GetGeometry().height - _icon_size - 2 * _space_between_icons) && !_drag_edge_touching) + if (options()->hide_mode != LAUNCHER_HIDE_NEVER) { - if (_dnd_hovered_icon) - _dnd_hovered_icon->SendDndLeave(); + if (monitor() == 0 && !IsOverlayOpen() && mouse_position_.x == 0 && !drag_edge_touching_ && + mouse_position_.y <= (parent_->GetGeometry().height - icon_size_ - 2 * SPACE_BETWEEN_ICONS)) + { + if (dnd_hovered_icon_) + dnd_hovered_icon_->SendDndLeave(); - _drag_edge_touching = true; - TimeUtil::SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3); - EnsureAnimation(); - } - else if (_mouse_position.x != 0 && _drag_edge_touching) - { - _drag_edge_touching = false; - TimeUtil::SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3); - EnsureAnimation(); + animation::StartOrReverse(dnd_hide_animation_, animation::Direction::FORWARD); + drag_edge_touching_ = true; + } + else if (mouse_position_.x != 0 && drag_edge_touching_) + { + animation::StartOrReverse(dnd_hide_animation_, animation::Direction::BACKWARD); + drag_edge_touching_ = false; + } } EventLogic(); - AbstractLauncherIcon::Ptr const& hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); + auto const& hovered_icon = MouseIconIntersection(mouse_position_.x, mouse_position_.y); bool hovered_icon_is_appropriate = false; if (hovered_icon) { if (hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH) - _steal_drag = false; + steal_drag_ = false; if (hovered_icon->position() == AbstractLauncherIcon::Position::FLOATING) hovered_icon_is_appropriate = true; } - if (_steal_drag) + if (steal_drag_) { - _drag_action = nux::DNDACTION_COPY; - if (!_dnd_hovered_icon && hovered_icon_is_appropriate) + drag_action_ = nux::DNDACTION_COPY; + if (!dnd_hovered_icon_ && hovered_icon_is_appropriate) { - _dnd_hovered_icon = new SpacerLauncherIcon(monitor()); - _model->AddIcon(_dnd_hovered_icon); - _model->ReorderBefore(_dnd_hovered_icon, hovered_icon, true); + dnd_hovered_icon_ = new SpacerLauncherIcon(monitor()); + model_->AddIcon(dnd_hovered_icon_); + model_->ReorderBefore(dnd_hovered_icon_, hovered_icon, true); } - else if (_dnd_hovered_icon) + else if (dnd_hovered_icon_) { if (hovered_icon) { if (hovered_icon_is_appropriate) { - _model->ReorderSmart(_dnd_hovered_icon, hovered_icon, true); + model_->ReorderSmart(dnd_hovered_icon_, hovered_icon, true); } else { - _dnd_hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false); - _dnd_hovered_icon->remove.emit(_dnd_hovered_icon); - _dnd_hovered_icon = nullptr; + dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false, monitor()); + dnd_hovered_icon_->remove.emit(dnd_hovered_icon_); + dnd_hovered_icon_ = nullptr; } } } } else { - if (!_drag_edge_touching && hovered_icon != _dnd_hovered_icon) + if (!drag_edge_touching_ && hovered_icon != dnd_hovered_icon_) { if (hovered_icon) { hovered_icon->SendDndEnter(); - _drag_action = hovered_icon->QueryAcceptDrop(_dnd_data); + drag_action_ = hovered_icon->QueryAcceptDrop(dnd_data_); } else { - _drag_action = nux::DNDACTION_NONE; + drag_action_ = nux::DNDACTION_NONE; } - if (_dnd_hovered_icon) - _dnd_hovered_icon->SendDndLeave(); + if (dnd_hovered_icon_) + dnd_hovered_icon_->SendDndLeave(); - _dnd_hovered_icon = hovered_icon; + dnd_hovered_icon_ = hovered_icon; } } bool accept; - if (_drag_action != nux::DNDACTION_NONE) + if (drag_action_ != nux::DNDACTION_NONE) accept = true; else accept = false; - SendDndStatus(accept, _drag_action, nux::Geometry(x, y, 1, 1)); + SendDndStatus(accept, drag_action_, nux::Geometry(x, y, 1, 1)); #endif } void Launcher::ProcessDndDrop(int x, int y) { #ifdef USE_X11 - if (_steal_drag) + if (steal_drag_) { - for (auto const& uri : _dnd_data.Uris()) + for (auto const& uri : dnd_data_.Uris()) { if (DndIsSpecialRequest(uri)) - add_request.emit(uri, _dnd_hovered_icon); + add_request.emit(uri, dnd_hovered_icon_); } } - else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE) + else if (dnd_hovered_icon_ && drag_action_ != nux::DNDACTION_NONE) { if (IsOverlayOpen()) ubus_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); - _dnd_hovered_icon->AcceptDrop(_dnd_data); + dnd_hovered_icon_->AcceptDrop(dnd_data_); } - if (_drag_action != nux::DNDACTION_NONE) - SendDndFinished(true, _drag_action); + if (drag_action_ != nux::DNDACTION_NONE) + SendDndFinished(true, drag_action_); else - SendDndFinished(false, _drag_action); + SendDndFinished(false, drag_action_); // reset our shiz DndReset(); @@ -2887,7 +2668,7 @@ AbstractLauncherIcon::Ptr Launcher::GetSelectedMenuIcon() const if (!IsInKeyNavMode()) return AbstractLauncherIcon::Ptr(); - return _model->Selection(); + return model_->Selection(); } // @@ -2903,7 +2684,7 @@ bool Launcher::InspectKeyEvent(unsigned int eventType, int Launcher::GetDragDelta() const { - return _launcher_drag_delta; + return launcher_drag_delta_; } void Launcher::DndStarted(std::string const& data) @@ -2911,30 +2692,30 @@ void Launcher::DndStarted(std::string const& data) #ifdef USE_X11 SetDndQuirk(); - _dnd_data.Fill(data.c_str()); + dnd_data_.Fill(data.c_str()); - auto const& uris = _dnd_data.Uris(); + auto const& uris = dnd_data_.Uris(); if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri) {return DndIsSpecialRequest(uri);}) != uris.end()) { - _steal_drag = true; + steal_drag_ = true; if (IsOverlayOpen()) SaturateIcons(); } else { - for (auto const& it : *_model) + for (auto const& it : *model_) { - if (it->ShouldHighlightOnDrag(_dnd_data)) + if (it->ShouldHighlightOnDrag(dnd_data_)) { - it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false); - it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, true); + it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false, monitor()); + it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, true, monitor()); } else { - it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true); - it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false); + it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true, monitor()); + it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false, monitor()); } } } @@ -2946,10 +2727,7 @@ void Launcher::DndFinished() #ifdef USE_X11 UnsetDndQuirk(); - _data_checked = false; - - if (IsOverlayOpen() && !_hovered) - DesaturateIcons(); + data_checked_ = false; DndReset(); #endif @@ -2958,15 +2736,29 @@ void Launcher::DndFinished() void Launcher::SetDndQuirk() { #ifdef USE_X11 - _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true); + hide_machine_.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true); #endif } void Launcher::UnsetDndQuirk() { #ifdef USE_X11 - _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false); - _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false); + + if (IsOverlayOpen() && !hovered_) + { + DesaturateIcons(); + } + else + { + for (auto const& it : *model_) + { + it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false, monitor()); + it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false, monitor()); + } + } + + hide_machine_.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false); + hide_machine_.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false); #endif } diff --git a/launcher/Launcher.h b/launcher/Launcher.h index 0faeb4169..b9d28a744 100644 --- a/launcher/Launcher.h +++ b/launcher/Launcher.h @@ -22,8 +22,8 @@ #define LAUNCHER_H #include <Nux/View.h> -#include <Nux/BaseWindow.h> #include <Nux/TimerProc.h> +#include <NuxCore/Animation.h> #include <NuxGraphics/GestureEvent.h> #ifndef USE_GLES # include <NuxGraphics/IOpenGLAsmShader.h> @@ -69,7 +69,6 @@ public: Launcher(MockableBaseWindow* parent, NUX_FILE_LINE_PROTO); - nux::Property<Display*> display; nux::Property<int> monitor; nux::Property<Options::Ptr> options; @@ -83,7 +82,7 @@ public: bool Hidden() const { - return _hidden; + return hidden_; } void ForceReveal(bool force); @@ -103,11 +102,11 @@ public: MockableBaseWindow* GetParent() const { - return _parent; + return parent_; }; nux::ObjectPtr<nux::View> const& GetActiveTooltip() const; - nux::ObjectPtr<LauncherDragWindow> const& GetDraggedIcon() const; + LauncherDragWindow::Ptr const& GetDraggedIcon() const; virtual void RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags); virtual void RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags); @@ -148,12 +147,9 @@ public: void EnterKeyNavMode(); void ExitKeyNavMode(); bool IsInKeyNavMode() const; - bool IsOverlayOpen() const; - static const int ANIM_DURATION_SHORT; - - void RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLauncherIcon::Ptr const& icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture); + void RenderIconToTexture(nux::GraphicsEngine&, nux::ObjectPtr<nux::IOpenGLBaseTexture> const&, AbstractLauncherIcon::Ptr const&); #ifdef NUX_GESTURES_SUPPORT virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event); @@ -179,24 +175,10 @@ private: ACTION_NONE, ACTION_DRAG_LAUNCHER, ACTION_DRAG_ICON, + ACTION_DRAG_ICON_CANCELLED, ACTION_DRAG_EXTERNAL, } LauncherActionState; - typedef enum - { - TIME_ENTER, - TIME_LEAVE, - TIME_DRAG_END, - TIME_DRAG_THRESHOLD, - TIME_AUTOHIDE, - TIME_DRAG_EDGE_TOUCH, - TIME_DRAG_OUT, - TIME_TAP_SUPER, - TIME_SUPER_PRESSED, - - TIME_LAST - } LauncherActionTimes; - void ConfigureBarrier(); void OnMonitorChanged(int monitor); @@ -214,7 +196,8 @@ private: ui::EdgeBarrierSubscriber::Result HandleBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event); #endif - void OnPluginStateChanged(); + void OnExpoChanged(); + void OnSpreadChanged(); void OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection); @@ -223,8 +206,8 @@ private: bool OnScrollTimeout(); void SetUrgentTimer(int urgent_wiggle_period); - void WiggleUrgentIcon(AbstractLauncherIcon::Ptr const& icon); - void HandleUrgentIcon(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current); + void AnimateUrgentIcon(AbstractLauncherIcon::Ptr const& icon); + void HandleUrgentIcon(AbstractLauncherIcon::Ptr const& icon); bool OnUrgentTimeout(); void SetMousePosition(int x, int y); @@ -236,51 +219,32 @@ private: void OnDragWindowAnimCompleted(); - bool IconNeedsAnimation(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; bool IconDrawEdgeOnly(AbstractLauncherIcon::Ptr const& icon) const; - bool AnimationInProgress() const; void SetActionState(LauncherActionState actionstate); LauncherActionState GetActionState() const; - void EnsureAnimation(); void EnsureScrollTimer(); - bool MouseOverTopScrollArea(); - bool MouseOverBottomScrollArea(); - float DnDStartProgress(struct timespec const& current) const; - float DnDExitProgress(struct timespec const& current) const; - float GetHoverProgress(struct timespec const& current) const; - float AutohideProgress(struct timespec const& current) const; - float DragThresholdProgress(struct timespec const& current) const; - float DragHideProgress(struct timespec const& current) const; - float DragOutProgress(struct timespec const& current) const; - float IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconShimmerProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const ¤t) const; - float IconUrgentWiggleValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconProgressBias(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconDropDimValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconCenterTransitionProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; - float IconVisibleProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; + float DragOutProgress() const; + float IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon) const; + float IconPulseOnceValue(AbstractLauncherIcon::Ptr const& icon) const; + float IconUrgentWiggleValue(AbstractLauncherIcon::Ptr const& icon) const; + float IconStartingBlinkValue(AbstractLauncherIcon::Ptr const& icon) const; + float IconStartingPulseValue(AbstractLauncherIcon::Ptr const& icon) const; + float IconBackgroundIntensity(AbstractLauncherIcon::Ptr const& icon) const; + float IconProgressBias(AbstractLauncherIcon::Ptr const& icon) const; void SetHidden(bool hidden); void UpdateChangeInMousePosition(int delta_x, int delta_y); - void SetDndDelta(float x, float y, nux::Geometry const& geo, timespec const& current); + void SetDndDelta(float x, float y, nux::Geometry const& geo); float DragLimiter(float x); - void SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current, ui::RenderArg& arg); + void SetupRenderArg(AbstractLauncherIcon::Ptr const& icon, ui::RenderArg& arg); void FillRenderArg(AbstractLauncherIcon::Ptr const& icon, ui::RenderArg& arg, nux::Point3& center, @@ -290,17 +254,16 @@ private: float folded_spacing, float autohide_offset, float folded_z_distance, - float animation_neg_rads, - struct timespec const& current); + float animation_neg_rads); void RenderArgs(std::list<ui::RenderArg> &launcher_args, nux::Geometry& box_geo, float* launcher_alpha, nux::Geometry const& parent_abs_geo); void OnIconAdded(AbstractLauncherIcon::Ptr const& icon); void OnIconRemoved(AbstractLauncherIcon::Ptr const& icon); - void OnOrderChanged(); + void OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon, int monitor); + void SetupIconAnimations(AbstractLauncherIcon::Ptr const& icon); - void OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon); void OnTooltipVisible(nux::ObjectPtr<nux::View> view); void OnOverlayHidden(GVariant* data); @@ -338,80 +301,70 @@ private: void DndHoveredIconReset(); bool DndIsSpecialRequest(std::string const& uri) const; - LauncherModel::Ptr _model; - MockableBaseWindow* _parent; - nux::ObjectPtr<nux::View> _active_tooltip; - QuicklistView* _active_quicklist; - - nux::HLayout* m_Layout; + LauncherModel::Ptr model_; + MockableBaseWindow* parent_; + ui::AbstractIconRenderer::Ptr icon_renderer_; + nux::ObjectPtr<nux::View> active_tooltip_; + std::set<AbstractLauncherIcon::Ptr> animating_urgent_icons_; // used by keyboard/a11y-navigation - AbstractLauncherIcon::Ptr _icon_under_mouse; - AbstractLauncherIcon::Ptr _icon_mouse_down; - AbstractLauncherIcon::Ptr _drag_icon; - AbstractLauncherIcon::Ptr _dnd_hovered_icon; - - bool _hovered; - bool _hidden; - bool _render_drag_window; - bool _shortcuts_shown; - bool _data_checked; - bool _steal_drag; - bool _drag_edge_touching; - bool _initial_drag_animation; - bool _dash_is_open; - bool _hud_is_open; - - float _folded_angle; - float _neg_folded_angle; - float _folded_z_distance; - float _edge_overcome_pressure; - - LauncherActionState _launcher_action_state; - - int _space_between_icons; - int _icon_image_size; - int _icon_image_size_delta; - int _icon_glow_size; - int _icon_size; - int _dnd_delta_y; - int _dnd_delta_x; - int _postreveal_mousemove_delta_x; - int _postreveal_mousemove_delta_y; - int _launcher_drag_delta; - int _launcher_drag_delta_max; - int _launcher_drag_delta_min; - int _enter_y; - int _last_button_press; - int _drag_icon_position; - int _urgent_wiggle_time; - bool _urgent_acked; - bool _urgent_timer_running; - bool _urgent_ack_needed; - float _drag_out_delta_x; - bool _drag_gesture_ongoing; - float _last_reveal_progress; - - nux::Point2 _mouse_position; - nux::ObjectPtr<nux::IOpenGLBaseTexture> _offscreen_drag_texture; - nux::ObjectPtr<LauncherDragWindow> _drag_window; - LauncherHideMachine _hide_machine; - LauncherHoverMachine _hover_machine; + AbstractLauncherIcon::Ptr icon_under_mouse_; + AbstractLauncherIcon::Ptr icon_mouse_down_; + AbstractLauncherIcon::Ptr drag_icon_; + AbstractLauncherIcon::Ptr dnd_hovered_icon_; + + bool hovered_; + bool hidden_; + bool folded_; + bool render_drag_window_; + bool shortcuts_shown_; + bool data_checked_; + bool steal_drag_; + bool drag_edge_touching_; + bool initial_drag_animation_; + bool dash_is_open_; + bool hud_is_open_; + + LauncherActionState launcher_action_state_; + + int icon_size_; + int dnd_delta_y_; + int dnd_delta_x_; + int postreveal_mousemove_delta_x_; + int postreveal_mousemove_delta_y_; + int launcher_drag_delta_; + int launcher_drag_delta_max_; + int launcher_drag_delta_min_; + int enter_y_; + int last_button_press_; + int drag_icon_position_; + int urgent_animation_period_; + bool urgent_ack_needed_; + float drag_out_delta_x_; + bool drag_gesture_ongoing_; + float last_reveal_progress_; + + nux::Point mouse_position_; + LauncherDragWindow::Ptr drag_window_; + LauncherHideMachine hide_machine_; + LauncherHoverMachine hover_machine_; TooltipManager tooltip_manager_; - unity::DndData _dnd_data; - nux::DndAction _drag_action; - Atom _selection_atom; - - struct timespec _times[TIME_LAST]; - struct timespec _urgent_finished_time; + unity::DndData dnd_data_; + nux::DndAction drag_action_; BaseTexturePtr launcher_sheen_; BaseTexturePtr launcher_pressure_effect_; - - ui::AbstractIconRenderer::Ptr icon_renderer; BackgroundEffectHelper bg_effect_helper_; + nux::animation::AnimateValue<float> auto_hide_animation_; + nux::animation::AnimateValue<float> hover_animation_; + nux::animation::AnimateValue<float> drag_over_animation_; + nux::animation::AnimateValue<float> drag_out_animation_; + nux::animation::AnimateValue<float> drag_icon_animation_; + nux::animation::AnimateValue<float> dnd_hide_animation_; + nux::animation::AnimateValue<float> dash_showing_animation_; + UBusManager ubus_; glib::SourceManager sources_; diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp index ae90a5ddf..bc4cbe455 100644 --- a/launcher/LauncherController.cpp +++ b/launcher/LauncherController.cpp @@ -82,7 +82,6 @@ namespace { const int launcher_minimum_show_duration = 1250; const int shortcuts_show_delay = 750; - const int ignore_repeat_shortcut_duration = 250; const std::string KEYPRESS_TIMEOUT = "keypress-timeout"; const std::string LABELS_TIMEOUT = "label-show-timeout"; @@ -104,13 +103,13 @@ std::string CreateAppUriNameFromDesktopPath(const std::string &desktop_path) } -Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager) +Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager, ui::EdgeBarrierController::Ptr const& edge_barriers) : parent_(parent) , model_(std::make_shared<LauncherModel>()) , xdnd_manager_(xdnd_manager) - , device_section_(std::make_shared<VolumeMonitorWrapper>(), std::make_shared<DevicesSettingsImp>()) , expo_icon_(new ExpoLauncherIcon()) , desktop_icon_(new DesktopLauncherIcon()) + , edge_barriers_(edge_barriers) , sort_priority_(AbstractLauncherIcon::DefaultPriority(AbstractLauncherIcon::IconType::APPLICATION)) , launcher_open(false) , launcher_keynav(false) @@ -118,24 +117,12 @@ Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager) , reactivate_keynav(false) , keynav_restore_window_(true) , launcher_key_press_time_(0) - , last_dnd_monitor_(-1) , dbus_server_(DBUS_NAME) { #ifdef USE_X11 - edge_barriers_.options = parent_->options(); + edge_barriers_->options = parent_->options(); #endif - ubus.RegisterInterest(UBUS_BACKGROUND_COLOR_CHANGED, [this](GVariant * data) { - ui::IconRenderer::DestroyShortcutTextures(); - - double red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f; - g_variant_get(data, "(dddd)", &red, &green, &blue, &alpha); - parent_->options()->background_color = nux::Color(red, green, blue, alpha); - }); - - // request the latest color from bghash - ubus.SendMessage(UBUS_BACKGROUND_REQUEST_COLOUR_EMIT); - UScreen* uscreen = UScreen::GetDefault(); EnsureLaunchers(uscreen->GetPrimaryMonitor(), uscreen->GetMonitors()); @@ -164,6 +151,9 @@ Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager) WindowManager& wm = WindowManager::Default(); wm.window_focus_changed.connect(sigc::mem_fun(this, &Controller::Impl::OnWindowFocusChanged)); wm.viewport_layout_changed.connect(sigc::group(sigc::mem_fun(this, &Controller::Impl::UpdateNumWorkspaces), sigc::_1 * sigc::_2)); + average_color_connection_ = wm.average_color.changed.connect([this] (nux::Color const& color) { + parent_->options()->background_color = color; + }); ubus.RegisterInterest(UBUS_QUICKLIST_END_KEY_NAV, [this](GVariant * args) { if (reactivate_keynav) @@ -174,8 +164,7 @@ Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager) if (selected) { - ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(selected->tooltip_text().c_str())); + ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, glib::Variant(selected->tooltip_text())); } }); @@ -209,6 +198,10 @@ void Controller::Impl::EnsureLaunchers(int primary, std::vector<nux::Geometry> c unsigned int launchers_size = launchers.size(); unsigned int last_launcher = 0; + // Reset the icon centers: only the used icon centers must contain valid values + for (auto const& icon : *model_) + icon->ResetCenters(); + for (unsigned int i = 0; i < num_launchers; ++i, ++last_launcher) { if (i >= launchers_size) @@ -225,7 +218,7 @@ void Controller::Impl::EnsureLaunchers(int primary, std::vector<nux::Geometry> c if (launchers[i]->monitor() != monitor) { #ifdef USE_X11 - edge_barriers_.Unsubscribe(launchers[i].GetPointer(), launchers[i]->monitor); + edge_barriers_->RemoveVerticalSubscriber(launchers[i].GetPointer(), launchers[i]->monitor); #endif launchers[i]->monitor = monitor; } @@ -235,7 +228,7 @@ void Controller::Impl::EnsureLaunchers(int primary, std::vector<nux::Geometry> c } #ifdef USE_X11 - edge_barriers_.Subscribe(launchers[i].GetPointer(), launchers[i]->monitor); + edge_barriers_->AddVerticalSubscriber(launchers[i].GetPointer(), launchers[i]->monitor); #endif } @@ -247,7 +240,7 @@ void Controller::Impl::EnsureLaunchers(int primary, std::vector<nux::Geometry> c parent_->RemoveChild(launcher.GetPointer()); launcher->GetParent()->UnReference(); #ifdef USE_X11 - edge_barriers_.Unsubscribe(launcher.GetPointer(), launcher->monitor); + edge_barriers_->RemoveVerticalSubscriber(launcher.GetPointer(), launcher->monitor); #endif } } @@ -284,8 +277,7 @@ void Controller::Impl::OnDndStarted(std::string const& data, int monitor) { if (parent_->multiple_launchers) { - last_dnd_monitor_ = monitor; - launchers[last_dnd_monitor_]->DndStarted(data); + launchers[monitor]->DndStarted(data); } else { @@ -297,8 +289,8 @@ void Controller::Impl::OnDndFinished() { if (parent_->multiple_launchers) { - launchers[last_dnd_monitor_]->DndFinished(); - last_dnd_monitor_ = -1; + if (xdnd_manager_->Monitor() >= 0) + launchers[xdnd_manager_->Monitor()]->DndFinished(); } else { @@ -306,14 +298,15 @@ void Controller::Impl::OnDndFinished() } } -void Controller::Impl::OnDndMonitorChanged(int monitor) +void Controller::Impl::OnDndMonitorChanged(std::string const& data, int old_monitor, int new_monitor) { if (parent_->multiple_launchers) { - launchers[last_dnd_monitor_]->UnsetDndQuirk(); - last_dnd_monitor_ = monitor; - launchers[last_dnd_monitor_]->SetDndQuirk(); - } + if (old_monitor >= 0) + launchers[old_monitor]->UnsetDndQuirk(); + + launchers[new_monitor]->DndStarted(data); + } } Launcher* Controller::Impl::CreateLauncher() @@ -362,18 +355,18 @@ void Controller::Impl::OnLauncherAddRequest(std::string const& icon_uri, Abstrac if (icon) { - icon->Stick(false); model_->ReorderAfter(icon, icon_before); + icon->Stick(true); } else { if (icon_before) - RegisterIcon(CreateFavoriteIcon(icon_uri), icon_before->SortPriority()); + RegisterIcon(CreateFavoriteIcon(icon_uri, true), icon_before->SortPriority()); else - RegisterIcon(CreateFavoriteIcon(icon_uri)); - } + RegisterIcon(CreateFavoriteIcon(icon_uri, true)); - SaveIconsOrder(); + SaveIconsOrder(); + } } void Controller::Impl::AddFavoriteKeepingOldPosition(FavoriteList& icons, std::string const& icon_uri) const @@ -471,8 +464,6 @@ Controller::Impl::OnLauncherUpdateIconStickyState(std::string const& icon_uri, b { existing_icon_entry->UnStick(); } - - SortAndUpdate(); } } else @@ -484,8 +475,9 @@ Controller::Impl::OnLauncherUpdateIconStickyState(std::string const& icon_uri, b { if (sticky) { - favorite_store.AddFavorite(target_uri, -1); - RegisterIcon(CreateFavoriteIcon(target_uri)); + auto prio = GetLastIconPriority<ApplicationLauncherIcon>("", true); + RegisterIcon(CreateFavoriteIcon(target_uri, true), prio); + SaveIconsOrder(); } else { @@ -527,13 +519,12 @@ Controller::Impl::OnLauncherAddRequestSpecial(std::string const& path, // This will ensure that the center of the new icon is set, so that // the animation could be done properly. sources_.AddIdle([this, icon_x, icon_y, result] { - result->Animate(CurrentLauncher(), icon_x, icon_y); - return false; + return !result->Animate(CurrentLauncher(), icon_x, icon_y); }); } else { - result->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true); + result->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true); } } } @@ -760,13 +751,18 @@ void Controller::Impl::RegisterIcon(AbstractLauncherIcon::Ptr const& icon, int p ResetIconPriorities(); }); - icon->position_forgot.connect([this, icon_uri] { - FavoriteStore::Instance().RemoveFavorite(icon_uri); + auto uri_ptr = std::make_shared<std::string>(icon_uri); + icon->position_forgot.connect([this, uri_ptr] { + FavoriteStore::Instance().RemoveFavorite(*uri_ptr); + }); + + icon->uri_changed.connect([this, uri_ptr] (std::string const& new_uri) { + *uri_ptr = new_uri; }); if (icon->GetIconType() == AbstractLauncherIcon::IconType::APPLICATION) { - icon->visibility_changed.connect(sigc::mem_fun(this, &Impl::SortAndUpdate)); + icon->visibility_changed.connect(sigc::hide(sigc::mem_fun(this, &Impl::SortAndUpdate))); SortAndUpdate(); } @@ -850,7 +846,7 @@ void Controller::Impl::OnDeviceIconAdded(AbstractLauncherIcon::Ptr const& icon) RegisterIcon(icon, GetLastIconPriority<VolumeLauncherIcon>(local::DEVICES_URI)); } -AbstractLauncherIcon::Ptr Controller::Impl::CreateFavoriteIcon(std::string const& icon_uri) +AbstractLauncherIcon::Ptr Controller::Impl::CreateFavoriteIcon(std::string const& icon_uri, bool emit_signal) { AbstractLauncherIcon::Ptr result; @@ -909,7 +905,7 @@ AbstractLauncherIcon::Ptr Controller::Impl::CreateFavoriteIcon(std::string const } if (result) - result->Stick(false); + result->Stick(emit_signal); return result; } @@ -940,7 +936,6 @@ SoftwareCenterLauncherIcon::Ptr Controller::Impl::CreateSCLauncherIcon(std::stri if (!app) return result; - app->sticky = true; if (app->seen) return result; @@ -959,6 +954,7 @@ void Controller::Impl::AddRunningApps() if (!app->seen()) { AbstractLauncherIcon::Ptr icon(new ApplicationLauncherIcon(app)); + icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::VISIBLE); RegisterIcon(icon, ++sort_priority_); } } @@ -970,7 +966,10 @@ void Controller::Impl::AddDevices() for (auto const& icon : device_section_.GetIcons()) { if (!icon->IsSticky() && !fav_store.IsFavorite(icon->RemoteUri())) + { + icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::VISIBLE); RegisterIcon(icon, ++sort_priority_); + } } } @@ -1019,7 +1018,14 @@ void Controller::Impl::SetupIcons() } LOG_INFO(logger) << "Adding favourite: " << fav_uri; - RegisterIcon(CreateFavoriteIcon(fav_uri), ++sort_priority_); + + auto const& icon = CreateFavoriteIcon(fav_uri); + + if (icon) + { + icon->SkipQuirkAnimation(AbstractLauncherIcon::Quirk::VISIBLE); + RegisterIcon(icon, ++sort_priority_); + } } if (!running_apps_added) @@ -1053,12 +1059,12 @@ void Controller::Impl::SendHomeActivationRequest() g_variant_new("(sus)", "home.scope", dash::NOT_HANDLED, "")); } -Controller::Controller(XdndManager::Ptr const& xdnd_manager) +Controller::Controller(XdndManager::Ptr const& xdnd_manager, ui::EdgeBarrierController::Ptr const& edge_barriers) : options(std::make_shared<Options>()) , multiple_launchers(true) - , pimpl(new Impl(this, xdnd_manager)) + , pimpl(new Impl(this, xdnd_manager, edge_barriers)) { - multiple_launchers.changed.connect([&](bool value) -> void { + multiple_launchers.changed.connect([this] (bool value) { UScreen* uscreen = UScreen::GetDefault(); auto monitors = uscreen->GetMonitors(); int primary = uscreen->GetPrimaryMonitor(); @@ -1157,7 +1163,7 @@ void Controller::HandleLauncherKeyPress(int when) { pimpl->launcher_key_press_time_ = when; - auto show_launcher = [&]() + auto show_launcher = [this] { if (pimpl->keyboard_launcher_.IsNull()) pimpl->keyboard_launcher_ = pimpl->CurrentLauncher(); @@ -1170,7 +1176,7 @@ void Controller::HandleLauncherKeyPress(int when) }; pimpl->sources_.AddTimeout(options()->super_tap_duration, show_launcher, local::KEYPRESS_TIMEOUT); - auto show_shortcuts = [&]() + auto show_shortcuts = [this] { if (!pimpl->launcher_keynav) { @@ -1226,7 +1232,7 @@ void Controller::HandleLauncherKeyRelease(bool was_tap, int when) { int time_left = local::launcher_minimum_show_duration - ms_since_show; - auto hide_launcher = [&]() + auto hide_launcher = [this] { if (pimpl->keyboard_launcher_.IsValid()) { @@ -1245,25 +1251,21 @@ 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, Time timestamp) +bool Controller::HandleLauncherKeyEvent(unsigned long key_state, unsigned int key_sym, Time timestamp) { - LauncherModel::iterator it; - // Shortcut to start launcher icons. Only relies on Keycode, ignore modifier - for (it = pimpl->model_->begin(); it != pimpl->model_->end(); ++it) + for (auto const& icon : *pimpl->model_) { - if ((XKeysymToKeycode(display, (*it)->GetShortcut()) == key_code) || - ((gchar)((*it)->GetShortcut()) == key_string[0])) + if (icon->GetShortcut() == key_sym) { - struct timespec last_action_time = (*it)->GetQuirkTime(AbstractLauncherIcon::Quirk::LAST_ACTION); - struct timespec current; - TimeUtil::SetTimeStruct(¤t); - if (TimeUtil::TimeDelta(¤t, &last_action_time) > local::ignore_repeat_shortcut_duration) + if ((key_state & nux::KEY_MODIFIER_SHIFT) && + icon->GetIconType() == AbstractLauncherIcon::IconType::APPLICATION) + { + icon->OpenInstance(ActionArg(ActionArg::Source::LAUNCHER_KEYBINDING, 0, timestamp)); + } + else { - if (g_ascii_isdigit((gchar)(*it)->GetShortcut()) && (key_state & ShiftMask)) - (*it)->OpenInstance(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp)); - else - (*it)->Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, timestamp)); + icon->Activate(ActionArg(ActionArg::Source::LAUNCHER_KEYBINDING, 0, timestamp)); } // disable the "tap on super" check @@ -1309,12 +1311,12 @@ void Controller::KeyNavActivate() if (pimpl->launcher_grabbed) { pimpl->ubus.SendMessage(UBUS_LAUNCHER_START_KEY_NAV, - g_variant_new_int32(pimpl->keyboard_launcher_->monitor)); + glib::Variant(pimpl->keyboard_launcher_->monitor())); } else { pimpl->ubus.SendMessage(UBUS_LAUNCHER_START_KEY_SWITCHER, - g_variant_new_int32(pimpl->keyboard_launcher_->monitor)); + glib::Variant(pimpl->keyboard_launcher_->monitor())); } AbstractLauncherIcon::Ptr const& selected = pimpl->model_->Selection(); @@ -1322,7 +1324,7 @@ void Controller::KeyNavActivate() if (selected) { pimpl->ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(selected->tooltip_text().c_str())); + glib::Variant(selected->tooltip_text())); } } @@ -1335,7 +1337,7 @@ void Controller::KeyNavNext() if (selected) { pimpl->ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(selected->tooltip_text().c_str())); + glib::Variant(selected->tooltip_text())); } } @@ -1348,7 +1350,7 @@ void Controller::KeyNavPrevious() if (selected) { pimpl->ubus.SendMessage(UBUS_LAUNCHER_SELECTION_CHANGED, - g_variant_new_string(selected->tooltip_text().c_str())); + glib::Variant(selected->tooltip_text())); } } @@ -1373,12 +1375,12 @@ void Controller::KeyNavTerminate(bool activate) pimpl->launcher_event_outside_connection_->disconnect(); pimpl->launcher_grabbed = false; pimpl->ubus.SendMessage(UBUS_LAUNCHER_END_KEY_NAV, - g_variant_new_boolean(pimpl->keynav_restore_window_)); + glib::Variant(pimpl->keynav_restore_window_)); } else { pimpl->ubus.SendMessage(UBUS_LAUNCHER_END_KEY_SWITCHER, - g_variant_new_boolean(pimpl->keynav_restore_window_)); + glib::Variant(pimpl->keynav_restore_window_)); } if (activate) diff --git a/launcher/LauncherController.h b/launcher/LauncherController.h index b1a0c6dda..4c6c6f9f8 100644 --- a/launcher/LauncherController.h +++ b/launcher/LauncherController.h @@ -25,6 +25,7 @@ #include <vector> #include <sigc++/sigc++.h> +#include "EdgeBarrierController.h" #include "LauncherOptions.h" #include "SoftwareCenterLauncherIcon.h" #include "XdndManager.h" @@ -48,7 +49,7 @@ public: nux::Property<Options::Ptr> options; nux::Property<bool> multiple_launchers; - Controller(XdndManager::Ptr const& xdnd_manager); + Controller(XdndManager::Ptr const& xdnd_manager, ui::EdgeBarrierController::Ptr const& edge_barriers); ~Controller(); Launcher& launcher() const; @@ -66,12 +67,7 @@ public: void HandleLauncherKeyPress(int when); void HandleLauncherKeyRelease(bool was_tap, int when); - bool HandleLauncherKeyEvent(Display *display, - unsigned int key_sym, - unsigned long key_code, - unsigned long key_state, - char* key_string, - Time timestamp); + bool HandleLauncherKeyEvent(unsigned long key_state, unsigned int key_sym, Time timestamp); void KeyNavActivate(); void KeyNavGrab(); diff --git a/launcher/LauncherControllerPrivate.h b/launcher/LauncherControllerPrivate.h index f3c92225d..ccb1de422 100644 --- a/launcher/LauncherControllerPrivate.h +++ b/launcher/LauncherControllerPrivate.h @@ -28,7 +28,6 @@ #include "AbstractLauncherIcon.h" #include "DeviceLauncherSection.h" -#include "DevicesSettingsImp.h" #ifdef USE_X11 #include "EdgeBarrierController.h" #endif @@ -39,7 +38,6 @@ #include "LauncherModel.h" #include "SoftwareCenterLauncherIcon.h" #include "unity-shared/UBusWrapper.h" -#include "VolumeMonitorWrapper.h" #include "XdndManager.h" namespace unity @@ -50,7 +48,7 @@ namespace launcher class Controller::Impl : public sigc::trackable { public: - Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager); + Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager, ui::EdgeBarrierController::Ptr const& edge_barriers); ~Impl(); void UpdateNumWorkspaces(int workspaces); @@ -88,7 +86,7 @@ public: void RegisterIcon(AbstractLauncherIcon::Ptr const& icon, int priority = std::numeric_limits<int>::min()); - AbstractLauncherIcon::Ptr CreateFavoriteIcon(std::string const& icon_uri); + AbstractLauncherIcon::Ptr CreateFavoriteIcon(std::string const& icon_uri, bool emit_signal = false); AbstractLauncherIcon::Ptr GetIconByUri(std::string const& icon_uri); SoftwareCenterLauncherIcon::Ptr CreateSCLauncherIcon(std::string const& file_path, std::string const& aptdaemon_trans_id, std::string const& icon_path); @@ -117,7 +115,7 @@ public: void OnDndStarted(std::string const& data, int monitor); void OnDndFinished(); - void OnDndMonitorChanged(int monitor); + void OnDndMonitorChanged(std::string const& data, int old_monitor, int new_monitor); GVariant* OnDBusMethodCall(std::string const& method, GVariant *parameters); Controller* parent_; @@ -131,7 +129,7 @@ public: AbstractLauncherIcon::Ptr desktop_icon_; #ifdef USE_X11 - ui::EdgeBarrierController edge_barriers_; + ui::EdgeBarrierController::Ptr edge_barriers_; #endif LauncherList launchers; @@ -144,7 +142,6 @@ public: int reactivate_index; bool keynav_restore_window_; int launcher_key_press_time_; - int last_dnd_monitor_; glib::DBusServer dbus_server_; glib::SourceManager sources_; @@ -152,6 +149,7 @@ public: connection::Wrapper launcher_key_press_connection_; connection::Wrapper launcher_event_outside_connection_; + connection::Wrapper average_color_connection_; }; } // launcher namespace diff --git a/launcher/LauncherDragWindow.cpp b/launcher/LauncherDragWindow.cpp index d87f1ec1d..31086e522 100644 --- a/launcher/LauncherDragWindow.cpp +++ b/launcher/LauncherDragWindow.cpp @@ -41,16 +41,16 @@ namespace NUX_IMPLEMENT_OBJECT_TYPE(LauncherDragWindow); -LauncherDragWindow::LauncherDragWindow(nux::ObjectPtr<nux::IOpenGLBaseTexture> texture, - std::function<void(nux::GraphicsEngine &)> const &deferred_icon_render_func) +LauncherDragWindow::LauncherDragWindow(unsigned size, DeferredIconRenderer const& renderer_func) : nux::BaseWindow("") , icon_rendered_(false) - , deferred_icon_render_func_(deferred_icon_render_func) + , renderer_func_(renderer_func) , animation_speed_(QUICK_ANIMATION_SPEED) , cancelled_(false) - , texture_(texture) + , texture_(nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture( + size, size, 1, nux::BITFMT_R8G8B8A8)) { - SetBaseSize(texture_->GetWidth(), texture_->GetHeight()); + SetBaseSize(size, size); key_down.connect([this] (unsigned long, unsigned long keysym, unsigned long, const char*, unsigned short) { if (keysym == NUX_VK_ESCAPE) @@ -115,7 +115,7 @@ void LauncherDragWindow::StartAnimation() } bool LauncherDragWindow::OnAnimationTimeout() -{ +{ nux::Geometry const& geo = GetGeometry(); int half_size = geo.width / 2; @@ -158,7 +158,7 @@ LauncherDragWindow::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw // Render the icon if we haven't already if (!icon_rendered_) { - deferred_icon_render_func_ (GfxContext); + renderer_func_(GfxContext, texture_); icon_rendered_ = true; } diff --git a/launcher/LauncherDragWindow.h b/launcher/LauncherDragWindow.h index 2cb660575..0d561dd47 100644 --- a/launcher/LauncherDragWindow.h +++ b/launcher/LauncherDragWindow.h @@ -38,11 +38,11 @@ class LauncherDragWindow : public nux::BaseWindow { NUX_DECLARE_OBJECT_TYPE(LauncherDragWindow, nux::BaseWindow); public: - LauncherDragWindow(nux::ObjectPtr<nux::IOpenGLBaseTexture> texture, - std::function<void(nux::GraphicsEngine &)> const &deferred_icon_render_func); - ~LauncherDragWindow(); + typedef nux::ObjectPtr<LauncherDragWindow> Ptr; + typedef std::function<void(nux::GraphicsEngine&, nux::ObjectPtr<nux::IOpenGLBaseTexture> const&)> DeferredIconRenderer; - void DrawContent(nux::GraphicsEngine& gfxContext, bool forceDraw); + LauncherDragWindow(unsigned size, DeferredIconRenderer const&); + ~LauncherDragWindow(); void SetAnimationTarget(int x, int y); void StartQuickAnimation(); @@ -53,21 +53,20 @@ public: sigc::signal<void> anim_completed; sigc::signal<void> drag_cancel_request; - connection::Wrapper on_anim_completed_conn_; protected: + void DrawContent(nux::GraphicsEngine& gfxContext, bool forceDraw); bool InspectKeyEvent(unsigned int event_type, unsigned int keysym, const char* character); bool AcceptKeyNavFocus(); - virtual bool DrawContentOnNuxLayer() const; private: void StartAnimation(); bool OnAnimationTimeout(); void CancelDrag(); - + bool icon_rendered_; - std::function<void(nux::GraphicsEngine &)> deferred_icon_render_func_; + DeferredIconRenderer renderer_func_; float animation_speed_; bool cancelled_; diff --git a/launcher/LauncherIcon.cpp b/launcher/LauncherIcon.cpp index f7403c173..171b7b20a 100644 --- a/launcher/LauncherIcon.cpp +++ b/launcher/LauncherIcon.cpp @@ -20,18 +20,12 @@ #include <sys/time.h> #include <Nux/Nux.h> -#include <Nux/VScrollBar.h> -#include <Nux/HLayout.h> -#include <Nux/VLayout.h> -#include <Nux/WindowCompositor.h> -#include <Nux/BaseWindow.h> #include <NuxCore/Color.h> #include <NuxCore/Logger.h> -#include "unity-shared/CairoTexture.h" #include "LauncherIcon.h" -#include "Launcher.h" -#include "unity-shared/TimeUtil.h" +#include "unity-shared/AnimationUtils.h" +#include "unity-shared/CairoTexture.h" #include "QuicklistManager.h" #include "QuicklistMenuItem.h" @@ -42,8 +36,6 @@ #include "MultiMonitor.h" -#include "unity-shared/UBusWrapper.h" -#include "unity-shared/UBusMessages.h" #include <UnityCore/GLibWrapper.h> #include <UnityCore/GTKWrapper.h> #include <UnityCore/Variant.h> @@ -56,6 +48,8 @@ DECLARE_LOGGER(logger, "unity.launcher.icon"); namespace { +const int IGNORE_REPEAT_SHORTCUT_DURATION = 250; + const std::string DEFAULT_ICON = "application-default-icon"; const std::string MONO_TEST_ICON = "gnome-home"; const std::string UNITY_THEME_NAME = "unity-icon-theme"; @@ -63,8 +57,6 @@ 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); @@ -77,37 +69,22 @@ LauncherIcon::LauncherIcon(IconType type) , _sticky(false) , _remote_urgent(false) , _present_urgency(0) - , _progress(0) + , _progress(0.0f) , _sort_priority(DefaultPriority(type)) , _last_monitor(0) , _background_color(nux::color::White) , _glow_color(nux::color::White) , _shortcut(0) - , _center(max_num_monitors) - , _has_visible_window(max_num_monitors) - , _last_stable(max_num_monitors) - , _parent_geo(max_num_monitors) - , _saved_center(max_num_monitors) , _allow_quicklist_to_show(true) - , _tooltip_fade_animator(TOOLTIP_FADE_DURATION) + , _center(monitors::MAX) + , _quirks(monitors::MAX) + , _quirk_animations(monitors::MAX, decltype(_quirk_animations)::value_type(unsigned(Quirk::LAST))) + , _last_stable(monitors::MAX) + , _saved_center(monitors::MAX) { - for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i) - { - _quirks[i] = false; - _quirk_times[i].tv_sec = 0; - _quirk_times[i].tv_nsec = 0; - } - - _is_visible_on_monitor.resize(max_num_monitors); - - for (int i = 0; i < max_num_monitors; ++i) - _is_visible_on_monitor[i] = true; - tooltip_enabled = true; tooltip_enabled.changed.connect(sigc::mem_fun(this, &LauncherIcon::OnTooltipEnabledChanged)); - tooltip_text.SetSetterFunction(sigc::mem_fun(this, &LauncherIcon::SetTooltipText)); - tooltip_text = "blank"; position = Position::FLOATING; removed = false; @@ -120,20 +97,17 @@ LauncherIcon::LauncherIcon(IconType type) 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) + for (unsigned i = 0; i < monitors::MAX; ++i) + { + for (unsigned j = 0; j < static_cast<unsigned>(Quirk::LAST); ++j) { - _tooltip->SetOpacity(opacity); - - if (opacity == 0.0f && _tooltip_fade_animator.GetStartValue() > _tooltip_fade_animator.GetFinishValue()) - _tooltip->ShowWindow(false); + _quirk_animations[i][j] = std::make_shared<Animation>(); + _quirk_animations[i][j]->updated.connect([this, i, j] (float value) { EmitNeedsRedraw(i); }); } - }); -} -LauncherIcon::~LauncherIcon() -{ - SetQuirk(Quirk::URGENT, false); + // Center must have set a default value + animation::SetValue(GetQuirkAnimation(Quirk::CENTER_SAVED, i), animation::Direction::FORWARD); + } } void LauncherIcon::LoadTooltip() @@ -158,19 +132,14 @@ void LauncherIcon::LoadQuicklist() QuicklistManager::Default()->RegisterQuicklist(_quicklist); } -const bool -LauncherIcon::WindowVisibleOnMonitor(int monitor) +const bool LauncherIcon::WindowVisibleOnMonitor(int monitor) { return _has_visible_window[monitor]; } const bool LauncherIcon::WindowVisibleOnViewport() { - for (int i = 0; i < max_num_monitors; ++i) - if (_has_visible_window[i]) - return true; - - return false; + return _has_visible_window.any(); } std::string @@ -185,7 +154,7 @@ LauncherIcon::AddProperties(GVariantBuilder* builder) GVariantBuilder monitors_builder; g_variant_builder_init(&monitors_builder, G_VARIANT_TYPE ("ab")); - for (int i = 0; i < max_num_monitors; ++i) + for (unsigned i = 0; i < monitors::MAX; ++i) g_variant_builder_add(&monitors_builder, "b", IsVisibleOnMonitor(i)); unity::variant::BuilderWrapper(builder) @@ -207,30 +176,45 @@ LauncherIcon::AddProperties(GVariantBuilder* builder) .add("presented", GetQuirk(Quirk::PRESENTED)); } -void -LauncherIcon::Activate(ActionArg arg) +bool LauncherIcon::IsActionArgValid(ActionArg const& arg) +{ + if (arg.source != ActionArg::Source::LAUNCHER_KEYBINDING) + return true; + + time::Spec now; + now.SetToNow(); + + return (now.TimeDelta(_last_action) > IGNORE_REPEAT_SHORTCUT_DURATION); +} + +void LauncherIcon::Activate(ActionArg arg) { + if (!IsActionArgValid(arg)) + return; + /* Launcher Icons that handle spread will adjust the spread state * accordingly, for all other icons we should terminate spread */ WindowManager& wm = WindowManager::Default(); - if (wm.IsScaleActive() && !HandlesSpread ()) + if (wm.IsScaleActive() && !HandlesSpread()) wm.TerminateScale(); ActivateLauncherIcon(arg); - UpdateQuirkTime(Quirk::LAST_ACTION); + _last_action.SetToNow(); } -void -LauncherIcon::OpenInstance(ActionArg arg) +void LauncherIcon::OpenInstance(ActionArg arg) { + if (!IsActionArgValid(arg)) + return; + WindowManager& wm = WindowManager::Default(); if (wm.IsScaleActive()) wm.TerminateScale(); OpenInstanceLauncherIcon(arg.timestamp); - UpdateQuirkTime(Quirk::LAST_ACTION); + _last_action.SetToNow(); } nux::Color LauncherIcon::BackgroundColor() const @@ -304,18 +288,15 @@ void LauncherIcon::ColorForIcon(GdkPixbuf* pixbuf, nux::Color& background, nux:: /* static */ bool LauncherIcon::IsMonoDefaultTheme() { - if (_current_theme_is_mono != -1) return (bool)_current_theme_is_mono; GtkIconTheme* default_theme; gtk::IconInfo info; - int size = 48; - default_theme = gtk_icon_theme_get_default(); _current_theme_is_mono = (int)false; - info = gtk_icon_theme_lookup_icon(default_theme, MONO_TEST_ICON.c_str(), size, (GtkIconLookupFlags)0); + info = gtk_icon_theme_lookup_icon(default_theme, MONO_TEST_ICON.c_str(), icon_size(), (GtkIconLookupFlags)0); if (!info) return (bool)_current_theme_is_mono; @@ -339,15 +320,13 @@ GtkIconTheme* LauncherIcon::GetUnityTheme() return _unity_theme; } -nux::BaseTexture* LauncherIcon::TextureFromGtkTheme(std::string icon_name, int size, bool update_glow_colors) +BaseTexturePtr LauncherIcon::TextureFromGtkTheme(std::string icon_name, int size, bool update_glow_colors) { GtkIconTheme* default_theme; - nux::BaseTexture* result = NULL; + BaseTexturePtr result; if (icon_name.empty()) - { icon_name = DEFAULT_ICON; - } default_theme = gtk_icon_theme_get_default(); @@ -361,23 +340,19 @@ nux::BaseTexture* LauncherIcon::TextureFromGtkTheme(std::string icon_name, int s if (!result) { - if (icon_name == "folder") - result = NULL; - else + if (icon_name != "folder") result = TextureFromSpecificGtkTheme(default_theme, "folder", size, update_glow_colors); } return result; - } -nux::BaseTexture* LauncherIcon::TextureFromSpecificGtkTheme(GtkIconTheme* theme, - std::string const& icon_name, - int size, - bool update_glow_colors, - bool is_default_theme) +BaseTexturePtr LauncherIcon::TextureFromSpecificGtkTheme(GtkIconTheme* theme, + std::string const& icon_name, + int size, + bool update_glow_colors, + bool is_default_theme) { - nux::BaseTexture* result = nullptr; glib::Object<GIcon> icon(g_icon_new_for_string(icon_name.c_str(), nullptr)); gtk::IconInfo info; auto flags = static_cast<GtkIconLookupFlags>(0); @@ -392,7 +367,7 @@ nux::BaseTexture* LauncherIcon::TextureFromSpecificGtkTheme(GtkIconTheme* theme, } if (!info && !is_default_theme) - return nullptr; + return BaseTexturePtr(); if (!info) { @@ -409,10 +384,13 @@ nux::BaseTexture* LauncherIcon::TextureFromSpecificGtkTheme(GtkIconTheme* theme, if (pbuf.IsType(GDK_TYPE_PIXBUF)) { - result = nux::CreateTexture2DFromPixbuf(pbuf, true); - if (update_glow_colors) ColorForIcon(pbuf, _background_color, _glow_color); + + BaseTexturePtr result; + result.Adopt(nux::CreateTexture2DFromPixbuf(pbuf, true)); + + return result; } else { @@ -420,13 +398,11 @@ nux::BaseTexture* LauncherIcon::TextureFromSpecificGtkTheme(GtkIconTheme* theme, << "' from icon theme: " << error; } - return result; + return BaseTexturePtr(); } -nux::BaseTexture* LauncherIcon::TextureFromPath(std::string const& icon_name, int size, bool update_glow_colors) +BaseTexturePtr LauncherIcon::TextureFromPath(std::string const& icon_name, int size, bool update_glow_colors) { - nux::BaseTexture* result; - if (icon_name.empty()) return TextureFromGtkTheme(DEFAULT_ICON, size, update_glow_colors); @@ -435,39 +411,39 @@ nux::BaseTexture* LauncherIcon::TextureFromPath(std::string const& icon_name, in if (GDK_IS_PIXBUF(pbuf.RawPtr())) { - result = nux::CreateTexture2DFromPixbuf(pbuf, true); - if (update_glow_colors) ColorForIcon(pbuf, _background_color, _glow_color); + + BaseTexturePtr result; + result.Adopt(nux::CreateTexture2DFromPixbuf(pbuf, true)); + return result; } else { LOG_WARN(logger) << "Unable to load '" << icon_name << "' icon: " << error; - result = TextureFromGtkTheme(DEFAULT_ICON, size, update_glow_colors); + return TextureFromGtkTheme(DEFAULT_ICON, size, update_glow_colors); } - return result; + return BaseTexturePtr(); } bool LauncherIcon::SetTooltipText(std::string& target, std::string const& value) { - bool result = false; - - gchar* esc = g_markup_escape_text(value.c_str(), -1); - std::string escaped = esc; - g_free(esc); + auto const& escaped = glib::String(g_markup_escape_text(value.c_str(), -1)).Str(); if (escaped != target) { target = escaped; + if (_tooltip) _tooltip->text = target; - result = true; + + return true; } - return result; + return false; } void LauncherIcon::OnTooltipEnabledChanged(bool value) @@ -476,8 +452,7 @@ void LauncherIcon::OnTooltipEnabledChanged(bool value) HideTooltip(); } -void -LauncherIcon::SetShortcut(guint64 shortcut) +void LauncherIcon::SetShortcut(guint64 shortcut) { // only relocate a digit with a digit (don't overwrite other shortcuts) if ((!_shortcut || (g_ascii_isdigit((gchar)_shortcut))) @@ -485,42 +460,31 @@ LauncherIcon::SetShortcut(guint64 shortcut) _shortcut = shortcut; } -guint64 -LauncherIcon::GetShortcut() +guint64 LauncherIcon::GetShortcut() { return _shortcut; } -void -LauncherIcon::ShowTooltip() +nux::Point LauncherIcon::GetTipPosition(int monitor) const { - if (!tooltip_enabled || (_quicklist && _quicklist->IsVisible())) - return; + return nux::Point(_center[monitor].x + icon_size()/2 + 1, _center[monitor].y); +} - int tip_x = 100; - int tip_y = 100; - if (_last_monitor >= 0) - { - nux::Geometry geo = _parent_geo[_last_monitor]; - tip_x = geo.x + geo.width - 4 * geo.width / 48; - tip_y = _center[_last_monitor].y; - } +void LauncherIcon::ShowTooltip() +{ + if (!tooltip_enabled || tooltip_text().empty() || (_quicklist && _quicklist->IsVisible())) + return; if (!_tooltip) LoadTooltip(); + + auto const& pos = GetTipPosition(_last_monitor); _tooltip->text = tooltip_text(); - _tooltip->ShowTooltipWithTipAt(tip_x, tip_y); - _tooltip->ShowWindow(!tooltip_text().empty()); + _tooltip->ShowTooltipWithTipAt(pos.x, pos.y); 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) +void LauncherIcon::RecvMouseEnter(int monitor) { _last_monitor = monitor; } @@ -542,7 +506,10 @@ bool LauncherIcon::OpenQuicklist(bool select_first_item, int monitor) return false; if (_tooltip) + { + // Hide the tooltip without fade animation _tooltip->ShowWindow(false); + } _quicklist->RemoveAllMenuItem(); @@ -589,28 +556,26 @@ bool LauncherIcon::OpenQuicklist(bool select_first_item, int monitor) monitor = 0; } - nux::Geometry const& geo = _parent_geo[monitor]; - int tip_x = geo.x + geo.width - 4 * geo.width / 48; - int tip_y = _center[monitor].y; - WindowManager& win_manager = WindowManager::Default(); if (win_manager.IsScaleActive()) win_manager.TerminateScale(); + auto const& pos = GetTipPosition(monitor); + /* If the expo plugin is active, we need to wait it to be terminated, before * showing the icon quicklist. */ if (win_manager.IsExpoActive()) { auto conn = std::make_shared<sigc::connection>(); - *conn = win_manager.terminate_expo.connect([this, conn, tip_x, tip_y] { - QuicklistManager::Default()->ShowQuicklist(_quicklist, tip_x, tip_y); + *conn = win_manager.terminate_expo.connect([this, conn, pos] { + QuicklistManager::Default()->ShowQuicklist(_quicklist, pos.x, pos.y); conn->disconnect(); }); } else { - QuicklistManager::Default()->ShowQuicklist(_quicklist, tip_x, tip_y); + QuicklistManager::Default()->ShowQuicklist(_quicklist, pos.x, pos.y); } return true; @@ -664,67 +629,66 @@ void LauncherIcon::RecvMouseClick(int button, int monitor, unsigned long key_fla void LauncherIcon::HideTooltip() { if (_tooltip) + _tooltip->Hide(); + + tooltip_visible.emit(nux::ObjectPtr<nux::View>()); +} + +void LauncherIcon::SetCenter(nux::Point3 const& new_center, int monitor) +{ + nux::Point3& center = _center[monitor]; + + if (center == new_center) + return; + + center = new_center; + + if (monitor == _last_monitor) { - if (_tooltip_fade_animator.CurrentState() == nux::animation::Animation::State::Running && - _tooltip_fade_animator.GetFinishValue() == 1.0) + if (_quicklist && _quicklist->IsVisible()) { - _tooltip_fade_animator.Reverse(); + auto const& pos = GetTipPosition(monitor); + QuicklistManager::Default()->MoveQuicklist(_quicklist, pos.x, pos.y); } - else + else if (_tooltip && _tooltip->IsVisible()) { - _tooltip_fade_animator.SetStartValue(1.0f).SetFinishValue(0.0f).Start(); + auto const& pos = GetTipPosition(monitor); + _tooltip->SetTooltipPosition(pos.x, pos.y); } } - tooltip_visible.emit(nux::ObjectPtr<nux::View>(nullptr)); -} + _source_manager.AddTimeout(500, [this] { + if (!std::equal(_center.begin(), _center.end(), _last_stable.begin())) + { + if (!removed()) + OnCenterStabilized(_center); -bool -LauncherIcon::OnCenterStabilizeTimeout() -{ - if (!std::equal(_center.begin(), _center.end(), _last_stable.begin())) - { - OnCenterStabilized(_center); - _last_stable = _center; - } + _last_stable = _center; + } - return false; + return false; + }, CENTER_STABILIZE_TIMEOUT + std::to_string(monitor)); } -void -LauncherIcon::SetCenter(nux::Point3 const& center, int monitor, nux::Geometry const& geo) +void LauncherIcon::ResetCenters(int monitor) { - _parent_geo[monitor] = geo; - - nux::Point3& new_center = _center[monitor]; - new_center.x = center.x + geo.x; - new_center.y = center.y + geo.y; - new_center.z = center.z; - - if (monitor == _last_monitor) + if (monitor < 0) { - int tip_x, tip_y; - tip_x = geo.x + geo.width - 4 * geo.width / 48; - tip_y = new_center.y; - - if (_quicklist && _quicklist->IsVisible()) - QuicklistManager::Default()->ShowQuicklist(_quicklist, tip_x, tip_y); - else if (_tooltip && _tooltip->IsVisible()) - _tooltip->ShowTooltipWithTipAt(tip_x, tip_y); + for (unsigned i = 0; i < monitors::MAX; ++i) + _center[i].Set(0, 0, 0); + } + else + { + _center[monitor].Set(0, 0, 0); } - - auto const& cb_func = sigc::mem_fun(this, &LauncherIcon::OnCenterStabilizeTimeout); - _source_manager.AddTimeout(500, cb_func, CENTER_STABILIZE_TIMEOUT); } -nux::Point3 -LauncherIcon::GetCenter(int monitor) +nux::Point3 LauncherIcon::GetCenter(int monitor) { return _center[monitor]; } -nux::Point3 -LauncherIcon::GetSavedCenter(int monitor) +nux::Point3 LauncherIcon::GetSavedCenter(int monitor) { return _saved_center[monitor]; } @@ -734,48 +698,45 @@ std::vector<nux::Point3> LauncherIcon::GetCenters() return _center; } -void -LauncherIcon::SaveCenter() +void LauncherIcon::SaveCenter() { _saved_center = _center; - UpdateQuirkTime(Quirk::CENTER_SAVED); + FullyAnimateQuirk(Quirk::CENTER_SAVED, 0); } -void -LauncherIcon::SetWindowVisibleOnMonitor(bool val, int monitor) +std::pair<int, nux::Point3> LauncherIcon::GetCenterForMonitor(int monitor) const { - if (_has_visible_window[monitor] == val) - return; + monitor = CLAMP(monitor, 0, static_cast<int>(_center.size() - 1)); - _has_visible_window[monitor] = val; - EmitNeedsRedraw(); + if (_center[monitor].x && _center[monitor].y) + return {monitor, _center[monitor]}; + + for (unsigned i = 0; i < _center.size(); ++i) + { + if (_center[i].x && _center[i].y) + return {i, _center[i]}; + } + + return {-1, nux::Point3()}; } -void -LauncherIcon::SetVisibleOnMonitor(int monitor, bool visible) +void LauncherIcon::SetWindowVisibleOnMonitor(bool val, int monitor) { - if (_is_visible_on_monitor[monitor] == visible) + if (_has_visible_window[monitor] == val) return; - _is_visible_on_monitor[monitor] = visible; - EmitNeedsRedraw(); + _has_visible_window[monitor] = val; + EmitNeedsRedraw(monitor); } -bool -LauncherIcon::IsVisibleOnMonitor(int monitor) const +void LauncherIcon::SetVisibleOnMonitor(int monitor, bool visible) { - return _is_visible_on_monitor[monitor]; + SetQuirk(Quirk::VISIBLE, visible, monitor); } -bool -LauncherIcon::OnPresentTimeout() +bool LauncherIcon::IsVisibleOnMonitor(int monitor) const { - if (!GetQuirk(Quirk::PRESENTED)) - return false; - - Unpresent(); - - return false; + return GetQuirk(Quirk::VISIBLE, monitor); } float LauncherIcon::PresentUrgency() @@ -783,52 +744,61 @@ float LauncherIcon::PresentUrgency() return _present_urgency; } -void -LauncherIcon::Present(float present_urgency, int length) +void LauncherIcon::Present(float present_urgency, int length, int monitor) { - if (GetQuirk(Quirk::PRESENTED)) + if (GetQuirk(Quirk::PRESENTED, monitor)) return; if (length >= 0) { - auto cb_func = sigc::mem_fun(this, &LauncherIcon::OnPresentTimeout); - _source_manager.AddTimeout(length, cb_func, PRESENT_TIMEOUT); + _source_manager.AddTimeout(length, [this, monitor] { + if (!GetQuirk(Quirk::PRESENTED, monitor)) + return false; + + Unpresent(monitor); + return false; + }, PRESENT_TIMEOUT + std::to_string(monitor)); } _present_urgency = CLAMP(present_urgency, 0.0f, 1.0f); - SetQuirk(Quirk::PRESENTED, true); - SetQuirk(Quirk::UNFOLDED, true); + SetQuirk(Quirk::PRESENTED, true, monitor); + SetQuirk(Quirk::UNFOLDED, true, monitor); } -void -LauncherIcon::Unpresent() +void LauncherIcon::Unpresent(int monitor) { - if (!GetQuirk(Quirk::PRESENTED)) + if (!GetQuirk(Quirk::PRESENTED, monitor)) return; - _source_manager.Remove(PRESENT_TIMEOUT); - SetQuirk(Quirk::PRESENTED, false); - SetQuirk(Quirk::UNFOLDED, false); + _source_manager.Remove(PRESENT_TIMEOUT + std::to_string(monitor)); + SetQuirk(Quirk::PRESENTED, false, monitor); + SetQuirk(Quirk::UNFOLDED, false, monitor); } -void -LauncherIcon::Remove() +void LauncherIcon::Remove() { if (_quicklist && _quicklist->IsVisible()) _quicklist->Hide(); + if (_tooltip && _tooltip->IsVisible()) + _tooltip->Hide(); + SetQuirk(Quirk::VISIBLE, false); EmitRemove(); + + // Disconnect all the callbacks that may interact with the icon data + _source_manager.RemoveAll(); + sigc::trackable::notify_callbacks(); + + removed = true; } -void -LauncherIcon::SetSortPriority(int priority) +void LauncherIcon::SetSortPriority(int priority) { _sort_priority = priority; } -int -LauncherIcon::SortPriority() +int LauncherIcon::SortPriority() { return _sort_priority; } @@ -839,75 +809,116 @@ LauncherIcon::GetIconType() const return _icon_type; } -bool -LauncherIcon::GetQuirk(LauncherIcon::Quirk quirk) const +bool LauncherIcon::GetQuirk(LauncherIcon::Quirk quirk, int monitor) const { - return _quirks[unsigned(quirk)]; + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + { + if (!_quirks[i][unsigned(quirk)]) + return false; + } + + return true; + } + + return _quirks[monitor][unsigned(quirk)]; } -void -LauncherIcon::SetQuirk(LauncherIcon::Quirk quirk, bool value) +void LauncherIcon::SetQuirk(LauncherIcon::Quirk quirk, bool value, int monitor) { - if (_quirks[unsigned(quirk)] == value) - return; + bool changed = false; - _quirks[unsigned(quirk)] = value; - if (quirk == Quirk::VISIBLE) - TimeUtil::SetTimeStruct(&(_quirk_times[unsigned(quirk)]), &(_quirk_times[unsigned(quirk)]), Launcher::ANIM_DURATION_SHORT); + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + { + if (_quirks[i][unsigned(quirk)] != value) + { + _quirks[i][unsigned(quirk)] = value; + animation::StartOrReverseIf(GetQuirkAnimation(quirk, i), value); + changed = true; + } + } + } else - clock_gettime(CLOCK_MONOTONIC, &(_quirk_times[unsigned(quirk)])); - EmitNeedsRedraw(); - - // Present on urgent as a general policy - if (quirk == Quirk::VISIBLE && value) - Present(0.5f, 1500); - if (quirk == Quirk::URGENT) { - if (value) + if (_quirks[monitor][unsigned(quirk)] != value) { - Present(0.5f, 1500); + _quirks[monitor][unsigned(quirk)] = value; + animation::StartOrReverseIf(GetQuirkAnimation(quirk, monitor), value); + changed = true; } - - UBusManager::SendMessage(UBUS_LAUNCHER_ICON_URGENT_CHANGED, g_variant_new_boolean(value)); } - if (quirk == Quirk::VISIBLE) + if (!changed) + return; + + // Present on urgent and visible as a general policy + if (value && (quirk == Quirk::URGENT || quirk == Quirk::VISIBLE)) { - visibility_changed.emit(); + Present(0.5f, 1500, monitor); } + + if (quirk == Quirk::VISIBLE) + visibility_changed.emit(monitor); } -void -LauncherIcon::UpdateQuirkTimeDelayed(guint ms, LauncherIcon::Quirk quirk) +void LauncherIcon::FullyAnimateQuirkDelayed(guint ms, LauncherIcon::Quirk quirk, int monitor) { - _source_manager.AddTimeout(ms, [&, quirk] { - UpdateQuirkTime(quirk); + _source_manager.AddTimeout(ms, [this, quirk, monitor] { + FullyAnimateQuirk(quirk, monitor); return false; - }, QUIRK_DELAY_TIMEOUT); + }, QUIRK_DELAY_TIMEOUT + std::to_string(unsigned(quirk)) + std::to_string(monitor)); } -void -LauncherIcon::UpdateQuirkTime(LauncherIcon::Quirk quirk) +void LauncherIcon::FullyAnimateQuirk(LauncherIcon::Quirk quirk, int monitor) { - clock_gettime(CLOCK_MONOTONIC, &(_quirk_times[unsigned(quirk)])); - EmitNeedsRedraw(); + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + animation::Start(GetQuirkAnimation(quirk, i), animation::Direction::FORWARD); + } + else + { + animation::Start(GetQuirkAnimation(quirk, monitor), animation::Direction::FORWARD); + } } -void -LauncherIcon::ResetQuirkTime(LauncherIcon::Quirk quirk) +void LauncherIcon::SkipQuirkAnimation(LauncherIcon::Quirk quirk, int monitor) { - _quirk_times[unsigned(quirk)].tv_sec = 0; - _quirk_times[unsigned(quirk)].tv_nsec = 0; + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + { + animation::Skip(GetQuirkAnimation(quirk, i)); + } + } + else + { + animation::Skip(GetQuirkAnimation(quirk, monitor)); + } } -struct timespec -LauncherIcon::GetQuirkTime(LauncherIcon::Quirk quirk) +float LauncherIcon::GetQuirkProgress(Quirk quirk, int monitor) const { - return _quirk_times[unsigned(quirk)]; + return GetQuirkAnimation(quirk, monitor).GetCurrentValue(); } -void -LauncherIcon::SetProgress(float progress) +void LauncherIcon::SetQuirkDuration(Quirk quirk, unsigned duration, int monitor) +{ + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + GetQuirkAnimation(quirk, i).SetDuration(duration); + } + else + { + GetQuirkAnimation(quirk, monitor).SetDuration(duration); + } +} + +void LauncherIcon::SetProgress(float progress) { if (progress == _progress) return; @@ -916,8 +927,7 @@ LauncherIcon::SetProgress(float progress) EmitNeedsRedraw(); } -float -LauncherIcon::GetProgress() +float LauncherIcon::GetProgress() { return _progress; } @@ -1192,10 +1202,22 @@ glib::Object<DbusmenuMenuitem> LauncherIcon::GetRemoteMenus() const return root; } -void LauncherIcon::EmitNeedsRedraw() +void LauncherIcon::EmitNeedsRedraw(int monitor) { if (OwnsTheReference() && GetReferenceCount() > 0) - needs_redraw.emit(AbstractLauncherIcon::Ptr(this)); + { + if (monitor < 0) + { + needs_redraw.emit(AbstractLauncherIcon::Ptr(this), monitor); + } + else + { + auto const& visibilty = GetQuirkAnimation(Quirk::VISIBLE, monitor); + + if (visibilty.GetCurrentValue() > 0.0f || visibilty.CurrentState() == na::Animation::State::Running) + needs_redraw.emit(AbstractLauncherIcon::Ptr(this), monitor); + } + } } void LauncherIcon::EmitRemove() @@ -1206,7 +1228,7 @@ void LauncherIcon::EmitRemove() void LauncherIcon::Stick(bool save) { - if (_sticky) + if (_sticky && !save) return; _sticky = true; diff --git a/launcher/LauncherIcon.h b/launcher/LauncherIcon.h index 477f7db2a..779eb709e 100644 --- a/launcher/LauncherIcon.h +++ b/launcher/LauncherIcon.h @@ -21,8 +21,8 @@ #ifndef LAUNCHERICON_H #define LAUNCHERICON_H +#include <bitset> #include <Nux/Nux.h> -#include <Nux/BaseWindow.h> #include <NuxCore/Animation.h> #include <gtk/gtk.h> @@ -31,17 +31,17 @@ #include <UnityCore/GLibSource.h> #include "AbstractLauncherIcon.h" +#include "MultiMonitor.h" #include "Tooltip.h" #include "QuicklistView.h" -#include "unity-shared/Introspectable.h" #include "LauncherEntryRemote.h" +#include "unity-shared/TimeUtil.h" namespace unity { namespace launcher { - class Launcher; class LauncherIcon : public AbstractLauncherIcon @@ -53,8 +53,6 @@ public: LauncherIcon(IconType type); - virtual ~LauncherIcon(); - bool SetTooltipText(std::string& target, std::string const& value); void SetShortcut(guint64 shortcut); @@ -80,7 +78,9 @@ public: bool OpenQuicklist(bool select_first_item = false, int monitor = -1); void CloseQuicklist(); - void SetCenter(nux::Point3 const& center, int parent_monitor, nux::Geometry const& parent_geo); + void SetCenter(nux::Point3 const& center, int parent_monitor); + + void ResetCenters(int monitor = -1); nux::Point3 GetCenter(int monitor); @@ -129,11 +129,15 @@ public: return 0; } - bool GetQuirk(Quirk quirk) const; + bool GetQuirk(Quirk quirk, int monitor = -1) const; + + void SetQuirk(Quirk quirk, bool value, int monitor = -1); + + float GetQuirkProgress(Quirk quirk, int monitor) const; - void SetQuirk(Quirk quirk, bool value); + void SetQuirkDuration(Quirk quirk, unsigned duration, int monitor = -1); - struct timespec GetQuirkTime(Quirk quirk); + void SkipQuirkAnimation(Quirk quirk, int monitor = -1); IconType GetIconType() const; @@ -141,7 +145,7 @@ public: virtual nux::Color GlowColor(); - std::string RemoteUri() + std::string RemoteUri() const { return GetRemoteUri(); } @@ -182,7 +186,7 @@ public: OnDndLeave(); } - virtual std::string DesktopFile() { return std::string(""); } + virtual std::string DesktopFile() const { return std::string(); } virtual bool IsSticky() const { return _sticky; } @@ -205,15 +209,15 @@ public: protected: std::vector<nux::Point3> GetCenters(); + std::pair<int, nux::Point3> GetCenterForMonitor(int monitor) const; + std::string GetName() const; void AddProperties(GVariantBuilder* builder); - void UpdateQuirkTimeDelayed(guint ms, Quirk quirk); - - void UpdateQuirkTime(Quirk quirk); + void FullyAnimateQuirkDelayed(guint ms, Quirk quirk, int monitor = -1); - void ResetQuirkTime(Quirk quirk); + void FullyAnimateQuirk(Quirk quirk, int monitor = -1); void Remove(); @@ -221,9 +225,9 @@ protected: void SetWindowVisibleOnMonitor(bool val, int monitor); - void Present(float urgency, int length); + void Present(float urgency, int length, int monitor = -1); - void Unpresent(); + void Unpresent(int monitor = -1); void SetEmblem(BaseTexturePtr const& emblem); @@ -231,9 +235,9 @@ protected: virtual nux::BaseTexture* GetTextureForSize(int size) = 0; - virtual void OnCenterStabilized(std::vector<nux::Point3> center) {} + virtual void OnCenterStabilized(std::vector<nux::Point3> const& centers) {} - virtual std::string GetRemoteUri() + virtual std::string GetRemoteUri() const { return ""; } @@ -260,11 +264,11 @@ protected: virtual bool HandlesSpread () { return false; } - nux::BaseTexture* TextureFromGtkTheme(std::string name, int size, bool update_glow_colors = true); + BaseTexturePtr TextureFromGtkTheme(std::string name, int size, bool update_glow_colors = true); - nux::BaseTexture* TextureFromSpecificGtkTheme(GtkIconTheme* theme, std::string const& name, int size, bool update_glow_colors = true, bool is_default_theme = false); + BaseTexturePtr TextureFromSpecificGtkTheme(GtkIconTheme* theme, std::string const& name, int size, bool update_glow_colors = true, bool is_default_theme = false); - nux::BaseTexture* TextureFromPath(std::string const& name, int size, bool update_glow_colors = true); + BaseTexturePtr TextureFromPath(std::string const& name, int size, bool update_glow_colors = true); static bool IsMonoDefaultTheme(); @@ -286,10 +290,18 @@ protected: void OnRemoteProgressVisibleChanged(LauncherEntryRemote* remote); - void EmitNeedsRedraw(); + void EmitNeedsRedraw(int monitor = -1); void EmitRemove(); + bool IsActionArgValid(ActionArg const&); + + typedef nux::animation::AnimateValue<float> Animation; + inline Animation& GetQuirkAnimation(Quirk quirk, int monitor) const + { + return *_quirk_animations[monitor][unsigned(quirk)]; + } + // This looks like a case for boost::logical::tribool static int _current_theme_is_mono; @@ -301,47 +313,39 @@ private: static void ChildRealized(DbusmenuMenuitem* newitem, QuicklistView* quicklist); static void RootChanged(DbusmenuClient* client, DbusmenuMenuitem* newroot, QuicklistView* quicklist); - bool OnPresentTimeout(); - bool OnCenterStabilizeTimeout(); - void ColorForIcon(GdkPixbuf* pixbuf, nux::Color& background, nux::Color& glow); + nux::Point GetTipPosition(int monitor) const; void LoadTooltip(); void LoadQuicklist(); void OnTooltipEnabledChanged(bool value); - bool _sticky; - bool _remote_urgent; - float _present_urgency; - float _progress; - int _sort_priority; - int _last_monitor; - nux::Color _background_color; - nux::Color _glow_color; - - gint64 _shortcut; + bool _sticky; + bool _remote_urgent; + float _present_urgency; + float _progress; + int _sort_priority; + int _last_monitor; + nux::Color _background_color; + nux::Color _glow_color; + gint64 _shortcut; + bool _allow_quicklist_to_show; std::vector<nux::Point3> _center; - std::vector<bool> _has_visible_window; - std::vector<bool> _is_visible_on_monitor; + std::bitset<monitors::MAX> _has_visible_window; + std::vector<std::bitset<std::size_t(Quirk::LAST)>> _quirks; + std::vector<std::vector<std::shared_ptr<Animation>>> _quirk_animations; std::vector<nux::Point3> _last_stable; - std::vector<nux::Geometry> _parent_geo; std::vector<nux::Point3> _saved_center; - - static glib::Object<GtkIconTheme> _unity_theme; + time::Spec _last_action; BaseTexturePtr _emblem; - bool _quirks[unsigned(Quirk::LAST)]; - struct timespec _quirk_times[unsigned(Quirk::LAST)]; - - bool _allow_quicklist_to_show; - std::list<LauncherEntryRemote::Ptr> _entry_list; glib::Object<DbusmenuClient> _remote_menus; - nux::animation::AnimateValue<double> _tooltip_fade_animator; + static glib::Object<GtkIconTheme> _unity_theme; protected: glib::SourceManager _source_manager; diff --git a/launcher/MockLauncherIcon.h b/launcher/MockLauncherIcon.h index 4f0cff51c..2b375c9b6 100644 --- a/launcher/MockLauncherIcon.h +++ b/launcher/MockLauncherIcon.h @@ -21,6 +21,7 @@ #ifndef MOCKLAUNCHERICON_H #define MOCKLAUNCHERICON_H +#include <bitset> #include <Nux/Nux.h> #include <Nux/BaseWindow.h> @@ -32,9 +33,11 @@ #include <libdbusmenu-glib/menuitem.h> #include "unity-shared/ApplicationManager.h" +#include "unity-shared/TimeUtil.h" #include <UnityCore/GTKWrapper.h> #include "AbstractLauncherIcon.h" +#include "MultiMonitor.h" namespace unity { @@ -69,14 +72,13 @@ public: : icon_(0) , type_(type) , sort_priority_(DefaultPriority(type)) + , quirks_(monitors::MAX) + , quirk_progress_(monitors::MAX, decltype(quirk_progress_)::value_type(unsigned(Quirk::LAST), 0.0f)) , remote_uri_("fake") , is_tooltip_visible_(false) { tooltip_text = "Mock Icon"; position = Position::FLOATING; - - for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i) - quirks_[i] = false; } std::string GetName() const { return "MockLauncherIcon"; } @@ -153,11 +155,15 @@ public: { } - void SetCenter(nux::Point3 const& center, int monitor, nux::Geometry const& geo) + void SetCenter(nux::Point3 const& center, int monitor) { center_[monitor] = center; - center_[monitor].x += geo.x; - center_[monitor].y += geo.y; + } + + void ResetCenters(int monitor = -1) + { + for (auto& pair : center_) + pair.second.Set(0, 0, 0); } nux::Point3 GetCenter(int monitor) @@ -232,24 +238,62 @@ public: return 0; } - bool GetQuirk(Quirk quirk) const + bool GetQuirk(Quirk quirk, int monitor = -1) const { - return quirks_[unsigned(quirk)]; + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + { + if (!quirks_[i][unsigned(quirk)]) + return false; + } + + return true; + } + + return quirks_[monitor][unsigned(quirk)]; } - void SetQuirk(Quirk quirk, bool value) + void SetQuirk(Quirk quirk, bool value, int monitor = -1) { - quirks_[unsigned(quirk)] = value; - clock_gettime(CLOCK_MONOTONIC, &(quirk_times_[unsigned(quirk)])); + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + { + quirks_[i][unsigned(quirk)] = value; + quirk_progress_[i][unsigned(quirk)] = value ? 1.0f : 0.0f; + } + } + else + { + quirks_[monitor][unsigned(quirk)] = value; + quirk_progress_[monitor][unsigned(quirk)] = value ? 1.0f : 0.0f; + } } - void ResetQuirkTime(Quirk quirk) {}; + void SkipQuirkAnimation(Quirk quirk, int monitor) + { + float value = GetQuirk(quirk, monitor) ? 1.0f : 0.0f; - struct timespec GetQuirkTime(Quirk quirk) + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + quirk_progress_[i][unsigned(quirk)] = value; + } + else + { + quirk_progress_[monitor][unsigned(quirk)] = value; + } + } + + float GetQuirkProgress(Quirk quirk, int monitor) const { - return quirk_times_[unsigned(quirk)]; + return quirk_progress_[monitor][unsigned(quirk)]; } + void SetQuirkDuration(Quirk quirk, unsigned duration, int monitor = -1) + {} + IconType GetIconType() const { return type_; @@ -265,7 +309,7 @@ public: return nux::Color(0xFFAAAAAA); } - std::string RemoteUri() + std::string RemoteUri() const { return remote_uri_; } @@ -309,7 +353,7 @@ public: void SendDndLeave() {} - std::string DesktopFile() { return std::string(""); } + std::string DesktopFile() const { return std::string(""); } bool IsSticky() const { return false; } @@ -373,8 +417,8 @@ private: nux::BaseTexture* icon_; IconType type_; int sort_priority_; - bool quirks_[unsigned(Quirk::LAST)]; - timespec quirk_times_[unsigned(Quirk::LAST)]; + std::vector<std::bitset<std::size_t(Quirk::LAST)>> quirks_; + std::vector<std::vector<float>> quirk_progress_; 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 a72b78d3d..7e7d1a72c 100644 --- a/launcher/PointerBarrier.cpp +++ b/launcher/PointerBarrier.cpp @@ -36,6 +36,7 @@ PointerBarrierWrapper::PointerBarrierWrapper() , smoothing(75) , max_velocity_multiplier(1.0f) , direction(BOTH) + , orientation(VERTICAL) , xi2_opcode_(0) , last_event_(0) , current_device_(0) @@ -137,7 +138,7 @@ bool PointerBarrierWrapper::HandleBarrierEvent(XIBarrierEvent* barrier_event) { int velocity = GetEventVelocity(barrier_event); smoothing_accum_ += velocity; - smoothing_count_++; + ++smoothing_count_; current_device_ = barrier_event->deviceid; diff --git a/launcher/PointerBarrier.h b/launcher/PointerBarrier.h index 88c9cc120..0a79175ba 100644 --- a/launcher/PointerBarrier.h +++ b/launcher/PointerBarrier.h @@ -51,7 +51,15 @@ enum BarrierDirection { BOTH = 0, LEFT = 1, + UP = 2, RIGHT = 4, + DOWN = 8 +}; + +enum BarrierOrientation +{ + VERTICAL = 0, + HORIZONTAL }; class PointerBarrierWrapper : public sigc::trackable @@ -80,6 +88,7 @@ public: nux::Property<int> index; nux::Property<BarrierDirection> direction; + nux::Property<BarrierOrientation> orientation; virtual void ConstructBarrier(); virtual void DestroyBarrier(); diff --git a/launcher/QuicklistManager.cpp b/launcher/QuicklistManager.cpp index e7280792c..ea3d61cb3 100644 --- a/launcher/QuicklistManager.cpp +++ b/launcher/QuicklistManager.cpp @@ -24,9 +24,6 @@ #include "QuicklistView.h" #include "QuicklistManager.h" -#include "unity-shared/UBusWrapper.h" -#include "unity-shared/UBusMessages.h" - namespace unity { @@ -81,11 +78,7 @@ void QuicklistManager::ShowQuicklist(nux::ObjectPtr<QuicklistView> const& quickl int tip_y, bool hide_existing_if_open) { if (_current_quicklist == quicklist) - { - // this quicklist is already active - // do we want to still redraw in case the position has changed? return; - } if (hide_existing_if_open && _current_quicklist) { @@ -96,6 +89,11 @@ void QuicklistManager::ShowQuicklist(nux::ObjectPtr<QuicklistView> const& quickl nux::GetWindowCompositor().SetKeyFocusArea(quicklist.GetPointer()); } +void QuicklistManager::MoveQuicklist(nux::ObjectPtr<QuicklistView> const& quicklist, int x, int y) +{ + quicklist->SetQuicklistPosition(x, y); +} + void QuicklistManager::HideQuicklist(nux::ObjectPtr<QuicklistView> const& quicklist) { quicklist->Hide(); @@ -108,7 +106,6 @@ void QuicklistManager::RecvShowQuicklist(nux::BaseWindow* window) _current_quicklist = quicklist; quicklist_opened.emit(nux::ObjectPtr<QuicklistView>(quicklist)); - UBusManager::SendMessage(UBUS_QUICKLIST_SHOWN); } void QuicklistManager::RecvHideQuicklist(nux::BaseWindow* window) diff --git a/launcher/QuicklistManager.h b/launcher/QuicklistManager.h index 71388024c..7f22e12c3 100644 --- a/launcher/QuicklistManager.h +++ b/launcher/QuicklistManager.h @@ -39,9 +39,10 @@ public: nux::ObjectPtr<QuicklistView> Current(); - bool RegisterQuicklist(nux::ObjectPtr<QuicklistView> const& quicklist); - void ShowQuicklist(nux::ObjectPtr<QuicklistView> const& quicklist, int tip_x, int tip_y, bool hide_existing_if_open = true); - void HideQuicklist(nux::ObjectPtr<QuicklistView> const& quicklist); + bool RegisterQuicklist(nux::ObjectPtr<QuicklistView> const&); + void ShowQuicklist(nux::ObjectPtr<QuicklistView> const&, int x, int y, bool hide_existing_if_open = true); + void HideQuicklist(nux::ObjectPtr<QuicklistView> const&); + void MoveQuicklist(nux::ObjectPtr<QuicklistView> const&, int x, int y); void RecvShowQuicklist(nux::BaseWindow* window); void RecvHideQuicklist(nux::BaseWindow* window); diff --git a/launcher/QuicklistView.cpp b/launcher/QuicklistView.cpp index 3851c7730..6ac11a1a6 100644 --- a/launcher/QuicklistView.cpp +++ b/launcher/QuicklistView.cpp @@ -51,6 +51,7 @@ namespace unity namespace { const int ANCHOR_WIDTH = 10.0f; + const int TOP_SIZE = 4; } NUX_IMPLEMENT_OBJECT_TYPE(QuicklistView); @@ -59,7 +60,7 @@ QuicklistView::QuicklistView() : _anchorX(0) , _anchorY(0) , _labelText("QuicklistView 1234567890") - , _top_size(4) + , _top_size(TOP_SIZE) , _mouse_down(false) , _enable_quicklist_for_testing(false) , _anchor_width(10) @@ -323,10 +324,10 @@ QuicklistView::EnableQuicklistForTesting(bool enable_testing) _enable_quicklist_for_testing = enable_testing; } -void QuicklistView::ShowQuicklistWithTipAt(int anchor_tip_x, int anchor_tip_y) +void QuicklistView::SetQuicklistPosition(int tip_x, int tip_y) { - _anchorX = anchor_tip_x; - _anchorY = anchor_tip_y; + _anchorX = tip_x; + _anchorY = tip_y; if (!_enable_quicklist_for_testing) { @@ -337,15 +338,14 @@ void QuicklistView::ShowQuicklistWithTipAt(int anchor_tip_x, int anchor_tip_y) nux::GetWindowThread()->GetGraphicsDisplay().GetWindowHeight(); if (offscreen_size > 0) - _top_size = offscreen_size; + _top_size = offscreen_size + TOP_SIZE; else - _top_size = 4; + _top_size = TOP_SIZE; int x = _anchorX - _padding; int y = _anchorY - _anchor_height / 2 - _top_size - _corner_radius - _padding; - SetBaseX(x); - SetBaseY(y); + SetBaseXY(x, y); } else { @@ -353,32 +353,24 @@ void QuicklistView::ShowQuicklistWithTipAt(int anchor_tip_x, int anchor_tip_y) int x = _anchorX - _padding; int y = _anchorY - _anchor_height / 2 - _top_size - _corner_radius - _padding; - SetBaseX(x); - SetBaseY(y); + SetBaseXY(x, y); } } - - Show(); } -void QuicklistView::ShowWindow(bool b, bool start_modal) +void QuicklistView::ShowQuicklistWithTipAt(int x, int y) { - unity::CairoBaseWindow::ShowWindow(b, start_modal); + SetQuicklistPosition(x, y); + Show(); } void QuicklistView::Show() { if (!IsVisible()) { - // FIXME: ShowWindow shouldn't need to be called first - ShowWindow(true); - PushToFront(); - //EnableInputWindow (true, "quicklist", false, true); - //SetInputFocus (); + CairoBaseWindow::Show(); GrabPointer(); GrabKeyboard(); - QueueDraw(); - _compute_blur_bkg = true; } } @@ -390,8 +382,7 @@ void QuicklistView::Hide() CaptureMouseDownAnyWhereElse(false); UnGrabPointer(); UnGrabKeyboard(); - //EnableInputWindow (false); - ShowWindow(false); + CairoBaseWindow::Hide(); if (_current_item_index != -1) { @@ -1182,9 +1173,9 @@ void QuicklistView::UpdateTexture() nux::GetWindowThread()->GetGraphicsDisplay().GetWindowHeight(); if (offscreen_size > 0) - _top_size = offscreen_size; + _top_size = offscreen_size + TOP_SIZE; else - _top_size = 4; + _top_size = TOP_SIZE; size_above_anchor = _top_size; int x = _anchorX - _padding; @@ -1215,24 +1206,12 @@ void QuicklistView::UpdateTexture() cairo_t* cr_mask = cairo_mask.GetContext(); cairo_t* cr_outline = cairo_outline.GetContext(); - float tint_color[4] = {0.0f, 0.0f, 0.0f, 0.60f}; + float tint_color[4] = {0.0f, 0.0f, 0.0f, HasBlurredBackground() ? 0.60f : 1.0f}; float hl_color[4] = {1.0f, 1.0f, 1.0f, 0.35f}; float dot_color[4] = {1.0f, 1.0f, 1.0f, 0.03f}; float shadow_color[4] = {0.0f, 0.0f, 0.0f, 1.00f}; float outline_color[4] = {1.0f, 1.0f, 1.0f, 0.40f}; float mask_color[4] = {1.0f, 1.0f, 1.0f, 1.00f}; - - if (Settings::Instance().GetLowGfxMode()) - { - float alpha_value = 1.0f; - - tint_color[3] = alpha_value; - hl_color[3] = 0.2f; - dot_color[3] = 0.0f; - shadow_color[3] = alpha_value; - outline_color[3] = alpha_value; - mask_color[3] = alpha_value; - } ql_tint_dot_hl(cr_bg, width, @@ -1324,6 +1303,7 @@ void QuicklistView::AddProperties(GVariantBuilder* builder) .add(GetAbsoluteGeometry()) .add("base_x", GetBaseX()) .add("base_y", GetBaseY()) + .add("base", nux::Point(GetBaseX(), GetBaseY())) .add("active", IsVisible()); } diff --git a/launcher/QuicklistView.h b/launcher/QuicklistView.h index 1516e9b62..9098a562b 100644 --- a/launcher/QuicklistView.h +++ b/launcher/QuicklistView.h @@ -55,8 +55,8 @@ public: void RenderQuicklistView(); - void ShowQuicklistWithTipAt(int anchor_tip_x, int anchor_tip_y); - virtual void ShowWindow(bool b, bool StartModal = false); + void SetQuicklistPosition(int x, int y); + void ShowQuicklistWithTipAt(int x, int y); void Show(); void Hide(); diff --git a/launcher/SimpleLauncherIcon.cpp b/launcher/SimpleLauncherIcon.cpp index 8cf1d97b0..4ed24a990 100644 --- a/launcher/SimpleLauncherIcon.cpp +++ b/launcher/SimpleLauncherIcon.cpp @@ -20,13 +20,11 @@ #ifndef UNITY_SIMPLELAUNCHERICON_H #define UNITY_SIMPLELAUNCHERICON_H +#include "SimpleLauncherIcon.h" + #include <NuxCore/Logger.h> -#include <Nux/Nux.h> -#include <Nux/BaseWindow.h> #include <UnityCore/Variant.h> -#include "SimpleLauncherIcon.h" - #include "unity-shared/UBusWrapper.h" #include "unity-shared/UBusMessages.h" @@ -41,72 +39,42 @@ NUX_IMPLEMENT_OBJECT_TYPE(SimpleLauncherIcon); SimpleLauncherIcon::SimpleLauncherIcon(IconType type) : LauncherIcon(type) , icon_name("", sigc::mem_fun(this, &SimpleLauncherIcon::SetIconName)) - , theme_changed_id_(0) -{ - LauncherIcon::mouse_down.connect(sigc::mem_fun(this, &SimpleLauncherIcon::OnMouseDown)); - LauncherIcon::mouse_up.connect(sigc::mem_fun(this, &SimpleLauncherIcon::OnMouseUp)); - LauncherIcon::mouse_click.connect(sigc::mem_fun(this, &SimpleLauncherIcon::OnMouseClick)); - LauncherIcon::mouse_enter.connect(sigc::mem_fun(this, &SimpleLauncherIcon::OnMouseEnter)); - LauncherIcon::mouse_leave.connect(sigc::mem_fun(this, &SimpleLauncherIcon::OnMouseLeave)); - - theme_changed_id_ = g_signal_connect(gtk_icon_theme_get_default(), "changed", - G_CALLBACK(SimpleLauncherIcon::OnIconThemeChanged), this); -} - -SimpleLauncherIcon::~SimpleLauncherIcon() -{ - for (auto element : texture_map) - if (element.second) - element.second->UnReference(); - - texture_map.clear (); - - if (theme_changed_id_) - g_signal_handler_disconnect(gtk_icon_theme_get_default(), theme_changed_id_); -} - -void SimpleLauncherIcon::OnMouseDown(int button, int monitor, unsigned long key_flags) -{ -} - -void SimpleLauncherIcon::OnMouseUp(int button, int monitor, unsigned long key_flags) -{ -} - -void SimpleLauncherIcon::OnMouseClick(int button, int monitor, unsigned long key_flags) -{ -} - -void SimpleLauncherIcon::OnMouseEnter(int monitor) -{ -} - -void SimpleLauncherIcon::OnMouseLeave(int monitor) { + auto* theme = gtk_icon_theme_get_default(); + theme_changed_signal_.Connect(theme, "changed", [this] (GtkIconTheme *) { + _current_theme_is_mono = -1; + ReloadIcon(); + }); } void SimpleLauncherIcon::ActivateLauncherIcon(ActionArg arg) { - activate.emit(); - UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST, - g_variant_new_boolean(FALSE)); + UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); } nux::BaseTexture* SimpleLauncherIcon::GetTextureForSize(int size) { - if (texture_map[size] != 0) - return texture_map[size]; + auto it = texture_map_.find(size); + if (it != texture_map_.end()) + return it->second.GetPointer(); - std::string icon_string(icon_name()); + std::string const& icon_string = icon_name(); if (icon_string.empty()) - return 0; + return nullptr; + + BaseTexturePtr texture; if (icon_string[0] == '/') - texture_map[size] = TextureFromPath(icon_string, size); + texture = TextureFromPath(icon_string, size); else - texture_map[size] = TextureFromGtkTheme(icon_string, size); - return texture_map[size]; + texture = TextureFromGtkTheme(icon_string, size); + + if (!texture) + return nullptr; + + texture_map_.insert({size, texture}); + return texture.GetPointer(); } bool SimpleLauncherIcon::SetIconName(std::string& target, std::string const& value) @@ -122,23 +90,10 @@ bool SimpleLauncherIcon::SetIconName(std::string& target, std::string const& val void SimpleLauncherIcon::ReloadIcon() { - for (auto element : texture_map) - if (element.second) - element.second->UnReference(); - - texture_map.clear (); + texture_map_.clear(); EmitNeedsRedraw(); } -void SimpleLauncherIcon::OnIconThemeChanged(GtkIconTheme* icon_theme, gpointer data) -{ - SimpleLauncherIcon* self = static_cast<SimpleLauncherIcon*>(data); - - // invalidate the current cache - self->_current_theme_is_mono = -1; - self->ReloadIcon(); -} - std::string SimpleLauncherIcon::GetName() const { return "SimpleLauncherIcon"; diff --git a/launcher/SimpleLauncherIcon.h b/launcher/SimpleLauncherIcon.h index 921f75559..aedbec507 100644 --- a/launcher/SimpleLauncherIcon.h +++ b/launcher/SimpleLauncherIcon.h @@ -20,6 +20,7 @@ #ifndef UNITYSHELL_SIMPLELAUNCHERICON_H #define UNITYSHELL_SIMPLELAUNCHERICON_H +#include <UnityCore/GLibSignal.h> #include "LauncherIcon.h" namespace unity @@ -34,38 +35,24 @@ class SimpleLauncherIcon : public LauncherIcon NUX_DECLARE_OBJECT_TYPE(SimpleLauncherIcon, LauncherIcon); public: SimpleLauncherIcon(IconType type); - virtual ~SimpleLauncherIcon(); - - // override - nux::BaseTexture* GetTextureForSize(int size); // Properties nux::Property<std::string> icon_name; - // Signals - sigc::signal<void> activate; - protected: std::string GetName() const; void AddProperties(GVariantBuilder* builder); - virtual void OnMouseDown(int button, int monitor, unsigned long key_flags = 0); - virtual void OnMouseUp(int button, int monitor, unsigned long key_flags = 0); - virtual void OnMouseClick(int button, int monitor, unsigned long key_flags = 0); - virtual void OnMouseEnter(int monitor); - virtual void OnMouseLeave(int monitor); + nux::BaseTexture* GetTextureForSize(int size) override; virtual void ActivateLauncherIcon(ActionArg arg); private: void ReloadIcon(); - static void OnIconThemeChanged(GtkIconTheme* icon_theme, gpointer data); bool SetIconName(std::string& target, std::string const& value); private: - guint32 theme_changed_id_; - - std::map<int, nux::BaseTexture*> texture_map; - int last_size_; + std::unordered_map<int, BaseTexturePtr> texture_map_; + glib::Signal<void, GtkIconTheme*> theme_changed_signal_; }; } diff --git a/launcher/SingleMonitorLauncherIcon.cpp b/launcher/SingleMonitorLauncherIcon.cpp index 7cb6355b7..403466683 100644 --- a/launcher/SingleMonitorLauncherIcon.cpp +++ b/launcher/SingleMonitorLauncherIcon.cpp @@ -20,7 +20,6 @@ #include <UnityCore/Variant.h> #include "SingleMonitorLauncherIcon.h" -#include "MultiMonitor.h" namespace unity { @@ -36,12 +35,8 @@ SingleMonitorLauncherIcon::SingleMonitorLauncherIcon(IconType type, int monitor) void SingleMonitorLauncherIcon::UpdateMonitor() { - for (int i = 0; i < max_num_monitors; ++i) - { - SetVisibleOnMonitor(i, i == monitor_); - } - - EmitNeedsRedraw(); + for (unsigned i = 0; i < monitors::MAX; ++i) + SetVisibleOnMonitor(i, static_cast<int>(i) == monitor_); } void SingleMonitorLauncherIcon::SetMonitor(int monitor) @@ -53,7 +48,7 @@ void SingleMonitorLauncherIcon::SetMonitor(int monitor) } } -int SingleMonitorLauncherIcon::GetMonitor() +int SingleMonitorLauncherIcon::GetMonitor() const { return monitor_; } diff --git a/launcher/SingleMonitorLauncherIcon.h b/launcher/SingleMonitorLauncherIcon.h index fdca150be..b24645e79 100644 --- a/launcher/SingleMonitorLauncherIcon.h +++ b/launcher/SingleMonitorLauncherIcon.h @@ -29,12 +29,11 @@ namespace launcher class SingleMonitorLauncherIcon : public SimpleLauncherIcon { - public: - SingleMonitorLauncherIcon(IconType type, int monitor); + SingleMonitorLauncherIcon(IconType type, int monitor = -1); void SetMonitor(int monitor); -int GetMonitor(); +int GetMonitor() const; protected: std::string GetName() const; diff --git a/launcher/SoftwareCenterLauncherIcon.cpp b/launcher/SoftwareCenterLauncherIcon.cpp index 4f3a94409..abd6abedf 100644 --- a/launcher/SoftwareCenterLauncherIcon.cpp +++ b/launcher/SoftwareCenterLauncherIcon.cpp @@ -39,30 +39,34 @@ namespace launcher namespace { -#define SOURCE_SHOW_TOOLTIP "ShowTooltip" -#define SOURCE_HIDE_TOOLTIP "HideTooltip" const int INSTALL_TIP_DURATION = 1500; } NUX_IMPLEMENT_OBJECT_TYPE(SoftwareCenterLauncherIcon); - SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(ApplicationPtr const& app, std::string const& aptdaemon_trans_id, std::string const& icon_path) : ApplicationLauncherIcon(app) - , aptdaemon_trans_("org.debian.apt", - aptdaemon_trans_id, - "org.debian.apt.transaction", - G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START) - , finished_(true) + , aptdaemon_trans_(std::make_shared<glib::DBusProxy>("org.debian.apt", + aptdaemon_trans_id, + "org.debian.apt.transaction", + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START)) + , finished_(false) , needs_urgent_(false) , aptdaemon_trans_id_(aptdaemon_trans_id) - , app_title_(app->title()) { + Stick(false); SetQuirk(Quirk::VISIBLE, false); - aptdaemon_trans_.Connect("PropertyChanged", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnPropertyChanged)); - aptdaemon_trans_.Connect("Finished", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnFinished)); + SkipQuirkAnimation(Quirk::VISIBLE); + + aptdaemon_trans_->Connect("PropertyChanged", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnPropertyChanged)); + aptdaemon_trans_->Connect("Finished", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnFinished)); + aptdaemon_trans_->GetProperty("Progress", [this] (GVariant *value) { + int32_t progress = glib::Variant(value).GetInt32(); + SetProgress(progress/100.0f); + SetQuirk(Quirk::PROGRESS, (progress > 0)); + }); if (!icon_path.empty()) icon_name = icon_path; @@ -71,50 +75,51 @@ SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(ApplicationPtr const& app tooltip_text = _("Waiting to install"); } -void SoftwareCenterLauncherIcon::Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y) +bool SoftwareCenterLauncherIcon::Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y) { using namespace std::placeholders; - launcher_ = launcher; - - // FIXME: this needs testing, if there is no useful coordinates - // then do not animate - if(start_x <= 0 && start_y <= 0) + if (start_x <= 0 && start_y <= 0) { - SetQuirk(Quirk::VISIBLE, true); - return; + SetQuirk(Quirk::VISIBLE, true); + return true; } - icon_texture_ = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture( - launcher->GetWidth(), - launcher->GetWidth(), - 1, - nux::BITFMT_R8G8B8A8); + int monitor = launcher->monitor(); + auto const& icon_center = GetCenter(monitor); - drag_window_ = new LauncherDragWindow(icon_texture_, - std::bind (&Launcher::RenderIconToTexture, - launcher.GetPointer(), - _1, - AbstractLauncherIcon::Ptr(this), - icon_texture_)); + if (icon_center.x == 0 && icon_center.y == 0) + return false; - launcher->ForceReveal(true); + auto* floating_icon = new SimpleLauncherIcon(GetIconType()); + AbstractLauncherIcon::Ptr floating_icon_ptr(floating_icon); + floating_icon->icon_name = icon_name(); - auto const& icon_center = GetCenter(launcher->monitor()); + // Transform this in a spacer-icon and make it visible only on launcher's monitor + icon_name = ""; + SetQuirk(Quirk::VISIBLE, true, monitor); + + auto rcb = std::bind(&Launcher::RenderIconToTexture, launcher.GetPointer(), _1, _2, floating_icon_ptr); + drag_window_ = new LauncherDragWindow(launcher->GetWidth(), rcb); drag_window_->SetBaseXY(start_x, start_y); - drag_window_->ShowWindow(true); drag_window_->SetAnimationTarget(icon_center.x, icon_center.y + (launcher->GetIconSize() / 2)); - drag_window_->on_anim_completed_conn_ = drag_window_->anim_completed.connect(sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnDragAnimationFinished)); + + launcher->ForceReveal(true); + drag_window_->ShowWindow(true); + + auto cb = sigc::bind(sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnDragAnimationFinished), launcher, floating_icon->icon_name()); + drag_window_->anim_completed.connect(cb); drag_window_->StartSlowAnimation(); + + return true; } -void SoftwareCenterLauncherIcon::OnDragAnimationFinished() +void SoftwareCenterLauncherIcon::OnDragAnimationFinished(nux::ObjectPtr<Launcher> const& launcher, std::string const& final_icon) { + icon_name = final_icon; drag_window_->ShowWindow(false); - drag_window_ = nullptr; - launcher_->ForceReveal(false); - launcher_ = nullptr; - icon_texture_ = nullptr; + drag_window_.Release(); + launcher->ForceReveal(false); SetQuirk(Quirk::VISIBLE, true); } @@ -138,127 +143,120 @@ void SoftwareCenterLauncherIcon::ActivateLauncherIcon(ActionArg arg) std::string SoftwareCenterLauncherIcon::GetActualDesktopFileAfterInstall() { - // Fixup the _desktop_file because the one we get from software-center - // is not the final one, e.g. the s-c-agent does send a temp one and - // app-install-data points to the "wrong" one in /usr/share/app-install - // - // So: - // - if there is a desktop file already and it startswith - // /usr/share/app-install/desktop, then transform to - // /usr/share/application - // - if there is a desktop file with prefix /tmp/software-center-agent: - // transform to /usr/share/application - // (its using "/tmp/software-center-agent:$random:$pkgname.desktop") - // maybe: - // - and search in /var/lib/apt/lists/$pkgname.list - // for a desktop file that roughly matches what we want - std::string filename = _desktop_file; - - // take /usr/share/app-install/desktop/foo:subdir__bar.desktop - // and tranform it - if (_desktop_file.find("/share/app-install/desktop/") != std::string::npos) - { - filename = filename.substr(filename.rfind(":") + 1, - filename.length() - filename.rfind(":")); - // the app-install-data package encodes subdirs in a funny way, once - // that is fixed, this code can be dropped - if (filename.find("__") != std::string::npos) - { - int pos = filename.find("__"); - filename = filename.replace(pos, 2, "-"); - } - filename = DesktopUtilities::GetDesktopPathById(filename); + // Fixup the _desktop_file because the one we get from software-center + // is not the final one, e.g. the s-c-agent does send a temp one and + // app-install-data points to the "wrong" one in /usr/share/app-install + // + // So: + // - if there is a desktop file already and it startswith + // /usr/share/app-install/desktop, then transform to + // /usr/share/application + // - if there is a desktop file with prefix /tmp/software-center-agent: + // transform to /usr/share/application + // (its using "/tmp/software-center-agent:$random:$pkgname.desktop") + // maybe: + // - and search in /var/lib/apt/lists/$pkgname.list + // for a desktop file that roughly matches what we want + auto const& desktop_file = DesktopFile(); + + // take /usr/share/app-install/desktop/foo:subdir__bar.desktop + // and tranform it + if (desktop_file.find("/share/app-install/desktop/") != std::string::npos) + { + auto colon_pos = desktop_file.rfind(":"); + auto filename = desktop_file.substr(colon_pos + 1, desktop_file.length() - colon_pos); + // the app-install-data package encodes subdirs in a funny way, once + // that is fixed, this code can be dropped + if (filename.find("__") != std::string::npos) + { + int pos = filename.find("__"); + filename = filename.replace(pos, 2, "-"); + } + filename = DesktopUtilities::GetDesktopPathById(filename); + return filename; + } + else if (desktop_file.find("/tmp/software-center-agent:") == 0) + { + // by convention the software-center-agent uses + // /usr/share/applications/$pkgname.desktop + // or + // /usr/share/applications/extras-$pkgname.desktop + auto colon_pos = desktop_file.rfind(":"); + auto desktopf = desktop_file.substr(colon_pos + 1, desktop_file.length() - colon_pos); + + auto filename = DesktopUtilities::GetDesktopPathById(desktopf); + + if (!filename.empty()) + return filename; + + // now try extras-$pkgname.desktop + filename = DesktopUtilities::GetDesktopPathById("extras-" + desktopf); + if (!filename.empty()) return filename; - } - else if (_desktop_file.find("/tmp/software-center-agent:") == 0) - { - // by convention the software-center-agent uses - // /usr/share/applications/$pkgname.desktop - // or - // /usr/share/applications/extras-$pkgname.desktop - std::string desktopf = filename.substr(filename.rfind(":") + 1, - filename.length() - filename.rfind(":")); - filename = DesktopUtilities::GetDesktopPathById(desktopf); - if (filename.size() > 0) - return filename; - // now try extras-$pkgname.desktop - filename = DesktopUtilities::GetDesktopPathById(std::string("extras-") + desktopf); - if (filename.size() > 0) - return filename; - - // FIXME: test if there is a file now and if not, search - // /var/lib/dpkg/info/$pkgname.list for a desktop file - } - - return _desktop_file; + + // FIXME: test if there is a file now and if not, search + // /var/lib/dpkg/info/$pkgname.list for a desktop file + } + + return desktop_file; } void SoftwareCenterLauncherIcon::OnFinished(GVariant *params) { - glib::String exit_state; - g_variant_get_child(params, 0, "s", &exit_state); - - if (exit_state.Str() == "exit-success") - { - tooltip_text = app_title_; - SetQuirk(Quirk::PROGRESS, false); - SetQuirk(Quirk::URGENT, true); - SetProgress(0.0f); - finished_ = true; - needs_urgent_ = true; - - // find and update to the real desktop file - std::string new_desktop_path = GetActualDesktopFileAfterInstall(); + if (glib::Variant(params).GetString() == "exit-success") + { + SetQuirk(Quirk::PROGRESS, false); + SetQuirk(Quirk::URGENT, true); + SetProgress(0.0f); + finished_ = true; + needs_urgent_ = true; - // exchange the temp Application with the real one - SetApplication(ApplicationManager::Default().GetApplicationForDesktopFile(new_desktop_path)); + // find and update to the real desktop file + std::string const& new_desktop_path = GetActualDesktopFileAfterInstall(); - UpdateDesktopFile(); - UpdateRemoteUri(); + // exchange the temp Application with the real one + auto& app_manager = ApplicationManager::Default(); + auto const& new_app = app_manager.GetApplicationForDesktopFile(new_desktop_path); + SetApplication(new_app); + if (new_app) + { Stick(); - position_saved.emit(); - _source_manager.AddIdle([this]() - { + _source_manager.AddIdle([this] { ShowTooltip(); - _source_manager.AddTimeout(INSTALL_TIP_DURATION, [this]() - { + _source_manager.AddTimeout(INSTALL_TIP_DURATION, [this] { HideTooltip(); return false; - }, SOURCE_HIDE_TOOLTIP); + }); return false; - }, SOURCE_SHOW_TOOLTIP); - } - else - { - // failure condition, remove icon again - UnStick(); - } + }); + } + } + else + { + // failure condition, remove icon again + UnStick(); + } + + aptdaemon_trans_.reset(); }; void SoftwareCenterLauncherIcon::OnPropertyChanged(GVariant* params) { - gint32 progress; - glib::String property_name; - - g_variant_get_child(params, 0, "s", &property_name); + glib::Variant property_name(g_variant_get_child_value(params, 0), glib::StealRef()); - if (property_name.Str() == "Progress") + if (property_name.GetString() == "Progress") { - GVariant* property_value = nullptr; - g_variant_get_child(params, 1, "v", &property_value); - g_variant_get(property_value, "i", &progress); + int32_t progress = glib::Variant(g_variant_get_child_value(params, 1), glib::StealRef()).GetInt32(); if (progress < 100) { SetQuirk(Quirk::PROGRESS, true); - finished_ = false; - tooltip_text = _("Installing..."); + tooltip_text = _("Installing…"); } SetProgress(progress/100.0f); - g_variant_unref(property_value); } } diff --git a/launcher/SoftwareCenterLauncherIcon.h b/launcher/SoftwareCenterLauncherIcon.h index e91cb067b..0c3e1cd2f 100644 --- a/launcher/SoftwareCenterLauncherIcon.h +++ b/launcher/SoftwareCenterLauncherIcon.h @@ -42,28 +42,25 @@ public: std::string const& aptdaemon_trans_id, std::string const& icon_path); - void Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y); + bool Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y); +protected: std::string GetName() const; + void ActivateLauncherIcon(ActionArg arg); -protected: +private: std::string GetActualDesktopFileAfterInstall(); - void ActivateLauncherIcon(ActionArg arg); void OnFinished(GVariant *params); void OnPropertyChanged(GVariant* params); + void OnDragAnimationFinished(nux::ObjectPtr<Launcher> const&, std::string const&); -private: - void OnDragAnimationFinished(); - - glib::DBusProxy aptdaemon_trans_; - - nux::ObjectPtr<nux::IOpenGLBaseTexture> icon_texture_; - nux::ObjectPtr<LauncherDragWindow> drag_window_; - nux::ObjectPtr<Launcher> launcher_; + glib::DBusProxy::Ptr aptdaemon_trans_; + LauncherDragWindow::Ptr drag_window_; bool finished_; bool needs_urgent_; std::string aptdaemon_trans_id_; - std::string app_title_; + + friend class TestSoftwareCenterLauncherIcon; }; } diff --git a/launcher/SpacerLauncherIcon.cpp b/launcher/SpacerLauncherIcon.cpp index 3839e4a77..86c7cbccd 100644 --- a/launcher/SpacerLauncherIcon.cpp +++ b/launcher/SpacerLauncherIcon.cpp @@ -18,8 +18,8 @@ */ #include "SpacerLauncherIcon.h" -#include "Launcher.h" +#include "config.h" #include <glib/gi18n-lib.h> namespace unity @@ -31,7 +31,6 @@ SpacerLauncherIcon::SpacerLauncherIcon(int monitor) : SingleMonitorLauncherIcon(IconType::SPACER, monitor) { SetQuirk(Quirk::VISIBLE, true); - SetQuirk(Quirk::RUNNING, false); tooltip_text = _("Drop To Add Application"); } diff --git a/launcher/StandaloneLauncher.cpp b/launcher/StandaloneLauncher.cpp index 9b84caaab..3c4493924 100644 --- a/launcher/StandaloneLauncher.cpp +++ b/launcher/StandaloneLauncher.cpp @@ -25,6 +25,7 @@ #include <gtk/gtk.h> #include "unity-shared/BackgroundEffectHelper.h" +#include "EdgeBarrierController.h" #include "FavoriteStoreGSettings.h" #include "LauncherController.h" #include "Launcher.h" @@ -42,6 +43,11 @@ const nux::Size win_size(1024, 768); const nux::Color bg_color(95/255.0f, 18/255.0f, 45/255.0f, 1.0f); } +struct StandaloneDndManager : XdndManager +{ + int Monitor() const { return 0; } +}; + struct LauncherWindow { LauncherWindow() @@ -67,7 +73,7 @@ private: void Init() { SetupBackground(); - controller.reset(new launcher::Controller(std::make_shared<XdndManager>())); + controller.reset(new launcher::Controller(std::make_shared<StandaloneDndManager>(), std::make_shared<ui::EdgeBarrierController>())); UScreen* uscreen = UScreen::GetDefault(); std::vector<nux::Geometry> fake_monitor({nux::Geometry(0, 0, win_size.width, win_size.height)}); diff --git a/launcher/StandaloneSwitcher.cpp b/launcher/StandaloneSwitcher.cpp index c9938571c..7adee5829 100644 --- a/launcher/StandaloneSwitcher.cpp +++ b/launcher/StandaloneSwitcher.cpp @@ -131,7 +131,6 @@ void ThreadWidgetInit(nux::NThread* thread, void* InitData) nux::VLayout* layout = new nux::VLayout(TEXT(""), NUX_TRACKER_LOCATION); controller = std::make_shared<Controller>(); - controller->SetWorkspace(nux::Geometry(0, 0, 900, 600), 0); layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER); layout->SetHorizontalExternalMargin (10); diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp index 4cf15251a..f38bb5d66 100644 --- a/launcher/SwitcherController.cpp +++ b/launcher/SwitcherController.cpp @@ -21,8 +21,10 @@ #include <Nux/Nux.h> #include <Nux/HLayout.h> +#include "unity-shared/AnimationUtils.h" #include "unity-shared/UBusMessages.h" #include "unity-shared/WindowManager.h" +#include "unity-shared/UScreen.h" #include "SwitcherController.h" #include "SwitcherControllerImpl.h" @@ -41,6 +43,8 @@ const std::string SHOW_TIMEOUT = "show-timeout"; const std::string DETAIL_TIMEOUT = "detail-timeout"; const std::string VIEW_CONSTRUCT_IDLE = "view-construct-idle"; const unsigned FADE_DURATION = 80; +const int XY_OFFSET = 100; +const int WH_OFFSET = -200; /** * Helper comparison functor for sorting application icons. @@ -78,7 +82,6 @@ Controller::Controller(WindowCreator const& create_window) , impl_(new Controller::Impl(this, 20, create_window)) {} - Controller::~Controller() {} @@ -93,6 +96,9 @@ void Controller::Show(ShowMode show, SortMode sort, std::vector<AbstractLauncherIcon::Ptr> results) { + auto uscreen = UScreen::GetDefault(); + monitor_ = uscreen->GetMonitorWithMouse(); + impl_->Show(show, sort, results); } @@ -102,15 +108,6 @@ void Controller::Select(int index) impl_->model_->Select(index); } -void Controller::SetWorkspace(nux::Geometry geo, int monitor) -{ - monitor_ = monitor; - impl_->workarea_ = geo; - - if (impl_->view_) - impl_->view_->monitor = monitor_; -} - void Controller::Hide(bool accept_state) { if (Visible()) @@ -124,44 +121,44 @@ bool Controller::Visible() return visible_; } -bool Controller::StartDetailMode() +nux::Geometry Controller::GetInputWindowGeometry() const { - if (visible_) + if (impl_->view_window_) + return impl_->view_window_->GetGeometry(); + + return {0, 0, 0, 0}; +} + +void Controller::Impl::StartDetailMode() +{ + if (obj_->visible_) { if (IsDetailViewShown() && - impl_->HasNextDetailRow()) + HasNextDetailRow()) { - impl_->NextDetailRow(); + NextDetailRow(); } else { SetDetail(true); } - - return true; } - - return false; } -bool Controller::StopDetailMode() +void Controller::Impl::StopDetailMode() { - if (visible_) + if (obj_->visible_) { if (IsDetailViewShown() && - impl_->HasPrevDetailRow()) + HasPrevDetailRow()) { - impl_->PrevDetailRow(); + PrevDetailRow(); } else { SetDetail(false); } - - return true; } - - return false; } void Controller::Next() @@ -224,6 +221,16 @@ void Controller::SetShowDesktopDisabled(bool disabled) show_desktop_disabled_ = disabled; } +bool Controller::IsMouseDisabled() const +{ + return mouse_disabled_; +} + +void Controller::SetMouseDisabled(bool disabled) +{ + mouse_disabled_ = disabled; +} + int Controller::StartIndex() const { return (IsShowDesktopDisabled() ? 0 : 1); @@ -284,10 +291,9 @@ Controller::Impl::Impl(Controller* obj, , obj_(obj) , create_window_(create_window) , main_layout_(nullptr) - , bg_color_(0, 0, 0, 0.5) , fade_animator_(FADE_DURATION) { - ubus_manager_.RegisterInterest(UBUS_BACKGROUND_COLOR_CHANGED, sigc::mem_fun(this, &Controller::Impl::OnBackgroundUpdate)); + WindowManager::Default().average_color.changed.connect(sigc::mem_fun(this, &Impl::OnBackgroundUpdate)); if (create_window_ == nullptr) create_window_ = []() { @@ -308,14 +314,10 @@ Controller::Impl::Impl(Controller* obj, }); } -void Controller::Impl::OnBackgroundUpdate(GVariant* data) +void Controller::Impl::OnBackgroundUpdate(nux::Color const& new_color) { - gdouble red, green, blue, alpha; - g_variant_get(data, "(dddd)", &red, &green, &blue, &alpha); - bg_color_ = nux::Color(red, green, blue, alpha); - if (view_) - view_->background_color = bg_color_; + view_->background_color = new_color; } @@ -333,6 +335,7 @@ void Controller::Impl::Show(ShowMode show, SortMode sort, std::vector<AbstractLa obj_->AddChild(model_.get()); model_->selection_changed.connect(sigc::mem_fun(this, &Controller::Impl::OnModelSelectionChanged)); model_->detail_selection.changed.connect([this] (bool) { sources_.Remove(DETAIL_TIMEOUT); }); + model_->request_detail_hide.connect(sigc::mem_fun(this, &Controller::Impl::DetailHide)); model_->only_detail_on_viewport = (show == ShowMode::CURRENT_VIEWPORT); SelectFirstItem(); @@ -350,17 +353,23 @@ void Controller::Impl::Show(ShowMode show, SortMode sort, std::vector<AbstractLa ShowView(); } - if (obj_->detail_on_timeout) - { - auto cb_func = sigc::mem_fun(this, &Controller::Impl::OnDetailTimer); - sources_.AddTimeout(obj_->initial_detail_timeout_length, cb_func, DETAIL_TIMEOUT); - } + nux::GetWindowCompositor().SetKeyFocusArea(view_.GetPointer()); + + ResetDetailTimer(obj_->initial_detail_timeout_length); ubus_manager_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); ubus_manager_.SendMessage(UBUS_SWITCHER_SHOWN, g_variant_new("(bi)", true, obj_->monitor_)); } +void Controller::Impl::ResetDetailTimer(int timeout_length) +{ + if (obj_->detail_on_timeout) + { + auto cb_func = sigc::mem_fun(this, &Controller::Impl::OnDetailTimer); + sources_.AddTimeout(timeout_length, cb_func, DETAIL_TIMEOUT); + } +} bool Controller::Impl::OnDetailTimer() { @@ -375,11 +384,7 @@ bool Controller::Impl::OnDetailTimer() void Controller::Impl::OnModelSelectionChanged(AbstractLauncherIcon::Ptr const& icon) { - if (obj_->detail_on_timeout) - { - auto cb_func = sigc::mem_fun(this, &Controller::Impl::OnDetailTimer); - sources_.AddTimeout(obj_->detail_timeout_length, cb_func, DETAIL_TIMEOUT); - } + ResetDetailTimer(obj_->detail_timeout_length); if (icon) { @@ -390,7 +395,7 @@ void Controller::Impl::OnModelSelectionChanged(AbstractLauncherIcon::Ptr const& } ubus_manager_.SendMessage(UBUS_SWITCHER_SELECTION_CHANGED, - g_variant_new_string(icon->tooltip_text().c_str())); + glib::Variant(icon->tooltip_text())); } } @@ -408,15 +413,7 @@ void Controller::Impl::ShowView() view_->live_background = true; view_window_->ShowWindow(true); view_window_->PushToFront(); - - if (fade_animator_.CurrentState() == nux::animation::Animation::State::Running) - { - fade_animator_.Reverse(); - } - else - { - fade_animator_.SetStartValue(0.0f).SetFinishValue(1.0f).Start(); - } + animation::StartOrReverse(fade_animator_, animation::Direction::FORWARD); } } @@ -434,10 +431,21 @@ void Controller::Impl::ConstructWindow() view_window_->SetOpacity(0.0f); view_window_->SetLayout(main_layout_); view_window_->SetBackgroundColor(nux::color::Transparent); - view_window_->SetGeometry(workarea_); } } +nux::Geometry GetSwitcherViewsGeometry() +{ + auto uscreen = UScreen::GetDefault(); + int monitor = uscreen->GetMonitorWithMouse(); + auto monitor_geo = uscreen->GetMonitorGeometry(monitor); + + monitor_geo.OffsetPosition(XY_OFFSET, XY_OFFSET); + monitor_geo.OffsetSize(WH_OFFSET, WH_OFFSET); + + return monitor_geo; +} + void Controller::Impl::ConstructView() { if (view_ || !model_) @@ -449,12 +457,29 @@ void Controller::Impl::ConstructView() view_ = SwitcherView::Ptr(new SwitcherView(view_window_.GetPointer())); obj_->AddChild(view_.GetPointer()); view_->SetModel(model_); - view_->background_color = bg_color_; + view_->background_color = WindowManager::Default().average_color(); view_->monitor = obj_->monitor_; + view_->hide_request.connect(sigc::mem_fun(this, &Controller::Impl::Hide)); + + view_->switcher_mouse_up.connect([this] (int icon_index, int button) { + if (button == 3) + InitiateDetail(true); + }); + + view_->switcher_mouse_move.connect([this] (int icon_index) { + if (icon_index >= 0) + ResetDetailTimer(obj_->detail_timeout_length); + }); + + view_->switcher_next.connect(sigc::mem_fun(this, &Impl::Next)); + view_->switcher_prev.connect(sigc::mem_fun(this, &Impl::Prev)); + view_->switcher_start_detail.connect(sigc::mem_fun(this, &Impl::StartDetailMode)); + view_->switcher_stop_detail.connect(sigc::mem_fun(this, &Impl::StopDetailMode)); + main_layout_->AddView(view_.GetPointer(), 1); view_window_->SetEnterFocusInputArea(view_.GetPointer()); - view_window_->SetGeometry(workarea_); + view_window_->SetGeometry(GetSwitcherViewsGeometry()); view_built.emit(); } @@ -472,7 +497,7 @@ void Controller::Impl::Hide(bool accept_state) } } - ubus_manager_.SendMessage(UBUS_SWITCHER_END, g_variant_new_boolean(!accept_state)); + ubus_manager_.SendMessage(UBUS_SWITCHER_END, glib::Variant(!accept_state)); ubus_manager_.SendMessage(UBUS_SWITCHER_SHOWN, g_variant_new("(bi)", false, obj_->monitor_)); sources_.Remove(VIEW_CONSTRUCT_IDLE); @@ -481,14 +506,15 @@ void Controller::Impl::Hide(bool accept_state) obj_->visible_ = false; - if (fade_animator_.CurrentState() == nux::animation::Animation::State::Running) - { - fade_animator_.Reverse(); - } - else - { - fade_animator_.SetStartValue(1.0f).SetFinishValue(0.0f).Start(); - } + animation::StartOrReverse(fade_animator_, animation::Direction::BACKWARD); +} + +void Controller::Impl::DetailHide() +{ + // FIXME We need to refactor SwitcherModel so we can add/remove icons without causing + // a crash. If you remove the last application in the list it crashes. + model_->detail_selection = false; + Hide(false); } void Controller::Impl::HideWindow() @@ -579,7 +605,7 @@ void Controller::Impl::SetDetail(bool value, unsigned int min_windows) obj_->detail_mode_ = DetailMode::TAB_NEXT_WINDOW; } else - { + { model_->detail_selection = false; } } @@ -728,6 +754,10 @@ void Controller::Impl::SelectFirstItem() for (auto& window : first->Windows()) { Window xid = window->window_id(); + + if (model_->only_detail_on_viewport && !wm.IsWindowOnCurrentDesktop(xid)) + continue; + uint64_t num = wm.GetWindowActiveNumber(xid); if (num > first_highest) diff --git a/launcher/SwitcherController.h b/launcher/SwitcherController.h index c4cadf128..0771c9d0e 100644 --- a/launcher/SwitcherController.h +++ b/launcher/SwitcherController.h @@ -88,9 +88,7 @@ public: bool CanShowSwitcher(const std::vector<launcher::AbstractLauncherIcon::Ptr>& resutls) const; bool Visible(); - - bool StartDetailMode(); - bool StopDetailMode(); + nux::Geometry GetInputWindowGeometry() const; void Next(); void Prev(); @@ -107,8 +105,6 @@ public: void SelectFirstItem(); - void SetWorkspace(nux::Geometry geo, int monitor); - nux::ObjectPtr<SwitcherView> GetView() const; ui::LayoutWindow::Vector ExternalRenderTargets(); @@ -117,6 +113,10 @@ public: bool IsShowDesktopDisabled() const; void SetShowDesktopDisabled(bool disabled); + + bool IsMouseDisabled() const; + void SetMouseDisabled(bool disabled); + int StartIndex() const; double Opacity() const; @@ -139,6 +139,7 @@ private: bool visible_; int monitor_; bool show_desktop_disabled_; + bool mouse_disabled_; DetailMode detail_mode_; ImplPtr impl_; diff --git a/launcher/SwitcherControllerImpl.h b/launcher/SwitcherControllerImpl.h index 3607b381f..255570e6f 100644 --- a/launcher/SwitcherControllerImpl.h +++ b/launcher/SwitcherControllerImpl.h @@ -40,7 +40,7 @@ namespace unity namespace switcher { -struct Controller::Impl +struct Controller::Impl : public sigc::trackable { Impl(Controller* obj, unsigned int load_timeout, @@ -48,6 +48,10 @@ struct Controller::Impl void Show(ShowMode show, SortMode sort, std::vector<launcher::AbstractLauncherIcon::Ptr> results); void Hide(bool accept_state); + void DetailHide(); + + void StartDetailMode(); + void StopDetailMode(); void Next(); void Prev(); @@ -82,9 +86,10 @@ struct Controller::Impl void ShowView(); void HideWindow(); + void ResetDetailTimer(int timeout_length); bool OnDetailTimer(); void OnModelSelectionChanged(launcher::AbstractLauncherIcon::Ptr const& icon); - void OnBackgroundUpdate(GVariant* data); + void OnBackgroundUpdate(nux::Color const&); unsigned int construct_timeout_; @@ -94,11 +99,9 @@ struct Controller::Impl SwitcherView::Ptr view_; // @todo move these view data into the SwitcherView class - nux::Geometry workarea_; Controller::WindowCreator create_window_; MockableBaseWindow::Ptr view_window_; nux::HLayout* main_layout_; - nux::Color bg_color_; nux::animation::AnimateValue<double> fade_animator_; UBusManager ubus_manager_; diff --git a/launcher/SwitcherModel.cpp b/launcher/SwitcherModel.cpp index c48171859..8427254cf 100644 --- a/launcher/SwitcherModel.cpp +++ b/launcher/SwitcherModel.cpp @@ -149,6 +149,12 @@ std::vector<Window> SwitcherModel::DetailXids() const results.push_back(xid); } + if (results.empty() && detail_selection) + { + request_detail_hide.emit(); + return results; + } + std::sort(results.begin(), results.end(), [&wm](Window first, Window second) { return wm.GetWindowActiveNumber(first) > wm.GetWindowActiveNumber(second); }); diff --git a/launcher/SwitcherModel.h b/launcher/SwitcherModel.h index 1b796798f..2f391b403 100644 --- a/launcher/SwitcherModel.h +++ b/launcher/SwitcherModel.h @@ -101,6 +101,7 @@ public: void Select(unsigned int index); sigc::signal<void, launcher::AbstractLauncherIcon::Ptr const&> selection_changed; + sigc::signal<void> request_detail_hide; protected: // Introspectable methods diff --git a/launcher/SwitcherView.cpp b/launcher/SwitcherView.cpp index 7ad3bab8f..1ac190c1e 100644 --- a/launcher/SwitcherView.cpp +++ b/launcher/SwitcherView.cpp @@ -21,6 +21,7 @@ #include "SwitcherView.h" #include "unity-shared/IconRenderer.h" #include "unity-shared/TimeUtil.h" +#include "unity-shared/UScreen.h" #include <Nux/Nux.h> #include <UnityCore/Variant.h> @@ -35,7 +36,10 @@ namespace switcher namespace { - const unsigned int VERTICAL_PADDING = 45; + unsigned int const VERTICAL_PADDING = 45; + unsigned int const SPREAD_OFFSET = 100; + unsigned int const EXTRA_ICON_SPACE = 10; + unsigned int const MAX_DIRECTIONS_CHANGED = 3; } NUX_IMPLEMENT_OBJECT_TYPE(SwitcherView); @@ -56,10 +60,13 @@ SwitcherView::SwitcherView(nux::BaseWindow *parent) , spread_size(3.5f) , icon_renderer_(std::make_shared<IconRenderer>()) , text_view_(new StaticCairoText("")) + , last_icon_selected_(-1) + , last_detail_icon_selected_(-1) , target_sizes_set_(false) + , check_mouse_first_time_(true) { icon_renderer_->pip_style = OVER_TILE; - icon_renderer_->monitor = max_num_monitors; + icon_renderer_->monitor = monitors::MAX; text_view_->SetMaximumWidth(tile_size * spread_size); text_view_->SetLines(1); @@ -69,7 +76,13 @@ SwitcherView::SwitcherView(nux::BaseWindow *parent) icon_size.changed.connect (sigc::mem_fun (this, &SwitcherView::OnIconSizeChanged)); tile_size.changed.connect (sigc::mem_fun (this, &SwitcherView::OnTileSizeChanged)); + mouse_move.connect (sigc::mem_fun(this, &SwitcherView::RecvMouseMove)); + mouse_down.connect (sigc::mem_fun(this, &SwitcherView::RecvMouseDown)); + mouse_up.connect (sigc::mem_fun(this, &SwitcherView::RecvMouseUp)); + mouse_wheel.connect(sigc::mem_fun(this, &SwitcherView::RecvMouseWheel)); + CaptureMouseDownAnyWhereElse(true); + SetAcceptMouseWheelEvent(true); ResetTimer(); animate.changed.connect([this] (bool enabled) { @@ -104,9 +117,33 @@ void SwitcherView::AddProperties(GVariantBuilder* builder) .add("animation-length", animation_length) .add("spread-size", (float)spread_size) .add("label", text_view_->GetText()) + .add("last_icon_selected", last_icon_selected_) + .add("spread_offset", SPREAD_OFFSET) .add("label_visible", text_view_->IsVisible()); } +debug::Introspectable::IntrospectableList SwitcherView::GetIntrospectableChildren() +{ + std::list<unity::debug::Introspectable*> introspection_results; + + if (model_->detail_selection) + { + for (auto const& target : render_targets_) + { + introspection_results.push_back(target.get()); + } + } + else if (!last_args_.empty()) + { + for (auto& args : last_args_) + { + introspection_results.push_back(&args); + } + } + + return introspection_results; +} + LayoutWindow::Vector SwitcherView::ExternalTargets () { return render_targets_; @@ -119,6 +156,8 @@ void SwitcherView::SetModel(SwitcherModel::Ptr model) model->detail_selection.changed.connect (sigc::mem_fun (this, &SwitcherView::OnDetailSelectionChanged)); model->detail_selection_index.changed.connect (sigc::mem_fun (this, &SwitcherView::OnDetailSelectionIndexChanged)); + last_icon_selected_ = -1; + if (!model->Selection()) return; @@ -130,12 +169,12 @@ void SwitcherView::SetModel(SwitcherModel::Ptr model) void SwitcherView::OnIconSizeChanged (int size) { - icon_renderer_->SetTargetSize(tile_size, icon_size, 10); + icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing); } void SwitcherView::OnTileSizeChanged (int size) { - icon_renderer_->SetTargetSize(tile_size, icon_size, 10); + icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing); vertical_size = tile_size + VERTICAL_PADDING * 2; } @@ -168,6 +207,9 @@ void SwitcherView::OnDetailSelectionChanged(bool detail) { text_view_->SetVisible(!detail); + last_detail_icon_selected_ = -1; + check_mouse_first_time_ = true; + if (!detail) { text_view_->SetText(model_->Selection()->tooltip_text()); @@ -183,10 +225,268 @@ void SwitcherView::OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection if (selection) text_view_->SetText(selection->tooltip_text()); + delta_tracker_.ResetState(); + SaveLast(); QueueDraw(); } +nux::Point CalculateMouseMonitorOffset(int x, int y) +{ + int monitor = unity::UScreen::GetDefault()->GetMonitorWithMouse(); + nux::Geometry const& geo = unity::UScreen::GetDefault()->GetMonitorGeometry(monitor); + + return {geo.x + x, geo.y + y}; +} + +void SwitcherView::MouseHandlingBackToNormal() +{ + check_mouse_first_time_ = false; + last_icon_selected_ = -1; + last_detail_icon_selected_ = -1; +} + +void SwitcherView::RecvMouseMove(int x, int y, int dx, int dy, unsigned long /*button_flags*/, unsigned long /*key_flags*/) +{ + // We just started, and want to check if we are a bump or not. + // Once we are no longer a bump, skip!! + if (check_mouse_first_time_) + { + if (CheckMouseInsideBackground(x,y)) + { + delta_tracker_.HandleNewMouseDelta(dx, dy); + if (delta_tracker_.AmountOfDirectionsChanged() >= MAX_DIRECTIONS_CHANGED) + { + MouseHandlingBackToNormal(); + } + } + else + { + MouseHandlingBackToNormal(); + } + } + + if (model_->detail_selection) + { + HandleDetailMouseMove(x, y); + } + else + { + HandleMouseMove(x, y); + } +} + +void SwitcherView::HandleDetailMouseMove(int x, int y) +{ + nux::Point const& mouse_pos = CalculateMouseMonitorOffset(x, y); + int detail_icon_index = DetailIconIdexAt(mouse_pos.x, mouse_pos.y); + + if (check_mouse_first_time_) + { + last_detail_icon_selected_ = detail_icon_index; + return; + } + + if (detail_icon_index >= 0 && detail_icon_index != last_detail_icon_selected_) + { + model_->detail_selection_index = detail_icon_index; + last_detail_icon_selected_ = detail_icon_index; + } + else if (detail_icon_index < 0) + { + last_detail_icon_selected_ = -1; + } +} + +void SwitcherView::HandleMouseMove(int x, int y) +{ + int icon_index = IconIndexAt(x, y); + + if (check_mouse_first_time_) + { + last_icon_selected_ = icon_index; + return; + } + + if (icon_index >= 0) + { + if (icon_index != last_icon_selected_) + { + if (icon_index != model_->SelectionIndex()) + { + model_->Select(icon_index); + } + + last_icon_selected_ = icon_index; + } + + switcher_mouse_move.emit(icon_index); + } + else if (icon_index < 0) + { + last_icon_selected_ = -1; + } +} + +void SwitcherView::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long /*key_flags*/) +{ + int button = nux::GetEventButton(button_flags); + + if (!CheckMouseInsideBackground(x, y)) + hide_request.emit(false); + + if (model_->detail_selection) + { + HandleDetailMouseDown(x, y, button); + } + else + { + HandleMouseDown(x, y, button); + } +} + +void SwitcherView::HandleDetailMouseDown(int x, int y, int button) +{ + nux::Point const& mouse_pos = CalculateMouseMonitorOffset(x, y); + int detail_icon_index = DetailIconIdexAt(mouse_pos.x, mouse_pos.y); + + last_detail_icon_selected_ = detail_icon_index; + + switcher_mouse_down.emit(detail_icon_index, button); +} + +void SwitcherView::HandleMouseDown(int x, int y, int button) +{ + int icon_index = IconIndexAt(x,y); + + last_icon_selected_ = icon_index; + + switcher_mouse_down.emit(icon_index, button); +} + +void SwitcherView::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long /*key_flags*/) +{ + int button = nux::GetEventButton(button_flags); + + if (model_->detail_selection) + { + HandleDetailMouseUp(x, y, button); + } + else + { + HandleMouseUp(x, y, button); + } +} + +void SwitcherView::HandleDetailMouseUp(int x, int y, int button) +{ + nux::Point const& mouse_pos = CalculateMouseMonitorOffset(x, y); + int detail_icon_index = DetailIconIdexAt(mouse_pos.x, mouse_pos.y); + + switcher_mouse_up.emit(detail_icon_index, button); + + if (button == 1) + { + if (detail_icon_index >= 0 && detail_icon_index == last_detail_icon_selected_) + { + model_->detail_selection_index = detail_icon_index; + hide_request.emit(true); + } + else if (detail_icon_index < 0) + { + model_->detail_selection = false; + } + } + else if (button == 3) + { + model_->detail_selection = false; + } +} + +void SwitcherView::HandleMouseUp(int x, int y, int button) +{ + int icon_index = IconIndexAt(x,y); + + switcher_mouse_up.emit(icon_index, button); + + if (button == 1) + { + if (icon_index >= 0 && icon_index == last_icon_selected_) + { + model_->Select(icon_index); + hide_request.emit(true); + } + } +} + +void SwitcherView::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned long /*button_flags*/, unsigned long /*key_flags*/) +{ + if (model_->detail_selection) + { + HandleDetailMouseWheel(wheel_delta); + } + else + { + HandleMouseWheel(wheel_delta); + } +} + +void SwitcherView::HandleDetailMouseWheel(int wheel_delta) +{ + if (wheel_delta > 0) + { + model_->NextDetail(); + } + else + { + model_->PrevDetail(); + } +} + +void SwitcherView::HandleMouseWheel(int wheel_delta) +{ + if (wheel_delta > 0) + { + model_->Next(); + } + else + { + model_->Prev(); + } +} + +bool SwitcherView::InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character) +{ + if (eventType == nux::NUX_KEYDOWN) + { + switch(keysym) + { + case NUX_VK_UP: + switcher_stop_detail.emit(); + break; + case NUX_VK_RIGHT: + switcher_next.emit(); + break; + case NUX_VK_LEFT: + switcher_prev.emit(); + break; + case NUX_VK_DOWN: + switcher_start_detail.emit(); + break; + default: + return false; + break; + } + } + + return true; +} + +nux::Area* SwitcherView::FindKeyFocusArea(unsigned int key_symbol, unsigned long x11_key_code, unsigned long special_keys_state) +{ + return this; +} + SwitcherModel::Ptr SwitcherView::GetModel() { return model_; @@ -322,13 +622,13 @@ nux::Size SwitcherView::SpreadSize() return result; } -void SwitcherView::GetFlatIconPositions (int n_flat_icons, - int size, - int selection, - int &first_flat, - int &last_flat, - int &half_fold_left, - int &half_fold_right) +void GetFlatIconPositions (int n_flat_icons, + int size, + int selection, + int &first_flat, + int &last_flat, + int &half_fold_left, + int &half_fold_right) { half_fold_left = -1; half_fold_right = -1; @@ -421,7 +721,7 @@ std::list<RenderArg> SwitcherView::RenderArgsFlat(nux::Geometry& background_geo, nux::Geometry const& spread_bounds = UpdateRenderTargets(progress); ResizeRenderTargets(spread_bounds, progress); // remove extra space consumed by spread - spread_padded_width = spread_bounds.width + 100; + spread_padded_width = spread_bounds.width + SPREAD_OFFSET; max_width -= spread_padded_width - tile_size; int expansion = std::max(0, spread_bounds.height - icon_size); @@ -552,7 +852,7 @@ void SwitcherView::PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw) if (!target_sizes_set_) { - icon_renderer_->SetTargetSize(tile_size, icon_size, 10); + icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing); target_sizes_set_ = true; } @@ -641,9 +941,9 @@ void SwitcherView::DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, } } -int SwitcherView::IconIndexAt(int x, int y) +int SwitcherView::IconIndexAt(int x, int y) const { - int half_size = icon_size.Get() / 2; + int half_size = icon_size.Get() / 2 + EXTRA_ICON_SPACE; int icon_index = -1; // Taking icon rotation into consideration will make selection more @@ -674,5 +974,27 @@ int SwitcherView::IconIndexAt(int x, int y) return icon_index; } +int SwitcherView::DetailIconIdexAt(int x, int y) const +{ + int index = -1; + + for (unsigned int i = 0; i < render_targets_.size(); ++i) + { + if (render_targets_[i]->result.IsPointInside(x + SPREAD_OFFSET, y + SPREAD_OFFSET)) + return i; + } + + return index; +} + +bool SwitcherView::CheckMouseInsideBackground(int x, int y) const +{ + nux::Point p(x,y); + if (last_background_.IsInside(p)) + return true; + + return false; +} + } } diff --git a/launcher/SwitcherView.h b/launcher/SwitcherView.h index 82bdb8081..16429b999 100644 --- a/launcher/SwitcherView.h +++ b/launcher/SwitcherView.h @@ -20,11 +20,13 @@ #ifndef SWITCHERVIEW_H #define SWITCHERVIEW_H +#include "DeltaTracker.h" #include "SwitcherModel.h" #include "unity-shared/AbstractIconRenderer.h" #include "unity-shared/StaticCairoText.h" #include "unity-shared/LayoutSystem.h" #include "unity-shared/BackgroundEffectHelper.h" +#include "unity-shared/Introspectable.h" #include "unity-shared/UnityWindowView.h" #include <Nux/View.h> @@ -70,13 +72,30 @@ public: // Returns the index of the icon at the given position, in window coordinates. // If there's no icon there, -1 is returned. - int IconIndexAt(int x, int y); + int IconIndexAt(int x, int y) const; + int DetailIconIdexAt(int x, int y) const; + /* void; int icon_index, int button*/ + sigc::signal<void, int, int> switcher_mouse_down; + sigc::signal<void, int, int> switcher_mouse_up; + + /* void; int icon_index */ + sigc::signal<void, int> switcher_mouse_move; + + /* void; */ + sigc::signal<void> switcher_next; + sigc::signal<void> switcher_prev; + sigc::signal<void> switcher_start_detail; + sigc::signal<void> switcher_stop_detail; + + /* void; bool visible */ + sigc::signal<void, bool> hide_request; protected: // Introspectable methods std::string GetName() const; void AddProperties(GVariantBuilder* builder); + IntrospectableList GetIntrospectableChildren(); void PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw); void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry const& clip); @@ -88,7 +107,27 @@ protected: std::list<ui::RenderArg> RenderArgsFlat(nux::Geometry& background_geo, int selection, float progress); ui::RenderArg CreateBaseArgForIcon(launcher::AbstractLauncherIcon::Ptr const& icon); + + virtual bool InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character); + virtual nux::Area* FindKeyFocusArea(unsigned int key_symbol, unsigned long x11_key_code, unsigned long special_keys_state); + private: + void RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags); + void HandleDetailMouseMove(int x, int y); + void HandleMouseMove(int x, int y); + + void RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags); + void HandleDetailMouseDown(int x, int y, int button); + void HandleMouseDown(int x, int y, int button); + + void RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags); + void HandleDetailMouseUp(int x, int y, int button); + void HandleMouseUp(int x, int y, int button); + + void RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags); + void HandleDetailMouseWheel(int wheel_delta); + void HandleMouseWheel(int wheel_delta); + void OnSelectionChanged(launcher::AbstractLauncherIcon::Ptr const& selection); void OnDetailSelectionChanged (bool detail); void OnDetailSelectionIndexChanged (unsigned int index); @@ -103,21 +142,25 @@ private: nux::Size SpreadSize(); double GetCurrentProgress(); - void GetFlatIconPositions(int n_flat_icons, int size, int selection, - int &first_flat, int &last_flat, - int &half_fold_left, int &half_fold_right); void SaveTime(); void ResetTimer(); void SaveLast(); + bool CheckMouseInsideBackground(int x, int y) const; + void MouseHandlingBackToNormal(); + SwitcherModel::Ptr model_; ui::LayoutSystem layout_system_; ui::AbstractIconRenderer::Ptr icon_renderer_; nux::ObjectPtr<StaticCairoText> text_view_; + int last_icon_selected_; + int last_detail_icon_selected_; bool target_sizes_set_; + bool check_mouse_first_time_; + DeltaTracker delta_tracker_; std::list<ui::RenderArg> last_args_; std::list<ui::RenderArg> saved_args_; diff --git a/launcher/Tooltip.cpp b/launcher/Tooltip.cpp index dd82740bd..f053a925f 100644 --- a/launcher/Tooltip.cpp +++ b/launcher/Tooltip.cpp @@ -24,8 +24,6 @@ #include <UnityCore/Variant.h> #include "unity-shared/CairoTexture.h" -#include "unity-shared/UBusWrapper.h" -#include "unity-shared/UBusMessages.h" #include <unity-shared/UnitySettings.h> #include "Tooltip.h" @@ -102,23 +100,21 @@ nux::Area* Tooltip::FindAreaUnderMouse(const nux::Point& mouse_position, nux::Nu return nullptr; } -void Tooltip::ShowTooltipWithTipAt(int anchor_tip_x, int anchor_tip_y) +void Tooltip::SetTooltipPosition(int tip_x, int tip_y) { - _anchorX = anchor_tip_x; - _anchorY = anchor_tip_y; + _anchorX = tip_x; + _anchorY = tip_y; int x = _anchorX - PADDING; - int y = anchor_tip_y - ANCHOR_HEIGHT / 2 - TOP_SIZE - CORNER_RADIUS - PADDING; + int y = _anchorY - ANCHOR_HEIGHT / 2 - TOP_SIZE - CORNER_RADIUS - PADDING; - _compute_blur_bkg = true; - - SetBaseX(x); - SetBaseY(y); - - PushToFront(); + SetBaseXY(x, y); +} - ShowWindow(true); - UBusManager::SendMessage(UBUS_TOOLTIP_SHOWN); +void Tooltip::ShowTooltipWithTipAt(int x, int y) +{ + SetTooltipPosition(x, y); + Show(); } void Tooltip::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) @@ -474,18 +470,15 @@ void Tooltip::UpdateTexture() float shadow_color[4] = {0.0f, 0.0f, 0.0f, 1.00f}; float outline_color[4] = {1.0f, 1.0f, 1.0f, 0.15f}; float mask_color[4] = {1.0f, 1.0f, 1.0f, 1.00f}; - - if (use_blur_ == false) + + if (!HasBlurredBackground()) { //If low gfx is detected then disable transparency because we're not bluring using our blur anymore. - float alpha_value = 1.0f; - + const float alpha_value = 1.0f; + tint_color[3] = alpha_value; hl_color[3] = alpha_value; dot_color[3] = alpha_value; - shadow_color[3] = alpha_value; - outline_color[3] = alpha_value; - mask_color[3] = alpha_value; } tint_dot_hl(cr_bg, @@ -566,11 +559,8 @@ void Tooltip::AddProperties(GVariantBuilder* builder) { variant::BuilderWrapper(builder) .add("text", text) - .add("x", GetBaseX()) - .add("y", GetBaseY()) - .add("width", GetBaseWidth()) - .add("height", GetBaseHeight()) - .add("active", IsVisible()); + .add("active", IsVisible()) + .add(GetAbsoluteGeometry()); } } // namespace nux diff --git a/launcher/Tooltip.h b/launcher/Tooltip.h index b1d9222b8..14c00cd51 100644 --- a/launcher/Tooltip.h +++ b/launcher/Tooltip.h @@ -44,7 +44,8 @@ public: void Draw(nux::GraphicsEngine& gfxContext, bool forceDraw); void DrawContent(nux::GraphicsEngine& gfxContext, bool forceDraw); - void ShowTooltipWithTipAt(int anchor_tip_x, int anchor_tip_y); + void SetTooltipPosition(int x, int y); + void ShowTooltipWithTipAt(int x, int y); // Introspection std::string GetName() const; diff --git a/launcher/TrashLauncherIcon.cpp b/launcher/TrashLauncherIcon.cpp index 28169f5d6..3d3c44d67 100644 --- a/launcher/TrashLauncherIcon.cpp +++ b/launcher/TrashLauncherIcon.cpp @@ -24,18 +24,19 @@ #include "config.h" #include <glib/gi18n-lib.h> #include <NuxCore/Logger.h> -#include <zeitgeist.h> #include "QuicklistMenuItemLabel.h" +#include "unity-shared/DesktopApplicationManager.h" #include "unity-shared/GnomeFileManager.h" +#include "unity-shared/ZeitgeistUtils.h" namespace unity { namespace launcher { -DECLARE_LOGGER(logger, "unity.launcher.icon.trash"); namespace { + DECLARE_LOGGER(logger, "unity.launcher.icon.trash"); const std::string ZEITGEIST_UNITY_ACTOR = "application://compiz.desktop"; const std::string TRASH_URI = "trash:"; } @@ -49,13 +50,15 @@ TrashLauncherIcon::TrashLauncherIcon(FileManager::Ptr const& fmo) icon_name = "user-trash"; position = Position::END; SetQuirk(Quirk::VISIBLE, true); + SkipQuirkAnimation(Quirk::VISIBLE); + SetQuirk(Quirk::RUNNING, file_manager_->IsTrashOpened()); SetShortcut('t'); glib::Object<GFile> location(g_file_new_for_uri(TRASH_URI.c_str())); glib::Error err; - trash_monitor_ = g_file_monitor_directory(location, G_FILE_MONITOR_NONE, nullptr, &err); + trash_monitor_ = g_file_monitor_directory(location, G_FILE_MONITOR_NONE, cancellable_, &err); g_file_monitor_set_rate_limit(trash_monitor_, 1000); if (err) @@ -154,32 +157,18 @@ void TrashLauncherIcon::OnAcceptDrop(DndData const& dnd_data) { for (auto const& uri : dnd_data.Uris()) { - 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 Scope. - See https://bugs.launchpad.net/unity/+bug/870150 */ - if (g_file_trash(file, NULL, NULL)) + if (file_manager_->TrashFile(uri)) { - // based on nautilus zg event logging code - glib::String origin(g_path_get_dirname(uri.c_str())); + /* Log ZG event when moving file to trash; this is requred by File Scope. + * See https://bugs.launchpad.net/unity/+bug/870150 */ + auto const& unity_app = ApplicationManager::Default().GetUnityApplication(); + auto subject = std::make_shared<desktop::ApplicationSubject>(); + subject->uri = uri; + subject->origin = glib::String(g_path_get_dirname(uri.c_str())).Str(); + glib::Object<GFile> file(g_file_new_for_uri(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(uri.c_str(), - NULL, // subject interpretation - NULL, // suject manifestation - NULL, // mime-type - origin, - display_name, - NULL /* storage */); - ZeitgeistEvent *event = zeitgeist_event_new_full(ZEITGEIST_ZG_DELETE_EVENT, - ZEITGEIST_ZG_USER_ACTIVITY, - ZEITGEIST_UNITY_ACTOR.c_str(), - subject, NULL); - ZeitgeistLog *log = zeitgeist_log_get_default(); - - // zeitgeist takes ownership of subject, event and log - zeitgeist_log_insert_events_no_reply(log, event, NULL); + subject->text = glib::String(g_path_get_basename(parse_name)).Str(); + unity_app->LogEvent(ApplicationEventType::DELETE, subject); } } diff --git a/launcher/Volume.h b/launcher/Volume.h index 83655d1f2..7df1eb7d7 100644 --- a/launcher/Volume.h +++ b/launcher/Volume.h @@ -44,18 +44,21 @@ public: virtual std::string GetName() const = 0; virtual std::string GetIconName() const = 0; virtual std::string GetIdentifier() const = 0; + virtual std::string GetUri() const = 0; virtual bool HasSiblings() const = 0; virtual bool IsMounted() const = 0; - virtual bool IsOpened() const = 0; - virtual void EjectAndShowNotification() = 0; - virtual void MountAndOpenInFileManager(uint64_t timestamp = 0) = 0; + virtual void Eject() = 0; + virtual void Mount() = 0; virtual void StopDrive() = 0; virtual void Unmount() = 0; sigc::signal<void> changed; sigc::signal<void> removed; - sigc::signal<void, bool> opened; + sigc::signal<void> mounted; + sigc::signal<void> unmounted; + sigc::signal<void> ejected; + sigc::signal<void> stopped; private: Volume(Volume const&) = delete; diff --git a/launcher/VolumeImp.cpp b/launcher/VolumeImp.cpp index cbdc74ca8..dd8a574dd 100644 --- a/launcher/VolumeImp.cpp +++ b/launcher/VolumeImp.cpp @@ -35,16 +35,9 @@ namespace launcher class VolumeImp::Impl : public sigc::trackable { public: - Impl(glib::Object<GVolume> const& volume, - FileManager::Ptr const& file_manager, - DeviceNotificationDisplay::Ptr const& device_notification_display, - VolumeImp* parent) + Impl(glib::Object<GVolume> const& volume, VolumeImp* parent) : parent_(parent) - , opened_(false) - , open_timestamp_(0) , volume_(volume) - , file_manager_(file_manager) - , device_notification_display_(device_notification_display) { signal_volume_changed_.Connect(volume_, "changed", [this] (GVolume*) { parent_->changed.emit(); @@ -53,19 +46,6 @@ public: signal_volume_removed_.Connect(volume_, "removed", [this] (GVolume*) { parent_->removed.emit(); }); - - file_manager_->locations_changed.connect(sigc::mem_fun(this, &Impl::OnLocationChanged)); - } - - void OnLocationChanged() - { - bool opened = file_manager_->IsPrefixOpened(GetUri()); - - if (opened_ != opened) - { - opened_ = opened; - parent_->opened.emit(opened_); - } } bool CanBeEjected() const @@ -126,67 +106,29 @@ public: return static_cast<bool>(mount); } - bool IsOpened() const - { - return opened_; - } - - void EjectAndShowNotification() + void Eject() { if (!CanBeEjected()) return; glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(nullptr)); - g_volume_eject_with_operation(volume_, - (GMountUnmountFlags)0, - mount_op, - cancellable_, - (GAsyncReadyCallback)OnEjectReady, - this); - } - - static void OnEjectReady(GObject* object, GAsyncResult* result, Impl* self) - { - if (g_volume_eject_with_operation_finish(self->volume_, result, nullptr)) - { - self->device_notification_display_->Display(self->GetIconName(), self->GetName()); - } - } - - void MountAndOpenInFileManager(uint64_t timestamp) - { - open_timestamp_ = timestamp; - - if (!IsMounted()) - MountAndOnFinishOpenInFileManager(); - else - OpenInFileManager(); + g_volume_eject_with_operation(volume_, G_MOUNT_UNMOUNT_NONE, mount_op, cancellable_, + [] (GObject* object, GAsyncResult* res, gpointer data) { + if (g_volume_eject_with_operation_finish(G_VOLUME(object), res, nullptr)) + static_cast<Impl*>(data)->parent_->ejected.emit(); + }, this); } - void MountAndOnFinishOpenInFileManager() + void Mount() { glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(nullptr)); - g_volume_mount(volume_, - (GMountMountFlags) 0, - mount_op, - cancellable_, - (GAsyncReadyCallback) &Impl::OnMountFinish, - this); - } - - static void OnMountFinish(GObject* object, - GAsyncResult* result, - Impl* self) - { - if (g_volume_mount_finish(self->volume_, result, nullptr)) - self->OpenInFileManager(); - } - - void OpenInFileManager() - { - file_manager_->OpenActiveChild(GetUri(), open_timestamp_); + g_volume_mount(volume_, G_MOUNT_MOUNT_NONE, mount_op, cancellable_, + [] (GObject* object, GAsyncResult* res, gpointer data) { + if (g_volume_mount_finish(G_VOLUME(object), res, nullptr)) + static_cast<Impl*>(data)->parent_->mounted.emit(); + }, this); } std::string GetUri() const @@ -212,10 +154,11 @@ public: glib::Object<GDrive> drive(g_volume_get_drive(volume_)); glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(NULL)); - g_drive_stop(drive, - (GMountUnmountFlags)0, - mount_op, - cancellable_, nullptr, nullptr); + g_drive_stop(drive, G_MOUNT_UNMOUNT_NONE, mount_op, cancellable_, + [] (GObject* object, GAsyncResult* res, gpointer data) { + if (g_drive_stop_finish(G_DRIVE(object), res, nullptr)) + static_cast<Impl*>(data)->parent_->stopped.emit(); + }, this); } void Unmount() @@ -226,22 +169,16 @@ public: glib::Object<GMount> mount(g_volume_get_mount(volume_)); glib::Object<GMountOperation> op(gtk_mount_operation_new(nullptr)); - g_mount_unmount_with_operation(mount, (GMountUnmountFlags) 0, op, cancellable_, - &VolumeImp::Impl::FinishUmount, nullptr); - } - - static void FinishUmount(GObject* object, GAsyncResult* res, gpointer) - { - g_mount_unmount_with_operation_finish(G_MOUNT(object), res, nullptr); + g_mount_unmount_with_operation(mount, G_MOUNT_UNMOUNT_NONE, op, cancellable_, + [] (GObject* object, GAsyncResult* res, gpointer data) { + if (g_mount_unmount_with_operation_finish(G_MOUNT(object), res, nullptr)) + static_cast<Impl*>(data)->parent_->unmounted.emit(); + }, this); } VolumeImp* parent_; - bool opened_; - uint64_t open_timestamp_; glib::Cancellable cancellable_; glib::Object<GVolume> volume_; - FileManager::Ptr file_manager_; - DeviceNotificationDisplay::Ptr device_notification_display_; glib::Signal<void, GVolume*> signal_volume_changed_; glib::Signal<void, GVolume*> signal_volume_removed_; @@ -251,10 +188,8 @@ public: // End private implementation // -VolumeImp::VolumeImp(glib::Object<GVolume> const& volume, - FileManager::Ptr const& file_manager, - DeviceNotificationDisplay::Ptr const& device_notification_display) - : pimpl(new Impl(volume, file_manager, device_notification_display, this)) +VolumeImp::VolumeImp(glib::Object<GVolume> const& volume) + : pimpl(new Impl(volume, this)) {} VolumeImp::~VolumeImp() @@ -290,6 +225,11 @@ std::string VolumeImp::GetIdentifier() const return pimpl->GetIdentifier(); } +std::string VolumeImp::GetUri() const +{ + return pimpl->GetUri(); +} + bool VolumeImp::HasSiblings() const { return pimpl->HasSiblings(); @@ -300,19 +240,14 @@ bool VolumeImp::IsMounted() const return pimpl->IsMounted(); } -bool VolumeImp::IsOpened() const -{ - return pimpl->IsOpened(); -} - -void VolumeImp::MountAndOpenInFileManager(uint64_t timestamp) +void VolumeImp::Mount() { - pimpl->MountAndOpenInFileManager(timestamp); + pimpl->Mount(); } -void VolumeImp::EjectAndShowNotification() +void VolumeImp::Eject() { - pimpl->EjectAndShowNotification(); + pimpl->Eject(); } void VolumeImp::StopDrive() diff --git a/launcher/VolumeImp.h b/launcher/VolumeImp.h index 821f3568b..005221c86 100644 --- a/launcher/VolumeImp.h +++ b/launcher/VolumeImp.h @@ -26,7 +26,6 @@ #include "DeviceNotificationDisplay.h" #include "Volume.h" -#include "unity-shared/FileManager.h" namespace unity { @@ -38,9 +37,7 @@ class VolumeImp : public Volume public: typedef std::shared_ptr<VolumeImp> Ptr; - VolumeImp(glib::Object<GVolume> const& volume, - FileManager::Ptr const& file_manager, - DeviceNotificationDisplay::Ptr const& device_notification_display); + VolumeImp(glib::Object<GVolume> const&); virtual ~VolumeImp(); virtual bool CanBeEjected() const; @@ -49,12 +46,12 @@ public: virtual std::string GetName() const; virtual std::string GetIconName() const; virtual std::string GetIdentifier() const; + virtual std::string GetUri() const; virtual bool HasSiblings() const; virtual bool IsMounted() const; - virtual bool IsOpened() const; - virtual void EjectAndShowNotification(); - virtual void MountAndOpenInFileManager(uint64_t timestamp); + virtual void Eject(); + virtual void Mount(); virtual void StopDrive(); virtual void Unmount(); diff --git a/launcher/VolumeLauncherIcon.cpp b/launcher/VolumeLauncherIcon.cpp index fdbe03249..18e88f6b3 100644 --- a/launcher/VolumeLauncherIcon.cpp +++ b/launcher/VolumeLauncherIcon.cpp @@ -25,8 +25,6 @@ #include <UnityCore/ConnectionManager.h> #include <UnityCore/GLibSignal.h> -#include "DevicesSettings.h" -#include "Volume.h" #include "VolumeLauncherIcon.h" #include "FavoriteStore.h" @@ -34,12 +32,7 @@ namespace unity { namespace launcher { -DECLARE_LOGGER(logger, "unity.launcher.icon"); -namespace -{ -const unsigned int volume_changed_timeout = 500; - -} +DECLARE_LOGGER(logger, "unity.launcher.icon.volume"); // // Start private implementation @@ -51,10 +44,14 @@ public: Impl(Volume::Ptr const& volume, DevicesSettings::Ptr const& devices_settings, + DeviceNotificationDisplay::Ptr const& notification, + FileManager::Ptr const& fm, VolumeLauncherIcon* parent) : parent_(parent) , volume_(volume) , devices_settings_(devices_settings) + , notification_(notification) + , file_manager_(fm) { UpdateIcon(); UpdateVisibility(); @@ -65,7 +62,7 @@ public: { parent_->tooltip_text = volume_->GetName(); parent_->icon_name = volume_->GetIconName(); - parent_->SetQuirk(Quirk::RUNNING, volume_->IsOpened()); + parent_->SetQuirk(Quirk::RUNNING, file_manager_->IsPrefixOpened(volume_->GetUri())); } void UpdateVisibility() @@ -85,7 +82,7 @@ public: connections_.Add(volume_->changed.connect(sigc::mem_fun(this, &Impl::OnVolumeChanged))); connections_.Add(volume_->removed.connect(sigc::mem_fun(this, &Impl::OnVolumeRemoved))); connections_.Add(devices_settings_->changed.connect(sigc::mem_fun(this, &Impl::OnSettingsChanged))); - connections_.Add(volume_->opened.connect(sigc::hide(sigc::mem_fun(this, &Impl::UpdateIcon)))); + connections_.Add(file_manager_->locations_changed.connect(sigc::mem_fun(this, &Impl::UpdateIcon))); } void OnVolumeChanged() @@ -114,7 +111,16 @@ public: void EjectAndShowNotification() { - return volume_->EjectAndShowNotification(); + if (!CanEject()) + return; + + auto conn = std::make_shared<sigc::connection>(); + *conn = volume_->ejected.connect([this, conn] { + notification_->Display(volume_->GetIconName(), volume_->GetName()); + conn->disconnect(); + }); + connections_.Add(*conn); + volume_->Eject(); } bool CanStop() const @@ -127,10 +133,36 @@ public: volume_->StopDrive(); } - void ActivateLauncherIcon(ActionArg arg) + void DoActionWhenMounted(std::function<void()> const& callback) + { + if (!volume_->IsMounted()) + { + auto conn = std::make_shared<sigc::connection>(); + *conn = volume_->mounted.connect([this, conn, callback] { + callback(); + conn->disconnect(); + }); + connections_.Add(*conn); + volume_->Mount(); + } + else + { + callback(); + } + } + + void OpenInFileManager(uint64_t timestamp) + { + DoActionWhenMounted([this, timestamp] { + file_manager_->OpenActiveChild(volume_->GetUri(), timestamp); + }); + } + + void CopyFilesToVolume(std::set<std::string> const& files, uint64_t timestamp) { - parent_->SimpleLauncherIcon::ActivateLauncherIcon(arg); - volume_->MountAndOpenInFileManager(arg.timestamp); + DoActionWhenMounted([this, files, timestamp] { + file_manager_->CopyFiles(files, volume_->GetUri(), timestamp); + }); } MenuItemsVector GetMenus() @@ -161,9 +193,9 @@ public: dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) { - auto const& identifier = volume_->GetIdentifier(); - parent_->UnStick(); - devices_settings_->TryToBlacklist(identifier); + auto const& identifier = volume_->GetIdentifier(); + parent_->UnStick(); + devices_settings_->TryToBlacklist(identifier); })); menu.push_back(menu_item); @@ -189,7 +221,7 @@ public: 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*, unsigned timestamp) { - volume_->MountAndOpenInFileManager(timestamp); + OpenInFileManager(timestamp); })); menu.push_back(menu_item); @@ -204,7 +236,7 @@ public: dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true); gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, unsigned timestamp) { - volume_->MountAndOpenInFileManager(timestamp); + OpenInFileManager(timestamp); })); menu.push_back(menu_item); @@ -222,7 +254,7 @@ public: 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_->EjectAndShowNotification(); + EjectAndShowNotification(); })); menu.push_back(menu_item); @@ -264,7 +296,7 @@ public: menu.push_back(menu_item); } - std::string GetRemoteUri() + std::string GetRemoteUri() const { auto const& identifier = volume_->GetIdentifier(); @@ -278,6 +310,8 @@ public: bool keep_in_launcher_; Volume::Ptr volume_; DevicesSettings::Ptr devices_settings_; + DeviceNotificationDisplay::Ptr notification_; + FileManager::Ptr file_manager_; glib::SignalManager gsignals_; connection::Manager connections_; @@ -288,9 +322,11 @@ public: // VolumeLauncherIcon::VolumeLauncherIcon(Volume::Ptr const& volume, - DevicesSettings::Ptr const& devices_settings) + DevicesSettings::Ptr const& devices_settings, + DeviceNotificationDisplay::Ptr const& notification, + FileManager::Ptr const& fm) : SimpleLauncherIcon(IconType::DEVICE) - , pimpl_(new Impl(volume, devices_settings, this)) + , pimpl_(new Impl(volume, devices_settings, notification, fm, this)) {} VolumeLauncherIcon::~VolumeLauncherIcon() @@ -326,7 +362,8 @@ void VolumeLauncherIcon::StopDrive() void VolumeLauncherIcon::ActivateLauncherIcon(ActionArg arg) { - pimpl_->ActivateLauncherIcon(arg); + SimpleLauncherIcon::ActivateLauncherIcon(arg); + pimpl_->OpenInFileManager(arg.timestamp); } AbstractLauncherIcon::MenuItemsVector VolumeLauncherIcon::GetMenus() @@ -334,7 +371,7 @@ AbstractLauncherIcon::MenuItemsVector VolumeLauncherIcon::GetMenus() return pimpl_->GetMenus(); } -std::string VolumeLauncherIcon::GetRemoteUri() +std::string VolumeLauncherIcon::GetRemoteUri() const { return pimpl_->GetRemoteUri(); } @@ -351,6 +388,29 @@ void VolumeLauncherIcon::UnStick() SetQuirk(Quirk::VISIBLE, true); } +bool VolumeLauncherIcon::OnShouldHighlightOnDrag(DndData const& dnd_data) +{ + for (auto const& uri : dnd_data.Uris()) + { + if (uri.find("file://") == 0) + return true; + } + + return false; +} + +nux::DndAction VolumeLauncherIcon::OnQueryAcceptDrop(DndData const& dnd_data) +{ + return dnd_data.Uris().empty() ? nux::DNDACTION_NONE : nux::DNDACTION_COPY; +} + +void VolumeLauncherIcon::OnAcceptDrop(DndData const& dnd_data) +{ + auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; + pimpl_->CopyFilesToVolume(dnd_data.Uris(), timestamp); + SetQuirk(Quirk::PULSE_ONCE, true); +} + // // Introspection // diff --git a/launcher/VolumeLauncherIcon.h b/launcher/VolumeLauncherIcon.h index aa9afd63c..a78e2199c 100644 --- a/launcher/VolumeLauncherIcon.h +++ b/launcher/VolumeLauncherIcon.h @@ -23,7 +23,9 @@ #include "Volume.h" #include "DevicesSettings.h" +#include "DeviceNotificationDisplay.h" #include "SimpleLauncherIcon.h" +#include "unity-shared/FileManager.h" namespace unity { @@ -35,8 +37,8 @@ class VolumeLauncherIcon : public SimpleLauncherIcon public: typedef nux::ObjectPtr<VolumeLauncherIcon> Ptr; - VolumeLauncherIcon(Volume::Ptr const& volume, - DevicesSettings::Ptr const& devices_settings); + VolumeLauncherIcon(Volume::Ptr const&, DevicesSettings::Ptr const&, + DeviceNotificationDisplay::Ptr const&, FileManager::Ptr const&); virtual ~VolumeLauncherIcon(); virtual void AboutToRemove(); @@ -48,17 +50,20 @@ public: void Stick(bool save = true); void UnStick(); MenuItemsVector GetMenus(); - std::string GetRemoteUri(); + std::string GetRemoteUri() const; protected: - virtual void ActivateLauncherIcon(ActionArg arg); + void ActivateLauncherIcon(ActionArg arg); + bool OnShouldHighlightOnDrag(DndData const&); + void OnAcceptDrop(DndData const&); + nux::DndAction OnQueryAcceptDrop(DndData const&); // Introspection virtual std::string GetName() const; private: class Impl; - std::shared_ptr<Impl> pimpl_; + std::unique_ptr<Impl> pimpl_; }; } diff --git a/launcher/XdndCollectionWindow.h b/launcher/XdndCollectionWindow.h index ce5a5681b..b4e7925dc 100644 --- a/launcher/XdndCollectionWindow.h +++ b/launcher/XdndCollectionWindow.h @@ -42,6 +42,7 @@ public: virtual void Collect() = 0; virtual void Deactivate() = 0; + virtual std::string GetData(std::string const& type) = 0; sigc::signal<void, std::vector<std::string>> collected; }; diff --git a/launcher/XdndCollectionWindowImp.cpp b/launcher/XdndCollectionWindowImp.cpp index 6be608ab5..57f979fa0 100644 --- a/launcher/XdndCollectionWindowImp.cpp +++ b/launcher/XdndCollectionWindowImp.cpp @@ -87,7 +87,7 @@ public: std::vector<std::string> data; for (auto mime : mimes) if (mime) data.push_back(mime); - + parent_->collected.emit(data); } @@ -120,5 +120,11 @@ void XdndCollectionWindowImp::Deactivate() if (nux::GetWindowThread()->IsEmbeddedWindow()) window_->EnableInputWindow(false, "XdndCollectionWindowImp"); } - + +std::string XdndCollectionWindowImp::GetData(std::string const& type) +{ + auto& gp_display = nux::GetWindowThread()->GetGraphicsDisplay(); + return glib::String(gp_display.GetDndData(const_cast<char*>(type.c_str()))).Str(); +} + } diff --git a/launcher/XdndCollectionWindowImp.h b/launcher/XdndCollectionWindowImp.h index bf0468471..5d0e1db2e 100644 --- a/launcher/XdndCollectionWindowImp.h +++ b/launcher/XdndCollectionWindowImp.h @@ -34,6 +34,7 @@ public: void Collect(); void Deactivate(); + std::string GetData(std::string const& type); private: nux::ObjectPtr<nux::BaseWindow> window_; diff --git a/launcher/XdndManager.h b/launcher/XdndManager.h index ffd3f1f00..ba01887ee 100644 --- a/launcher/XdndManager.h +++ b/launcher/XdndManager.h @@ -33,9 +33,11 @@ public: virtual ~XdndManager() {} - sigc::signal<void, std::string, int> dnd_started; + virtual int Monitor() const = 0; + + sigc::signal<void, std::string const&, int> dnd_started; + sigc::signal<void, std::string const&, int, int> monitor_changed; sigc::signal<void> dnd_finished; - sigc::signal<void, int> monitor_changed; }; } diff --git a/launcher/XdndManagerImp.cpp b/launcher/XdndManagerImp.cpp index 5bbd224e6..11d68e2d8 100644 --- a/launcher/XdndManagerImp.cpp +++ b/launcher/XdndManagerImp.cpp @@ -22,13 +22,16 @@ #include "unity-shared/UScreen.h" namespace unity { +namespace +{ + const std::string URI_TYPE = "text/uri-list"; +} -XdndManagerImp::XdndManagerImp(XdndStartStopNotifier::Ptr const& xdnd_start_stop_notifier, +XdndManagerImp::XdndManagerImp(XdndStartStopNotifier::Ptr const& xdnd_start_stop_notifier, XdndCollectionWindow::Ptr const& xdnd_collection_window) : xdnd_start_stop_notifier_(xdnd_start_stop_notifier) , xdnd_collection_window_(xdnd_collection_window) , last_monitor_(-1) - , valid_dnd_in_progress_(false) { xdnd_start_stop_notifier_->started.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndStarted)); xdnd_start_stop_notifier_->finished.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndFinished)); @@ -36,6 +39,11 @@ XdndManagerImp::XdndManagerImp(XdndStartStopNotifier::Ptr const& xdnd_start_stop xdnd_collection_window_->collected.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndDataCollected)); } +int XdndManagerImp::Monitor() const +{ + return last_monitor_; +} + void XdndManagerImp::OnDndStarted() { xdnd_collection_window_->Collect(); @@ -46,9 +54,9 @@ void XdndManagerImp::OnDndFinished() xdnd_collection_window_->Deactivate(); mouse_poller_timeout_.reset(); - if (valid_dnd_in_progress_) + if (!dnd_data_.empty()) { - valid_dnd_in_progress_ = false; + dnd_data_.clear(); dnd_finished.emit(); } } @@ -58,24 +66,23 @@ void XdndManagerImp::OnDndDataCollected(std::vector<std::string> const& mimes) if (!IsAValidDnd(mimes)) return; - valid_dnd_in_progress_ = true; + dnd_data_ = xdnd_collection_window_->GetData(URI_TYPE); - auto& gp_display = nux::GetWindowThread()->GetGraphicsDisplay(); - char target[] = "text/uri-list"; - glib::String data(gp_display.GetDndData(target)); + if (dnd_data_.empty()) + return; auto uscreen = UScreen::GetDefault(); last_monitor_ = uscreen->GetMonitorWithMouse(); mouse_poller_timeout_.reset(new glib::Timeout(20, sigc::mem_fun(this, &XdndManagerImp::CheckMousePosition))); - dnd_started.emit(data.Str(), last_monitor_); + dnd_started.emit(dnd_data_, last_monitor_); } bool XdndManagerImp::IsAValidDnd(std::vector<std::string> const& mimes) { auto end = std::end(mimes); - auto it = std::find(std::begin(mimes), end, "text/uri-list"); + auto it = std::find(std::begin(mimes), end, URI_TYPE); return it != end; } @@ -85,10 +92,11 @@ bool XdndManagerImp::CheckMousePosition() auto uscreen = UScreen::GetDefault(); auto monitor = uscreen->GetMonitorWithMouse(); - if (valid_dnd_in_progress_ && monitor != last_monitor_) + if (!dnd_data_.empty() && monitor != last_monitor_) { + int old_monitor = last_monitor_; last_monitor_ = monitor; - monitor_changed.emit(last_monitor_); + monitor_changed.emit(dnd_data_, old_monitor, last_monitor_); } return true; diff --git a/launcher/XdndManagerImp.h b/launcher/XdndManagerImp.h index e3e237e72..756b813c8 100644 --- a/launcher/XdndManagerImp.h +++ b/launcher/XdndManagerImp.h @@ -30,10 +30,13 @@ namespace unity { -class XdndManagerImp : public XdndManager, public sigc::trackable { +class XdndManagerImp : public XdndManager, public sigc::trackable +{ public: XdndManagerImp(XdndStartStopNotifier::Ptr const&, XdndCollectionWindow::Ptr const&); + virtual int Monitor() const; + private: void OnDndStarted(); void OnDndFinished(); @@ -44,7 +47,7 @@ private: XdndStartStopNotifier::Ptr xdnd_start_stop_notifier_; XdndCollectionWindow::Ptr xdnd_collection_window_; int last_monitor_; - bool valid_dnd_in_progress_; + std::string dnd_data_; glib::Source::UniquePtr mouse_poller_timeout_; }; |
