diff options
| author | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2013-11-01 00:24:38 -0700 |
|---|---|---|
| committer | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2013-11-01 00:24:38 -0700 |
| commit | 3321e140ca58582b44cc904f9ba9460361378882 (patch) | |
| tree | ee6651b7616f079f50e09f25cc5ba7ea43df6981 /launcher | |
| parent | 7b520bab35b945360f29018d1c1f66f17d39721f (diff) | |
| parent | 6810fd1d785bb8f08a29421dc6cf2e7ad0cb05e8 (diff) | |
Merging with trunk
(bzr r3506.5.36)
Diffstat (limited to 'launcher')
55 files changed, 1418 insertions, 1176 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 0606561d3..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 }; @@ -135,6 +133,7 @@ public: 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,13 +186,15 @@ 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; @@ -241,10 +244,10 @@ 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; diff --git a/launcher/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp index 73aa1efb6..b5b5c8836 100644 --- a/launcher/ApplicationLauncherIcon.cpp +++ b/launcher/ApplicationLauncherIcon.cpp @@ -39,8 +39,6 @@ #include <glib/gi18n-lib.h> #include <gio/gdesktopappinfo.h> -#include <libbamf/bamf-tab.h> - namespace unity { namespace launcher @@ -97,7 +95,7 @@ ApplicationLauncherIcon::ApplicationLauncherIcon(ApplicationPtr const& app) ApplicationLauncherIcon::~ApplicationLauncherIcon() { - SetApplication(nullptr); + UnsetApplication(); } ApplicationPtr ApplicationLauncherIcon::GetApplication() const @@ -110,18 +108,16 @@ void ApplicationLauncherIcon::SetApplication(ApplicationPtr const& app) if (app_ == app) return; - if (app_) + if (!app) { - app_->sticky = false; - app_->seen = false; + Remove(); + return; } - signals_conn_.Clear(); - app_ = app; - - if (!app) - return; + bool was_sticky = IsSticky(); + UnsetApplication(); + app_ = app; app_->seen = true; SetupApplicationSignalsConnections(); @@ -134,10 +130,26 @@ void ApplicationLauncherIcon::SetApplication(ApplicationPtr const& app) app_->desktop_file.changed.emit(app_->desktop_file()); // Make sure we set the LauncherIcon stick bit too... - if (app_->sticky()) + 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() { // Lambda functions should be fine here because when the application the icon @@ -198,6 +210,7 @@ void ApplicationLauncherIcon::SetupApplicationSignalsConnections() if (!IsSticky()) { SetQuirk(Quirk::VISIBLE, false); + HideTooltip(); /* Use a timeout to remove the icon, this avoids * that we remove an application that is going @@ -213,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") @@ -229,20 +242,13 @@ bool ApplicationLauncherIcon::GetQuirk(AbstractLauncherIcon::Quirk quirk) const return app_->OwnsWindow(WindowManager::Default().GetActiveWindow()); } - return SimpleLauncherIcon::GetQuirk(quirk); + return SimpleLauncherIcon::GetQuirk(quirk, monitor); } void ApplicationLauncherIcon::Remove() { LogUnityEvent(ApplicationEventType::LEAVE); - /* 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 + UnsetApplication(); SimpleLauncherIcon::Remove(); } @@ -485,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; - Present(0.5f, 600); - UpdateQuirkTimeDelayed(300, Quirk::SHIMMER); + if (monitor >= 0) + { + Present(0.5f, 600, monitor); + FullyAnimateQuirkDelayed(300, Quirk::SHIMMER, monitor); + } + + break; + } + } } void ApplicationLauncherIcon::OnWindowMoved(guint32 moved_win) @@ -644,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) @@ -685,7 +701,7 @@ bool ApplicationLauncherIcon::Spread(bool current_desktop, int state, bool force void ApplicationLauncherIcon::EnsureWindowState() { - std::vector<bool> monitors(monitors::MAX); + std::bitset<monitors::MAX> monitors; for (auto& window: app_->GetWindows()) { @@ -697,18 +713,18 @@ void ApplicationLauncherIcon::EnsureWindowState() // If monitor is -1 (or negative), show on all monitors. if (monitor < 0) { - for (unsigned j = 0; j < monitors::MAX; j++) - monitors[j] = true; + monitors.set(); + break; } else + { monitors[monitor] = true; + } } } for (unsigned i = 0; i < monitors::MAX; i++) SetWindowVisibleOnMonitor(monitors[i], i); - - EmitNeedsRedraw(); } void ApplicationLauncherIcon::UpdateDesktopQuickList() @@ -852,7 +868,7 @@ void ApplicationLauncherIcon::AboutToRemove() void ApplicationLauncherIcon::Stick(bool save) { - if (IsSticky()) + if (IsSticky() && !save) return; app_->sticky = true; @@ -1068,33 +1084,33 @@ 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; + + if (monitor < 0) + { + WindowManager::Default().SetWindowIconGeometry(xid, nux::Geometry()); + continue; + } - // TODO: replace 24 with icon_size / 2; - geo.x = center[monitor].x - 24; - geo.y = center[monitor].y - 24; + 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); + UpdateIconGeometries(centers); } void ApplicationLauncherIcon::UpdateRemoteUri() @@ -1116,16 +1132,6 @@ std::string ApplicationLauncherIcon::GetRemoteUri() const return _remote_uri; } -std::set<std::string> ApplicationLauncherIcon::ValidateUrisForLaunch(DndData const& uris) -{ - std::set<std::string> result; - - for (auto uri : uris.Uris()) - result.insert(uri); - - return result; -} - void ApplicationLauncherIcon::OnDndHovered() { // for now, let's not do this, it turns out to be quite buggy @@ -1163,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; @@ -1189,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 @@ -1198,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) diff --git a/launcher/ApplicationLauncherIcon.h b/launcher/ApplicationLauncherIcon.h index 082a938a1..4aed11e48 100644 --- a/launcher/ApplicationLauncherIcon.h +++ b/launcher/ApplicationLauncherIcon.h @@ -52,7 +52,7 @@ public: 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(); @@ -77,8 +77,8 @@ protected: 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(); @@ -93,7 +93,6 @@ protected: nux::DndAction OnQueryAcceptDrop(DndData const& dnd_data); MenuItemsVector GetMenus(); - std::set<std::string> ValidateUrisForLaunch(DndData const& dnd_data); std::string GetRemoteUri() const; @@ -114,6 +113,7 @@ private: ON_ALL_MONITORS = (1 << 3), }; + void UnsetApplication(); void SetupApplicationSignalsConnections(); void EnsureWindowState(); void EnsureMenuItemsWindowsReady(); diff --git a/launcher/BFBLauncherIcon.cpp b/launcher/BFBLauncherIcon.cpp index 6d0550b22..15fe55cd3 100644 --- a/launcher/BFBLauncherIcon.cpp +++ b/launcher/BFBLauncherIcon.cpp @@ -38,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; @@ -64,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") @@ -73,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..751386ae9 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,47 @@ 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); + }); +} + +void CairoBaseWindow::Show() +{ + 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_; } -CairoBaseWindow::~CairoBaseWindow() +void CairoBaseWindow::NeedSoftRedraw() { - // nothing to do + compute_blur_bkg_ = true; + QueueDraw(); } void CairoBaseWindow::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) @@ -58,7 +85,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 +110,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 +123,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 +137,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 +177,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..a92a76070 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,13 @@ 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(); + + void NeedSoftRedraw() override; + bool HasBlurredBackground() const; protected: void Draw(nux::GraphicsEngine& gfxContext, bool forceDraw); @@ -39,12 +46,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 349484e2b..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'); } 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/EdgeBarrierController.cpp b/launcher/EdgeBarrierController.cpp index 0b85da89e..f310b24de 100644 --- a/launcher/EdgeBarrierController.cpp +++ b/launcher/EdgeBarrierController.cpp @@ -111,8 +111,7 @@ EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent) options->option_changed.connect([&]() { SetupBarriers(UScreen::GetDefault()->GetMonitors()); });*/ - options->option_changed.connect(sigc::bind<1>(sigc::mem_fun(this, &EdgeBarrierController::Impl::SetupBarriers), - UScreen::GetDefault()->GetMonitors())); + options->option_changed.connect(sigc::mem_fun(this, &EdgeBarrierController::Impl::OnOptionsChanged)); SetupBarriers(UScreen::GetDefault()->GetMonitors()); }); @@ -130,6 +129,11 @@ void EdgeBarrierController::Impl::OnUScreenChanged(int primary, std::vector<nux: 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()) diff --git a/launcher/EdgeBarrierControllerPrivate.h b/launcher/EdgeBarrierControllerPrivate.h index 834322c26..9a31d4155 100644 --- a/launcher/EdgeBarrierControllerPrivate.h +++ b/launcher/EdgeBarrierControllerPrivate.h @@ -42,6 +42,7 @@ struct EdgeBarrierController::Impl : public sigc::trackable 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); diff --git a/launcher/ExpoLauncherIcon.cpp b/launcher/ExpoLauncherIcon.cpp index eb4de1a24..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(); diff --git a/launcher/HudLauncherIcon.cpp b/launcher/HudLauncherIcon.cpp index ff579473a..a4ba04997 100644 --- a/launcher/HudLauncherIcon.cpp +++ b/launcher/HudLauncherIcon.cpp @@ -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 87051bb07..de74c6ba7 100644 --- a/launcher/Launcher.cpp +++ b/launcher/Launcher.cpp @@ -69,6 +69,7 @@ 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; @@ -87,27 +88,25 @@ 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) , monitor(0) , parent_(parent) , icon_renderer_(std::make_shared<ui::IconRenderer>()) - , active_quicklist_(nullptr) , hovered_(false) , hidden_(false) , folded_(true) @@ -129,9 +128,7 @@ Launcher::Launcher(MockableBaseWindow* parent, , launcher_drag_delta_min_(0) , enter_y_(0) , last_button_press_(0) - , urgent_wiggle_time_(0) - , urgent_acked_(false) - , urgent_timer_running_(false) + , urgent_animation_period_(0) , urgent_ack_needed_(false) , drag_out_delta_x_(0.0f) , drag_gesture_ongoing_(false) @@ -174,15 +171,12 @@ Launcher::Launcher(MockableBaseWindow* parent, 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.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)); - urgent_finished_time_.tv_sec = 0; - urgent_finished_time_.tv_nsec = 0; - 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)); @@ -313,80 +307,6 @@ float Launcher::DragOutProgress() const return progress * drag_out_animation_.GetCurrentValue(); } -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 - - // short circuit to avoid unneeded calculations - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - - // animations happening on specific icons - for (auto const& icon : *model_) - if (IconNeedsAnimation(icon, current)) - return true; - - return false; -} - /* Min is when you are on the trigger */ float Launcher::GetAutohidePositionMin() const { @@ -405,33 +325,9 @@ float Launcher::GetAutohidePositionMax() const return 0.75f; } -float Launcher::IconVisibleProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const -{ - 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) +void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo) { - AbstractLauncherIcon::Ptr const& anchor = MouseIconIntersection(x, enter_y_); + auto const& anchor = MouseIconIntersection(x, enter_y_); if (anchor) { @@ -448,170 +344,88 @@ void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo, timespec 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) @@ -628,53 +442,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 @@ -688,21 +497,21 @@ 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.system_item = icon->GetIconType() == AbstractLauncherIcon::IconType::HOME || @@ -721,7 +530,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 */ @@ -744,7 +553,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; } @@ -763,20 +572,21 @@ 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()) @@ -795,22 +605,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; @@ -847,14 +657,14 @@ void Launcher::FillRenderArg(AbstractLauncherIcon::Ptr const& icon, // 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 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 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 @@ -865,7 +675,7 @@ void Launcher::FillRenderArg(AbstractLauncherIcon::Ptr const& icon, 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; @@ -877,12 +687,12 @@ 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()) { - auto const& icon_center = drag_icon_->GetCenter(monitor); drag_window_->SetAnimationTarget(icon_center.x, icon_center.y); } @@ -898,9 +708,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); @@ -914,8 +724,6 @@ 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); @@ -941,13 +749,14 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, 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); } @@ -1006,7 +815,7 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, // 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); + SetDndDelta(last_geo.x + last_geo.width / 2, center.y, geo); // Update the last_geo value. last_geo = box_geo; @@ -1059,12 +868,11 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, 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); } @@ -1073,7 +881,8 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, float shelf_sum = 0.0f; 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; } @@ -1091,7 +900,7 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, 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); } @@ -1128,23 +937,28 @@ void Launcher::OnLockHideChanged(GVariant *data) 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()); } } @@ -1179,7 +993,9 @@ void Launcher::OnOverlayShown(GVariant* data) { hud_is_open_ = true; } + bg_effect_helper_.enabled = true; + // Don't desaturate icons if the mouse is over the launcher: if (!hovered_) { @@ -1190,7 +1006,6 @@ void Launcher::OnOverlayShown(GVariant* data) if (icon_under_mouse_) icon_under_mouse_->HideTooltip(); } - QueueDraw(); } void Launcher::OnOverlayHidden(GVariant* data) @@ -1231,19 +1046,24 @@ 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; + } } // as the leave event is no more received when the place is opened // FIXME: remove when we change the mouse grab strategy in nux nux::Point pt = nux::GetWindowCompositor().GetMousePosition(); SetStateMouseOverLauncher(GetAbsoluteGeometry().IsInside(pt)); - - QueueDraw(); } 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) @@ -1300,11 +1120,51 @@ int Launcher::GetMouseY() const 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 @@ -1340,6 +1200,12 @@ 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(); QueueDraw(); } @@ -1496,110 +1362,116 @@ 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) + if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::URGENT, monitor())) { - urgent_timer_running_ = true; - urgent_ack_needed_ = true; - 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 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) + + bool animating = (animating_urgent_icons_.find(icon) != animating_urgent_icons_.end()); + + if (hidden_ && !animating) { - urgent_wiggle_time_ = 0; - SetUrgentTimer(BASE_URGENT_WIGGLE_PERIOD); + 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_ack_needed_ = true; + SetUrgentTimer(BASE_URGENT_ANIMATION_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 (urgent_timer_running && urgent_animation_period_ != 0) + { + 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_) { - if (last_reveal_progress_ > 0) - { - urgent_acked_ = false; - } - else - { - 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; - } - } + 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_) { // Look for any icons that are still urgent and wiggle them 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)) + if (!foundUrgent || (urgent_animation_period_ > MAX_URGENT_ANIMATION_DELTA)) { - continue_urgent = false; - urgent_timer_running_ = false; - } - else - { - SetUrgentTimer(urgent_wiggle_time_); + return false; } - return continue_urgent; + SetUrgentTimer(urgent_animation_period_); + return false; } void Launcher::SetIconSize(int tile_size, int icon_size) @@ -1608,6 +1480,7 @@ void Launcher::SetIconSize(int tile_size, int icon_size) 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(); Resize(nux::Point(parent_geo.x, parent_geo.y), parent_geo.height); @@ -1628,12 +1501,27 @@ void Launcher::Resize(nux::Point const& offset, int 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) { - QueueDraw(); + SetupIconAnimations(icon); - icon->needs_redraw.connect(sigc::hide(sigc::mem_fun(this, &Launcher::QueueDraw))); + 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) @@ -1644,16 +1532,41 @@ void Launcher::OnIconRemoved(AbstractLauncherIcon::Ptr const& icon) if (icon == drag_icon_) drag_icon_ = nullptr; - QueueDraw(); + animating_urgent_icons_.erase(icon); + + if (icon->IsVisibleOnMonitor(monitor())) + QueueDraw(); +} + +void Launcher::SetupIconAnimations(AbstractLauncherIcon::Ptr const& icon) +{ + 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; - auto const& queue_draw_cb = sigc::hide(sigc::mem_fun(this, &Launcher::QueueDraw)); + auto const& queue_draw_cb = 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)); @@ -1673,7 +1586,7 @@ void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr const& selection) int natural_y = 0; for (auto icon : *model_) { - if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor)) + if (!icon->IsVisibleOnMonitor(monitor)) continue; if (icon == selection) @@ -1715,14 +1628,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([this]() { QueueDraw(); return false; }); - } - nux::ROPConfig ROP; ROP.Blend = false; ROP.SrcBlend = GL_ONE; @@ -1778,9 +1683,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::Geometry blur_geo(geo_absolute.x, geo_absolute.y, base.width, base.height); nux::ObjectPtr<nux::IOpenGLBaseTexture> blur_texture; @@ -1875,6 +1780,7 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER); + // XXX: It would be very cool to move the Rendering part out of the drawing part icon_renderer_->PreprocessIcons(args, base); EventLogic(); @@ -1957,8 +1863,8 @@ 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 @@ -2016,7 +1922,7 @@ void Launcher::EndIconDrag() 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_); @@ -2114,7 +2020,7 @@ void Launcher::UpdateDragWindowPosition(int x, int y) { auto const& icon = *it; - if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor)) + if (!icon->IsVisibleOnMonitor(monitor)) continue; if (y >= icon->GetCenter(monitor).y) @@ -2226,13 +2132,20 @@ void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags) { SetMousePosition(x, y); - tooltip_manager_.MouseMoved(icon_under_mouse_); if (!hidden_) UpdateChangeInMousePosition(dx, dy); // 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) @@ -2437,7 +2350,7 @@ AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) const for (it = model_->begin(); it != model_->end(); ++it) { - if (!(*it)->IsVisible() || !(*it)->IsVisibleOnMonitor(monitor)) + if (!(*it)->IsVisibleOnMonitor(monitor)) continue; nux::Point2 screen_coord [4]; @@ -2458,10 +2371,7 @@ AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) const 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; @@ -2492,6 +2402,12 @@ void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, nux::ObjectP unity::graphics::PopOffscreenRenderTarget(); } +// FIXME: This will need to be removed when the Unity performance branch is merged. +void Launcher::NeedSoftRedraw() +{ + QueueDraw(); +} + #ifdef NUX_GESTURES_SUPPORT nux::GestureDeliveryRequest Launcher::GestureEvent(const nux::GestureEvent &event) { @@ -2542,18 +2458,16 @@ void Launcher::DndReset() 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(); @@ -2567,7 +2481,7 @@ void Launcher::DndHoveredIconReset() if (steal_drag_ && dnd_hovered_icon_) { - dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false); + dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false, monitor()); dnd_hovered_icon_->remove.emit(dnd_hovered_icon_); } @@ -2620,17 +2534,6 @@ void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) // 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); @@ -2654,7 +2557,7 @@ void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) } 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) @@ -2685,7 +2588,7 @@ void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) } else { - dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false); + dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false, monitor()); dnd_hovered_icon_->remove.emit(dnd_hovered_icon_); dnd_hovered_icon_ = nullptr; } @@ -2802,13 +2705,13 @@ void Launcher::DndStarted(std::string const& 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()); } } } @@ -2822,9 +2725,6 @@ void Launcher::DndFinished() data_checked_ = false; - if (IsOverlayOpen() && !hovered_) - DesaturateIcons(); - DndReset(); #endif } @@ -2839,6 +2739,20 @@ void Launcher::SetDndQuirk() void Launcher::UnsetDndQuirk() { #ifdef USE_X11 + + 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 f9941b008..09282a853 100644 --- a/launcher/Launcher.h +++ b/launcher/Launcher.h @@ -147,13 +147,13 @@ public: void EnterKeyNavMode(); void ExitKeyNavMode(); bool IsInKeyNavMode() const; - bool IsOverlayOpen() const; - static const int ANIM_DURATION_SHORT; - void RenderIconToTexture(nux::GraphicsEngine&, nux::ObjectPtr<nux::IOpenGLBaseTexture> const&, AbstractLauncherIcon::Ptr const&); + // FIXME: This will need to be removed when the Unity performance branch is merged. + void NeedSoftRedraw() override; + #ifdef NUX_GESTURES_SUPPORT virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event); #endif @@ -199,7 +199,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); @@ -208,8 +209,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); @@ -221,9 +222,7 @@ 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; @@ -233,30 +232,22 @@ private: bool MouseOverBottomScrollArea(); float DragOutProgress() 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 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, @@ -266,14 +257,15 @@ 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 OnIconNeedsRedraw(AbstractLauncherIcon::Ptr const& icon, int monitor); + void SetupIconAnimations(AbstractLauncherIcon::Ptr const& icon); void OnTooltipVisible(nux::ObjectPtr<nux::View> view); @@ -316,7 +308,7 @@ private: MockableBaseWindow* parent_; ui::AbstractIconRenderer::Ptr icon_renderer_; nux::ObjectPtr<nux::View> active_tooltip_; - QuicklistView* active_quicklist_; + std::set<AbstractLauncherIcon::Ptr> animating_urgent_icons_; // used by keyboard/a11y-navigation AbstractLauncherIcon::Ptr icon_under_mouse_; @@ -349,9 +341,7 @@ private: int enter_y_; int last_button_press_; int drag_icon_position_; - int urgent_wiggle_time_; - bool urgent_acked_; - bool urgent_timer_running_; + int urgent_animation_period_; bool urgent_ack_needed_; float drag_out_delta_x_; bool drag_gesture_ongoing_; @@ -365,7 +355,6 @@ private: unity::DndData dnd_data_; nux::DndAction drag_action_; - struct timespec urgent_finished_time_; BaseTexturePtr launcher_sheen_; BaseTexturePtr launcher_pressure_effect_; diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp index ed5bdafe1..5f687f0f7 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"; @@ -108,7 +107,6 @@ Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager, : 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) @@ -119,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(); #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()); @@ -165,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) @@ -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) @@ -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() @@ -769,7 +762,7 @@ void Controller::Impl::RegisterIcon(AbstractLauncherIcon::Ptr const& icon, int p 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(); } @@ -947,7 +940,6 @@ SoftwareCenterLauncherIcon::Ptr Controller::Impl::CreateSCLauncherIcon(std::stri return result; result = new SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path); - result->Stick(false); return result; } @@ -962,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_); } } @@ -973,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_); + } } } @@ -1022,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) @@ -1248,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 diff --git a/launcher/LauncherController.h b/launcher/LauncherController.h index ad97b87fa..4c6c6f9f8 100644 --- a/launcher/LauncherController.h +++ b/launcher/LauncherController.h @@ -67,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 47b262d5b..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 @@ -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_; @@ -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/LauncherIcon.cpp b/launcher/LauncherIcon.cpp index 7a0901826..171b7b20a 100644 --- a/launcher/LauncherIcon.cpp +++ b/launcher/LauncherIcon.cpp @@ -23,11 +23,9 @@ #include <NuxCore/Color.h> #include <NuxCore/Logger.h> -#include "Launcher.h" #include "LauncherIcon.h" #include "unity-shared/AnimationUtils.h" #include "unity-shared/CairoTexture.h" -#include "unity-shared/TimeUtil.h" #include "QuicklistManager.h" #include "QuicklistMenuItem.h" @@ -50,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"; @@ -57,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,27 +75,16 @@ LauncherIcon::LauncherIcon(IconType type) , _background_color(nux::color::White) , _glow_color(nux::color::White) , _shortcut(0) + , _allow_quicklist_to_show(true) , _center(monitors::MAX) - , _has_visible_window(monitors::MAX, false) - , _is_visible_on_monitor(monitors::MAX, true) + , _quirks(monitors::MAX) + , _quirk_animations(monitors::MAX, decltype(_quirk_animations)::value_type(unsigned(Quirk::LAST))) , _last_stable(monitors::MAX) - , _parent_geo(monitors::MAX) , _saved_center(monitors::MAX) - , _allow_quicklist_to_show(true) - , _tooltip_fade_animator(TOOLTIP_FADE_DURATION) { - for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i) - { - _quirks[i] = false; - _quirk_times[i].tv_sec = 0; - _quirk_times[i].tv_nsec = 0; - } - 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; @@ -110,13 +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) _tooltip->SetOpacity(opacity); - }); - _tooltip_fade_animator.finished.connect([this] { - if (_tooltip && animation::GetDirection(_tooltip_fade_animator) == animation::Direction::BACKWARD) - _tooltip->ShowWindow(false); - }); + for (unsigned i = 0; i < monitors::MAX; ++i) + { + for (unsigned j = 0; j < static_cast<unsigned>(Quirk::LAST); ++j) + { + _quirk_animations[i][j] = std::make_shared<Animation>(); + _quirk_animations[i][j]->updated.connect([this, i, j] (float value) { EmitNeedsRedraw(i); }); + } + + // Center must have set a default value + animation::SetValue(GetQuirkAnimation(Quirk::CENTER_SAVED, i), animation::Direction::FORWARD); + } } void LauncherIcon::LoadTooltip() @@ -141,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 (unsigned i = 0; i < monitors::MAX; ++i) - if (_has_visible_window[i]) - return true; - - return false; + return _has_visible_window.any(); } std::string @@ -190,9 +176,22 @@ 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(); @@ -201,19 +200,21 @@ LauncherIcon::Activate(ActionArg arg) 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 @@ -287,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; @@ -433,21 +431,19 @@ BaseTexturePtr LauncherIcon::TextureFromPath(std::string const& icon_name, int s 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) @@ -456,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))) @@ -465,39 +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); - - animation::StartOrReverse(_tooltip_fade_animator, animation::Direction::FORWARD); } -void -LauncherIcon::RecvMouseEnter(int monitor) +void LauncherIcon::RecvMouseEnter(int monitor) { _last_monitor = monitor; } @@ -519,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(); @@ -566,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; @@ -641,57 +629,66 @@ void LauncherIcon::RecvMouseClick(int button, int monitor, unsigned long key_fla void LauncherIcon::HideTooltip() { if (_tooltip) - animation::StartOrReverse(_tooltip_fade_animator, animation::Direction::BACKWARD); + _tooltip->Hide(); - tooltip_visible.emit(nux::ObjectPtr<nux::View>(nullptr)); + tooltip_visible.emit(nux::ObjectPtr<nux::View>()); } -bool -LauncherIcon::OnCenterStabilizeTimeout() +void LauncherIcon::SetCenter(nux::Point3 const& new_center, int monitor) { - if (!std::equal(_center.begin(), _center.end(), _last_stable.begin())) - { - OnCenterStabilized(_center); - _last_stable = _center; - } - - return false; -} + nux::Point3& center = _center[monitor]; -void -LauncherIcon::SetCenter(nux::Point3 const& center, int monitor, nux::Geometry const& geo) -{ - _parent_geo[monitor] = geo; + if (center == new_center) + return; - 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; + center = new_center; if (monitor == _last_monitor) { - 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); + { + auto const& pos = GetTipPosition(monitor); + QuicklistManager::Default()->MoveQuicklist(_quicklist, pos.x, pos.y); + } else if (_tooltip && _tooltip->IsVisible()) - _tooltip->ShowTooltipWithTipAt(tip_x, tip_y); + { + auto const& pos = GetTipPosition(monitor); + _tooltip->SetTooltipPosition(pos.x, pos.y); + } } - auto const& cb_func = sigc::mem_fun(this, &LauncherIcon::OnCenterStabilizeTimeout); - _source_manager.AddTimeout(500, cb_func, CENTER_STABILIZE_TIMEOUT); + _source_manager.AddTimeout(500, [this] { + if (!std::equal(_center.begin(), _center.end(), _last_stable.begin())) + { + if (!removed()) + OnCenterStabilized(_center); + + _last_stable = _center; + } + + return false; + }, CENTER_STABILIZE_TIMEOUT + std::to_string(monitor)); +} + +void LauncherIcon::ResetCenters(int monitor) +{ + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + _center[i].Set(0, 0, 0); + } + else + { + _center[monitor].Set(0, 0, 0); + } } -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]; } @@ -701,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() @@ -750,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; } @@ -806,73 +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; } } - 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) +{ + if (monitor < 0) + { + for (unsigned i = 0; i < monitors::MAX; ++i) + { + animation::Skip(GetQuirkAnimation(quirk, i)); + } + } + else + { + animation::Skip(GetQuirkAnimation(quirk, monitor)); + } +} + +float LauncherIcon::GetQuirkProgress(Quirk quirk, int monitor) const { - _quirk_times[unsigned(quirk)].tv_sec = 0; - _quirk_times[unsigned(quirk)].tv_nsec = 0; + return GetQuirkAnimation(quirk, monitor).GetCurrentValue(); } -struct timespec -LauncherIcon::GetQuirkTime(LauncherIcon::Quirk quirk) +void LauncherIcon::SetQuirkDuration(Quirk quirk, unsigned duration, int monitor) { - return _quirk_times[unsigned(quirk)]; + 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) +void LauncherIcon::SetProgress(float progress) { if (progress == _progress) return; @@ -881,8 +927,7 @@ LauncherIcon::SetProgress(float progress) EmitNeedsRedraw(); } -float -LauncherIcon::GetProgress() +float LauncherIcon::GetProgress() { return _progress; } @@ -1157,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() @@ -1171,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 99eb50ce6..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 @@ -78,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); @@ -127,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); - void SetQuirk(Quirk quirk, bool value); + float GetQuirkProgress(Quirk quirk, int monitor) const; - struct timespec GetQuirkTime(Quirk quirk); + void SetQuirkDuration(Quirk quirk, unsigned duration, int monitor = -1); + + void SkipQuirkAnimation(Quirk quirk, int monitor = -1); IconType GetIconType() const; @@ -203,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 FullyAnimateQuirkDelayed(guint ms, Quirk quirk, int monitor = -1); - void UpdateQuirkTime(Quirk quirk); - - void ResetQuirkTime(Quirk quirk); + void FullyAnimateQuirk(Quirk quirk, int monitor = -1); void Remove(); @@ -219,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); @@ -229,7 +235,7 @@ 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() const { @@ -284,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; @@ -299,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 9f3b46754..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_; @@ -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/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 183360eec..6ac11a1a6 100644 --- a/launcher/QuicklistView.cpp +++ b/launcher/QuicklistView.cpp @@ -324,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) { @@ -345,8 +345,7 @@ 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); } else { @@ -354,31 +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(); } } @@ -390,8 +382,7 @@ void QuicklistView::Hide() CaptureMouseDownAnyWhereElse(false); UnGrabPointer(); UnGrabKeyboard(); - //EnableInputWindow (false); - ShowWindow(false); + CairoBaseWindow::Hide(); if (_current_item_index != -1) { @@ -410,7 +401,6 @@ void QuicklistView::HideAndEndQuicklistNav() void QuicklistView::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw) { - _compute_blur_bkg = true; CairoBaseWindow::Draw(gfxContext, forceDraw); nux::Geometry base(GetGeometry()); @@ -1216,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, 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 95f118753..4ed24a990 100644 --- a/launcher/SimpleLauncherIcon.cpp +++ b/launcher/SimpleLauncherIcon.cpp @@ -49,7 +49,7 @@ SimpleLauncherIcon::SimpleLauncherIcon(IconType type) void SimpleLauncherIcon::ActivateLauncherIcon(ActionArg arg) { - UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST, glib::Variant(false)); + UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); } nux::BaseTexture* SimpleLauncherIcon::GetTextureForSize(int size) diff --git a/launcher/SingleMonitorLauncherIcon.cpp b/launcher/SingleMonitorLauncherIcon.cpp index 2700b64d7..403466683 100644 --- a/launcher/SingleMonitorLauncherIcon.cpp +++ b/launcher/SingleMonitorLauncherIcon.cpp @@ -20,14 +20,13 @@ #include <UnityCore/Variant.h> #include "SingleMonitorLauncherIcon.h" -#include "MultiMonitor.h" namespace unity { namespace launcher { -SingleMonitorLauncherIcon::SingleMonitorLauncherIcon(IconType type, unsigned monitor) +SingleMonitorLauncherIcon::SingleMonitorLauncherIcon(IconType type, int monitor) : SimpleLauncherIcon(type) , monitor_(monitor) { @@ -37,12 +36,10 @@ SingleMonitorLauncherIcon::SingleMonitorLauncherIcon(IconType type, unsigned mon void SingleMonitorLauncherIcon::UpdateMonitor() { for (unsigned i = 0; i < monitors::MAX; ++i) - SetVisibleOnMonitor(i, i == monitor_); - - EmitNeedsRedraw(); + SetVisibleOnMonitor(i, static_cast<int>(i) == monitor_); } -void SingleMonitorLauncherIcon::SetMonitor(unsigned monitor) +void SingleMonitorLauncherIcon::SetMonitor(int monitor) { if (monitor != monitor_) { @@ -51,7 +48,7 @@ void SingleMonitorLauncherIcon::SetMonitor(unsigned monitor) } } -unsigned SingleMonitorLauncherIcon::GetMonitor() const +int SingleMonitorLauncherIcon::GetMonitor() const { return monitor_; } diff --git a/launcher/SingleMonitorLauncherIcon.h b/launcher/SingleMonitorLauncherIcon.h index 369aed51c..b24645e79 100644 --- a/launcher/SingleMonitorLauncherIcon.h +++ b/launcher/SingleMonitorLauncherIcon.h @@ -29,12 +29,11 @@ namespace launcher class SingleMonitorLauncherIcon : public SimpleLauncherIcon { - public: - SingleMonitorLauncherIcon(IconType type, unsigned monitor); + SingleMonitorLauncherIcon(IconType type, int monitor = -1); -void SetMonitor(unsigned monitor); -unsigned GetMonitor() const; +void SetMonitor(int monitor); +int GetMonitor() const; protected: std::string GetName() const; @@ -43,7 +42,7 @@ protected: private: void UpdateMonitor(); - unsigned monitor_; + int monitor_; }; } diff --git a/launcher/SoftwareCenterLauncherIcon.cpp b/launcher/SoftwareCenterLauncherIcon.cpp index c841edf2c..abd6abedf 100644 --- a/launcher/SoftwareCenterLauncherIcon.cpp +++ b/launcher/SoftwareCenterLauncherIcon.cpp @@ -31,7 +31,6 @@ #include "LauncherDragWindow.h" #include "LauncherModel.h" #include "DesktopUtilities.h" -#include "MultiMonitor.h" namespace unity { @@ -57,7 +56,10 @@ SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(ApplicationPtr const& app , needs_urgent_(false) , aptdaemon_trans_id_(aptdaemon_trans_id) { + Stick(false); SetQuirk(Quirk::VISIBLE, false); + 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) { @@ -94,11 +96,8 @@ bool SoftwareCenterLauncherIcon::Animate(nux::ObjectPtr<Launcher> const& launche floating_icon->icon_name = icon_name(); // Transform this in a spacer-icon and make it visible only on launcher's monitor - for (unsigned i = 0; i < monitors::MAX; ++i) - SetVisibleOnMonitor(i, static_cast<int>(i) == monitor); - icon_name = ""; - SetQuirk(Quirk::VISIBLE, true); + 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); @@ -121,9 +120,7 @@ void SoftwareCenterLauncherIcon::OnDragAnimationFinished(nux::ObjectPtr<Launcher drag_window_->ShowWindow(false); drag_window_.Release(); launcher->ForceReveal(false); - - for (unsigned i = 0; i < monitors::MAX; ++i) - SetVisibleOnMonitor(i, true); + SetQuirk(Quirk::VISIBLE, true); } void SoftwareCenterLauncherIcon::ActivateLauncherIcon(ActionArg arg) @@ -220,18 +217,21 @@ void SoftwareCenterLauncherIcon::OnFinished(GVariant *params) // exchange the temp Application with the real one auto& app_manager = ApplicationManager::Default(); auto const& new_app = app_manager.GetApplicationForDesktopFile(new_desktop_path); - if (new_app) new_app->sticky = IsSticky(); SetApplication(new_app); - Stick(); - _source_manager.AddIdle([this] { - ShowTooltip(); - _source_manager.AddTimeout(INSTALL_TIP_DURATION, [this] { - HideTooltip(); + if (new_app) + { + Stick(); + + _source_manager.AddIdle([this] { + ShowTooltip(); + _source_manager.AddTimeout(INSTALL_TIP_DURATION, [this] { + HideTooltip(); + return false; + }); return false; }); - return false; - }); + } } else { diff --git a/launcher/SpacerLauncherIcon.cpp b/launcher/SpacerLauncherIcon.cpp index d5a32e6e5..86c7cbccd 100644 --- a/launcher/SpacerLauncherIcon.cpp +++ b/launcher/SpacerLauncherIcon.cpp @@ -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 198caa926..3c4493924 100644 --- a/launcher/StandaloneLauncher.cpp +++ b/launcher/StandaloneLauncher.cpp @@ -43,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() @@ -68,7 +73,7 @@ private: void Init() { SetupBackground(); - controller.reset(new launcher::Controller(std::make_shared<XdndManager>(), std::make_shared<ui::EdgeBarrierController>())); + 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/SwitcherController.cpp b/launcher/SwitcherController.cpp index 8087a18c7..618c76a10 100644 --- a/launcher/SwitcherController.cpp +++ b/launcher/SwitcherController.cpp @@ -129,44 +129,36 @@ nux::Geometry Controller::GetInputWindowGeometry() const return {0, 0, 0, 0}; } -bool Controller::StartDetailMode() +void Controller::Impl::StartDetailMode() { - if (visible_) + 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() @@ -299,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_ = []() { @@ -323,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; } @@ -366,6 +353,8 @@ void Controller::Impl::Show(ShowMode show, SortMode sort, std::vector<AbstractLa ShowView(); } + nux::GetWindowCompositor().SetKeyFocusArea(view_.GetPointer()); + ResetDetailTimer(obj_->initial_detail_timeout_length); ubus_manager_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); @@ -467,7 +456,7 @@ void Controller::Impl::ConstructView() view_ = SwitcherView::Ptr(new SwitcherView()); 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)); @@ -482,6 +471,11 @@ void Controller::Impl::ConstructView() 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)); + ConstructWindow(); main_layout_->AddView(view_.GetPointer(), 1); view_window_->SetEnterFocusInputArea(view_.GetPointer()); diff --git a/launcher/SwitcherController.h b/launcher/SwitcherController.h index 2e60bce6f..0771c9d0e 100644 --- a/launcher/SwitcherController.h +++ b/launcher/SwitcherController.h @@ -90,9 +90,6 @@ public: bool Visible(); nux::Geometry GetInputWindowGeometry() const; - bool StartDetailMode(); - bool StopDetailMode(); - void Next(); void Prev(); diff --git a/launcher/SwitcherControllerImpl.h b/launcher/SwitcherControllerImpl.h index 068df1091..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, @@ -50,6 +50,9 @@ struct Controller::Impl void Hide(bool accept_state); void DetailHide(); + void StartDetailMode(); + void StopDetailMode(); + void Next(); void Prev(); @@ -86,7 +89,7 @@ struct Controller::Impl 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_; @@ -99,7 +102,6 @@ struct Controller::Impl 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/SwitcherView.cpp b/launcher/SwitcherView.cpp index e9b3c0678..a28957ce2 100644 --- a/launcher/SwitcherView.cpp +++ b/launcher/SwitcherView.cpp @@ -39,6 +39,7 @@ namespace 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); @@ -206,6 +207,7 @@ void SwitcherView::OnDetailSelectionChanged(bool detail) text_view_->SetVisible(!detail); last_detail_icon_selected_ = -1; + check_mouse_first_time_ = true; if (!detail) { @@ -222,6 +224,8 @@ void SwitcherView::OnSelectionChanged(AbstractLauncherIcon::Ptr const& selection if (selection) text_view_->SetText(selection->tooltip_text()); + delta_tracker_.ResetState(); + SaveLast(); QueueDraw(); } @@ -234,8 +238,33 @@ nux::Point CalculateMouseMonitorOffset(int x, int y) return {geo.x + x, geo.y + y}; } -void SwitcherView::RecvMouseMove(int x, int y, int /*dx*/, int /*dy*/, unsigned long /*button_flags*/, unsigned long /*key_flags*/) +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); @@ -254,7 +283,6 @@ void SwitcherView::HandleDetailMouseMove(int x, int y) if (check_mouse_first_time_) { last_detail_icon_selected_ = detail_icon_index; - check_mouse_first_time_ = false; return; } @@ -276,7 +304,6 @@ void SwitcherView::HandleMouseMove(int x, int y) if (check_mouse_first_time_) { last_icon_selected_ = icon_index; - check_mouse_first_time_ = false; return; } @@ -364,6 +391,10 @@ void SwitcherView::HandleDetailMouseUp(int x, int y, int button) 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) { @@ -423,6 +454,38 @@ void SwitcherView::HandleMouseWheel(int wheel_delta) } } +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_; @@ -558,13 +621,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; diff --git a/launcher/SwitcherView.h b/launcher/SwitcherView.h index 9a225e305..8ceb23abb 100644 --- a/launcher/SwitcherView.h +++ b/launcher/SwitcherView.h @@ -20,6 +20,7 @@ #ifndef SWITCHERVIEW_H #define SWITCHERVIEW_H +#include "DeltaTracker.h" #include "SwitcherModel.h" #include "unity-shared/AbstractIconRenderer.h" #include "unity-shared/StaticCairoText.h" @@ -75,11 +76,17 @@ public: 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; + 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; + 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; @@ -101,6 +108,9 @@ protected: 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); @@ -132,15 +142,13 @@ 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_; @@ -152,6 +160,8 @@ private: 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 d94b88f47..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,26 +100,25 @@ 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; - 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) { - _compute_blur_bkg = true; CairoBaseWindow::Draw(gfxContext, forceDraw); _tooltip_text->ProcessDraw(gfxContext, forceDraw); } @@ -473,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, 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 66e3209c2..3d3c44d67 100644 --- a/launcher/TrashLauncherIcon.cpp +++ b/launcher/TrashLauncherIcon.cpp @@ -50,6 +50,8 @@ 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'); 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 84a3f7b76..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); @@ -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() @@ -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 36de1b852..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(); @@ -51,14 +53,17 @@ public: 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 a7ca834ad..6b240edec 100644 --- a/launcher/XdndCollectionWindowImp.cpp +++ b/launcher/XdndCollectionWindowImp.cpp @@ -83,7 +83,7 @@ public: std::vector<std::string> data; for (auto mime : mimes) if (mime) data.push_back(mime); - + parent_->collected.emit(data); } @@ -116,5 +116,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_; }; |
