diff options
75 files changed, 3337 insertions, 2322 deletions
diff --git a/plugins/unityshell/src/AbstractIconRenderer.h b/plugins/unityshell/src/AbstractIconRenderer.h index 5c98dbf99..ce383307f 100644 --- a/plugins/unityshell/src/AbstractIconRenderer.h +++ b/plugins/unityshell/src/AbstractIconRenderer.h @@ -103,6 +103,7 @@ public: virtual ~AbstractIconRenderer() {} nux::Property<PipRenderStyle> pip_style; + nux::Property<int> monitor; // RenderArgs not const in case processor needs to modify positions to do a perspective correct. virtual void PreprocessIcons(std::list<RenderArg>& args, nux::Geometry const& target_window) = 0; diff --git a/plugins/unityshell/src/AbstractLauncherIcon.h b/plugins/unityshell/src/AbstractLauncherIcon.h index 14afb45f3..c84f6cc7e 100644 --- a/plugins/unityshell/src/AbstractLauncherIcon.h +++ b/plugins/unityshell/src/AbstractLauncherIcon.h @@ -33,6 +33,7 @@ #include "DndData.h" #include "Introspectable.h" +#include "LauncherEntryRemote.h" namespace unity { @@ -53,19 +54,22 @@ public: : source(OTHER) , button(0) , target(0) + , monitor(-1) { } - ActionArg(Source source, int button, Window target = 0) + ActionArg(Source source, int button, Window target = 0, int monitor = -1) : source(source) , button(button) , target(target) + , monitor(monitor) { } Source source; int button; Window target; + int monitor; }; class AbstractLauncherIcon : public nux::InitiallyUnownedObject, public debug::Introspectable @@ -104,6 +108,7 @@ public: QUIRK_DROP_DIM, QUIRK_DESAT, QUIRK_PULSE_ONCE, + QUIRK_LAST_ACTION, QUIRK_LAST, } Quirk; @@ -129,13 +134,17 @@ public: virtual void SetSortPriority(int priority) = 0; - virtual bool OpenQuicklist(bool default_to_first_item = false) = 0; + virtual bool OpenQuicklist(bool default_to_first_item = false, int monitor = -1) = 0; - virtual void SetCenter(nux::Point3 center) = 0; + virtual void SetCenter(nux::Point3 center, int monitor, nux::Geometry parent_geo) = 0; - virtual nux::Point3 GetCenter() = 0; + virtual nux::Point3 GetCenter(int monitor) = 0; - virtual std::vector<nux::Vector4> & GetTransform(TransformIndex index) = 0; + virtual nux::Point3 GetSavedCenter(int monitor) = 0; + + virtual void SaveCenter() = 0; + + virtual std::vector<nux::Vector4> & GetTransform(TransformIndex index, int monitor) = 0; virtual void Activate(ActionArg arg) = 0; @@ -143,13 +152,13 @@ public: virtual int SortPriority() = 0; - virtual int RelatedWindows() = 0; + virtual std::vector<Window> Windows() = 0; - virtual std::vector<Window> RelatedXids () = 0; + virtual std::vector<Window> WindowsForMonitor(int monitor) = 0; virtual std::string NameForWindow (Window window) = 0; - virtual const bool HasWindowOnViewport() = 0; + virtual const bool WindowVisibleOnMonitor(int monitor) = 0; virtual bool IsSpacer() = 0; @@ -157,7 +166,7 @@ public: virtual float GetProgress() = 0; - virtual bool ShowInSwitcher() = 0; + virtual bool ShowInSwitcher(bool current) = 0; virtual unsigned long long SwitcherPriority() = 0; @@ -167,6 +176,8 @@ public: virtual struct timespec GetQuirkTime(Quirk quirk) = 0; + virtual void ResetQuirkTime(Quirk quirk) = 0; + virtual IconType Type() = 0; virtual nux::Color BackgroundColor() = 0; @@ -189,16 +200,26 @@ public: virtual void SendDndLeave() = 0; - sigc::signal<void, int> mouse_down; - sigc::signal<void, int> mouse_up; - sigc::signal<void, int> mouse_click; - sigc::signal<void> mouse_enter; - sigc::signal<void> mouse_leave; + virtual void InsertEntryRemote(LauncherEntryRemote* remote) = 0; + + virtual void RemoveEntryRemote(LauncherEntryRemote* remote) = 0; + + sigc::signal<void, int, int> mouse_down; + sigc::signal<void, int, int> mouse_up; + sigc::signal<void, int, int> mouse_click; + sigc::signal<void, int> mouse_enter; + sigc::signal<void, int> mouse_leave; sigc::signal<void, AbstractLauncherIcon*> show; sigc::signal<void, AbstractLauncherIcon*> hide; sigc::signal<void, AbstractLauncherIcon*> needs_redraw; + sigc::signal<void, AbstractLauncherIcon*> remove; + sigc::connection needs_redraw_connection; + sigc::connection on_icon_added_connection; + sigc::connection on_icon_removed_connection; + sigc::connection on_order_changed_connection; + sigc::connection on_expo_terminated_connection; }; } diff --git a/plugins/unityshell/src/BFBLauncherIcon.cpp b/plugins/unityshell/src/BFBLauncherIcon.cpp index 11e05de4a..c7d6f46ac 100644 --- a/plugins/unityshell/src/BFBLauncherIcon.cpp +++ b/plugins/unityshell/src/BFBLauncherIcon.cpp @@ -32,8 +32,8 @@ namespace launcher UBusManager BFBLauncherIcon::ubus_manager_; -BFBLauncherIcon::BFBLauncherIcon(Launcher* IconManager) - : SimpleLauncherIcon(IconManager) +BFBLauncherIcon::BFBLauncherIcon() + : SimpleLauncherIcon() { tooltip_text = _("Dash home"); icon_name = PKGDATADIR"/launcher_bfb.png"; @@ -43,7 +43,7 @@ BFBLauncherIcon::BFBLauncherIcon(Launcher* IconManager) background_color_ = nux::color::White; - mouse_enter.connect([&]() { ubus_manager_.SendMessage(UBUS_DASH_ABOUT_TO_SHOW, NULL); }); + mouse_enter.connect([&](int m) { ubus_manager_.SendMessage(UBUS_DASH_ABOUT_TO_SHOW, NULL); }); } nux::Color BFBLauncherIcon::BackgroundColor() diff --git a/plugins/unityshell/src/BFBLauncherIcon.h b/plugins/unityshell/src/BFBLauncherIcon.h index 115c416bc..441448e73 100644 --- a/plugins/unityshell/src/BFBLauncherIcon.h +++ b/plugins/unityshell/src/BFBLauncherIcon.h @@ -35,7 +35,7 @@ class BFBLauncherIcon : public SimpleLauncherIcon { public: - BFBLauncherIcon(Launcher* launcher); + BFBLauncherIcon(); virtual nux::Color BackgroundColor(); virtual nux::Color GlowColor(); diff --git a/plugins/unityshell/src/BamfLauncherIcon.cpp b/plugins/unityshell/src/BamfLauncherIcon.cpp index fa4f007fb..10a330002 100644 --- a/plugins/unityshell/src/BamfLauncherIcon.cpp +++ b/plugins/unityshell/src/BamfLauncherIcon.cpp @@ -166,8 +166,8 @@ void BamfLauncherIcon::ActivateLauncherIcon(ActionArg arg) ubus_server_send_message(ubus_server_get_default(), UBUS_LAUNCHER_ACTION_DONE, NULL); } -BamfLauncherIcon::BamfLauncherIcon(Launcher* IconManager, BamfApplication* app) - : SimpleLauncherIcon(IconManager) +BamfLauncherIcon::BamfLauncherIcon(BamfApplication* app) + : SimpleLauncherIcon() , _supported_types_filled(false) , _fill_supported_types_id(0) { @@ -177,7 +177,6 @@ BamfLauncherIcon::BamfLauncherIcon(Launcher* IconManager, BamfApplication* app) _remote_uri = 0; _dnd_hover_timer = 0; _dnd_hovered = false; - _launcher = IconManager; _desktop_file_monitor = NULL; _menu_desktop_shortcuts = NULL; _on_desktop_file_changed_handler_id = 0; @@ -215,8 +214,6 @@ BamfLauncherIcon::BamfLauncherIcon(Launcher* IconManager, BamfApplication* app) WindowManager::Default()->window_moved.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnWindowMoved)); WindowManager::Default()->compiz_screen_viewport_switch_ended.connect(sigc::mem_fun(this, &BamfLauncherIcon::EnsureWindowState)); WindowManager::Default()->terminate_expo.connect(sigc::mem_fun(this, &BamfLauncherIcon::EnsureWindowState)); - IconManager->hidden_changed.connect(sigc::mem_fun(this, &BamfLauncherIcon::OnLauncherHiddenChanged)); - // hack SetProgress(0.0f); @@ -285,7 +282,7 @@ BamfLauncherIcon::~BamfLauncherIcon() g_free(_cached_name); } -std::vector<Window> BamfLauncherIcon::RelatedXids () +std::vector<Window> BamfLauncherIcon::Windows () { std::vector<Window> results; GList* children, *l; @@ -301,9 +298,32 @@ std::vector<Window> BamfLauncherIcon::RelatedXids () guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view)); if (wm->IsWindowMapped(xid)) - { - results.push_back (xid); - } + results.push_back ((Window) xid); + } + } + + g_list_free(children); + return results; +} + +std::vector<Window> BamfLauncherIcon::WindowsForMonitor (int monitor) +{ + std::vector<Window> results; + GList* children, *l; + BamfView* view; + WindowManager *wm = WindowManager::Default (); + + children = bamf_view_get_children(BAMF_VIEW(m_App)); + for (l = children; l; l = l->next) + { + view = static_cast <BamfView*> (l->data); + if (BAMF_IS_WINDOW(view) && bamf_window_get_monitor(BAMF_WINDOW(view)) == monitor) + { + guint32 xid = bamf_window_get_xid(BAMF_WINDOW(view)); + bool user_visible = bamf_view_user_visible(view); + + if (user_visible && wm->IsWindowMapped(xid) && wm->IsWindowOnCurrentDesktop(xid)) + results.push_back ((Window) xid); } } @@ -332,11 +352,6 @@ std::string BamfLauncherIcon::NameForWindow (Window window) return result; } -void BamfLauncherIcon::OnLauncherHiddenChanged() -{ - UpdateIconGeometries(GetCenter()); -} - void BamfLauncherIcon::OnWindowMinimized(guint32 xid) { if (!OwnsWindow(xid)) @@ -594,18 +609,18 @@ void BamfLauncherIcon::Focus(ActionArg arg) if (any_visible) { WindowManager::Default()->FocusWindowGroup(windows, - WindowManager::FocusVisibility::ForceUnminimizeInvisible); + WindowManager::FocusVisibility::ForceUnminimizeInvisible, arg.monitor); } else { WindowManager::Default()->FocusWindowGroup(windows, - WindowManager::FocusVisibility::ForceUnminimizeOnCurrentDesktop); + WindowManager::FocusVisibility::ForceUnminimizeOnCurrentDesktop, arg.monitor); } } else { WindowManager::Default()->FocusWindowGroup(windows, - WindowManager::FocusVisibility::OnlyVisible); + WindowManager::FocusVisibility::OnlyVisible, arg.monitor); } } @@ -662,7 +677,7 @@ void BamfLauncherIcon::OnRunningChanged(BamfView* view, gboolean running, if (running) { self->EnsureWindowState(); - self->UpdateIconGeometries(self->GetCenter()); + self->UpdateIconGeometries(self->GetCenters()); } } @@ -681,9 +696,9 @@ void BamfLauncherIcon::OnUrgentChanged(BamfView* view, gboolean urgent, gpointer void BamfLauncherIcon::EnsureWindowState() { GList* children, *l; - bool has_win_on_current_vp = false; - unsigned int user_visible_count = 0; - unsigned int children_count = 0; + + std::vector<bool> monitors; + monitors.resize(max_num_monitors); children = bamf_view_get_children(BAMF_VIEW(m_App)); for (l = children; l; l = l->next) @@ -692,29 +707,13 @@ void BamfLauncherIcon::EnsureWindowState() continue; Window xid = bamf_window_get_xid(BAMF_WINDOW(l->data)); - if (WindowManager::Default()->IsWindowOnCurrentDesktop(xid)) - { - has_win_on_current_vp = true; - - if (bamf_view_user_visible (BAMF_VIEW (l->data))) - { - user_visible_count++; - } - } - - children_count++; - } - - if (user_visible_count > 0) - { - SetRelatedWindows(user_visible_count); - } - else if (children_count > 0) - { - SetRelatedWindows(1); + int monitor = bamf_window_get_monitor(BAMF_WINDOW(l->data)); + if (monitor >= 0 && WindowManager::Default()->IsWindowOnCurrentDesktop(xid)) + monitors[monitor] = true; } - SetHasWindowOnViewport(has_win_on_current_vp); + for (int i = 0; i < max_num_monitors; i++) + SetWindowVisibleOnMonitor(monitors[i], i); g_list_free(children); } @@ -724,13 +723,17 @@ void BamfLauncherIcon::OnChildAdded(BamfView* view, BamfView* child, gpointer da BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data); self->EnsureWindowState(); self->UpdateMenus(); - self->UpdateIconGeometries(self->GetCenter()); + self->UpdateIconGeometries(self->GetCenters()); + + self->needs_redraw.emit(self); } void BamfLauncherIcon::OnChildRemoved(BamfView* view, BamfView* child, gpointer data) { BamfLauncherIcon* self = static_cast <BamfLauncherIcon*> (data); self->EnsureWindowState(); + + self->needs_redraw.emit(self); } void BamfLauncherIcon::UpdateDesktopQuickList() @@ -1122,22 +1125,14 @@ std::list<DbusmenuMenuitem*> BamfLauncherIcon::GetMenus() } -void BamfLauncherIcon::UpdateIconGeometries(nux::Point3 center) +void BamfLauncherIcon::UpdateIconGeometries(std::vector<nux::Point3> center) { GList* children, *l; BamfView* view; nux::Geometry geo; - if (_launcher->Hidden() && !_launcher->ShowOnEdge()) - { - geo.x = 0; - geo.y = 0; - } - else - { - geo.x = center.x - 24; - geo.y = center.y - 24; - } + geo.x = center[0].x - 24; + geo.y = center[0].y - 24; geo.width = 48; geo.height = 48; @@ -1157,7 +1152,7 @@ void BamfLauncherIcon::UpdateIconGeometries(nux::Point3 center) g_list_free(children); } -void BamfLauncherIcon::OnCenterStabilized(nux::Point3 center) +void BamfLauncherIcon::OnCenterStabilized(std::vector<nux::Point3> center) { UpdateIconGeometries(center); } @@ -1260,9 +1255,30 @@ void BamfLauncherIcon::OnDesktopFileChanged(GFileMonitor* monitor, } bool -BamfLauncherIcon::ShowInSwitcher() +BamfLauncherIcon::ShowInSwitcher(bool current) { - return GetQuirk(QUIRK_RUNNING) && GetQuirk(QUIRK_VISIBLE); + bool result = false; + + if (GetQuirk(QUIRK_RUNNING) && GetQuirk(QUIRK_VISIBLE)) + { + if (current) + { + result = true; + } + else + { + for (int i = 0; i < max_num_monitors; i++) + { + if (WindowVisibleOnMonitor(i)) + { + result = true; + break; + } + } + } + } + + return result; } unsigned long long diff --git a/plugins/unityshell/src/BamfLauncherIcon.h b/plugins/unityshell/src/BamfLauncherIcon.h index 24c1e053a..80409aa41 100644 --- a/plugins/unityshell/src/BamfLauncherIcon.h +++ b/plugins/unityshell/src/BamfLauncherIcon.h @@ -41,7 +41,7 @@ class Launcher; class BamfLauncherIcon : public SimpleLauncherIcon { public: - BamfLauncherIcon(Launcher* IconManager, BamfApplication* app); + BamfLauncherIcon(BamfApplication* app); virtual ~BamfLauncherIcon(); const char* DesktopFile(); @@ -52,18 +52,19 @@ public: void ActivateLauncherIcon(ActionArg arg); - virtual bool ShowInSwitcher(); + virtual bool ShowInSwitcher(bool current); virtual unsigned long long SwitcherPriority(); - std::vector<Window> RelatedXids (); + std::vector<Window> Windows (); + std::vector<Window> WindowsForMonitor(int monitor); std::string NameForWindow (Window window); protected: std::list<DbusmenuMenuitem*> GetMenus(); - void UpdateIconGeometries(nux::Point3 center); - void OnCenterStabilized(nux::Point3 center); + void UpdateIconGeometries(std::vector<nux::Point3> center); + void OnCenterStabilized(std::vector<nux::Point3> center); void OnLauncherHiddenChanged(); @@ -86,7 +87,6 @@ protected: private: BamfApplication* m_App; - Launcher* _launcher; std::map<std::string, DbusmenuClient*> _menu_clients; std::map<std::string, DbusmenuMenuitem*> _menu_items; std::map<std::string, DbusmenuMenuitem*> _menu_items_extra; diff --git a/plugins/unityshell/src/DashController.cpp b/plugins/unityshell/src/DashController.cpp index d0e2cbac9..592b8f9be 100644 --- a/plugins/unityshell/src/DashController.cpp +++ b/plugins/unityshell/src/DashController.cpp @@ -151,7 +151,7 @@ void Controller::OnWindowConfigure(int window_width, int window_height, nux::Geometry Controller::GetIdealWindowGeometry() { UScreen *uscreen = UScreen::GetDefault(); - int primary_monitor = uscreen->GetPrimaryMonitor(); + int primary_monitor = uscreen->GetMonitorWithMouse(); auto monitor_geo = uscreen->GetMonitorGeometry(primary_monitor); // We want to cover as much of the screen as possible to grab any mouse events outside @@ -169,6 +169,7 @@ void Controller::Relayout(GdkScreen*screen) nux::Geometry geo = GetIdealWindowGeometry(); window_->SetGeometry(geo); view_->Relayout(); + view_->SetMonitorOffset(launcher_width, panel_height); } void Controller::OnMouseDownOutsideWindow(int x, int y, @@ -242,7 +243,7 @@ void Controller::ShowDash() StartShowHideTimeline(); - ubus_manager_.SendMessage(UBUS_PLACE_VIEW_SHOWN); + ubus_manager_.SendMessage(UBUS_PLACE_VIEW_SHOWN, g_variant_new_int32(UScreen::GetDefault()->GetMonitorWithMouse())); } void Controller::HideDash(bool restore) diff --git a/plugins/unityshell/src/DashSettings.cpp b/plugins/unityshell/src/DashSettings.cpp index 7833f79a5..e1a417853 100644 --- a/plugins/unityshell/src/DashSettings.cpp +++ b/plugins/unityshell/src/DashSettings.cpp @@ -80,7 +80,7 @@ void Settings::Impl::Refresh() if (raw_from_factor == 0) //Automatic { UScreen *uscreen = UScreen::GetDefault(); - int primary_monitor = uscreen->GetPrimaryMonitor(); + int primary_monitor = uscreen->GetMonitorWithMouse(); auto geo = uscreen->GetMonitorGeometry(primary_monitor); form_factor_ = geo.height > 799 ? FormFactor::DESKTOP : FormFactor::NETBOOK; diff --git a/plugins/unityshell/src/DashView.cpp b/plugins/unityshell/src/DashView.cpp index bf998c647..c341bd137 100644 --- a/plugins/unityshell/src/DashView.cpp +++ b/plugins/unityshell/src/DashView.cpp @@ -79,6 +79,12 @@ DashView::~DashView() g_source_remove (searching_timeout_id_); } +void DashView::SetMonitorOffset(int x, int y) +{ + renderer_.x_offset = x; + renderer_.y_offset = y; +} + void DashView::AboutToShow() { ubus_manager_.SendMessage(UBUS_BACKGROUND_REQUEST_COLOUR_EMIT); diff --git a/plugins/unityshell/src/DashView.h b/plugins/unityshell/src/DashView.h index 9c881289d..938950665 100644 --- a/plugins/unityshell/src/DashView.h +++ b/plugins/unityshell/src/DashView.h @@ -56,6 +56,7 @@ public: void Relayout(); void DisableBlur(); void OnActivateRequest(GVariant* args); + void SetMonitorOffset(int x, int y); std::string const GetIdForShortcutActivation(std::string const& shortcut) const; std::vector<char> GetAllShortcuts(); diff --git a/plugins/unityshell/src/Decaymulator.cpp b/plugins/unityshell/src/Decaymulator.cpp new file mode 100644 index 000000000..03fe54a09 --- /dev/null +++ b/plugins/unityshell/src/Decaymulator.cpp @@ -0,0 +1,58 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2010 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: Jason Smith <jason.smith@canonical.com> + */ + +#include "Decaymulator.h" + +namespace unity { +namespace ui { + +Decaymulator::Decaymulator() +{ + on_decay_handle = 0; + value.changed.connect(sigc::mem_fun(this, &Decaymulator::OnValueChanged)); +} + +void Decaymulator::OnValueChanged(int value) +{ + if (!on_decay_handle && value > 0) + { + on_decay_handle = g_timeout_add(10, &Decaymulator::OnDecayTimeout, this); + } +} + +gboolean Decaymulator::OnDecayTimeout(gpointer data) +{ + Decaymulator* self = (Decaymulator*) data; + + int partial_decay = self->rate_of_decay / 100; + + if (self->value <= partial_decay) + { + self->value = 0; + self->on_decay_handle = 0; + return FALSE; + } + + + self->value = self->value - partial_decay; + return TRUE; +} + +} +} \ No newline at end of file diff --git a/plugins/unityshell/src/Decaymulator.h b/plugins/unityshell/src/Decaymulator.h new file mode 100644 index 000000000..a0f26aa13 --- /dev/null +++ b/plugins/unityshell/src/Decaymulator.h @@ -0,0 +1,51 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2010 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: Jason Smith <jason.smith@canonical.com> + */ + +#ifndef UNITY_DECAYMULATOR_H +#define UNITY_DECAYMULATOR_H + +#include <Nux/Nux.h> +#include <glib.h> + +namespace unity +{ +namespace ui +{ + +class Decaymulator +{ +public: + typedef std::shared_ptr<Decaymulator> Ptr; + + nux::Property<int> rate_of_decay; + nux::Property<int> value; + + Decaymulator(); + +private: + void OnValueChanged(int value); + static gboolean OnDecayTimeout (gpointer value); + + guint on_decay_handle; +}; + +} +} + +#endif \ No newline at end of file diff --git a/plugins/unityshell/src/DesktopLauncherIcon.cpp b/plugins/unityshell/src/DesktopLauncherIcon.cpp index 0adc79de7..ae474aade 100644 --- a/plugins/unityshell/src/DesktopLauncherIcon.cpp +++ b/plugins/unityshell/src/DesktopLauncherIcon.cpp @@ -27,14 +27,14 @@ namespace unity namespace launcher { -DesktopLauncherIcon::DesktopLauncherIcon(Launcher* IconManager) - : SimpleLauncherIcon(IconManager) +DesktopLauncherIcon::DesktopLauncherIcon() + : SimpleLauncherIcon() , show_in_switcher_(true) { tooltip_text = _("Show Desktop"); icon_name = "desktop"; SetQuirk(QUIRK_VISIBLE, true); - SetQuirk(QUIRK_RUNNING, true); + SetQuirk(QUIRK_RUNNING, false); SetIconType(TYPE_BEGIN); } diff --git a/plugins/unityshell/src/DesktopLauncherIcon.h b/plugins/unityshell/src/DesktopLauncherIcon.h index 078228bde..05ad51f31 100644 --- a/plugins/unityshell/src/DesktopLauncherIcon.h +++ b/plugins/unityshell/src/DesktopLauncherIcon.h @@ -31,7 +31,7 @@ class DesktopLauncherIcon : public SimpleLauncherIcon { public: - DesktopLauncherIcon(Launcher* launcher); + DesktopLauncherIcon(); ~DesktopLauncherIcon(); virtual nux::Color BackgroundColor(); @@ -42,12 +42,7 @@ public: show_in_switcher_ = show_in_switcher; } - const bool HasWindowOnViewport() - { - return true; - } - - bool ShowInSwitcher() + bool ShowInSwitcher(bool current) { return show_in_switcher_; } diff --git a/plugins/unityshell/src/DeviceLauncherIcon.cpp b/plugins/unityshell/src/DeviceLauncherIcon.cpp index dac1c9f76..eca15f17a 100644 --- a/plugins/unityshell/src/DeviceLauncherIcon.cpp +++ b/plugins/unityshell/src/DeviceLauncherIcon.cpp @@ -43,8 +43,8 @@ GduDevice* get_device_for_device_file (const gchar *device_file); } -DeviceLauncherIcon::DeviceLauncherIcon(Launcher* launcher, GVolume* volume) - : SimpleLauncherIcon(launcher) +DeviceLauncherIcon::DeviceLauncherIcon(GVolume* volume) + : SimpleLauncherIcon() , volume_(volume) , device_file_(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE)) , gdu_device_(get_device_for_device_file(device_file_)) diff --git a/plugins/unityshell/src/DeviceLauncherIcon.h b/plugins/unityshell/src/DeviceLauncherIcon.h index 28b8204a7..4c52b451b 100644 --- a/plugins/unityshell/src/DeviceLauncherIcon.h +++ b/plugins/unityshell/src/DeviceLauncherIcon.h @@ -36,7 +36,7 @@ class DeviceLauncherIcon : public SimpleLauncherIcon { public: - DeviceLauncherIcon(Launcher* launcher, GVolume* volume); + DeviceLauncherIcon(GVolume* volume); virtual nux::Color BackgroundColor(); virtual nux::Color GlowColor(); diff --git a/plugins/unityshell/src/DeviceLauncherSection.cpp b/plugins/unityshell/src/DeviceLauncherSection.cpp index cf9c79f09..6958f0a12 100644 --- a/plugins/unityshell/src/DeviceLauncherSection.cpp +++ b/plugins/unityshell/src/DeviceLauncherSection.cpp @@ -23,9 +23,8 @@ namespace unity namespace launcher { -DeviceLauncherSection::DeviceLauncherSection(Launcher* launcher) - : launcher_(launcher) - , monitor_(g_volume_monitor_get()) +DeviceLauncherSection::DeviceLauncherSection() + : monitor_(g_volume_monitor_get()) { on_volume_added_handler_id_ = g_signal_connect(monitor_, "volume-added", @@ -79,7 +78,7 @@ bool DeviceLauncherSection::PopulateEntries(DeviceLauncherSection* self) for (GList* v = volumes; v; v = v->next) { glib::Object<GVolume> volume((GVolume* )v->data); - DeviceLauncherIcon* icon = new DeviceLauncherIcon(self->launcher_, volume); + DeviceLauncherIcon* icon = new DeviceLauncherIcon(volume); self->map_[volume] = icon; self->IconAdded.emit(icon); @@ -100,7 +99,7 @@ void DeviceLauncherSection::OnVolumeAdded(GVolumeMonitor* monitor, GVolume* volume, DeviceLauncherSection* self) { - DeviceLauncherIcon* icon = new DeviceLauncherIcon(self->launcher_, volume); + DeviceLauncherIcon* icon = new DeviceLauncherIcon(volume); self->map_[volume] = icon; self->IconAdded.emit(icon); diff --git a/plugins/unityshell/src/DeviceLauncherSection.h b/plugins/unityshell/src/DeviceLauncherSection.h index e940eec89..6cc770d9f 100644 --- a/plugins/unityshell/src/DeviceLauncherSection.h +++ b/plugins/unityshell/src/DeviceLauncherSection.h @@ -39,7 +39,7 @@ namespace launcher class DeviceLauncherSection : public sigc::trackable { public: - DeviceLauncherSection(Launcher* launcher); + DeviceLauncherSection(); ~DeviceLauncherSection(); sigc::signal<void, LauncherIcon*> IconAdded; @@ -64,7 +64,6 @@ private: DeviceLauncherSection* self); private: - Launcher* launcher_; glib::Object<GVolumeMonitor> monitor_; std::map<GVolume*, DeviceLauncherIcon*> map_; gulong on_volume_added_handler_id_; diff --git a/plugins/unityshell/src/IconRenderer.cpp b/plugins/unityshell/src/IconRenderer.cpp index 2c6cb41e4..80e9a0da2 100644 --- a/plugins/unityshell/src/IconRenderer.cpp +++ b/plugins/unityshell/src/IconRenderer.cpp @@ -369,7 +369,7 @@ void IconRenderer::UpdateIconSectionTransform(launcher::AbstractLauncherIcon* ic v3.y = -geo.height * (v3.y - 1.0f) / 2.0f - geo.height / 2.0f + yy + hh / 2.0f; - std::vector<nux::Vector4>& vectors = icon->GetTransform(index); + std::vector<nux::Vector4>& vectors = icon->GetTransform(index, monitor); vectors[0] = v0; vectors[1] = v1; @@ -420,7 +420,7 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& shine = local::squircle_shine; } - auto tile_transform = arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_TILE); + auto tile_transform = arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_TILE, monitor); // draw tile if (backlight_intensity > 0 && !arg.draw_edge_only) @@ -452,7 +452,7 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& arg.icon->TextureForSize(image_size)->GetDeviceTexture(), nux::color::White, arg.alpha, - arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_IMAGE)); + arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_IMAGE, monitor)); // draw overlay shine RenderElement(GfxContext, @@ -470,7 +470,7 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& glow->GetDeviceTexture(), glow_color, glow_intensity * arg.alpha, - arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_GLOW)); + arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_GLOW, monitor)); } // draw shimmer @@ -490,7 +490,7 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& local::icon_glow[size]->GetDeviceTexture(), arg.icon->GlowColor(), fade_out * arg.alpha, - arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_GLOW)); + arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_GLOW, monitor)); GfxContext.PopClippingRectangle(); } @@ -521,7 +521,7 @@ void IconRenderer::RenderIcon(nux::GraphicsEngine& GfxContext, RenderArg const& arg.icon->Emblem()->GetDeviceTexture(), nux::color::White, arg.alpha, - arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_EMBLEM)); + arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_EMBLEM, monitor)); } // draw indicators @@ -787,7 +787,7 @@ void IconRenderer::RenderIndicators(nux::GraphicsEngine& GfxContext, } else { - auto bounds = arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_TILE); + auto bounds = arg.icon->GetTransform(launcher::AbstractLauncherIcon::TRANSFORM_TILE, monitor); markerX = bounds[0].x + 2; scale = 2; } diff --git a/plugins/unityshell/src/Launcher.cpp b/plugins/unityshell/src/Launcher.cpp index 7fbbf011b..33e82da43 100644 --- a/plugins/unityshell/src/Launcher.cpp +++ b/plugins/unityshell/src/Launcher.cpp @@ -36,7 +36,7 @@ #include <Nux/WindowCompositor.h> #include "Launcher.h" -#include "LauncherIcon.h" +#include "AbstractLauncherIcon.h" #include "SpacerLauncherIcon.h" #include "LauncherModel.h" #include "QuicklistManager.h" @@ -44,6 +44,7 @@ #include "IconRenderer.h" #include "TimeUtil.h" #include "WindowManager.h" +#include "UScreen.h" #include "ubus-server.h" #include "UBusMessages.h" @@ -54,6 +55,8 @@ namespace unity { using ui::RenderArg; +using ui::PointerBarrierWrapper; +using ui::Decaymulator; namespace launcher { @@ -72,6 +75,7 @@ const int STARTING_BLINK_LAMBDA = 3; const int PULSE_BLINK_LAMBDA = 2; const float BACKLIGHT_STRENGTH = 0.9f; +const int panel_height = 24; } @@ -94,19 +98,6 @@ const float BACKLIGHT_STRENGTH = 0.9f; NUX_IMPLEMENT_OBJECT_TYPE(Launcher); -void SetTimeBack(struct timespec* timeref, int remove) -{ - timeref->tv_sec -= remove / 1000; - remove = remove % 1000; - - if (remove > timeref->tv_nsec / 1000000) - { - timeref->tv_sec--; - timeref->tv_nsec += 1000000000; - } - timeref->tv_nsec -= remove * 1000000; -} - const gchar Launcher::introspection_xml[] = "<node>" " <interface name='com.canonical.Unity.Launcher'>" @@ -134,8 +125,6 @@ GDBusInterfaceVTable Launcher::interface_vtable = Launcher::Launcher(nux::BaseWindow* parent, NUX_FILE_LINE_DECL) : View(NUX_FILE_LINE_PARAM) - , m_ContentOffsetY(0) - , m_BackgroundLayer(0) , _model(0) , _collection_window(NULL) , _background_color(nux::color::DimGray) @@ -143,10 +132,13 @@ Launcher::Launcher(nux::BaseWindow* parent, { _parent = parent; - _active_quicklist = 0; + _active_quicklist = nullptr; + + monitor = 0; _hide_machine = new LauncherHideMachine(); _hide_machine->should_hide_changed.connect(sigc::mem_fun(this, &Launcher::SetHidden)); + _hover_machine = new LauncherHoverMachine(); _hover_machine->should_hover_changed.connect(sigc::mem_fun(this, &Launcher::SetHover)); @@ -161,8 +153,6 @@ Launcher::Launcher(nux::BaseWindow* parent, mouse_leave.connect(sigc::mem_fun(this, &Launcher::RecvMouseLeave)); mouse_move.connect(sigc::mem_fun(this, &Launcher::RecvMouseMove)); mouse_wheel.connect(sigc::mem_fun(this, &Launcher::RecvMouseWheel)); - key_down.connect(sigc::mem_fun(this, &Launcher::RecvKeyPressed)); - mouse_down_outside_pointer_grab_area.connect(sigc::mem_fun(this, &Launcher::RecvMouseDownOutsideArea)); //OnEndFocus.connect (sigc::mem_fun (this, &Launcher::exitKeyNavMode)); CaptureMouseDownAnyWhereElse(true); @@ -199,10 +189,6 @@ Launcher::Launcher(nux::BaseWindow* parent, display.changed.connect(sigc::mem_fun(this, &Launcher::OnDisplayChanged)); - _current_icon = NULL; - _current_icon_index = -1; - _last_icon_index = -1; - SetCompositionLayout(m_Layout); _folded_angle = 1.0f; @@ -231,23 +217,15 @@ Launcher::Launcher(nux::BaseWindow* parent, _dnd_delta_x = 0; _autoscroll_handle = 0; - _super_show_launcher_handle = 0; - _super_hide_launcher_handle = 0; - _super_show_shortcuts_handle = 0; _start_dragicon_handle = 0; - _focus_keynav_handle = 0; _dnd_check_handle = 0; - _ignore_repeat_shortcut_handle = 0; - _latest_shortcut = 0; _shortcuts_shown = false; _floating = false; _hovered = false; _hidden = false; _render_drag_window = false; _drag_edge_touching = false; - _keynav_activated = false; - _key_switcher_activated = false; _backlight_mode = BACKLIGHT_NORMAL; _last_button_press = 0; _selection_atom = 0; @@ -261,10 +239,6 @@ Launcher::Launcher(nux::BaseWindow* parent, _postreveal_mousemove_delta_x = 0; _postreveal_mousemove_delta_y = 0; - // set them to 1 instead of 0 to avoid :0 in case something is racy - _bfb_width = 1; - _bfb_height = 1; - _data_checked = false; _collection_window = new unity::DNDCollectionWindow(); _collection_window->SinkReference(); @@ -326,6 +300,12 @@ Launcher::Launcher(nux::BaseWindow* parent, launcher_sheen_->UnReference(); } + _pointer_barrier = PointerBarrierWrapper::Ptr(new PointerBarrierWrapper()); + _pointer_barrier->barrier_event.connect(sigc::mem_fun(this, &Launcher::OnPointerBarrierEvent)); + + decaymulator_ = Decaymulator::Ptr(new Decaymulator()); + + options.changed.connect (sigc::mem_fun (this, &Launcher::OnOptionsChanged)); } Launcher::~Launcher() @@ -336,18 +316,8 @@ Launcher::~Launcher() g_source_remove(_dnd_check_handle); if (_autoscroll_handle) g_source_remove(_autoscroll_handle); - if (_focus_keynav_handle) - g_source_remove(_focus_keynav_handle); - if (_super_show_launcher_handle) - g_source_remove(_super_show_launcher_handle); - if (_super_show_shortcuts_handle) - g_source_remove(_super_show_shortcuts_handle); if (_start_dragicon_handle) g_source_remove(_start_dragicon_handle); - if (_ignore_repeat_shortcut_handle) - g_source_remove(_ignore_repeat_shortcut_handle); - if (_super_hide_launcher_handle) - g_source_remove(_super_hide_launcher_handle); if (_launcher_animation_timeout > 0) g_source_remove(_launcher_animation_timeout); @@ -414,93 +384,20 @@ Launcher::OnDragFinish(GeisAdapter::GeisDragData* data) { if (_drag_out_delta_x >= DRAG_OUT_PIXELS - 90.0f) _hide_machine->SetQuirk(LauncherHideMachine::MT_DRAG_OUT, true); - SetTimeStruct(&_times[TIME_DRAG_OUT], &_times[TIME_DRAG_OUT], ANIM_DURATION_SHORT); + TimeUtil::SetTimeStruct(&_times[TIME_DRAG_OUT], &_times[TIME_DRAG_OUT], ANIM_DURATION_SHORT); _drag_out_id = 0; EnsureAnimation(); } } void -Launcher::startKeyNavMode() -{ - SetStateKeyNav(true); - _hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false); - - GrabKeyboard(); - - // FIXME: long term solution is to rewrite the keynav handle - if (_focus_keynav_handle > 0) - g_source_remove(_focus_keynav_handle); - _focus_keynav_handle = g_timeout_add(ANIM_DURATION_SHORT, &Launcher::MoveFocusToKeyNavModeTimeout, this); - -} - -gboolean -Launcher::MoveFocusToKeyNavModeTimeout(gpointer data) -{ - Launcher* self = (Launcher*) data; - - // move focus to key nav mode when activated - if (!(self->_keynav_activated)) - return false; - - if (self->_last_icon_index == -1) - { - self->_current_icon_index = 0; - } - else - self->_current_icon_index = self->_last_icon_index; - self->EnsureAnimation(); - - ubus_server_send_message(ubus_server_get_default(), - UBUS_LAUNCHER_START_KEY_NAV, - NULL); - - self->selection_change.emit(); - self->_focus_keynav_handle = 0; - - return false; -} - -void -Launcher::leaveKeyNavMode(bool preserve_focus) -{ - _last_icon_index = _current_icon_index; - _current_icon_index = -1; - QueueDraw(); - - ubus_server_send_message(ubus_server_get_default(), - UBUS_LAUNCHER_END_KEY_NAV, - g_variant_new_boolean(preserve_focus)); - - selection_change.emit(); -} - -void -Launcher::exitKeyNavMode() -{ - if (!_keynav_activated) - return; - - UnGrabKeyboard(); - UnGrabPointer(); - SetStateKeyNav(false); - - _current_icon_index = -1; - _last_icon_index = _current_icon_index; - QueueDraw(); - ubus_server_send_message(ubus_server_get_default(), - UBUS_LAUNCHER_END_KEY_NAV, - g_variant_new_boolean(true)); - selection_change.emit(); -} - -void Launcher::AddProperties(GVariantBuilder* builder) { timespec current; clock_gettime(CLOCK_MONOTONIC, ¤t); + nux::Geometry abs_geo = GetAbsoluteGeometry(); + unity::variant::BuilderWrapper(builder) .add("hover-progress", GetHoverProgress(current)) .add("dnd-exit-progress", DnDExitProgress(current)) @@ -510,6 +407,12 @@ Launcher::AddProperties(GVariantBuilder* builder) .add("hovered", _hovered) .add("hidemode", _hidemode) .add("hidden", _hidden) + .add("x", abs_geo.x) + .add("y", abs_geo.y) + .add("width", abs_geo.width) + .add("height", abs_geo.height) + .add("monitor", monitor()) + .add("quicklist-open", _hide_machine->GetQuirk(LauncherHideMachine::QUICKLIST_OPEN)) .add("hide-quirks", _hide_machine->DebugHideQuirks().c_str()) .add("hover-quirks", _hover_machine->DebugHoverQuirks().c_str()) .add("icon-size", _icon_size); @@ -521,7 +424,7 @@ void Launcher::SetMousePosition(int x, int y) _mouse_position = nux::Point2(x, y); if (beyond_drag_threshold != MouseBeyondDragThreshold()) - SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT); + TimeUtil::SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT); EnsureScrollTimer(); } @@ -529,24 +432,11 @@ void Launcher::SetMousePosition(int x, int y) void Launcher::SetStateMouseOverLauncher(bool over_launcher) { _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_LAUNCHER, over_launcher); + _hide_machine->SetQuirk(LauncherHideMachine::REVEAL_PRESSURE_PASS, false); _hover_machine->SetQuirk(LauncherHoverMachine::MOUSE_OVER_LAUNCHER, over_launcher); - - if (!over_launcher) - { - // reset state for some corner case like x=0, show dash (leave event not received) - _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE, false); - } -} - -void Launcher::SetStateKeyNav(bool keynav_activated) -{ - _hide_machine->SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, keynav_activated); - _hover_machine->SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, keynav_activated); - - _keynav_activated = keynav_activated; } -bool Launcher::MouseBeyondDragThreshold() +bool Launcher::MouseBeyondDragThreshold() const { if (GetActionState() == ACTION_DRAG_ICON) return _mouse_position.x > GetGeometry().width + _icon_size / 2; @@ -554,7 +444,7 @@ bool Launcher::MouseBeyondDragThreshold() } /* Render Layout Logic */ -float Launcher::GetHoverProgress(struct timespec const& current) +float Launcher::GetHoverProgress(struct timespec const& current) const { if (_hovered) return CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_ENTER])) / (float) ANIM_DURATION, 0.0f, 1.0f); @@ -562,12 +452,12 @@ float Launcher::GetHoverProgress(struct timespec const& current) return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_LEAVE])) / (float) ANIM_DURATION, 0.0f, 1.0f); } -float Launcher::DnDExitProgress(struct timespec const& current) +float Launcher::DnDExitProgress(struct timespec const& current) const { return pow(1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_END])) / (float) ANIM_DURATION_LONG, 0.0f, 1.0f), 2); } -float Launcher::DragOutProgress(struct timespec const& current) +float Launcher::DragOutProgress(struct timespec const& current) const { float timeout = CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_OUT])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); float progress = CLAMP(_drag_out_delta_x / DRAG_OUT_PIXELS, 0.0f, 1.0f); @@ -577,7 +467,7 @@ float Launcher::DragOutProgress(struct timespec const& current) return progress * (1.0f - timeout); } -float Launcher::AutohideProgress(struct timespec const& current) +float Launcher::AutohideProgress(struct timespec const& current) const { // time-based progress (full scale or finish the TRIGGER_AUTOHIDE_MIN -> 0.00f on bfb) float animation_progress; @@ -588,7 +478,7 @@ float Launcher::AutohideProgress(struct timespec const& current) return 1.0f - animation_progress; } -float Launcher::DragHideProgress(struct timespec const& current) +float Launcher::DragHideProgress(struct timespec const& current) const { if (_drag_edge_touching) return CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f); @@ -596,7 +486,7 @@ float Launcher::DragHideProgress(struct timespec const& current) return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_EDGE_TOUCH])) / (float)(ANIM_DURATION * 3), 0.0f, 1.0f); } -float Launcher::DragThresholdProgress(struct timespec const& current) +float Launcher::DragThresholdProgress(struct timespec const& current) const { if (MouseBeyondDragThreshold()) return 1.0f - CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_THRESHOLD])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); @@ -617,60 +507,60 @@ void Launcher::EnsureAnimation() NeedRedraw(); } -bool Launcher::IconNeedsAnimation(LauncherIcon* icon, struct timespec const& current) +bool Launcher::IconNeedsAnimation(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec time = icon->GetQuirkTime(LauncherIcon::QUIRK_VISIBLE); + struct timespec time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_VISIBLE); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_RUNNING); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_RUNNING); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_STARTING); + 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(LauncherIcon::QUIRK_URGENT); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_URGENT); if (unity::TimeUtil::TimeDelta(¤t, &time) < (ANIM_DURATION_LONG * URGENT_BLINKS * 2)) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_PULSE_ONCE); + 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(LauncherIcon::QUIRK_PRESENTED); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_PRESENTED); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_SHIMMER); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_SHIMMER); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_LONG) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_CENTER_SAVED); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_CENTER_SAVED); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_PROGRESS); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_PROGRESS); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_DROP_DIM); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_DROP_DIM); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_DESAT); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_DESAT); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_SHORT_SHORT) return true; - time = icon->GetQuirkTime(LauncherIcon::QUIRK_DROP_PRELIGHT); + time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_DROP_PRELIGHT); if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) return true; return false; } -bool Launcher::AnimationInProgress() +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 @@ -716,27 +606,8 @@ bool Launcher::AnimationInProgress() return false; } -void Launcher::SetTimeStruct(struct timespec* timer, struct timespec* sister, int sister_relation) -{ - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - - if (sister) - { - int diff = unity::TimeUtil::TimeDelta(¤t, sister); - - if (diff < sister_relation) - { - int remove = sister_relation - diff; - SetTimeBack(¤t, remove); - } - } - - timer->tv_sec = current.tv_sec; - timer->tv_nsec = current.tv_nsec; -} /* Min is when you are on the trigger */ -float Launcher::GetAutohidePositionMin() +float Launcher::GetAutohidePositionMin() const { if (_autohide_animation == SLIDE_ONLY || _autohide_animation == FADE_AND_SLIDE) return 0.35f; @@ -744,7 +615,7 @@ float Launcher::GetAutohidePositionMin() return 0.25f; } /* Max is the initial state over the bfb */ -float Launcher::GetAutohidePositionMax() +float Launcher::GetAutohidePositionMax() const { if (_autohide_animation == SLIDE_ONLY || _autohide_animation == FADE_AND_SLIDE) return 1.00f; @@ -753,17 +624,17 @@ float Launcher::GetAutohidePositionMax() } -float IconVisibleProgress(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconVisibleProgress(AbstractLauncherIcon* icon, struct timespec const& current) const { - if (icon->GetQuirk(LauncherIcon::QUIRK_VISIBLE)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE)) { - struct timespec icon_visible_time = icon->GetQuirkTime(LauncherIcon::QUIRK_VISIBLE); + struct timespec icon_visible_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_VISIBLE); int 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(LauncherIcon::QUIRK_VISIBLE); + struct timespec icon_hide_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_VISIBLE); int hide_ms = unity::TimeUtil::TimeDelta(¤t, &icon_hide_time); return 1.0f - CLAMP((float) hide_ms / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); } @@ -771,7 +642,7 @@ float IconVisibleProgress(LauncherIcon* icon, struct timespec const& current) void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo, timespec const& current) { - LauncherIcon* anchor = 0; + AbstractLauncherIcon* anchor = nullptr; LauncherModel::iterator it; anchor = MouseIconIntersection(x, _enter_y); @@ -795,21 +666,21 @@ void Launcher::SetDndDelta(float x, float y, nux::Geometry const& geo, timespec } } -float Launcher::IconPresentProgress(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconPresentProgress(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec icon_present_time = icon->GetQuirkTime(LauncherIcon::QUIRK_PRESENTED); + struct timespec icon_present_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_PRESENTED); int ms = unity::TimeUtil::TimeDelta(¤t, &icon_present_time); float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f); - if (icon->GetQuirk(LauncherIcon::QUIRK_PRESENTED)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_PRESENTED)) return result; else return 1.0f - result; } -float Launcher::IconUrgentProgress(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconUrgentProgress(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec urgent_time = icon->GetQuirkTime(LauncherIcon::QUIRK_URGENT); + struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_URGENT); int urgent_ms = unity::TimeUtil::TimeDelta(¤t, &urgent_time); float result; @@ -818,118 +689,118 @@ float Launcher::IconUrgentProgress(LauncherIcon* icon, struct timespec const& cu else result = CLAMP((float) urgent_ms / (float)(ANIM_DURATION_LONG * URGENT_BLINKS * 2), 0.0f, 1.0f); - if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_URGENT)) return result; else return 1.0f - result; } -float Launcher::IconDropDimValue(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconDropDimValue(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec dim_time = icon->GetQuirkTime(LauncherIcon::QUIRK_DROP_DIM); + struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_DROP_DIM); int dim_ms = unity::TimeUtil::TimeDelta(¤t, &dim_time); float result = CLAMP((float) dim_ms / (float) ANIM_DURATION, 0.0f, 1.0f); - if (icon->GetQuirk(LauncherIcon::QUIRK_DROP_DIM)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_DROP_DIM)) return 1.0f - result; else return result; } -float Launcher::IconDesatValue(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconDesatValue(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec dim_time = icon->GetQuirkTime(LauncherIcon::QUIRK_DESAT); + struct timespec dim_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_DESAT); int ms = unity::TimeUtil::TimeDelta(¤t, &dim_time); float result = CLAMP((float) ms / (float) ANIM_DURATION_SHORT_SHORT, 0.0f, 1.0f); - if (icon->GetQuirk(LauncherIcon::QUIRK_DESAT)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_DESAT)) return 1.0f - result; else return result; } -float Launcher::IconShimmerProgress(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconShimmerProgress(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec shimmer_time = icon->GetQuirkTime(LauncherIcon::QUIRK_SHIMMER); + struct timespec shimmer_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_SHIMMER); int shimmer_ms = unity::TimeUtil::TimeDelta(¤t, &shimmer_time); return CLAMP((float) shimmer_ms / (float) ANIM_DURATION_LONG, 0.0f, 1.0f); } -float Launcher::IconCenterTransitionProgress(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconCenterTransitionProgress(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec save_time = icon->GetQuirkTime(LauncherIcon::QUIRK_CENTER_SAVED); + struct timespec save_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_CENTER_SAVED); int save_ms = unity::TimeUtil::TimeDelta(¤t, &save_time); return CLAMP((float) save_ms / (float) ANIM_DURATION, 0.0f, 1.0f); } -float Launcher::IconUrgentPulseValue(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconUrgentPulseValue(AbstractLauncherIcon* icon, struct timespec const& current) const { - if (!icon->GetQuirk(LauncherIcon::QUIRK_URGENT)) + if (!icon->GetQuirk(AbstractLauncherIcon::QUIRK_URGENT)) return 1.0f; // we are full on in a normal condition double urgent_progress = (double) IconUrgentProgress(icon, current); return 0.5f + (float)(std::cos(M_PI * (float)(URGENT_BLINKS * 2) * urgent_progress)) * 0.5f; } -float Launcher::IconPulseOnceValue(LauncherIcon *icon, struct timespec const ¤t) +float Launcher::IconPulseOnceValue(AbstractLauncherIcon *icon, struct timespec const ¤t) const { - struct timespec pulse_time = icon->GetQuirkTime(LauncherIcon::QUIRK_PULSE_ONCE); + struct timespec pulse_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_PULSE_ONCE); int 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); if (pulse_progress == 1.0f) - icon->SetQuirk(LauncherIcon::QUIRK_PULSE_ONCE, false); + icon->SetQuirk(AbstractLauncherIcon::QUIRK_PULSE_ONCE, false); return 0.5f + (float) (std::cos(M_PI * 2.0 * pulse_progress)) * 0.5f; } -float Launcher::IconUrgentWiggleValue(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconUrgentWiggleValue(AbstractLauncherIcon* icon, struct timespec const& current) const { - if (!icon->GetQuirk(LauncherIcon::QUIRK_URGENT)) + if (!icon->GetQuirk(AbstractLauncherIcon::QUIRK_URGENT)) return 0.0f; // we are full on in a normal condition double urgent_progress = (double) IconUrgentProgress(icon, current); return 0.3f * (float)(std::sin(M_PI * (float)(WIGGLE_CYCLES * 2) * urgent_progress)) * 0.5f; } -float Launcher::IconStartingBlinkValue(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconStartingBlinkValue(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec starting_time = icon->GetQuirkTime(LauncherIcon::QUIRK_STARTING); + struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_STARTING); int 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); double val = IsBackLightModeToggles() ? 3.0f : 4.0f; return 0.5f + (float)(std::cos(M_PI * val * starting_progress)) * 0.5f; } -float Launcher::IconStartingPulseValue(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconStartingPulseValue(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec starting_time = icon->GetQuirkTime(LauncherIcon::QUIRK_STARTING); + struct timespec starting_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_STARTING); int 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); - if (starting_progress == 1.0f && !icon->GetQuirk(LauncherIcon::QUIRK_RUNNING)) + if (starting_progress == 1.0f && !icon->GetQuirk(AbstractLauncherIcon::QUIRK_RUNNING)) { - icon->SetQuirk(LauncherIcon::QUIRK_STARTING, false); - icon->ResetQuirkTime(LauncherIcon::QUIRK_STARTING); + icon->SetQuirk(AbstractLauncherIcon::QUIRK_STARTING, false); + icon->ResetQuirkTime(AbstractLauncherIcon::QUIRK_STARTING); } return 0.5f + (float)(std::cos(M_PI * (float)(MAX_STARTING_BLINKS * 2) * starting_progress)) * 0.5f; } -float Launcher::IconBackgroundIntensity(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconBackgroundIntensity(AbstractLauncherIcon* icon, struct timespec const& current) const { float result = 0.0f; - struct timespec running_time = icon->GetQuirkTime(LauncherIcon::QUIRK_RUNNING); + struct timespec running_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_RUNNING); int 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(LauncherIcon::QUIRK_RUNNING)) + 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(LauncherIcon::QUIRK_RUNNING)) - icon->SetQuirk(LauncherIcon::QUIRK_STARTING, false); + if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::QUIRK_RUNNING)) + icon->SetQuirk(AbstractLauncherIcon::QUIRK_STARTING, false); float backlight_strength; if (_backlight_mode == BACKLIGHT_ALWAYS_ON) @@ -953,8 +824,8 @@ float Launcher::IconBackgroundIntensity(LauncherIcon* icon, struct timespec cons 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(LauncherIcon::QUIRK_RUNNING)) - icon->ResetQuirkTime(LauncherIcon::QUIRK_STARTING); + if (running_progress == 1.0f && icon->GetQuirk(AbstractLauncherIcon::QUIRK_RUNNING)) + icon->ResetQuirkTime(AbstractLauncherIcon::QUIRK_STARTING); result = backlight_strength; if (_backlight_mode == BACKLIGHT_ALWAYS_ON) @@ -966,7 +837,7 @@ float Launcher::IconBackgroundIntensity(LauncherIcon* icon, struct timespec cons break; } - if (icon->GetQuirk(LauncherIcon::QUIRK_PULSE_ONCE)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_PULSE_ONCE)) { if (_backlight_mode == BACKLIGHT_ALWAYS_ON) result *= CLAMP(running_progress + IconPulseOnceValue(icon, current), 0.0f, 1.0f); @@ -977,44 +848,44 @@ float Launcher::IconBackgroundIntensity(LauncherIcon* icon, struct timespec cons } // urgent serves to bring the total down only - if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT) && _urgent_animation == URGENT_ANIMATION_PULSE) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_URGENT) && _urgent_animation == URGENT_ANIMATION_PULSE) result *= 0.2f + 0.8f * IconUrgentPulseValue(icon, current); return result; } -float Launcher::IconProgressBias(LauncherIcon* icon, struct timespec const& current) +float Launcher::IconProgressBias(AbstractLauncherIcon* icon, struct timespec const& current) const { - struct timespec icon_progress_time = icon->GetQuirkTime(LauncherIcon::QUIRK_PROGRESS); + struct timespec icon_progress_time = icon->GetQuirkTime(AbstractLauncherIcon::QUIRK_PROGRESS); int ms = unity::TimeUtil::TimeDelta(¤t, &icon_progress_time); float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f); - if (icon->GetQuirk(LauncherIcon::QUIRK_PROGRESS)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_PROGRESS)) return -1.0f + result; else return result; } -bool Launcher::IconDrawEdgeOnly(LauncherIcon* icon) +bool Launcher::IconDrawEdgeOnly(AbstractLauncherIcon* icon) const { if (_backlight_mode == BACKLIGHT_EDGE_TOGGLE) return true; - if (_backlight_mode == BACKLIGHT_NORMAL_EDGE_TOGGLE && !icon->HasWindowOnViewport()) + if (_backlight_mode == BACKLIGHT_NORMAL_EDGE_TOGGLE && !icon->WindowVisibleOnMonitor(monitor)) return true; return false; } -void Launcher::SetupRenderArg(LauncherIcon* icon, struct timespec const& current, RenderArg& arg) +void Launcher::SetupRenderArg(AbstractLauncherIcon* icon, struct timespec const& current, RenderArg& arg) { float desat_value = IconDesatValue(icon, current); arg.icon = icon; arg.alpha = 0.5f + 0.5f * desat_value; arg.saturation = desat_value; - arg.running_arrow = icon->GetQuirk(LauncherIcon::QUIRK_RUNNING); - arg.running_colored = icon->GetQuirk(LauncherIcon::QUIRK_URGENT); - arg.running_on_viewport = icon->HasWindowOnViewport(); + arg.running_arrow = icon->GetQuirk(AbstractLauncherIcon::QUIRK_RUNNING); + arg.running_colored = icon->GetQuirk(AbstractLauncherIcon::QUIRK_URGENT); + arg.running_on_viewport = icon->WindowVisibleOnMonitor(monitor); arg.draw_edge_only = IconDrawEdgeOnly(icon); arg.active_colored = false; arg.x_rotation = 0.0f; @@ -1026,12 +897,12 @@ void Launcher::SetupRenderArg(LauncherIcon* icon, struct timespec const& current arg.progress_bias = IconProgressBias(icon, current); arg.progress = CLAMP(icon->GetProgress(), 0.0f, 1.0f); arg.draw_shortcut = _shortcuts_shown && !_hide_machine->GetQuirk(LauncherHideMachine::PLACES_VISIBLE); - arg.system_item = icon->Type() == LauncherIcon::TYPE_HOME; + arg.system_item = icon->Type() == AbstractLauncherIcon::TYPE_HOME; if (_dash_is_open) - arg.active_arrow = icon->Type() == LauncherIcon::TYPE_HOME; + arg.active_arrow = icon->Type() == AbstractLauncherIcon::TYPE_HOME; else - arg.active_arrow = icon->GetQuirk(LauncherIcon::QUIRK_ACTIVE); + arg.active_arrow = icon->GetQuirk(AbstractLauncherIcon::QUIRK_ACTIVE); guint64 shortcut = icon->GetShortcut(); if (shortcut > 32) @@ -1040,9 +911,9 @@ void Launcher::SetupRenderArg(LauncherIcon* icon, struct timespec const& current arg.shortcut_label = 0; // we dont need to show strays - if (!icon->GetQuirk(LauncherIcon::QUIRK_RUNNING)) + if (!icon->GetQuirk(AbstractLauncherIcon::QUIRK_RUNNING)) { - if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_URGENT)) { arg.running_arrow = true; arg.window_indicators = 1; @@ -1052,7 +923,7 @@ void Launcher::SetupRenderArg(LauncherIcon* icon, struct timespec const& current } else { - arg.window_indicators = icon->RelatedWindows(); + arg.window_indicators = std::max<int> (icon->WindowsForMonitor(monitor).size(), 1); } arg.backlight_intensity = IconBackgroundIntensity(icon, current); @@ -1060,31 +931,28 @@ void Launcher::SetupRenderArg(LauncherIcon* icon, struct timespec const& current float urgent_progress = IconUrgentProgress(icon, current); - if (icon->GetQuirk(LauncherIcon::QUIRK_URGENT)) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_URGENT)) 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(LauncherIcon::QUIRK_URGENT) && _urgent_animation == URGENT_ANIMATION_WIGGLE) + if (icon->GetQuirk(AbstractLauncherIcon::QUIRK_URGENT) && _urgent_animation == URGENT_ANIMATION_WIGGLE) { arg.z_rotation = IconUrgentWiggleValue(icon, current); } - // we've to walk the list since it is a STL-list and not a STL-vector, thus - // we can't use the random-access operator [] :( - LauncherModel::iterator it; - int i; - for (it = _model->begin(), i = 0; it != _model->end(); it++, ++i) - if (i == _current_icon_index && *it == icon) - { + if (IsInKeyNavMode()) + { + if (icon == _model->Selection()) arg.keyboard_nav_hl = true; - } + } } -void Launcher::FillRenderArg(LauncherIcon* icon, +void Launcher::FillRenderArg(AbstractLauncherIcon* icon, RenderArg& arg, nux::Point3& center, + nux::Geometry const& parent_abs_geo, float folding_threshold, float folded_size, float folded_spacing, @@ -1134,7 +1002,7 @@ void Launcher::FillRenderArg(LauncherIcon* icon, 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; - icon_hide_offset *= 1.0f - (present_progress * (_hide_machine->GetShowOnEdge() ? icon->PresentUrgency() : 0.0f)); + icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency()); // icon is crossing threshold, start folding center.z += folded_z_distance * folding_progress; @@ -1147,7 +1015,7 @@ void Launcher::FillRenderArg(LauncherIcon* icon, float center_transit_progress = IconCenterTransitionProgress(icon, current); if (center_transit_progress <= 1.0f) { - centerOffset.y = (icon->_saved_center.y - (center.y + (half_size * size_modifier))) * (1.0f - center_transit_progress); + centerOffset.y = (icon->GetSavedCenter(monitor).y - (center.y + (half_size * size_modifier))) * (1.0f - center_transit_progress); } center.y += half_size * size_modifier; // move to center @@ -1155,7 +1023,7 @@ void Launcher::FillRenderArg(LauncherIcon* 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))); + icon->SetCenter(nux::Point3(roundf(center.x), roundf(center.y), roundf(center.z)), monitor, parent_abs_geo); // FIXME: this is a hack, we should have a look why SetAnimationTarget is necessary in SetAnimationTarget // we should ideally just need it at start to set the target @@ -1175,7 +1043,7 @@ float Launcher::DragLimiter(float x) } void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, - nux::Geometry& box_geo, float* launcher_alpha) + nux::Geometry& box_geo, float* launcher_alpha, nux::Geometry const& parent_abs_geo) { nux::Geometry geo = GetGeometry(); LauncherModel::iterator it; @@ -1224,7 +1092,9 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, float autohide_progress = AutohideProgress(current) * (1.0f - DragOutProgress(current)); if (_autohide_animation == FADE_ONLY) + { *launcher_alpha = 1.0f - autohide_progress; + } else { if (autohide_progress > 0.0f) @@ -1312,9 +1182,9 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, for (it = _model->main_begin(); it != _model->main_end(); it++) { RenderArg arg; - LauncherIcon* icon = *it; + AbstractLauncherIcon* icon = *it; - FillRenderArg(icon, arg, center, folding_threshold, folded_size, folded_spacing, + FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing, autohide_offset, folded_z_distance, animation_neg_rads, current); launcher_args.push_back(arg); @@ -1340,9 +1210,9 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, for (it = _model->shelf_begin(); it != _model->shelf_end(); it++) { RenderArg arg; - LauncherIcon* icon = *it; + AbstractLauncherIcon* icon = *it; - FillRenderArg(icon, arg, center, folding_threshold, folded_size, folded_spacing, + FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing, autohide_offset, folded_z_distance, animation_neg_rads, current); launcher_args.push_back(arg); @@ -1351,100 +1221,15 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, /* End Render Layout Logic */ -gboolean Launcher::TapOnSuper() +void Launcher::ForceReveal(bool force_reveal) { - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - - return (unity::TimeUtil::TimeDelta(¤t, &_times[TIME_TAP_SUPER]) < SUPER_TAP_DURATION); + _hide_machine->SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, force_reveal); } -/* Launcher Show/Hide logic */ - -void Launcher::StartKeyShowLauncher() +void Launcher::ShowShortcuts(bool show) { - _hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false); - - SetTimeStruct(&_times[TIME_TAP_SUPER]); - SetTimeStruct(&_times[TIME_SUPER_PRESSED]); - - if (_super_show_launcher_handle > 0) - g_source_remove(_super_show_launcher_handle); - _super_show_launcher_handle = g_timeout_add(SUPER_TAP_DURATION, &Launcher::SuperShowLauncherTimeout, this); - - if (_super_show_shortcuts_handle > 0) - g_source_remove(_super_show_shortcuts_handle); - _super_show_shortcuts_handle = g_timeout_add(SHORTCUTS_SHOWN_DELAY, &Launcher::SuperShowShortcutsTimeout, this); - - ubus_server_send_message(ubus_server_get_default(), UBUS_DASH_ABOUT_TO_SHOW, NULL); - ubus_server_force_message_pump(ubus_server_get_default()); -} - -void Launcher::EndKeyShowLauncher() -{ - int remaining_time_before_hide; - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - - _hover_machine->SetQuirk(LauncherHoverMachine::SHORTCUT_KEYS_VISIBLE, false); - _shortcuts_shown = false; - QueueDraw(); - - // remove further show launcher (which can happen when we close the dash with super) - if (_super_show_launcher_handle > 0) - g_source_remove(_super_show_launcher_handle); - if (_super_show_shortcuts_handle > 0) - g_source_remove(_super_show_shortcuts_handle); - _super_show_launcher_handle = 0; - _super_show_shortcuts_handle = 0; - - // it's a tap on super and we didn't use any shortcuts - if (TapOnSuper() && !_latest_shortcut) - ubus_server_send_message(ubus_server_get_default(), - UBUS_PLACE_ENTRY_ACTIVATE_REQUEST, - g_variant_new("(sus)", "home.lens", 0, "")); - - remaining_time_before_hide = BEFORE_HIDE_LAUNCHER_ON_SUPER_DURATION - CLAMP((int)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_SUPER_PRESSED])), 0, BEFORE_HIDE_LAUNCHER_ON_SUPER_DURATION); - - if (_super_hide_launcher_handle > 0) - g_source_remove(_super_hide_launcher_handle); - _super_hide_launcher_handle = g_timeout_add(remaining_time_before_hide, &Launcher::SuperHideLauncherTimeout, this); -} - -gboolean Launcher::SuperHideLauncherTimeout(gpointer data) -{ - Launcher* self = (Launcher*) data; - - self->_hide_machine->SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, false); - - self->_super_hide_launcher_handle = 0; - return false; -} - -gboolean Launcher::SuperShowLauncherTimeout(gpointer data) -{ - Launcher* self = (Launcher*) data; - - self->_hide_machine->SetQuirk(LauncherHideMachine::TRIGGER_BUTTON_SHOW, true); - - self->_super_show_launcher_handle = 0; - return false; -} - -gboolean Launcher::SuperShowShortcutsTimeout(gpointer data) -{ - Launcher* self = (Launcher*) data; - - if (!self->_key_switcher_activated) - { - self->_shortcuts_shown = true; - self->_hover_machine->SetQuirk(LauncherHoverMachine::SHORTCUT_KEYS_VISIBLE, true); - - self->QueueDraw(); - } - - self->_super_show_shortcuts_handle = 0; - return false; + _shortcuts_shown = show; + _hover_machine->SetQuirk(LauncherHoverMachine::SHORTCUT_KEYS_VISIBLE, show); } void Launcher::OnBGColorChanged(GVariant *data) @@ -1461,15 +1246,13 @@ void Launcher::OnLockHideChanged(GVariant *data) gboolean enable_lock = FALSE; g_variant_get(data, "(b)", &enable_lock); - if (enable_lock) + if (enable_lock) { _hide_machine->SetQuirk(LauncherHideMachine::LOCK_HIDE, true); - _hide_machine->SetShowOnEdge(false); } else { _hide_machine->SetQuirk(LauncherHideMachine::LOCK_HIDE, false); - _hide_machine->SetShowOnEdge(true); } } @@ -1477,8 +1260,8 @@ void Launcher::DesaturateIcons() { for (auto icon : *_model) { - if (icon->Type () != LauncherIcon::TYPE_HOME) - icon->SetQuirk(LauncherIcon::QUIRK_DESAT, true); + if (icon->Type () != AbstractLauncherIcon::TYPE_HOME) + icon->SetQuirk(AbstractLauncherIcon::QUIRK_DESAT, true); icon->HideTooltip(); } } @@ -1487,12 +1270,15 @@ void Launcher::SaturateIcons() { for (auto icon : *_model) { - icon->SetQuirk(LauncherIcon::QUIRK_DESAT, false); + icon->SetQuirk(AbstractLauncherIcon::QUIRK_DESAT, false); } } void Launcher::OnPlaceViewShown(GVariant* data) { + if (g_variant_get_int32(data) != monitor) + return; + LauncherModel::iterator it; _dash_is_open = true; @@ -1505,6 +1291,9 @@ void Launcher::OnPlaceViewShown(GVariant* data) void Launcher::OnPlaceViewHidden(GVariant* data) { + if (!_dash_is_open) + return; + LauncherModel::iterator it; _dash_is_open = false; @@ -1536,10 +1325,7 @@ void Launcher::SetHidden(bool hidden) _hover_machine->SetQuirk(LauncherHoverMachine::LAUNCHER_HIDDEN, hidden); _hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false); - if (_hide_machine->GetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE)) - _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true); - else - _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, false); + _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, false); if (hidden) { _hide_machine->SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false); @@ -1549,7 +1335,7 @@ void Launcher::SetHidden(bool hidden) _postreveal_mousemove_delta_x = 0; _postreveal_mousemove_delta_y = 0; - SetTimeStruct(&_times[TIME_AUTOHIDE], &_times[TIME_AUTOHIDE], ANIM_DURATION_SHORT); + TimeUtil::SetTimeStruct(&_times[TIME_AUTOHIDE], &_times[TIME_AUTOHIDE], ANIM_DURATION_SHORT); _parent->EnableInputWindow(!hidden, "launcher", false, false); @@ -1562,13 +1348,13 @@ void Launcher::SetHidden(bool hidden) } int -Launcher::GetMouseX() +Launcher::GetMouseX() const { return _mouse_position.x; } int -Launcher::GetMouseY() +Launcher::GetMouseY() const { return _mouse_position.y; } @@ -1720,7 +1506,7 @@ Launcher::OnViewPortSwitchEnded() CheckWindowOverLauncher(); } -Launcher::LauncherHideMode Launcher::GetHideMode() +LauncherHideMode Launcher::GetHideMode() const { return _hidemode; } @@ -1739,6 +1525,40 @@ gboolean Launcher::StrutHack(gpointer data) return false; } +void +Launcher::OnOptionsChanged(Options::Ptr options) +{ + UpdateOptions(options); + + options->option_changed.connect(sigc::mem_fun(this, &Launcher::OnOptionChanged)); +} + +void +Launcher::OnOptionChanged() +{ + UpdateOptions(options()); +} + +void +Launcher::UpdateOptions(Options::Ptr options) +{ + SetHideMode(options->hide_mode); + SetAutoHideAnimation(options->auto_hide_animation); + SetFloating(options->floating); + SetBacklightMode(options->backlight_mode); + SetLaunchAnimation(options->launch_animation); + SetUrgentAnimation(options->urgent_animation); + SetIconSize(options->tile_size, options->icon_size); + decaymulator_->rate_of_decay = options->edge_decay_rate(); + + _pointer_barrier->threshold = options->edge_stop_velocity(); + _pointer_barrier->DestroyBarrier(); + _pointer_barrier->ConstructBarrier(); + + _hide_machine->reveal_pressure = options->edge_reveal_pressure(); + _hide_machine->edge_decay_rate = options->edge_decay_rate(); +} + void Launcher::SetHideMode(LauncherHideMode hidemode) { if (_hidemode == hidemode) @@ -1760,7 +1580,7 @@ void Launcher::SetHideMode(LauncherHideMode hidemode) EnsureAnimation(); } -Launcher::AutoHideAnimation Launcher::GetAutoHideAnimation() +AutoHideAnimation Launcher::GetAutoHideAnimation() const { return _autohide_animation; } @@ -1791,12 +1611,12 @@ void Launcher::SetBacklightMode(BacklightMode mode) EnsureAnimation(); } -Launcher::BacklightMode Launcher::GetBacklightMode() +BacklightMode Launcher::GetBacklightMode() const { return _backlight_mode; } -bool Launcher::IsBackLightModeToggles() +bool Launcher::IsBackLightModeToggles() const { switch (_backlight_mode) { case BACKLIGHT_NORMAL: @@ -1817,8 +1637,8 @@ Launcher::SetLaunchAnimation(LaunchAnimation animation) _launch_animation = animation; } -Launcher::LaunchAnimation -Launcher::GetLaunchAnimation() +LaunchAnimation +Launcher::GetLaunchAnimation() const { return _launch_animation; } @@ -1832,8 +1652,8 @@ Launcher::SetUrgentAnimation(UrgentAnimation animation) _urgent_animation = animation; } -Launcher::UrgentAnimation -Launcher::GetUrgentAnimation() +UrgentAnimation +Launcher::GetUrgentAnimation() const { return _urgent_animation; } @@ -1847,13 +1667,10 @@ Launcher::SetActionState(LauncherActionState actionstate) _launcher_action_state = actionstate; _hover_machine->SetQuirk(LauncherHoverMachine::LAUNCHER_IN_ACTION, (actionstate != ACTION_NONE)); - - if (_keynav_activated) - exitKeyNavMode(); } Launcher::LauncherActionState -Launcher::GetActionState() +Launcher::GetActionState() const { return _launcher_action_state; } @@ -1869,11 +1686,11 @@ void Launcher::SetHover(bool hovered) if (_hovered) { _enter_y = (int) _mouse_position.y; - SetTimeStruct(&_times[TIME_ENTER], &_times[TIME_LEAVE], ANIM_DURATION); + TimeUtil::SetTimeStruct(&_times[TIME_ENTER], &_times[TIME_LEAVE], ANIM_DURATION); } else { - SetTimeStruct(&_times[TIME_LEAVE], &_times[TIME_ENTER], ANIM_DURATION); + TimeUtil::SetTimeStruct(&_times[TIME_LEAVE], &_times[TIME_ENTER], ANIM_DURATION); } if (_dash_is_open && !_hide_machine->GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE)) @@ -1889,7 +1706,7 @@ void Launcher::SetHover(bool hovered) bool Launcher::MouseOverTopScrollArea() { - return _mouse_position.y < 24; + return _mouse_position.y < panel_height; } bool Launcher::MouseOverTopScrollExtrema() @@ -1899,7 +1716,7 @@ bool Launcher::MouseOverTopScrollExtrema() bool Launcher::MouseOverBottomScrollArea() { - return _mouse_position.y > GetGeometry().height - 24; + return _mouse_position.y > GetGeometry().height - panel_height; } bool Launcher::MouseOverBottomScrollExtrema() @@ -1912,7 +1729,7 @@ gboolean Launcher::OnScrollTimeout(gpointer data) Launcher* self = (Launcher*) data; nux::Geometry geo = self->GetGeometry(); - if (self->_keynav_activated || self->_key_switcher_activated || !self->_hovered || + if (self->IsInKeyNavMode() || !self->_hovered || self->GetActionState() == ACTION_DRAG_LAUNCHER) return TRUE; @@ -1952,16 +1769,36 @@ void Launcher::EnsureScrollTimer() void Launcher::SetIconSize(int tile_size, int icon_size) { - nux::Geometry geo = _parent->GetGeometry(); - _icon_size = tile_size; _icon_image_size = icon_size; _icon_image_size_delta = tile_size - icon_size; _icon_glow_size = icon_size + 14; - _parent->SetGeometry(nux::Geometry(geo.x, geo.y, tile_size + 12, geo.height)); - icon_renderer->SetTargetSize(_icon_size, _icon_image_size, _space_between_icons); + + Resize(); +} + +void Launcher::Resize() +{ + UScreen* uscreen = UScreen::GetDefault(); + auto geo = uscreen->GetMonitorGeometry(monitor()); + + nux::Geometry new_geometry(geo.x, geo.y + panel_height, _icon_size + 12, geo.height - panel_height); + SetMaximumHeight(new_geometry.height); + _parent->SetGeometry(new_geometry); + SetGeometry(new_geometry); + + _pointer_barrier->DestroyBarrier(); + + _pointer_barrier->x1 = new_geometry.x; + _pointer_barrier->x2 = new_geometry.x; + _pointer_barrier->y1 = new_geometry.y; + _pointer_barrier->y2 = new_geometry.y + new_geometry.height; + _pointer_barrier->threshold = options()->edge_stop_velocity(); + + _pointer_barrier->ConstructBarrier(); + } void Launcher::SetBackgroundAlpha(float background_alpha) @@ -1973,29 +1810,26 @@ void Launcher::SetBackgroundAlpha(float background_alpha) NeedRedraw(); } -void Launcher::OnIconAdded(LauncherIcon* icon) +void Launcher::OnIconAdded(AbstractLauncherIcon* icon) { EnsureAnimation(); - // needs to be disconnected - icon->needs_redraw_connection = icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw)); + icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw)); AddChild(icon); } -void Launcher::OnIconRemoved(LauncherIcon* icon) +void Launcher::OnIconRemoved(AbstractLauncherIcon* icon) { if (icon->needs_redraw_connection.connected()) icon->needs_redraw_connection.disconnect(); - if (icon == _current_icon) - _current_icon = 0; if (icon == _icon_under_mouse) - _icon_under_mouse = 0; + _icon_under_mouse = nullptr; if (icon == _icon_mouse_down) - _icon_mouse_down = 0; + _icon_mouse_down = nullptr; if (icon == _drag_icon) - _drag_icon = 0; + _drag_icon = nullptr; EnsureAnimation(); RemoveChild(icon); @@ -2010,22 +1844,47 @@ void Launcher::SetModel(LauncherModel* model) { _model = model; - if (_model->on_icon_added_connection.connected()) - _model->on_icon_added_connection.disconnect(); - _model->on_icon_added_connection = _model->icon_added.connect(sigc::mem_fun(this, &Launcher::OnIconAdded)); + _model->icon_added.connect(sigc::mem_fun(this, &Launcher::OnIconAdded)); + _model->icon_removed.connect(sigc::mem_fun(this, &Launcher::OnIconRemoved)); + _model->order_changed.connect(sigc::mem_fun(this, &Launcher::OnOrderChanged)); + _model->selection_changed.connect(sigc::mem_fun(this, &Launcher::OnSelectionChanged)); +} + +LauncherModel* Launcher::GetModel() const +{ + return _model; +} - if (_model->on_icon_removed_connection.connected()) - _model->on_icon_removed_connection.disconnect(); - _model->on_icon_removed_connection = _model->icon_removed.connect(sigc::mem_fun(this, &Launcher::OnIconRemoved)); +void Launcher::EnsureIconOnScreen(AbstractLauncherIcon* selection) +{ + nux::Point3 center = selection->GetCenter(monitor); + nux::Geometry geo = GetGeometry(); - if (_model->on_order_changed_connection.connected()) - _model->on_order_changed_connection.disconnect(); - _model->on_order_changed_connection = _model->order_changed.connect(sigc::mem_fun(this, &Launcher::OnOrderChanged)); + int natural_y = 0; + for (auto icon : *_model) + { + if (!icon->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE)) + continue; + + if (icon == selection) + break; + + natural_y += _icon_size + _space_between_icons; + } + + int max_drag_delta = geo.height - (natural_y + _icon_size + (2 * _space_between_icons)); + int min_drag_delta = -natural_y; + + _launcher_drag_delta = std::max<int>(min_drag_delta, std::min<int>(max_drag_delta, _launcher_drag_delta)); } -LauncherModel* Launcher::GetModel() +void Launcher::OnSelectionChanged(AbstractLauncherIcon* selection) { - return _model; + if (IsInKeyNavMode()) + { + EnsureIconOnScreen(selection); + EnsureAnimation(); + } } void Launcher::OnIconNeedsRedraw(AbstractLauncherIcon* icon) @@ -2038,11 +1897,10 @@ void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) } - - - void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) { + icon_renderer->monitor = monitor(); + nux::Geometry base = GetGeometry(); nux::Geometry bkg_box; std::list<RenderArg> args; @@ -2058,7 +1916,8 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) ROP.SrcBlend = GL_ONE; ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA; - RenderArgs(args, bkg_box, &launcher_alpha); + nux::Geometry geo_absolute = GetAbsoluteGeometry(); + RenderArgs(args, bkg_box, &launcher_alpha, geo_absolute); if (_drag_icon && _render_drag_window) { @@ -2085,8 +1944,6 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) { if (BackgroundEffectHelper::blur_type != unity::BLUR_NONE && (bkg_box.x + bkg_box.width > 0)) { - nux::Geometry geo_absolute = GetAbsoluteGeometry(); - nux::Geometry blur_geo(geo_absolute.x, geo_absolute.y, base.width, base.height); auto blur_texture = bg_effect_helper_.GetBlurRegion(blur_geo); @@ -2127,8 +1984,8 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) nux::TexCoordXForm texxform; texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); texxform.SetWrap(nux::TEXWRAP_CLAMP, nux::TEXWRAP_CLAMP); - texxform.uoffset = (1.0f / launcher_sheen_->GetWidth()) * (GetAbsoluteGeometry().x); // TODO (gord) don't use absolute values here - texxform.voffset = (1.0f / launcher_sheen_->GetHeight()) * (GetAbsoluteGeometry().y); + texxform.uoffset = (1.0f / launcher_sheen_->GetWidth()); // TODO (gord) don't use absolute values here + texxform.voffset = (1.0f / launcher_sheen_->GetHeight()) * panel_height; GfxContext.QRP_1Tex(base.x, base.y, base.width, base.height, launcher_sheen_->GetDeviceTexture(), texxform, @@ -2239,8 +2096,8 @@ gboolean Launcher::StartIconDragTimeout(gpointer data) { if (self->_icon_under_mouse) { - self->_icon_under_mouse->mouse_leave.emit(); - self->_icon_under_mouse = 0; + self->_icon_under_mouse->mouse_leave.emit(self->monitor); + self->_icon_under_mouse = nullptr; } self->_initial_drag_animation = true; self->StartIconDragRequest(self->GetMouseX(), self->GetMouseY()); @@ -2251,7 +2108,7 @@ gboolean Launcher::StartIconDragTimeout(gpointer data) void Launcher::StartIconDragRequest(int x, int y) { - LauncherIcon* drag_icon = MouseIconIntersection((int)(GetGeometry().x / 2.0f), y); + AbstractLauncherIcon* drag_icon = MouseIconIntersection((int)(GetGeometry().x / 2.0f), y); // FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying // on an internal Launcher property then @@ -2259,7 +2116,7 @@ void Launcher::StartIconDragRequest(int x, int y) { SetActionState(ACTION_DRAG_ICON); StartIconDrag(drag_icon); - UpdateDragWindowPosition(drag_icon->GetCenter().x, drag_icon->GetCenter().y); + UpdateDragWindowPosition(drag_icon->GetCenter(monitor).x, drag_icon->GetCenter(monitor).y); if (_initial_drag_animation) { _drag_window->SetAnimationTarget(x, y + _drag_window->GetGeometry().height / 2); @@ -2280,7 +2137,7 @@ void Launcher::StartIconDragRequest(int x, int y) } } -void Launcher::StartIconDrag(LauncherIcon* icon) +void Launcher::StartIconDrag(AbstractLauncherIcon* icon) { if (!icon) return; @@ -2309,11 +2166,11 @@ void Launcher::EndIconDrag() { if (_drag_window) { - LauncherIcon* hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); + AbstractLauncherIcon* hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); - if (hovered_icon && hovered_icon->Type() == LauncherIcon::TYPE_TRASH) + if (hovered_icon && hovered_icon->Type() == AbstractLauncherIcon::TYPE_TRASH) { - hovered_icon->SetQuirk(LauncherIcon::QUIRK_PULSE_ONCE, true); + hovered_icon->SetQuirk(AbstractLauncherIcon::QUIRK_PULSE_ONCE, true); launcher_removerequest.emit(_drag_icon); @@ -2324,7 +2181,7 @@ void Launcher::EndIconDrag() { _model->Save(); - _drag_window->SetAnimationTarget((int)(_drag_icon->GetCenter().x), (int)(_drag_icon->GetCenter().y)); + _drag_window->SetAnimationTarget((int)(_drag_icon->GetCenter(monitor).x), (int)(_drag_icon->GetCenter(monitor).y)); _drag_window->StartAnimation(); if (_drag_window->on_anim_completed.connected()) @@ -2334,7 +2191,7 @@ void Launcher::EndIconDrag() } if (MouseBeyondDragThreshold()) - SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT); + TimeUtil::SetTimeStruct(&_times[TIME_DRAG_THRESHOLD], &_times[TIME_DRAG_THRESHOLD], ANIM_DURATION_SHORT); _render_drag_window = false; @@ -2350,7 +2207,7 @@ void Launcher::UpdateDragWindowPosition(int x, int y) nux::Geometry geo = _drag_window->GetGeometry(); _drag_window->SetBaseXY(x - geo.width / 2 + _parent->GetGeometry().x, y - geo.height / 2 + _parent->GetGeometry().y); - LauncherIcon* hovered_icon = MouseIconIntersection((int)(GetGeometry().x / 2.0f), y); + AbstractLauncherIcon* hovered_icon = MouseIconIntersection((int)(GetGeometry().x / 2.0f), y); struct timespec current; clock_gettime(CLOCK_MONOTONIC, ¤t); @@ -2375,12 +2232,6 @@ void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned EnsureAnimation(); } -void Launcher::RecvMouseDownOutsideArea(int x, int y, unsigned long button_flags, unsigned long key_flags) -{ - if (_keynav_activated) - exitKeyNavMode(); -} - void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags) { SetMousePosition(x, y); @@ -2424,8 +2275,8 @@ void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_ if (_icon_under_mouse) { - _icon_under_mouse->mouse_leave.emit(); - _icon_under_mouse = 0; + _icon_under_mouse->mouse_leave.emit(monitor); + _icon_under_mouse = nullptr; } if (GetActionState() == ACTION_NONE) @@ -2461,10 +2312,6 @@ void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned SetMousePosition(x, y); SetStateMouseOverLauncher(true); - // make sure we actually get a chance to get events before turning this off - if (x > 0) - _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE, false); - EventLogic(); EnsureAnimation(); } @@ -2473,7 +2320,7 @@ void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned { SetMousePosition(x, y); SetStateMouseOverLauncher(false); - LauncherIcon::SetSkipTooltipDelay(false); + //AbstractLauncherIcon::SetSkipTooltipDelay(false); EventLogic(); EnsureAnimation(); @@ -2483,18 +2330,18 @@ void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_ { SetMousePosition(x, y); - // make sure we actually get a chance to get events before turning this off - if (x > 0) - _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE, false); + if (!_hidden) + { + _postreveal_mousemove_delta_x += dx; + _postreveal_mousemove_delta_y += dy; - _postreveal_mousemove_delta_x += dx; - _postreveal_mousemove_delta_y += dy; + // check the state before changing it to avoid uneeded hide calls + if (!_hide_machine->GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL) && + (nux::Abs(_postreveal_mousemove_delta_x) > MOUSE_DEADZONE || + nux::Abs(_postreveal_mousemove_delta_y) > MOUSE_DEADZONE)) + _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true); + } - // check the state before changing it to avoid uneeded hide calls - if (!_hide_machine->GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL) && - (nux::Abs(_postreveal_mousemove_delta_x) > MOUSE_DEADZONE || - nux::Abs(_postreveal_mousemove_delta_y) > MOUSE_DEADZONE)) - _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true); // Every time the mouse moves, we check if it is inside an icon... @@ -2520,316 +2367,53 @@ void Launcher::RecvMouseWheel(int x, int y, int wheel_delta, unsigned long butto EnsureAnimation(); } - -gboolean -Launcher::ResetRepeatShorcutTimeout(gpointer data) -{ - Launcher* self = (Launcher*) data; - - self->_latest_shortcut = 0; - - self->_ignore_repeat_shortcut_handle = 0; - return false; -} - -gboolean -Launcher::CheckSuperShortcutPressed(Display *x_display, - unsigned int key_sym, - unsigned long key_code, - unsigned long key_state, - char* key_string) +void Launcher::OnPointerBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event) { - LauncherModel::iterator it; - - // Shortcut to start launcher icons. Only relies on Keycode, ignore modifier - for (it = _model->begin(); it != _model->end(); it++) + nux::Geometry abs_geo = GetAbsoluteGeometry(); + if (_hidden && event->x >= abs_geo.x && event->x <= abs_geo.x + abs_geo.width) { - if ((XKeysymToKeycode(x_display, (*it)->GetShortcut()) == key_code) || - ((gchar)((*it)->GetShortcut()) == key_string[0])) - { - if (_latest_shortcut == (*it)->GetShortcut()) - return true; - - if (g_ascii_isdigit((gchar)(*it)->GetShortcut()) && (key_state & ShiftMask)) - (*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0)); - else - (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0)); - - SetLatestShortcut((*it)->GetShortcut()); - - // disable the "tap on super" check - _times[TIME_TAP_SUPER].tv_sec = 0; - _times[TIME_TAP_SUPER].tv_nsec = 0; - return true; - } + _hide_machine->AddRevealPressure(event->velocity); + decaymulator_->value = 0; } - - return false; -} - -void Launcher::SetLatestShortcut(guint64 shortcut) -{ - _latest_shortcut = shortcut; - /* - * start a timeout while repressing the same shortcut will be ignored. - * This is because the keypress repeat is handled by Xorg and we have no - * way to know if a press is an actual press or just an automated repetition - * because the button is hold down. (key release events are sent in both cases) - */ - if (_ignore_repeat_shortcut_handle > 0) - g_source_remove(_ignore_repeat_shortcut_handle); - _ignore_repeat_shortcut_handle = g_timeout_add(IGNORE_REPEAT_SHORTCUT_DURATION, &Launcher::ResetRepeatShorcutTimeout, this); -} - -void -Launcher::EdgeRevealTriggered(int mouse_x, int mouse_y) -{ - SetMousePosition(mouse_x, mouse_y - GetAbsoluteGeometry().y); - - _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_OVER_ACTIVE_EDGE, true); - _hide_machine->SetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL, true); -} - -void Launcher::SelectPreviousIcon() -{ - if (_current_icon_index > 0) + else { - LauncherModel::iterator it; - int temp_current_icon_index = _current_icon_index; - do + decaymulator_->value = decaymulator_->value + event->velocity; + if (decaymulator_->value > options()->edge_overcome_pressure) { - temp_current_icon_index --; - it = _model->at(temp_current_icon_index); - } - while (it != (LauncherModel::iterator)NULL && !(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE)); - - if (it != (LauncherModel::iterator)NULL) - { - _current_icon_index = temp_current_icon_index; - - if ((*it)->GetCenter().y - _icon_size / 2 < GetGeometry().y) - { - _launcher_drag_delta += (_icon_size + _space_between_icons); - } - else if ((*it)->GetCenter().y + _icon_size / 2 > GetGeometry().height) - { - _launcher_drag_delta -= (*it)->GetCenter().y + _icon_size/2 + - _space_between_icons - GetGeometry().height; - } + _pointer_barrier->ReleaseBarrier(event->event_id); } - - EnsureAnimation(); - selection_change.emit(); } } -void Launcher::SelectNextIcon() +bool Launcher::IsInKeyNavMode() const { - if (_current_icon_index < _model->Size() - 1) - { - LauncherModel::iterator it; - int temp_current_icon_index = _current_icon_index; - - do - { - temp_current_icon_index ++; - it = _model->at(temp_current_icon_index); - } - while (it != (LauncherModel::iterator)nullptr && - !(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE)); - - if (it != (LauncherModel::iterator)nullptr) - { - _current_icon_index = temp_current_icon_index; - - if ((*it)->GetCenter().y + _icon_size / 2 > GetGeometry().height) - { - _launcher_drag_delta -= (_icon_size + _space_between_icons); - } - else if ((*it)->GetCenter().y - _icon_size / 2 < GetGeometry().y) - { - _launcher_drag_delta += GetGeometry().y - ((*it)->GetCenter().y - _icon_size); - } - } - - EnsureAnimation(); - selection_change.emit(); - } + return _hide_machine->GetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE); } -void Launcher::KeySwitcherActivate() +void Launcher::EnterKeyNavMode() { - if (_key_switcher_activated) - return; - _hide_machine->SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, true); _hover_machine->SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, true); - - _key_switcher_activated = true; - - ubus_server_send_message(ubus_server_get_default(), - UBUS_LAUNCHER_START_KEY_SWTICHER, - g_variant_new_boolean(true)); - - KeySwitcherNext(); } -void Launcher::KeySwitcherTerminate() +void Launcher::ExitKeyNavMode() { - if (!_key_switcher_activated) - return; - - LauncherModel::iterator it = _model->at(_current_icon_index); - - if (it != (LauncherModel::iterator)NULL) - (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0)); - _hide_machine->SetQuirk(LauncherHideMachine::KEY_NAV_ACTIVE, false); _hover_machine->SetQuirk(LauncherHoverMachine::KEY_NAV_ACTIVE, false); - - ubus_server_send_message(ubus_server_get_default(), - UBUS_LAUNCHER_END_KEY_SWTICHER, - g_variant_new_boolean(true)); - - _key_switcher_activated = false; - _current_icon_index = -1; - _last_icon_index = -1; - QueueDraw(); - - selection_change.emit(); -} - -void Launcher::KeySwitcherCancel() -{ - if (!_key_switcher_activated) - return; - - _current_icon_index = -1; - KeySwitcherTerminate(); -} - -bool Launcher::KeySwitcherIsActive() -{ - return _key_switcher_activated; } -void Launcher::KeySwitcherNext() -{ - if (!_key_switcher_activated) - return; - - if (_current_icon_index == _model->Size() - 1) - { - _current_icon_index = -1; - } - - SelectNextIcon(); -} - -void Launcher::KeySwitcherPrevious() +void Launcher::RecvQuicklistOpened(QuicklistView* quicklist) { - if (!_key_switcher_activated) - return; - - if (_current_icon_index == 0) + UScreen* uscreen = UScreen::GetDefault(); + if (uscreen->GetMonitorGeometry(monitor).IsInside(nux::Point(quicklist->GetGeometry().x, quicklist->GetGeometry().y))) { - _current_icon_index = _model->Size(); - } - - SelectPreviousIcon(); -} - -void -Launcher::RecvKeyPressed(unsigned long eventType, - unsigned long key_sym, - unsigned long key_state, - const char* character, - unsigned short keyCount) -{ - - LauncherModel::iterator it; - - /* - * all key events below are related to keynavigation. Make an additional - * check that we are in a keynav mode when we inadvertadly receive the focus - */ - if (!_keynav_activated) - return; - - switch (key_sym) - { - // up (move selection up or go to global-menu if at top-most icon) - case NUX_VK_UP: - case NUX_KP_UP: - SelectPreviousIcon(); - break; - - // down (move selection down and unfold launcher if needed) - case NUX_VK_DOWN: - case NUX_KP_DOWN: - SelectNextIcon(); - break; - - // esc/left (close quicklist or exit laucher key-focus) - case NUX_VK_LEFT: - case NUX_KP_LEFT: - case NUX_VK_ESCAPE: - // hide again - exitKeyNavMode(); - break; - - // right/shift-f10 (open quicklist of currently selected icon) - case XK_F10: - if (!(key_state & nux::NUX_STATE_SHIFT)) - break; - case NUX_VK_RIGHT: - case NUX_KP_RIGHT: - case XK_Menu: - // open quicklist of currently selected icon - it = _model->at(_current_icon_index); - if (it != (LauncherModel::iterator)NULL) - { - if ((*it)->OpenQuicklist(true)) - leaveKeyNavMode(false); - } - break; - - // <SPACE> (open a new instance) - case NUX_VK_SPACE: - // start currently selected icon - it = _model->at(_current_icon_index); - if (it != (LauncherModel::iterator)NULL) - { - (*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0)); - } - exitKeyNavMode(); - break; - - // <RETURN> (start/activate currently selected icon) - case NUX_VK_ENTER: - case NUX_KP_ENTER: - { - // start currently selected icon - it = _model->at(_current_icon_index); - if (it != (LauncherModel::iterator)NULL) - (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0)); - } - exitKeyNavMode(); - break; - - default: - break; + _hide_machine->SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, true); + _hover_machine->SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, true); + EventLogic(); + EnsureAnimation(); } } -void Launcher::RecvQuicklistOpened(QuicklistView* quicklist) -{ - _hide_machine->SetQuirk(LauncherHideMachine::QUICKLIST_OPEN, true); - _hover_machine->SetQuirk(LauncherHoverMachine::QUICKLIST_OPEN, true); - EventLogic(); - EnsureAnimation(); -} - void Launcher::RecvQuicklistClosed(QuicklistView* quicklist) { nux::Point pt = nux::GetWindowCompositor().GetMousePosition(); @@ -2855,10 +2439,9 @@ void Launcher::EventLogic() GetActionState() == ACTION_DRAG_LAUNCHER) return; - LauncherIcon* launcher_icon = 0; + AbstractLauncherIcon* launcher_icon = nullptr; - if (_hide_machine->GetQuirk(LauncherHideMachine::MOUSE_OVER_LAUNCHER) - && _hide_machine->GetQuirk(LauncherHideMachine::MOUSE_MOVE_POST_REVEAL)) + if (!_hidden && !IsInKeyNavMode() && _hovered) { launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); } @@ -2866,13 +2449,13 @@ void Launcher::EventLogic() if (_icon_under_mouse && (_icon_under_mouse != launcher_icon)) { - _icon_under_mouse->mouse_leave.emit(); - _icon_under_mouse = 0; + _icon_under_mouse->mouse_leave.emit(monitor); + _icon_under_mouse = nullptr; } if (launcher_icon && (_icon_under_mouse != launcher_icon)) { - launcher_icon->mouse_enter.emit(); + launcher_icon->mouse_enter.emit(monitor); _icon_under_mouse = launcher_icon; _hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false); @@ -2881,7 +2464,7 @@ void Launcher::EventLogic() void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags) { - LauncherIcon* launcher_icon = 0; + AbstractLauncherIcon* launcher_icon = nullptr; launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); _hide_machine->SetQuirk(LauncherHideMachine::LAST_ACTION_ACTIVATE, false); @@ -2894,15 +2477,13 @@ void Launcher::MouseDownLogic(int x, int y, unsigned long button_flags, unsigned g_source_remove(_start_dragicon_handle); _start_dragicon_handle = g_timeout_add(START_DRAGICON_DURATION, &Launcher::StartIconDragTimeout, this); - launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags)); + launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags), monitor); } - - KeySwitcherCancel(); } void Launcher::MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags) { - LauncherIcon* launcher_icon = 0; + AbstractLauncherIcon* launcher_icon = nullptr; launcher_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); @@ -2912,28 +2493,28 @@ void Launcher::MouseUpLogic(int x, int y, unsigned long button_flags, unsigned l if (_icon_mouse_down && (_icon_mouse_down == launcher_icon)) { - _icon_mouse_down->mouse_up.emit(nux::GetEventButton(button_flags)); + _icon_mouse_down->mouse_up.emit(nux::GetEventButton(button_flags), monitor); if (GetActionState() == ACTION_NONE) { - _icon_mouse_down->mouse_click.emit(nux::GetEventButton(button_flags)); + _icon_mouse_down->mouse_click.emit(nux::GetEventButton(button_flags), monitor); } } if (launcher_icon && (_icon_mouse_down != launcher_icon)) { - launcher_icon->mouse_up.emit(nux::GetEventButton(button_flags)); + launcher_icon->mouse_up.emit(nux::GetEventButton(button_flags), monitor); } if (GetActionState() == ACTION_DRAG_LAUNCHER) { - SetTimeStruct(&_times[TIME_DRAG_END]); + TimeUtil::SetTimeStruct(&_times[TIME_DRAG_END]); } - _icon_mouse_down = 0; + _icon_mouse_down = nullptr; } -LauncherIcon* Launcher::MouseIconIntersection(int x, int y) +AbstractLauncherIcon* Launcher::MouseIconIntersection(int x, int y) { LauncherModel::iterator it; // We are looking for the icon at screen coordinates x, y; @@ -2942,13 +2523,13 @@ LauncherIcon* Launcher::MouseIconIntersection(int x, int y) for (it = _model->begin(); it != _model->end(); it++) { - if (!(*it)->GetQuirk(LauncherIcon::QUIRK_VISIBLE)) + if (!(*it)->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE)) continue; nux::Point2 screen_coord [4]; for (int i = 0; i < 4; ++i) { - auto hit_transform = (*it)->GetTransform(AbstractLauncherIcon::TRANSFORM_HIT_AREA); + auto hit_transform = (*it)->GetTransform(AbstractLauncherIcon::TRANSFORM_HIT_AREA, monitor); screen_coord [i].x = hit_transform [i].x; screen_coord [i].y = hit_transform [i].y; } @@ -2961,7 +2542,7 @@ LauncherIcon* Launcher::MouseIconIntersection(int x, int y) } void -Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, LauncherIcon* icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture) +Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLauncherIcon* icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture) { RenderArg arg; struct timespec current; @@ -2992,14 +2573,17 @@ Launcher::SetOffscreenRenderTarget(nux::ObjectPtr<nux::IOpenGLBaseTexture> textu int width = texture->GetWidth(); int height = texture->GetHeight(); - nux::GetGraphicsDisplay()->GetGpuDevice()->FormatFrameBufferObject(width, height, nux::BITFMT_R8G8B8A8); - nux::GetGraphicsDisplay()->GetGpuDevice()->SetColorRenderTargetSurface(0, texture->GetSurfaceLevel(0)); - nux::GetGraphicsDisplay()->GetGpuDevice()->ActivateFrameBuffer(); + auto graphics_display = nux::GetGraphicsDisplay(); + auto gpu_device = graphics_display->GetGpuDevice(); + gpu_device->FormatFrameBufferObject(width, height, nux::BITFMT_R8G8B8A8); + gpu_device->SetColorRenderTargetSurface(0, texture->GetSurfaceLevel(0)); + gpu_device->ActivateFrameBuffer(); - nux::GetGraphicsDisplay()->GetGraphicsEngine()->SetContext(0, 0, width, height); - nux::GetGraphicsDisplay()->GetGraphicsEngine()->SetViewport(0, 0, width, height); - nux::GetGraphicsDisplay()->GetGraphicsEngine()->Push2DWindow(width, height); - nux::GetGraphicsDisplay()->GetGraphicsEngine()->EmptyClippingRegion(); + auto graphics_engine = graphics_display->GetGraphicsEngine(); + graphics_engine->SetContext(0, 0, width, height); + graphics_engine->SetViewport(0, 0, width, height); + graphics_engine->Push2DWindow(width, height); + graphics_engine->EmptyClippingRegion(); } void @@ -3045,9 +2629,9 @@ void Launcher::OnDNDDataCollected(const std::list<char*>& mimes) for (auto it : *_model) { if (it->QueryAcceptDrop(_dnd_data) != nux::DNDACTION_NONE) - it->SetQuirk(LauncherIcon::QUIRK_DROP_PRELIGHT, true); + it->SetQuirk(AbstractLauncherIcon::QUIRK_DROP_PRELIGHT, true); else - it->SetQuirk(LauncherIcon::QUIRK_DROP_DIM, true); + it->SetQuirk(AbstractLauncherIcon::QUIRK_DROP_DIM, true); } } } @@ -3062,7 +2646,7 @@ Launcher::ProcessDndEnter() _steal_drag = false; _data_checked = false; _drag_edge_touching = false; - _dnd_hovered_icon = 0; + _dnd_hovered_icon = nullptr; } void @@ -3072,8 +2656,8 @@ Launcher::DndReset() for (auto it : *_model) { - it->SetQuirk(LauncherIcon::QUIRK_DROP_PRELIGHT, false); - it->SetQuirk(LauncherIcon::QUIRK_DROP_DIM, false); + it->SetQuirk(AbstractLauncherIcon::QUIRK_DROP_PRELIGHT, false); + it->SetQuirk(AbstractLauncherIcon::QUIRK_DROP_DIM, false); } DndHoveredIconReset(); @@ -3086,18 +2670,18 @@ void Launcher::DndHoveredIconReset() if (_steal_drag && _dnd_hovered_icon) { - _dnd_hovered_icon->SetQuirk(LauncherIcon::QUIRK_VISIBLE, false); + _dnd_hovered_icon->SetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE, false); _dnd_hovered_icon->remove.emit(_dnd_hovered_icon); } if (!_steal_drag && _dnd_hovered_icon) { _dnd_hovered_icon->SendDndLeave(); - _dnd_hovered_icon = 0; + _dnd_hovered_icon = nullptr; } _steal_drag = false; - _dnd_hovered_icon = 0; + _dnd_hovered_icon = nullptr; } void @@ -3148,9 +2732,9 @@ Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) for (auto it : *_model) { if (it->QueryAcceptDrop(_dnd_data) != nux::DNDACTION_NONE) - it->SetQuirk(LauncherIcon::QUIRK_DROP_PRELIGHT, true); + it->SetQuirk(AbstractLauncherIcon::QUIRK_DROP_PRELIGHT, true); else - it->SetQuirk(LauncherIcon::QUIRK_DROP_DIM, true); + it->SetQuirk(AbstractLauncherIcon::QUIRK_DROP_DIM, true); } } } @@ -3163,26 +2747,26 @@ Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) _dnd_hovered_icon->SendDndLeave(); _drag_edge_touching = true; - SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3); + TimeUtil::SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3); EnsureAnimation(); } else if (_mouse_position.x != 0 && _drag_edge_touching) { _drag_edge_touching = false; - SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3); + TimeUtil::SetTimeStruct(&_times[TIME_DRAG_EDGE_TOUCH], &_times[TIME_DRAG_EDGE_TOUCH], ANIM_DURATION * 3); EnsureAnimation(); } EventLogic(); - LauncherIcon* hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); + AbstractLauncherIcon* hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y); bool hovered_icon_is_appropriate = false; if (hovered_icon) { - if (hovered_icon->Type() == LauncherIcon::TYPE_TRASH) + if (hovered_icon->Type() == AbstractLauncherIcon::TYPE_TRASH) _steal_drag = false; - if (hovered_icon->Type() == LauncherIcon::TYPE_APPLICATION || hovered_icon->Type() == LauncherIcon::TYPE_EXPO) + if (hovered_icon->Type() == AbstractLauncherIcon::TYPE_APPLICATION || hovered_icon->Type() == AbstractLauncherIcon::TYPE_EXPO) hovered_icon_is_appropriate = true; } @@ -3191,7 +2775,7 @@ Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) _drag_action = nux::DNDACTION_COPY; if (!_dnd_hovered_icon && hovered_icon_is_appropriate) { - _dnd_hovered_icon = new SpacerLauncherIcon(this); + _dnd_hovered_icon = new SpacerLauncherIcon(); _dnd_hovered_icon->SetSortPriority(G_MAXINT); _model->AddIcon(_dnd_hovered_icon); _model->ReorderBefore(_dnd_hovered_icon, hovered_icon, true); @@ -3206,9 +2790,9 @@ Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes) } else { - _dnd_hovered_icon->SetQuirk(LauncherIcon::QUIRK_VISIBLE, false); + _dnd_hovered_icon->SetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE, false); _dnd_hovered_icon->remove.emit(_dnd_hovered_icon); - _dnd_hovered_icon = 0; + _dnd_hovered_icon = nullptr; } } } @@ -3252,7 +2836,7 @@ Launcher::ProcessDndDrop(int x, int y) { if (g_str_has_suffix(it.c_str(), ".desktop")) { - char* path = 0; + char* path = nullptr; if (g_str_has_prefix(it.c_str(), "application://")) { @@ -3291,20 +2875,12 @@ Launcher::ProcessDndDrop(int x, int y) * Returns the current selected icon if it is in keynavmode * It will return NULL if it is not on keynavmode */ -LauncherIcon* -Launcher::GetSelectedMenuIcon() +AbstractLauncherIcon* +Launcher::GetSelectedMenuIcon() const { - LauncherModel::iterator it; - - if (_current_icon_index == -1) - return NULL; - - it = _model->at(_current_icon_index); - - if (it != (LauncherModel::iterator)NULL) - return *it; - else + if (!IsInKeyNavMode()) return NULL; + return _model->Selection(); } /* dbus handlers */ diff --git a/plugins/unityshell/src/Launcher.h b/plugins/unityshell/src/Launcher.h index 6cec077ef..28f716e49 100644 --- a/plugins/unityshell/src/Launcher.h +++ b/plugins/unityshell/src/Launcher.h @@ -28,12 +28,14 @@ #include <Nux/TimerProc.h> #include <NuxGraphics/IOpenGLAsmShader.h> +#include "PointerBarrier.h" #include "AbstractIconRenderer.h" #include "BackgroundEffectHelper.h" #include "DNDCollectionWindow.h" #include "DndData.h" #include "GeisAdapter.h" #include "Introspectable.h" +#include "LauncherOptions.h" #include "LauncherDragWindow.h" #include "LauncherHideMachine.h" #include "LauncherHoverMachine.h" @@ -44,128 +46,81 @@ #define ANIM_DURATION 200 #define ANIM_DURATION_LONG 350 -#define SUPER_TAP_DURATION 250 -#define SHORTCUTS_SHOWN_DELAY 750 -#define START_DRAGICON_DURATION 250 -#define BEFORE_HIDE_LAUNCHER_ON_SUPER_DURATION 1000 - -#define IGNORE_REPEAT_SHORTCUT_DURATION 250 - #define MAX_SUPERKEY_LABELS 10 +#define START_DRAGICON_DURATION 250 + class QuicklistView; namespace unity { namespace launcher { -class LauncherIcon; +class AbstractLauncherIcon; class LauncherModel; class Launcher : public unity::debug::Introspectable, public nux::View { NUX_DECLARE_OBJECT_TYPE(Launcher, nux::View); public: - typedef enum - { - LAUNCHER_HIDE_NEVER, - LAUNCHER_HIDE_AUTOHIDE, - LAUNCHER_HIDE_DODGE_WINDOWS, - LAUNCHER_HIDE_DODGE_ACTIVE_WINDOW, - } LauncherHideMode; - - typedef enum - { - LAUNCH_ANIMATION_NONE, - LAUNCH_ANIMATION_PULSE, - LAUNCH_ANIMATION_BLINK, - } LaunchAnimation; - - typedef enum - { - URGENT_ANIMATION_NONE, - URGENT_ANIMATION_PULSE, - URGENT_ANIMATION_WIGGLE, - } UrgentAnimation; - - typedef enum - { - FADE_OR_SLIDE, - SLIDE_ONLY, - FADE_ONLY, - FADE_AND_SLIDE, - } AutoHideAnimation; - - typedef enum - { - BACKLIGHT_ALWAYS_ON, - BACKLIGHT_NORMAL, - BACKLIGHT_ALWAYS_OFF, - BACKLIGHT_EDGE_TOGGLE, - BACKLIGHT_NORMAL_EDGE_TOGGLE - } BacklightMode; Launcher(nux::BaseWindow* parent, NUX_FILE_LINE_PROTO); ~Launcher(); nux::Property<Display*> display; + nux::Property<int> monitor; + nux::Property<Options::Ptr> options; virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw); virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw); virtual void PostDraw(nux::GraphicsEngine& GfxContext, bool force_draw); - LauncherIcon* GetSelectedMenuIcon(); + AbstractLauncherIcon* GetSelectedMenuIcon() const; void SetIconSize(int tile_size, int icon_size); void SetBackgroundAlpha(float background_alpha); LauncherHideMachine* HideMachine() { return _hide_machine; } - bool Hidden() + bool Hidden() const { return _hidden; } - bool ShowOnEdge() - { - return _hide_machine->GetShowOnEdge(); - } + + void ForceReveal(bool force); + void ShowShortcuts(bool show); void SetModel(LauncherModel* model); - LauncherModel* GetModel(); + LauncherModel* GetModel() const; void SetFloating(bool floating); void SetHideMode(LauncherHideMode hidemode); - LauncherHideMode GetHideMode(); + LauncherHideMode GetHideMode() const; void StartKeyShowLauncher(); void EndKeyShowLauncher(); + void EnsureIconOnScreen(AbstractLauncherIcon* icon); + void SetBacklightMode(BacklightMode mode); - BacklightMode GetBacklightMode(); - bool IsBackLightModeToggles(); + BacklightMode GetBacklightMode() const; + bool IsBackLightModeToggles() const; void SetLaunchAnimation(LaunchAnimation animation); - LaunchAnimation GetLaunchAnimation(); + LaunchAnimation GetLaunchAnimation() const; void SetUrgentAnimation(UrgentAnimation animation); - UrgentAnimation GetUrgentAnimation(); + UrgentAnimation GetUrgentAnimation() const; void SetAutoHideAnimation(AutoHideAnimation animation); - AutoHideAnimation GetAutoHideAnimation(); + AutoHideAnimation GetAutoHideAnimation() const; - void EdgeRevealTriggered(int x, int y); - - gboolean CheckSuperShortcutPressed(Display *x_display, unsigned int key_sym, unsigned long key_code, unsigned long key_state, char* key_string); - void SetLatestShortcut(guint64 shortcut); - - nux::BaseWindow* GetParent() + nux::BaseWindow* GetParent() const { return _parent; }; - static void SetTimeStruct(struct timespec* timer, struct timespec* sister = 0, int sister_relation = 0); - virtual void RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags); virtual void RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags); virtual void RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags); @@ -173,48 +128,31 @@ public: virtual void RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags); virtual void RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags); virtual void RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags); - virtual void RecvMouseDownOutsideArea(int x, int y, unsigned long button_flags, unsigned long key_flags); - - virtual void RecvKeyPressed(unsigned long eventType , /*event type*/ - unsigned long keysym , /*event keysym*/ - unsigned long state , /*event state*/ - const char* character , /*character*/ - unsigned short keyCount /*key repeat count*/); virtual void RecvQuicklistOpened(QuicklistView* quicklist); virtual void RecvQuicklistClosed(QuicklistView* quicklist); - void startKeyNavMode(); - void leaveKeyNavMode(bool preserve_focus = true); + int GetMouseX() const; + int GetMouseY() const; - void exitKeyNavMode(); // Connected to signal OnEndFocus - - int GetMouseX(); - int GetMouseY(); + void Resize(); void CheckWindowOverLauncher(); void EnableCheckWindowOverLauncher(gboolean enabled); - sigc::signal<void, char*, LauncherIcon*> launcher_addrequest; - sigc::signal<void, char*, LauncherIcon*, char*, char*> launcher_addrequest_special; - sigc::signal<void, LauncherIcon*> launcher_removerequest; + sigc::signal<void, char*, AbstractLauncherIcon*> launcher_addrequest; + sigc::signal<void, char*, AbstractLauncherIcon*, char*, char*> launcher_addrequest_special; + sigc::signal<void, AbstractLauncherIcon*> launcher_removerequest; sigc::signal<void> selection_change; sigc::signal<void> hidden_changed; - // Key navigation virtual bool InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character); - void SelectPreviousIcon(); - void SelectNextIcon(); - - void KeySwitcherActivate(); - void KeySwitcherTerminate(); - void KeySwitcherCancel(); - bool KeySwitcherIsActive(); - void KeySwitcherNext(); - void KeySwitcherPrevious(); + void EnterKeyNavMode(); + void ExitKeyNavMode(); + bool IsInKeyNavMode() const; protected: // Introspectable methods @@ -251,6 +189,10 @@ private: TIME_LAST } LauncherActionTimes; + void OnOptionsChanged(Options::Ptr options); + void OnOptionChanged(); + void UpdateOptions(Options::Ptr options); + void OnWindowMaybeIntellihide(guint32 xid); void OnWindowMaybeIntellihideDelayed(guint32 xid); static gboolean CheckWindowOverLauncherSync(Launcher* self); @@ -261,35 +203,33 @@ private: void OnDragUpdate(GeisAdapter::GeisDragData* data); void OnDragFinish(GeisAdapter::GeisDragData* data); + void OnPointerBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event); + void OnPluginStateChanged(); + void OnSelectionChanged(AbstractLauncherIcon* selection); + void OnViewPortSwitchStarted(); void OnViewPortSwitchEnded(); static gboolean AnimationTimeout(gpointer data); - static gboolean SuperShowLauncherTimeout(gpointer data); - static gboolean SuperHideLauncherTimeout(gpointer data); - static gboolean SuperShowShortcutsTimeout(gpointer data); static gboolean StrutHack(gpointer data); - static gboolean MoveFocusToKeyNavModeTimeout(gpointer data); static gboolean StartIconDragTimeout(gpointer data); - static gboolean ResetRepeatShorcutTimeout(gpointer data); void SetMousePosition(int x, int y); void SetStateMouseOverLauncher(bool over_launcher); - void SetStateKeyNav(bool keynav_activated); - bool MouseBeyondDragThreshold(); + bool MouseBeyondDragThreshold() const; void OnDragWindowAnimCompleted(); - bool IconNeedsAnimation(LauncherIcon* icon, struct timespec const& current); - bool IconDrawEdgeOnly(LauncherIcon* icon); - bool AnimationInProgress(); + bool IconNeedsAnimation(AbstractLauncherIcon* icon, struct timespec const& current) const; + bool IconDrawEdgeOnly(AbstractLauncherIcon* icon) const; + bool AnimationInProgress() const; void SetActionState(LauncherActionState actionstate); - LauncherActionState GetActionState(); + LauncherActionState GetActionState() const; void EnsureAnimation(); void EnsureScrollTimer(); @@ -303,26 +243,27 @@ private: static gboolean OnScrollTimeout(gpointer data); static gboolean OnUpdateDragManagerTimeout(gpointer data); - float DnDStartProgress(struct timespec const& current); - float DnDExitProgress(struct timespec const& current); - float GetHoverProgress(struct timespec const& current); - float AutohideProgress(struct timespec const& current); - float DragThresholdProgress(struct timespec const& current); - float DragHideProgress(struct timespec const& current); - float DragOutProgress(struct timespec const& current); - float IconDesatValue(LauncherIcon* icon, struct timespec const& current); - float IconPresentProgress(LauncherIcon* icon, struct timespec const& current); - float IconUrgentProgress(LauncherIcon* icon, struct timespec const& current); - float IconShimmerProgress(LauncherIcon* icon, struct timespec const& current); - float IconUrgentPulseValue(LauncherIcon* icon, struct timespec const& current); - float IconPulseOnceValue(LauncherIcon *icon, struct timespec const ¤t); - float IconUrgentWiggleValue(LauncherIcon* icon, struct timespec const& current); - float IconStartingBlinkValue(LauncherIcon* icon, struct timespec const& current); - float IconStartingPulseValue(LauncherIcon* icon, struct timespec const& current); - float IconBackgroundIntensity(LauncherIcon* icon, struct timespec const& current); - float IconProgressBias(LauncherIcon* icon, struct timespec const& current); - float IconDropDimValue(LauncherIcon* icon, struct timespec const& current); - float IconCenterTransitionProgress(LauncherIcon* icon, struct timespec const& current); + float DnDStartProgress(struct timespec const& current) const; + float DnDExitProgress(struct timespec const& current) const; + float GetHoverProgress(struct timespec const& current) const; + float AutohideProgress(struct timespec const& current) const; + float DragThresholdProgress(struct timespec const& current) const; + float DragHideProgress(struct timespec const& current) const; + float DragOutProgress(struct timespec const& current) const; + float IconDesatValue(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconPresentProgress(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconUrgentProgress(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconShimmerProgress(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconUrgentPulseValue(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconPulseOnceValue(AbstractLauncherIcon *icon, struct timespec const ¤t) const; + float IconUrgentWiggleValue(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconStartingBlinkValue(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconStartingPulseValue(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconBackgroundIntensity(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconProgressBias(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconDropDimValue(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconCenterTransitionProgress(AbstractLauncherIcon* icon, struct timespec const& current) const; + float IconVisibleProgress(AbstractLauncherIcon* icon, struct timespec const& current) const; void SetHover(bool hovered); void SetHidden(bool hidden); @@ -330,10 +271,11 @@ private: void SetDndDelta(float x, float y, nux::Geometry const& geo, timespec const& current); float DragLimiter(float x); - void SetupRenderArg(LauncherIcon* icon, struct timespec const& current, ui::RenderArg& arg); - void FillRenderArg(LauncherIcon* icon, + void SetupRenderArg(AbstractLauncherIcon* icon, struct timespec const& current, ui::RenderArg& arg); + void FillRenderArg(AbstractLauncherIcon* icon, ui::RenderArg& arg, nux::Point3& center, + nux::Geometry const& parent_abs_geo, float folding_threshold, float folded_size, float folded_spacing, @@ -343,10 +285,10 @@ private: struct timespec const& current); void RenderArgs(std::list<ui::RenderArg> &launcher_args, - nux::Geometry& box_geo, float* launcher_alpha); + nux::Geometry& box_geo, float* launcher_alpha, nux::Geometry const& parent_abs_geo); - void OnIconAdded(LauncherIcon* icon); - void OnIconRemoved(LauncherIcon* icon); + void OnIconAdded(AbstractLauncherIcon* icon); + void OnIconRemoved(AbstractLauncherIcon* icon); void OnOrderChanged(); void OnIconNeedsRedraw(AbstractLauncherIcon* icon); @@ -363,20 +305,20 @@ private: void OnActionDone(GVariant* data); - void RenderIconToTexture(nux::GraphicsEngine& GfxContext, LauncherIcon* icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture); + void RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLauncherIcon* icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture); - LauncherIcon* MouseIconIntersection(int x, int y); + AbstractLauncherIcon* MouseIconIntersection(int x, int y); void EventLogic(); void MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags); void MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags); void StartIconDragRequest(int x, int y); - void StartIconDrag(LauncherIcon* icon); + void StartIconDrag(AbstractLauncherIcon* icon); void EndIconDrag(); void UpdateDragWindowPosition(int x, int y); - float GetAutohidePositionMin(); - float GetAutohidePositionMax(); + float GetAutohidePositionMin() const; + float GetAutohidePositionMax() const; virtual void PreLayoutManagement(); virtual long PostLayoutManagement(long LayoutResult); @@ -385,8 +327,6 @@ private: void SetOffscreenRenderTarget(nux::ObjectPtr<nux::IOpenGLBaseTexture> texture); void RestoreSystemRenderTarget(); - gboolean TapOnSuper(); - void OnDisplayChanged(Display* display); void OnDNDDataCollected(const std::list<char*>& mimes); @@ -394,17 +334,11 @@ private: void DndHoveredIconReset(); nux::HLayout* m_Layout; - int m_ContentOffsetY; // used by keyboard/a11y-navigation - LauncherIcon* _current_icon; - LauncherIcon* m_ActiveTooltipIcon; - LauncherIcon* _icon_under_mouse; - LauncherIcon* _icon_mouse_down; - LauncherIcon* _drag_icon; - - int _current_icon_index; - int _last_icon_index; + AbstractLauncherIcon* _icon_under_mouse; + AbstractLauncherIcon* _icon_mouse_down; + AbstractLauncherIcon* _drag_icon; QuicklistView* _active_quicklist; @@ -415,9 +349,6 @@ private: bool _check_window_over_launcher; bool _shortcuts_shown; - bool _keynav_activated; - bool _key_switcher_activated; - guint64 _latest_shortcut; BacklightMode _backlight_mode; @@ -436,6 +367,9 @@ private: nux::ObjectPtr<nux::IOpenGLBaseTexture> _offscreen_drag_texture; + ui::PointerBarrierWrapper::Ptr _pointer_barrier; + ui::Decaymulator::Ptr decaymulator_; + int _space_between_icons; int _icon_size; int _icon_image_size; @@ -452,21 +386,11 @@ private: float _drag_out_delta_x; float _background_alpha; - int _bfb_width; - int _bfb_height; - guint _autoscroll_handle; - guint _focus_keynav_handle; - guint _super_show_launcher_handle; - guint _super_hide_launcher_handle; - guint _super_show_shortcuts_handle; guint _start_dragicon_handle; guint _dnd_check_handle; - guint _ignore_repeat_shortcut_handle; nux::Point2 _mouse_position; - nux::Point2 _bfb_mouse_position; - nux::AbstractPaintLayer* m_BackgroundLayer; nux::BaseWindow* _parent; LauncherModel* _model; LauncherDragWindow* _drag_window; @@ -478,7 +402,7 @@ private: bool _data_checked; bool _steal_drag; bool _drag_edge_touching; - LauncherIcon* _dnd_hovered_icon; + AbstractLauncherIcon* _dnd_hovered_icon; unity::DNDCollectionWindow* _collection_window; sigc::connection _on_data_collected_connection; diff --git a/plugins/unityshell/src/LauncherController.cpp b/plugins/unityshell/src/LauncherController.cpp index a06ab3042..51f192d86 100644 --- a/plugins/unityshell/src/LauncherController.cpp +++ b/plugins/unityshell/src/LauncherController.cpp @@ -20,14 +20,13 @@ #include <glib/gi18n-lib.h> #include <libbamf/libbamf.h> -/* Compiz */ -#include <core/core.h> #include <Nux/Nux.h> #include <Nux/HLayout.h> #include <Nux/BaseWindow.h> #include <NuxCore/Logger.h> +#include "LauncherOptions.h" #include "BamfLauncherIcon.h" #include "DesktopLauncherIcon.h" #include "DeviceLauncherIcon.h" @@ -37,12 +36,16 @@ #include "LauncherController.h" #include "LauncherEntryRemote.h" #include "LauncherEntryRemoteModel.h" -#include "LauncherIcon.h" +#include "AbstractLauncherIcon.h" #include "SoftwareCenterLauncherIcon.h" #include "LauncherModel.h" #include "WindowManager.h" #include "TrashLauncherIcon.h" #include "BFBLauncherIcon.h" +#include "UScreen.h" +#include "UBusWrapper.h" +#include "UBusMessages.h" +#include "TimeUtil.h" namespace unity { @@ -53,27 +56,47 @@ namespace nux::logging::Logger logger("unity.launcher"); } +namespace local +{ +namespace +{ + const int super_tap_duration = 250; + const int launcher_minimum_show_duration = 1250; + const int shortcuts_show_delay = 750; + const int ignore_repeat_shortcut_duration = 250; +} +} + +// FIXME: key-code defines for Up/Down/Left/Right of numeric keypad - needs to +// be moved to the correct place in NuxGraphics-headers +#define NUX_KP_DOWN 0xFF99 +#define NUX_KP_UP 0xFF97 +#define NUX_KP_LEFT 0xFF96 +#define NUX_KP_RIGHT 0xFF98 + class Controller::Impl { public: - Impl(Display* display); + Impl(Display* display, Controller* parent); ~Impl(); void UpdateNumWorkspaces(int workspaces); + Launcher* CreateLauncher(int monitor); + void Save(); void SortAndUpdate(); - void OnIconAdded(LauncherIcon* icon); - void OnIconRemoved(LauncherIcon* icon); + void OnIconAdded(AbstractLauncherIcon* icon); + void OnIconRemoved(AbstractLauncherIcon* icon); - void OnLauncherAddRequest(char* path, LauncherIcon* before); - void OnLauncherAddRequestSpecial(char* path, LauncherIcon* before, char* aptdaemon_trans_id, char* icon_path); - void OnLauncherRemoveRequest(LauncherIcon* icon); + void OnLauncherAddRequest(char* path, AbstractLauncherIcon* before); + void OnLauncherAddRequestSpecial(char* path, AbstractLauncherIcon* before, char* aptdaemon_trans_id, char* icon_path); + void OnLauncherRemoveRequest(AbstractLauncherIcon* icon); void OnLauncherEntryRemoteAdded(LauncherEntryRemote* entry); void OnLauncherEntryRemoteRemoved(LauncherEntryRemote* entry); - + void OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before); void OnFavoriteStoreFavoriteRemoved(std::string const& entry); void OnFavoriteStoreReordered(); @@ -85,11 +108,19 @@ public: void InsertDesktopIcon(); void RemoveDesktopIcon(); + bool TapTimeUnderLimit(); + + void SendHomeActivationRequest(); + + int TimeSinceLauncherKeyPress(); + + int MonitorWithMouse(); + void InsertTrash(); - void RegisterIcon(LauncherIcon* icon); + void RegisterIcon(AbstractLauncherIcon* icon); - LauncherIcon* CreateFavorite(const char* file_path); + AbstractLauncherIcon* CreateFavorite(const char* file_path); SoftwareCenterLauncherIcon* CreateSCLauncherIcon(const char* file_path, const char* aptdaemon_trans_id, char* icon_path); @@ -97,14 +128,25 @@ public: void OnExpoActivated(); + void OnScreenChanged(int primary_monitor, std::vector<nux::Geometry>& monitors); + + void ReceiveMouseDownOutsideArea(int x, int y, unsigned long button_flags, unsigned long key_flags); + + void ReceiveLauncherKeyPress(unsigned long eventType, + unsigned long keysym, + unsigned long state, + const char* character, + unsigned short keyCount); + /* statics */ static void OnViewOpened(BamfMatcher* matcher, BamfView* view, gpointer data); + Controller* parent_; glib::Object<BamfMatcher> matcher_; LauncherModel::Ptr model_; - nux::ObjectPtr<nux::BaseWindow> launcher_window_; nux::ObjectPtr<Launcher> launcher_; + nux::ObjectPtr<Launcher> keyboard_launcher_; int sort_priority_; DeviceLauncherSection* device_section_; LauncherEntryRemoteModel remote_model_; @@ -113,53 +155,59 @@ public: nux::ObjectPtr<AbstractLauncherIcon> desktop_icon_; int num_workspaces_; bool show_desktop_icon_; + Display* display_; + + guint bamf_timer_handler_id_; + guint on_view_opened_id_; + guint launcher_key_press_handler_id_; + guint launcher_label_show_handler_id_; + guint launcher_hide_handler_id_; + + bool launcher_open; + bool launcher_keynav; + bool launcher_grabbed; + bool reactivate_keynav; + int reactivate_index; + + UBusManager ubus; - guint bamf_timer_handler_id_; + struct timespec launcher_key_press_time_; - guint32 on_view_opened_id_; + LauncherList launchers; sigc::connection on_expoicon_activate_connection_; + sigc::connection launcher_key_press_connection_; + sigc::connection launcher_event_outside_connection_; }; -Controller::Impl::Impl(Display* display) - : matcher_(nullptr) +Controller::Impl::Impl(Display* display, Controller* parent) + : parent_(parent) + , matcher_(nullptr) , model_(new LauncherModel()) , sort_priority_(0) , show_desktop_icon_(false) + , display_(display) { - // NOTE: should the launcher itself hold the base window? - // seems like it probably should... - launcher_window_ = new nux::BaseWindow(TEXT("LauncherWindow")); + UScreen* uscreen = UScreen::GetDefault(); + auto monitors = uscreen->GetMonitors(); - Launcher* raw_launcher = new Launcher(launcher_window_.GetPointer()); - launcher_ = raw_launcher; - launcher_->display = display; - launcher_->SetIconSize(54, 48); - launcher_->SetBacklightMode(Launcher::BACKLIGHT_ALWAYS_ON); - launcher_->SetHideMode(Launcher::LAUNCHER_HIDE_DODGE_WINDOWS); - launcher_->SetLaunchAnimation(Launcher::LAUNCH_ANIMATION_PULSE); - launcher_->SetUrgentAnimation(Launcher::URGENT_ANIMATION_WIGGLE); + launcher_open = false; + launcher_keynav = false; + launcher_grabbed = false; + reactivate_keynav = false; - nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION); - layout->AddView(raw_launcher, 1); - layout->SetContentDistribution(nux::eStackLeft); - layout->SetVerticalExternalMargin(0); - layout->SetHorizontalExternalMargin(0); - - launcher_window_->SetLayout(layout); - launcher_window_->SetBackgroundColor(nux::color::Transparent); - launcher_window_->ShowWindow(true); - launcher_window_->EnableInputWindow(true, "launcher", false, false); - launcher_window_->InputWindowEnableStruts(false); - launcher_window_->SetEnterFocusInputArea(raw_launcher); + int i = 0; + for (auto monitor : monitors) + { + Launcher* launcher = CreateLauncher(i); + launchers.push_back(nux::ObjectPtr<Launcher> (launcher)); + i++; + } - launcher_->SetModel(model_.get()); - launcher_->launcher_addrequest.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest)); - launcher_->launcher_addrequest_special.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequestSpecial)); - launcher_->launcher_removerequest.connect(sigc::mem_fun(this, &Impl::OnLauncherRemoveRequest)); + launcher_ = launchers[0]; - device_section_ = new DeviceLauncherSection(raw_launcher); + device_section_ = new DeviceLauncherSection(); device_section_->IconAdded.connect(sigc::mem_fun(this, &Impl::OnIconAdded)); num_workspaces_ = WindowManager::Default()->WorkspaceCount(); @@ -184,13 +232,23 @@ Controller::Impl::Impl(Display* display) remote_model_.entry_added.connect(sigc::mem_fun(this, &Impl::OnLauncherEntryRemoteAdded)); remote_model_.entry_removed.connect(sigc::mem_fun(this, &Impl::OnLauncherEntryRemoteRemoved)); - + FavoriteStore::GetDefault().favorite_added.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteAdded)); FavoriteStore::GetDefault().favorite_removed.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteRemoved)); FavoriteStore::GetDefault().reordered.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreReordered)); - RegisterIcon(new BFBLauncherIcon(raw_launcher)); - desktop_icon_ = new DesktopLauncherIcon(raw_launcher); + RegisterIcon(new BFBLauncherIcon()); + desktop_icon_ = new DesktopLauncherIcon(); + + uscreen->changed.connect(sigc::mem_fun(this, &Controller::Impl::OnScreenChanged)); + + launcher_key_press_time_ = { 0, 0 }; + + ubus.RegisterInterest(UBUS_QUICKLIST_END_KEY_NAV, [&](GVariant * args) { + if (reactivate_keynav) + parent_->KeyNavGrab(); + model_->SetSelection(reactivate_index); + }); } Controller::Impl::~Impl() @@ -204,8 +262,53 @@ Controller::Impl::~Impl() delete device_section_; } +void Controller::Impl::OnScreenChanged(int primary_monitor, std::vector<nux::Geometry>& monitors) +{ + unsigned int num_monitors = monitors.size(); + + for (unsigned int i = 0; i < num_monitors; i++) + { + if (i >= launchers.size()) + launchers.push_back(nux::ObjectPtr<Launcher> (CreateLauncher(i))); + + launchers[i]->Resize(); + } + + launchers.resize(num_monitors); +} + +Launcher* Controller::Impl::CreateLauncher(int monitor) +{ + nux::BaseWindow* launcher_window = new nux::BaseWindow(TEXT("LauncherWindow")); + + Launcher* launcher = new Launcher(launcher_window); + launcher->display = display_; + launcher->monitor = monitor; + launcher->options = parent_->options(); + + nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION); + layout->AddView(launcher, 1); + layout->SetContentDistribution(nux::eStackLeft); + layout->SetVerticalExternalMargin(0); + layout->SetHorizontalExternalMargin(0); + + launcher_window->SetLayout(layout); + launcher_window->SetBackgroundColor(nux::color::Transparent); + launcher_window->ShowWindow(true); + launcher_window->EnableInputWindow(true, "launcher", false, false); + launcher_window->InputWindowEnableStruts(false); + launcher_window->SetEnterFocusInputArea(launcher); + + launcher->SetModel(model_.get()); + launcher->launcher_addrequest.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest)); + launcher->launcher_removerequest.connect(sigc::mem_fun(this, &Impl::OnLauncherRemoveRequest)); + + parent_->AddChild(launcher); + + return launcher; +} -void Controller::Impl::OnLauncherAddRequest(char* path, LauncherIcon* before) +void Controller::Impl::OnLauncherAddRequest(char* path, AbstractLauncherIcon* before) { for (auto it : model_->GetSublist<BamfLauncherIcon> ()) { @@ -218,7 +321,7 @@ void Controller::Impl::OnLauncherAddRequest(char* path, LauncherIcon* before) } } - LauncherIcon* result = CreateFavorite(path); + AbstractLauncherIcon* result = CreateFavorite(path); if (result) { RegisterIcon(result); @@ -250,7 +353,7 @@ void Controller::Impl::Save() } void -Controller::Impl::OnLauncherAddRequestSpecial(char* path, LauncherIcon* before, char* aptdaemon_trans_id, char* icon_path) +Controller::Impl::OnLauncherAddRequestSpecial(char* path, AbstractLauncherIcon* before, char* aptdaemon_trans_id, char* icon_path) { std::list<BamfLauncherIcon*> launchers; std::list<BamfLauncherIcon*>::iterator it; @@ -281,7 +384,7 @@ void Controller::Impl::SortAndUpdate() std::list<BamfLauncherIcon*> launchers = model_->GetSublist<BamfLauncherIcon> (); for (auto it : launchers) { - if (shortcut < 11 && it->GetQuirk(LauncherIcon::QUIRK_VISIBLE)) + if (shortcut < 11 && it->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE)) { buff = g_strdup_printf("%d", shortcut % 10); it->SetShortcut(buff[0]); @@ -296,21 +399,21 @@ void Controller::Impl::SortAndUpdate() } } -void Controller::Impl::OnIconAdded(LauncherIcon* icon) +void Controller::Impl::OnIconAdded(AbstractLauncherIcon* icon) { this->RegisterIcon(icon); } -void Controller::Impl::OnIconRemoved(LauncherIcon* icon) +void Controller::Impl::OnIconRemoved(AbstractLauncherIcon* icon) { SortAndUpdate(); } -void Controller::Impl::OnLauncherRemoveRequest(LauncherIcon* icon) +void Controller::Impl::OnLauncherRemoveRequest(AbstractLauncherIcon* icon) { switch (icon->Type()) { - case LauncherIcon::TYPE_APPLICATION: + case AbstractLauncherIcon::TYPE_APPLICATION: { BamfLauncherIcon* bamf_icon = dynamic_cast<BamfLauncherIcon*>(icon); @@ -322,7 +425,7 @@ void Controller::Impl::OnLauncherRemoveRequest(LauncherIcon* icon) break; } - case LauncherIcon::TYPE_DEVICE: + case AbstractLauncherIcon::TYPE_DEVICE: { DeviceLauncherIcon* device_icon = dynamic_cast<DeviceLauncherIcon*>(icon); @@ -359,19 +462,19 @@ void Controller::Impl::OnLauncherEntryRemoteRemoved(LauncherEntryRemote* entry) } void Controller::Impl::OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before) -{ - auto bamf_list = model_->GetSublist<BamfLauncherIcon>(); - LauncherIcon* other = (bamf_list.size() > 0) ? *(bamf_list.begin()) : nullptr; - +{ + auto bamf_list = model_->GetSublist<BamfLauncherIcon>(); + AbstractLauncherIcon* other = (bamf_list.size() > 0) ? *(bamf_list.begin()) : nullptr; + if (!pos.empty()) { for (auto it : bamf_list) { - if (it->GetQuirk(LauncherIcon::QUIRK_VISIBLE) && pos == it->DesktopFile()) + if (it->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE) && pos == it->DesktopFile()) other = it; } } - + for (auto it : bamf_list) { if (entry == it->DesktopFile()) @@ -385,7 +488,7 @@ void Controller::Impl::OnFavoriteStoreFavoriteAdded(std::string const& entry, st } } - LauncherIcon* result = CreateFavorite(entry.c_str()); + AbstractLauncherIcon* result = CreateFavorite(entry.c_str()); if (result) { RegisterIcon(result); @@ -409,28 +512,28 @@ void Controller::Impl::OnFavoriteStoreFavoriteRemoved(std::string const& entry) } void Controller::Impl::OnFavoriteStoreReordered() -{ +{ FavoriteList const& favs = FavoriteStore::GetDefault().GetFavorites(); auto bamf_list = model_->GetSublist<BamfLauncherIcon>(); - + int i = 0; for (auto it : favs) - { + { auto icon = std::find_if(bamf_list.begin(), bamf_list.end(), [&it](BamfLauncherIcon* x) { return (x->DesktopFile() == it); }); - + if (icon != bamf_list.end()) { (*icon)->SetSortPriority(i++); } } - + for (auto it : bamf_list) { if (!it->IsSticky()) it->SetSortPriority(i++); } - + model_->Sort(); } @@ -442,7 +545,7 @@ void Controller::Impl::OnExpoActivated() void Controller::Impl::InsertTrash() { TrashLauncherIcon* icon; - icon = new TrashLauncherIcon(launcher_.GetPointer()); + icon = new TrashLauncherIcon(); RegisterIcon(icon); } @@ -462,13 +565,13 @@ void Controller::Impl::UpdateNumWorkspaces(int workspaces) void Controller::Impl::InsertExpoAction() { - expo_icon_ = new SimpleLauncherIcon(launcher_.GetPointer()); + expo_icon_ = new SimpleLauncherIcon(); expo_icon_->tooltip_text = _("Workspace Switcher"); expo_icon_->icon_name = "workspace-switcher"; - expo_icon_->SetQuirk(LauncherIcon::QUIRK_VISIBLE, true); - expo_icon_->SetQuirk(LauncherIcon::QUIRK_RUNNING, false); - expo_icon_->SetIconType(LauncherIcon::TYPE_EXPO); + expo_icon_->SetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE, true); + expo_icon_->SetQuirk(AbstractLauncherIcon::QUIRK_RUNNING, false); + expo_icon_->SetIconType(AbstractLauncherIcon::TYPE_EXPO); expo_icon_->SetShortcut('s'); on_expoicon_activate_connection_ = expo_icon_->activate.connect(sigc::mem_fun(this, &Impl::OnExpoActivated)); @@ -485,8 +588,8 @@ void Controller::Impl::RemoveExpoAction() void Controller::Impl::InsertDesktopIcon() { - desktop_launcher_icon_ = new DesktopLauncherIcon(launcher_.GetPointer()); - desktop_launcher_icon_->SetIconType(LauncherIcon::TYPE_DESKTOP); + desktop_launcher_icon_ = new DesktopLauncherIcon(); + desktop_launcher_icon_->SetIconType(AbstractLauncherIcon::TYPE_DESKTOP); desktop_launcher_icon_->SetShowInSwitcher(false); RegisterIcon(desktop_launcher_icon_); @@ -497,7 +600,7 @@ void Controller::Impl::RemoveDesktopIcon() model_->RemoveIcon(desktop_launcher_icon_); } -void Controller::Impl::RegisterIcon(LauncherIcon* icon) +void Controller::Impl::RegisterIcon(AbstractLauncherIcon* icon) { model_->AddIcon(icon); @@ -531,14 +634,14 @@ void Controller::Impl::OnViewOpened(BamfMatcher* matcher, BamfView* view, gpoint return; } - BamfLauncherIcon* icon = new BamfLauncherIcon(self->launcher_.GetPointer(), app); - icon->SetIconType(LauncherIcon::TYPE_APPLICATION); + BamfLauncherIcon* icon = new BamfLauncherIcon(app); + icon->SetIconType(AbstractLauncherIcon::TYPE_APPLICATION); icon->SetSortPriority(self->sort_priority_++); self->RegisterIcon(icon); } -LauncherIcon* Controller::Impl::CreateFavorite(const char* file_path) +AbstractLauncherIcon* Controller::Impl::CreateFavorite(const char* file_path) { BamfApplication* app; BamfLauncherIcon* icon; @@ -556,8 +659,8 @@ LauncherIcon* Controller::Impl::CreateFavorite(const char* file_path) g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(1)); bamf_view_set_sticky(BAMF_VIEW(app), true); - icon = new BamfLauncherIcon(launcher_.GetPointer(), app); - icon->SetIconType(LauncherIcon::TYPE_APPLICATION); + icon = new BamfLauncherIcon(app); + icon->SetIconType(AbstractLauncherIcon::TYPE_APPLICATION); icon->SetSortPriority(sort_priority_++); return icon; @@ -582,7 +685,7 @@ Controller::Impl::CreateSCLauncherIcon(const char* file_path, const char* aptdae g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(1)); bamf_view_set_sticky(BAMF_VIEW(app), true); - icon = new SoftwareCenterLauncherIcon(launcher_.GetPointer(), app, (char*)aptdaemon_trans_id, icon_path); + icon = new SoftwareCenterLauncherIcon(app, (char*)aptdaemon_trans_id, icon_path); icon->SetIconType(LauncherIcon::TYPE_APPLICATION); icon->SetSortPriority(sort_priority_++); @@ -606,7 +709,7 @@ void Controller::Impl::SetupBamf() for (FavoriteList::const_iterator i = favs.begin(), end = favs.end(); i != end; ++i) { - LauncherIcon* fav = CreateFavorite(i->c_str()); + AbstractLauncherIcon* fav = CreateFavorite(i->c_str()); if (fav) { @@ -627,7 +730,7 @@ void Controller::Impl::SetupBamf() continue; g_object_set_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen"), GINT_TO_POINTER(1)); - icon = new BamfLauncherIcon(launcher_.GetPointer(), app); + icon = new BamfLauncherIcon(app); icon->SetSortPriority(sort_priority_++); RegisterIcon(icon); } @@ -639,10 +742,42 @@ void Controller::Impl::SetupBamf() bamf_timer_handler_id_ = 0; } +int Controller::Impl::TimeSinceLauncherKeyPress() +{ + struct timespec current; + unity::TimeUtil::SetTimeStruct(¤t); + return unity::TimeUtil::TimeDelta(¤t, &launcher_key_press_time_); +} + +bool Controller::Impl::TapTimeUnderLimit() +{ + int time_difference = TimeSinceLauncherKeyPress(); + return time_difference < local::super_tap_duration; +} + +void Controller::Impl::SendHomeActivationRequest() +{ + ubus.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST, g_variant_new("(sus)", "home.lens", 0, "")); +} Controller::Controller(Display* display) - : pimpl(new Impl(display)) { + options = Options::Ptr(new Options()); + + // defaults must match XML file + options()->tile_size = 54; + options()->icon_size = 48; + options()->backlight_mode = BACKLIGHT_ALWAYS_ON; + options()->hide_mode = LAUNCHER_HIDE_DODGE_WINDOWS; + options()->launch_animation = LAUNCH_ANIMATION_PULSE; + options()->urgent_animation = URGENT_ANIMATION_WIGGLE; + options()->edge_decay_rate = 7500; + options()->edge_overcome_pressure = 7500; + options()->edge_stop_velocity = 10000; + options()->edge_reveal_pressure = 8000; + + // options must be set before creating pimpl which loads launchers + pimpl = new Impl(display, this); } Controller::~Controller() @@ -655,12 +790,17 @@ void Controller::UpdateNumWorkspaces(int workspaces) pimpl->UpdateNumWorkspaces(workspaces); } -Launcher& Controller::launcher() +Launcher& Controller::launcher() const { return *(pimpl->launcher_); } -std::vector<char> Controller::GetAllShortcuts() +Controller::LauncherList& Controller::launchers() const +{ + return pimpl->launchers; +} + +std::vector<char> Controller::GetAllShortcuts() const { std::vector<char> shortcuts; for (auto icon : *(pimpl->model_)) @@ -673,50 +813,34 @@ std::vector<char> Controller::GetAllShortcuts() return shortcuts; } -std::vector<AbstractLauncherIcon*> Controller::GetAltTabIcons() +std::vector<AbstractLauncherIcon*> Controller::GetAltTabIcons(bool current) const { std::vector<AbstractLauncherIcon*> results; results.push_back(pimpl->desktop_icon_.GetPointer()); for (auto icon : *(pimpl->model_)) - if (icon->ShowInSwitcher()) + if (icon->ShowInSwitcher(current)) results.push_back(icon); return results; } -void Controller::PrimaryMonitorGeometryChanged(nux::Geometry const& rect) +Window Controller::LauncherWindowId(int launcher) const { - const int panel_height = 24; - - int launcher_width = pimpl->launcher_window_->GetGeometry().width; - - nux::Geometry new_geometry(rect.x, - rect.y + panel_height, - launcher_width, - rect.height - panel_height); - - LOG_DEBUG(logger) << "Setting to launcher rect:" - << " x=" << new_geometry.x - << " y=" << new_geometry.y - << " w=" << new_geometry.width - << " h=" << new_geometry.height; - - pimpl->launcher_->SetMaximumHeight(new_geometry.height); - - pimpl->launcher_window_->SetGeometry(new_geometry); - pimpl->launcher_->SetGeometry(new_geometry); + return pimpl->launchers[launcher]->GetParent()->GetInputWindowId(); } -Window Controller::launcher_input_window_id() +Window Controller::KeyNavLauncherInputWindowId() const { - return pimpl->launcher_window_->GetInputWindowId(); + if (KeyNavIsActive()) + return pimpl->keyboard_launcher_->GetParent()->GetInputWindowId(); + return 0; } void Controller::PushToFront() { - pimpl->launcher_window_->PushToFront(); + pimpl->launcher_->GetParent()->PushToFront(); } void Controller::SetShowDesktopIcon(bool show_desktop_icon) @@ -732,6 +856,298 @@ void Controller::SetShowDesktopIcon(bool show_desktop_icon) pimpl->RemoveDesktopIcon(); } +int Controller::Impl::MonitorWithMouse() +{ + UScreen* uscreen = UScreen::GetDefault(); + return uscreen->GetMonitorWithMouse(); +} + +void Controller::HandleLauncherKeyPress() +{ + unity::TimeUtil::SetTimeStruct(&pimpl->launcher_key_press_time_); + + auto show_launcher = [](gpointer user_data) -> gboolean + { + Impl* self = static_cast<Impl*>(user_data); + if (self->keyboard_launcher_.IsNull()) + self->keyboard_launcher_ = self->launchers[self->MonitorWithMouse()]; + + if (self->launcher_hide_handler_id_ > 0) + { + g_source_remove(self->launcher_hide_handler_id_); + self->launcher_hide_handler_id_ = 0; + } + + self->keyboard_launcher_->ForceReveal(true); + self->launcher_open = true; + self->launcher_key_press_handler_id_ = 0; + return FALSE; + }; + pimpl->launcher_key_press_handler_id_ = g_timeout_add(local::super_tap_duration, show_launcher, pimpl); + + auto show_shortcuts = [](gpointer user_data) -> gboolean + { + Impl* self = static_cast<Impl*>(user_data); + if (!self->launcher_keynav) + { + if (self->keyboard_launcher_.IsNull()) + self->keyboard_launcher_ = self->launchers[self->MonitorWithMouse()]; + + self->keyboard_launcher_->ShowShortcuts(true); + self->launcher_open = true; + self->launcher_label_show_handler_id_ = 0; + } + return FALSE; + }; + pimpl->launcher_label_show_handler_id_ = g_timeout_add(local::shortcuts_show_delay, show_shortcuts, pimpl); +} + +void Controller::HandleLauncherKeyRelease() +{ + if (pimpl->TapTimeUnderLimit()) + { + pimpl->SendHomeActivationRequest(); + } + + if (pimpl->launcher_label_show_handler_id_) + { + g_source_remove(pimpl->launcher_label_show_handler_id_); + pimpl->launcher_label_show_handler_id_ = 0; + } + + if (pimpl->launcher_key_press_handler_id_) + { + g_source_remove(pimpl->launcher_key_press_handler_id_); + pimpl->launcher_key_press_handler_id_ = 0; + } + + if (pimpl->keyboard_launcher_.IsValid()) + { + pimpl->keyboard_launcher_->ShowShortcuts(false); + + int ms_since_show = pimpl->TimeSinceLauncherKeyPress(); + if (ms_since_show > local::launcher_minimum_show_duration) + { + pimpl->keyboard_launcher_->ForceReveal(false); + pimpl->launcher_open = false; + + if (!pimpl->launcher_keynav) + pimpl->keyboard_launcher_.Release(); + } + else + { + int time_left = local::launcher_minimum_show_duration - ms_since_show; + auto hide_launcher = [](gpointer user_data) -> gboolean + { + Impl *self = static_cast<Impl*>(user_data); + if (self->keyboard_launcher_.IsValid()) + { + self->keyboard_launcher_->ForceReveal(false); + self->launcher_open = false; + + if (!self->launcher_keynav) + self->keyboard_launcher_.Release(); + } + + self->launcher_hide_handler_id_ = 0; + return FALSE; + }; + + pimpl->launcher_hide_handler_id_ = g_timeout_add(time_left, hide_launcher, pimpl); + } + } +} + +bool Controller::HandleLauncherKeyEvent(Display *display, unsigned int key_sym, unsigned long key_code, unsigned long key_state, char* key_string) +{ + LauncherModel::iterator it; + + // Shortcut to start launcher icons. Only relies on Keycode, ignore modifier + for (it = pimpl->model_->begin(); it != pimpl->model_->end(); it++) + { + if ((XKeysymToKeycode(display, (*it)->GetShortcut()) == key_code) || + ((gchar)((*it)->GetShortcut()) == key_string[0])) + { + 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 (g_ascii_isdigit((gchar)(*it)->GetShortcut()) && (key_state & ShiftMask)) + (*it)->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0)); + else + (*it)->Activate(ActionArg(ActionArg::LAUNCHER, 0)); + } + + // disable the "tap on super" check + pimpl->launcher_key_press_time_ = { 0, 0 }; + return true; + } + } + + return false; +} + +void Controller::Impl::ReceiveMouseDownOutsideArea(int x, int y, unsigned long button_flags, unsigned long key_flags) +{ + if (launcher_grabbed) + parent_->KeyNavTerminate(false); +} + +void Controller::KeyNavGrab() +{ + KeyNavActivate(); + pimpl->keyboard_launcher_->GrabKeyboard(); + pimpl->launcher_grabbed = true; + + pimpl->launcher_key_press_connection_ = + pimpl->keyboard_launcher_->key_down.connect(sigc::mem_fun(pimpl, &Controller::Impl::ReceiveLauncherKeyPress)); + pimpl->launcher_event_outside_connection_ = + pimpl->keyboard_launcher_->mouse_down_outside_pointer_grab_area.connect(sigc::mem_fun(pimpl, &Controller::Impl::ReceiveMouseDownOutsideArea)); +} + +void Controller::KeyNavActivate() +{ + if (pimpl->launcher_keynav) + return; + + pimpl->reactivate_keynav = false; + pimpl->launcher_keynav = true; + pimpl->keyboard_launcher_ = pimpl->launchers[pimpl->MonitorWithMouse()]; + pimpl->keyboard_launcher_->ShowShortcuts(false); + + pimpl->keyboard_launcher_->EnterKeyNavMode(); + pimpl->model_->SetSelection(0); + + pimpl->ubus.SendMessage(UBUS_LAUNCHER_START_KEY_SWTICHER, g_variant_new_boolean(true)); +} + +void Controller::KeyNavNext() +{ + pimpl->model_->SelectNext(); +} + +void Controller::KeyNavPrevious() +{ + pimpl->model_->SelectPrevious(); +} + +void Controller::KeyNavTerminate(bool activate) +{ + if (!pimpl->launcher_keynav) + return; + + pimpl->keyboard_launcher_->ExitKeyNavMode(); + if (pimpl->launcher_grabbed) + { + pimpl->keyboard_launcher_->UnGrabKeyboard(); + pimpl->launcher_key_press_connection_.disconnect(); + pimpl->launcher_event_outside_connection_.disconnect(); + pimpl->launcher_grabbed = false; + } + + if (activate) + pimpl->model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0)); + + pimpl->launcher_keynav = false; + if (!pimpl->launcher_open) + pimpl->keyboard_launcher_.Release(); + + pimpl->ubus.SendMessage(UBUS_LAUNCHER_END_KEY_SWTICHER, g_variant_new_boolean(true)); +} + +bool Controller::KeyNavIsActive() const +{ + return pimpl->launcher_keynav; +} + +std::string +Controller::GetName() const +{ + return "LauncherController"; +} + +void +Controller::AddProperties(GVariantBuilder* builder) +{ + timespec current; + clock_gettime(CLOCK_MONOTONIC, ¤t); + + unity::variant::BuilderWrapper(builder) + .add("key_nav_is_active", KeyNavIsActive()) + .add("key_nav_launcher_monitor", pimpl->keyboard_launcher_.IsValid() ? pimpl->keyboard_launcher_->monitor : -1) + .add("key_nav_selection", pimpl->model_->SelectionIndex()) + .add("key_nav_is_grabbed", pimpl->launcher_grabbed); +} + +void Controller::Impl::ReceiveLauncherKeyPress(unsigned long eventType, + unsigned long keysym, + unsigned long state, + const char* character, + unsigned short keyCount) +{ + /* + * all key events below are related to keynavigation. Make an additional + * check that we are in a keynav mode when we inadvertadly receive the focus + */ + if (!launcher_grabbed) + return; + + switch (keysym) + { + // up (move selection up or go to global-menu if at top-most icon) + case NUX_VK_UP: + case NUX_KP_UP: + parent_->KeyNavPrevious(); + break; + + // down (move selection down and unfold launcher if needed) + case NUX_VK_DOWN: + case NUX_KP_DOWN: + parent_->KeyNavNext(); + break; + + // esc/left (close quicklist or exit laucher key-focus) + case NUX_VK_LEFT: + case NUX_KP_LEFT: + case NUX_VK_ESCAPE: + // hide again + parent_->KeyNavTerminate(false); + break; + + // right/shift-f10 (open quicklist of currently selected icon) + case XK_F10: + if (!(state & nux::NUX_STATE_SHIFT)) + break; + case NUX_VK_RIGHT: + case NUX_KP_RIGHT: + case XK_Menu: + if (model_->Selection()->OpenQuicklist(true, keyboard_launcher_->monitor())) + { + reactivate_keynav = true; + reactivate_index = model_->SelectionIndex(); + parent_->KeyNavTerminate(false); + } + break; + + // <SPACE> (open a new instance) + case NUX_VK_SPACE: + model_->Selection()->OpenInstance(ActionArg(ActionArg::LAUNCHER, 0)); + parent_->KeyNavTerminate(false); + break; + + // <RETURN> (start/activate currently selected icon) + case NUX_VK_ENTER: + case NUX_KP_ENTER: + model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0)); + parent_->KeyNavTerminate(false); + break; + + default: + break; + } +} + } // namespace launcher } // namespace unity diff --git a/plugins/unityshell/src/LauncherController.h b/plugins/unityshell/src/LauncherController.h index d8492a2ad..b9cb20601 100644 --- a/plugins/unityshell/src/LauncherController.h +++ b/plugins/unityshell/src/LauncherController.h @@ -24,7 +24,6 @@ #include <memory> #include <vector> #include <sigc++/sigc++.h> -#include <core/core.h> #include "SoftwareCenterLauncherIcon.h" @@ -36,26 +35,50 @@ class AbstractLauncherIcon; class Launcher; class LauncherModel; -class Controller : public sigc::trackable +class Controller : public unity::debug::Introspectable, public sigc::trackable { public: typedef std::shared_ptr<Controller> Ptr; + typedef std::vector<nux::ObjectPtr<Launcher> > LauncherList; + + nux::Property<Options::Ptr> options; Controller(Display* display); ~Controller(); - Launcher& launcher(); - Window launcher_input_window_id(); + Launcher& launcher() const; + LauncherList& launchers() const; + Window LauncherWindowId(int launcher) const; + Window KeyNavLauncherInputWindowId() const; void UpdateNumWorkspaces(int workspaces); - std::vector<char> GetAllShortcuts(); - std::vector<AbstractLauncherIcon*> GetAltTabIcons(); + std::vector<char> GetAllShortcuts() const; + std::vector<AbstractLauncherIcon*> GetAltTabIcons(bool current) const; - void PrimaryMonitorGeometryChanged(nux::Geometry const& geo); void PushToFront(); void SetShowDesktopIcon(bool show_desktop_icon); + void HandleLauncherKeyPress(); + void HandleLauncherKeyRelease(); + bool HandleLauncherKeyEvent(Display *display, + unsigned int key_sym, + unsigned long key_code, + unsigned long key_state, + char* key_string); + + void KeyNavActivate(); + void KeyNavGrab(); + void KeyNavTerminate(bool activate = true); + void KeyNavNext(); + void KeyNavPrevious(); + bool KeyNavIsActive() const; + +protected: + // Introspectable methods + std::string GetName() const; + void AddProperties(GVariantBuilder* builder); + private: class Impl; Impl* pimpl; diff --git a/plugins/unityshell/src/LauncherHideMachine.cpp b/plugins/unityshell/src/LauncherHideMachine.cpp index e7fc62c1c..81ab98cf4 100644 --- a/plugins/unityshell/src/LauncherHideMachine.cpp +++ b/plugins/unityshell/src/LauncherHideMachine.cpp @@ -35,13 +35,23 @@ LauncherHideMachine::LauncherHideMachine() _mode = HIDE_NEVER; _quirks = DEFAULT; _should_hide = false; - _show_on_edge = true; _latest_emit_should_hide = false; _hide_changed_emit_handle = 0; + reveal_progress = 0; _hide_delay_handle = 0; _hide_delay_timeout_length = 750; + + decaymulator_ = unity::ui::Decaymulator::Ptr(new unity::ui::Decaymulator()); + decaymulator_->value.changed.connect([&](int value) -> void { reveal_progress = (float)value / (float)reveal_pressure; }); + + edge_decay_rate.changed.connect(sigc::mem_fun (this, &LauncherHideMachine::OnDecayRateChanged)); +} + +void LauncherHideMachine::OnDecayRateChanged(int value) +{ + decaymulator_->rate_of_decay = value; } LauncherHideMachine::~LauncherHideMachine() @@ -59,6 +69,18 @@ LauncherHideMachine::~LauncherHideMachine() } void +LauncherHideMachine::AddRevealPressure(int pressure) +{ + decaymulator_->value = decaymulator_->value + pressure; + + if (decaymulator_->value > reveal_pressure) + { + SetQuirk(REVEAL_PRESSURE_PASS, true); + decaymulator_->value = 0; + } +} + +void LauncherHideMachine::SetShouldHide(bool value, bool skip_delay) { if (_should_hide == value) @@ -99,7 +121,6 @@ LauncherHideMachine::SetShouldHide(bool value, bool skip_delay) SCALE_ACTIVE = 1 << 16, 64k #VISIBLE_REQUIRED EXPO_ACTIVE = 1 << 17, 128k #VISIBLE_REQUIRED MT_DRAG_OUT = 1 << 18, 256k #VISIBLE_REQUIRED - MOUSE_OVER_ACTIVE_EDGE = 1 << 19, 512k LAUNCHER_PULSE = 1 << 20, 1M #VISIBLE_REQUIRED LOCK_HIDE = 1 << 21, 2M */ @@ -156,11 +177,7 @@ LauncherHideMachine::EnsureHideState(bool skip_delay) HideQuirk _should_show_quirk; if (GetQuirk(LAUNCHER_HIDDEN)) { - _should_show_quirk = (HideQuirk)(VISIBLE_REQUIRED); - - if (_show_on_edge) - _should_show_quirk = (HideQuirk)(_should_show_quirk | MOUSE_OVER_ACTIVE_EDGE); - + _should_show_quirk = (HideQuirk) ((VISIBLE_REQUIRED) | REVEAL_PRESSURE_PASS); } else { @@ -168,9 +185,6 @@ LauncherHideMachine::EnsureHideState(bool skip_delay) // mouse position over launcher is only taken into account if we move it after the revealing state if (GetQuirk(MOUSE_MOVE_POST_REVEAL)) _should_show_quirk = (HideQuirk)(_should_show_quirk | MOUSE_OVER_LAUNCHER); - - if (_show_on_edge) - _should_show_quirk = (HideQuirk)(_should_show_quirk | MOUSE_OVER_ACTIVE_EDGE); } if (GetQuirk(_should_show_quirk)) @@ -199,7 +213,7 @@ LauncherHideMachine::SetMode(LauncherHideMachine::HideMode mode) } LauncherHideMachine::HideMode -LauncherHideMachine::GetMode() +LauncherHideMachine::GetMode() const { return _mode; } @@ -229,7 +243,7 @@ LauncherHideMachine::SetQuirk(LauncherHideMachine::HideQuirk quirk, bool active) } bool -LauncherHideMachine::GetQuirk(LauncherHideMachine::HideQuirk quirk, bool allow_partial) +LauncherHideMachine::GetQuirk(LauncherHideMachine::HideQuirk quirk, bool allow_partial) const { if (allow_partial) return _quirks & quirk; @@ -237,28 +251,11 @@ LauncherHideMachine::GetQuirk(LauncherHideMachine::HideQuirk quirk, bool allow_p } bool -LauncherHideMachine::ShouldHide() +LauncherHideMachine::ShouldHide() const { return _should_hide; } -void -LauncherHideMachine::SetShowOnEdge(bool value) -{ - if (value == _show_on_edge) - return; - - _show_on_edge = value; - - LOG_DEBUG(logger) << "Shows on edge: " << _show_on_edge; -} - -bool -LauncherHideMachine::GetShowOnEdge() -{ - return _show_on_edge; -} - gboolean LauncherHideMachine::OnHideDelayTimeout(gpointer data) { @@ -285,7 +282,7 @@ LauncherHideMachine::EmitShouldHideChanged(gpointer data) } std::string -LauncherHideMachine::DebugHideQuirks() +LauncherHideMachine::DebugHideQuirks() const { // Although I do wonder why we are returning a string representation // of the enum value as an integer anyway. diff --git a/plugins/unityshell/src/LauncherHideMachine.h b/plugins/unityshell/src/LauncherHideMachine.h index e5efeacb5..efe4835ed 100644 --- a/plugins/unityshell/src/LauncherHideMachine.h +++ b/plugins/unityshell/src/LauncherHideMachine.h @@ -24,6 +24,8 @@ #include <glib.h> #include <string> +#include "Decaymulator.h" + class LauncherHideMachine : public sigc::trackable { public: @@ -55,28 +57,32 @@ public: SCALE_ACTIVE = 1 << 16, EXPO_ACTIVE = 1 << 17, MT_DRAG_OUT = 1 << 18, - MOUSE_OVER_ACTIVE_EDGE = 1 << 19, + REVEAL_PRESSURE_PASS = 1 << 19, LAUNCHER_PULSE = 1 << 20, LOCK_HIDE = 1 << 21 } HideQuirk; + nux::Property<int> reveal_pressure; + nux::Property<int> edge_decay_rate; + + nux::Property<float> reveal_progress; + LauncherHideMachine(); virtual ~LauncherHideMachine(); void SetMode(HideMode mode); - HideMode GetMode(); + HideMode GetMode() const; - void SetShowOnEdge(bool value); - bool GetShowOnEdge(); + void AddRevealPressure(int pressure); void SetQuirk(HideQuirk quirk, bool active); - bool GetQuirk(HideQuirk quirk, bool allow_partial = true); + bool GetQuirk(HideQuirk quirk, bool allow_partial = true) const; - bool ShouldHide(); + bool ShouldHide() const; sigc::signal<void, bool> should_hide_changed; - std::string DebugHideQuirks(); + std::string DebugHideQuirks() const; private: void EnsureHideState(bool skip_delay); @@ -85,9 +91,12 @@ private: static gboolean OnHideDelayTimeout(gpointer data); static gboolean EmitShouldHideChanged(gpointer data); + void OnDecayRateChanged (int value); + + unity::ui::Decaymulator::Ptr decaymulator_; + bool _should_hide; bool _latest_emit_should_hide; - bool _show_on_edge; HideQuirk _quirks; HideMode _mode; unsigned int _hide_delay_timeout_length; diff --git a/plugins/unityshell/src/LauncherIcon.cpp b/plugins/unityshell/src/LauncherIcon.cpp index cdfbd8b52..0addde9ce 100644 --- a/plugins/unityshell/src/LauncherIcon.cpp +++ b/plugins/unityshell/src/LauncherIcon.cpp @@ -33,6 +33,7 @@ #include "CairoTexture.h" #include "LauncherIcon.h" #include "Launcher.h" +#include "TimeUtil.h" #include "QuicklistManager.h" #include "QuicklistMenuItem.h" @@ -69,12 +70,9 @@ QuicklistView* LauncherIcon::_current_quicklist = 0; int LauncherIcon::_current_theme_is_mono = -1; GtkIconTheme* LauncherIcon::_unity_theme = NULL; -gboolean LauncherIcon::_skip_tooltip_delay = false; -LauncherIcon::LauncherIcon(Launcher* launcher) - : _launcher(launcher) - , _menuclient_dynamic_quicklist(nullptr) - , _has_visible_window(false) +LauncherIcon::LauncherIcon() + : _menuclient_dynamic_quicklist(nullptr) , _quicklist_is_initialized(false) , _remote_urgent(false) , _present_urgency(0) @@ -82,14 +80,19 @@ LauncherIcon::LauncherIcon(Launcher* launcher) , _center_stabilize_handle(0) , _present_time_handle(0) , _time_delay_handle(0) - , _tooltip_delay_handle(0) - , _related_windows(0) , _sort_priority(0) , _background_color(nux::color::White) , _glow_color(nux::color::White) , _shortcut(0) , _icon_type(TYPE_NONE) { + _has_visible_window.resize(max_num_monitors); + _center.resize(max_num_monitors); + _saved_center.resize(max_num_monitors); + _last_stable.resize(max_num_monitors); + _parent_geo.resize(max_num_monitors); + transform_map.resize(max_num_monitors); + for (int i = 0; i < QUIRK_LAST; i++) { _quirks[i] = false; @@ -141,9 +144,6 @@ LauncherIcon::~LauncherIcon() g_source_remove(_time_delay_handle); _time_delay_handle = 0; - if (_tooltip_delay_handle) - g_source_remove(_tooltip_delay_handle); - _tooltip_delay_handle = 0; // clean up the whole signal-callback mess if (needs_redraw_connection.connected()) needs_redraw_connection.disconnect(); @@ -168,9 +168,9 @@ LauncherIcon::~LauncherIcon() } const bool -LauncherIcon::HasWindowOnViewport() +LauncherIcon::WindowVisibleOnMonitor(int monitor) { - return _has_visible_window; + return _has_visible_window[monitor]; } std::string @@ -183,10 +183,10 @@ void LauncherIcon::AddProperties(GVariantBuilder* builder) { unity::variant::BuilderWrapper(builder) - .add("x", _center.x) - .add("y", _center.y) - .add("z", _center.z) - .add("related-windows", _related_windows) + .add("x", _center[0].x) + .add("y", _center[0].y) + .add("z", _center[0].z) + .add("related-windows", (int)Windows().size()) .add("icon-type", _icon_type) .add("tooltip-text", tooltip_text().c_str()) .add("sort-priority", _sort_priority) @@ -206,6 +206,8 @@ LauncherIcon::Activate(ActionArg arg) WindowManager::Default()->TerminateScale(); ActivateLauncherIcon(arg); + + UpdateQuirkTime(QUIRK_LAST_ACTION); } void @@ -215,6 +217,8 @@ LauncherIcon::OpenInstance(ActionArg arg) WindowManager::Default()->TerminateScale(); OpenInstanceLauncherIcon(arg); + + UpdateQuirkTime(QUIRK_LAST_ACTION); } nux::Color LauncherIcon::BackgroundColor() @@ -479,71 +483,51 @@ LauncherIcon::GetShortcut() } void -LauncherIcon::SetSkipTooltipDelay(gboolean skip_tooltip_delay) -{ - _skip_tooltip_delay = skip_tooltip_delay; -} - -gboolean -LauncherIcon::OnTooltipTimeout(gpointer data) +LauncherIcon::ShowTooltip() { - LauncherIcon* self = (LauncherIcon*) data; - - if (!self->_launcher) - return FALSE; - - nux::Geometry geo = self->_launcher->GetAbsoluteGeometry(); - int tip_x = geo.x + geo.width + 1; - int tip_y = geo.y + self->_center.y; - - self->_tooltip->ShowTooltipWithTipAt(tip_x, tip_y); + if (_quicklist->IsVisible()) + return; - if (!self->_quicklist->IsVisible()) + int tip_x = 100; + int tip_y = 100; + if (_last_monitor >= 0) { - self->_tooltip->ShowWindow(!self->tooltip_text().empty()); - _skip_tooltip_delay = TRUE; + nux::Geometry geo = _parent_geo[_last_monitor]; + tip_x = geo.x + geo.width + 1; + tip_y = geo.y + _center[_last_monitor].y; } - self->_tooltip_delay_handle = 0; - return FALSE; + _tooltip->ShowTooltipWithTipAt(tip_x, tip_y); + _tooltip->ShowWindow(!tooltip_text().empty()); } void -LauncherIcon::RecvMouseEnter() +LauncherIcon::RecvMouseEnter(int monitor) { + _last_monitor = monitor; if (QuicklistManager::Default()->Current()) { // A quicklist is active return; } - if (!_skip_tooltip_delay) - _tooltip_delay_handle = g_timeout_add(500, &LauncherIcon::OnTooltipTimeout, this); - else - OnTooltipTimeout(this); + ShowTooltip(); } -void LauncherIcon::RecvMouseLeave() +void LauncherIcon::RecvMouseLeave(int monitor) { - if (_tooltip_delay_handle) - g_source_remove(_tooltip_delay_handle); - _tooltip_delay_handle = 0; + _last_monitor = -1; _tooltip->ShowWindow(false); } -bool LauncherIcon::OpenQuicklist(bool default_to_first_item) +bool LauncherIcon::OpenQuicklist(bool default_to_first_item, int monitor) { std::list<DbusmenuMenuitem*> menus = Menus(); if (menus.empty()) return false; - if (_tooltip_delay_handle) - g_source_remove(_tooltip_delay_handle); - _tooltip_delay_handle = 0; - _skip_tooltip_delay = false; - _tooltip->ShowWindow(false); _quicklist->RemoveAllMenuItem(); @@ -582,19 +566,18 @@ bool LauncherIcon::OpenQuicklist(bool default_to_first_item) if (default_to_first_item) _quicklist->DefaultToFirstItem(); - int tip_x, tip_y; - if (_launcher) + if (monitor < 0) { - nux::Geometry geo = _launcher->GetAbsoluteGeometry(); - tip_x = geo.x + geo.width + 1; - tip_y = geo.y + _center.y; - } - else - { - tip_x = 0; - tip_y = _center.y; + if (_last_monitor >= 0) + monitor = _last_monitor; + else + monitor = 0; } + nux::Geometry geo = _parent_geo[monitor]; + int tip_x = geo.x + geo.width + 1; + int tip_y = geo.y + _center[monitor].y; + auto win_manager = WindowManager::Default(); if (win_manager->IsScaleActive()) @@ -617,13 +600,13 @@ bool LauncherIcon::OpenQuicklist(bool default_to_first_item) return true; } -void LauncherIcon::RecvMouseDown(int button) +void LauncherIcon::RecvMouseDown(int button, int monitor) { if (button == 3) OpenQuicklist(); } -void LauncherIcon::RecvMouseUp(int button) +void LauncherIcon::RecvMouseUp(int button, int monitor) { if (button == 3) { @@ -632,9 +615,11 @@ void LauncherIcon::RecvMouseUp(int button) } } -void LauncherIcon::RecvMouseClick(int button) +void LauncherIcon::RecvMouseClick(int button, int monitor) { ActionArg arg(ActionArg::LAUNCHER, button); + arg.monitor = monitor; + if (button == 1) Activate(arg); else if (button == 2) @@ -643,11 +628,6 @@ void LauncherIcon::RecvMouseClick(int button) void LauncherIcon::HideTooltip() { - if (_tooltip_delay_handle) - g_source_remove(_tooltip_delay_handle); - _tooltip_delay_handle = 0; - _skip_tooltip_delay = false; - _tooltip->ShowWindow(false); } @@ -656,7 +636,7 @@ LauncherIcon::OnCenterTimeout(gpointer data) { LauncherIcon* self = (LauncherIcon*)data; - if (self->_last_stable != self->_center) + if (!std::equal(self->_center.begin(), self->_center.end(), self->_last_stable.begin())) { self->OnCenterStabilized(self->_center); self->_last_stable = self->_center; @@ -667,27 +647,22 @@ LauncherIcon::OnCenterTimeout(gpointer data) } void -LauncherIcon::SetCenter(nux::Point3 center) +LauncherIcon::SetCenter(nux::Point3 center, int monitor, nux::Geometry geo) { - _center = center; + _center[monitor] = center; + _parent_geo[monitor] = geo; - int tip_x, tip_y; - if (_launcher) + if (monitor == _last_monitor) { - nux::Geometry geo = _launcher->GetAbsoluteGeometry(); + int tip_x, tip_y; tip_x = geo.x + geo.width + 1; - tip_y = geo.y + _center.y; - } - else - { - tip_x = 0; - tip_y = _center.y; - } + tip_y = geo.y + _center[monitor].y; - if (_quicklist->IsVisible()) - QuicklistManager::Default()->ShowQuicklist(_quicklist, tip_x, tip_y); - else if (_tooltip->IsVisible()) - _tooltip->ShowTooltipWithTipAt(tip_x, tip_y); + if (_quicklist->IsVisible()) + QuicklistManager::Default()->ShowQuicklist(_quicklist, tip_x, tip_y); + else if (_tooltip->IsVisible()) + _tooltip->ShowTooltipWithTipAt(tip_x, tip_y); + } if (_center_stabilize_handle) g_source_remove(_center_stabilize_handle); @@ -696,7 +671,18 @@ LauncherIcon::SetCenter(nux::Point3 center) } nux::Point3 -LauncherIcon::GetCenter() +LauncherIcon::GetCenter(int monitor) +{ + return _center[monitor]; +} + +nux::Point3 +LauncherIcon::GetSavedCenter(int monitor) +{ + return _saved_center[monitor]; +} + +std::vector<nux::Point3> LauncherIcon::GetCenters() { return _center; } @@ -709,12 +695,12 @@ LauncherIcon::SaveCenter() } void -LauncherIcon::SetHasWindowOnViewport(bool val) +LauncherIcon::SetWindowVisibleOnMonitor(bool val, int monitor) { - if (_has_visible_window == val) + if (_has_visible_window[monitor] == val) return; - _has_visible_window = val; + _has_visible_window[monitor] = val; needs_redraw.emit(this); } @@ -763,16 +749,6 @@ LauncherIcon::Unpresent() } void -LauncherIcon::SetRelatedWindows(int windows) -{ - if (_related_windows == windows) - return; - - _related_windows = windows; - needs_redraw.emit(this); -} - -void LauncherIcon::Remove() { if (_quicklist->IsVisible()) @@ -817,13 +793,10 @@ LauncherIcon::SetQuirk(LauncherIcon::Quirk quirk, bool value) { if (_quirks[quirk] == value) return; - - if (quirk == QUIRK_PULSE_ONCE) - _launcher->HideMachine()->SetQuirk(LauncherHideMachine::LAUNCHER_PULSE, value); _quirks[quirk] = value; if (quirk == QUIRK_VISIBLE) - Launcher::SetTimeStruct(&(_quirk_times[quirk]), &(_quirk_times[quirk]), ANIM_DURATION_SHORT); + TimeUtil::SetTimeStruct(&(_quirk_times[quirk]), &(_quirk_times[quirk]), ANIM_DURATION_SHORT); else clock_gettime(CLOCK_MONOTONIC, &(_quirk_times[quirk])); needs_redraw.emit(this); @@ -887,12 +860,6 @@ LauncherIcon::GetQuirkTime(LauncherIcon::Quirk quirk) return _quirk_times[quirk]; } -int -LauncherIcon::RelatedWindows() -{ - return _related_windows; -} - void LauncherIcon::SetProgress(float progress) { @@ -949,12 +916,12 @@ LauncherIcon::SetEmblemIconName(const char* name) } std::vector<nux::Vector4> & -LauncherIcon::GetTransform(TransformIndex index) +LauncherIcon::GetTransform(TransformIndex index, int monitor) { - auto iter = transform_map.find(index); - if (iter == transform_map.end()) + auto iter = transform_map[monitor].find(index); + if (iter == transform_map[monitor].end()) { - auto iter2 = transform_map.insert(std::map<TransformIndex, std::vector<nux::Vector4> >::value_type(index, std::vector<nux::Vector4>(4))); + auto iter2 = transform_map[monitor].insert(std::map<TransformIndex, std::vector<nux::Vector4> >::value_type(index, std::vector<nux::Vector4>(4))); return iter2.first->second; } diff --git a/plugins/unityshell/src/LauncherIcon.h b/plugins/unityshell/src/LauncherIcon.h index 5d455f7a2..d6e95e435 100644 --- a/plugins/unityshell/src/LauncherIcon.h +++ b/plugins/unityshell/src/LauncherIcon.h @@ -51,6 +51,8 @@ namespace unity namespace launcher { +const int max_num_monitors = 6; + class Launcher; class LauncherIcon : public AbstractLauncherIcon @@ -60,15 +62,10 @@ class LauncherIcon : public AbstractLauncherIcon public: typedef nux::ObjectPtr<nux::BaseTexture> BaseTexturePtr; - LauncherIcon(Launcher* launcher); + LauncherIcon(); virtual ~LauncherIcon(); - Launcher* GetLauncher() - { - return _launcher; - }; - bool SetTooltipText(std::string& target, std::string const& value); void SetShortcut(guint64 shortcut); @@ -77,23 +74,25 @@ public: void SetSortPriority(int priority); - void RecvMouseEnter(); + void RecvMouseEnter(int monitor); - void RecvMouseLeave(); + void RecvMouseLeave(int monitor); - void RecvMouseDown(int button); + void RecvMouseDown(int button, int monitor); - void RecvMouseUp(int button); + void RecvMouseUp(int button, int monitor); - void RecvMouseClick(int button); + void RecvMouseClick(int button, int monitor); void HideTooltip(); - bool OpenQuicklist(bool default_to_first_item = false); + void ShowTooltip(); - void SetCenter(nux::Point3 center); + bool OpenQuicklist(bool default_to_first_item = false, int monitor = -1); - nux::Point3 GetCenter(); + void SetCenter(nux::Point3 center, int parent_monitor, nux::Geometry parent_geo); + + nux::Point3 GetCenter(int monitor); virtual void Activate(ActionArg arg); @@ -101,15 +100,17 @@ public: void SaveCenter(); + nux::Point3 GetSavedCenter(int monitor); + int SortPriority(); - int RelatedWindows(); + virtual std::vector<Window> Windows () { return std::vector<Window> (); } - virtual std::vector<Window> RelatedXids () { return std::vector<Window> (); } + virtual std::vector<Window> WindowsForMonitor (int monitor) { return std::vector<Window> (); } virtual std::string NameForWindow (Window window) { return std::string(); } - const bool HasWindowOnViewport(); + const bool WindowVisibleOnMonitor(int monitor); virtual bool IsSpacer() { @@ -126,7 +127,7 @@ public: void DeleteEmblem(); - virtual bool ShowInSwitcher() + virtual bool ShowInSwitcher(bool current) { return false; }; @@ -185,19 +186,11 @@ public: void SetIconType(IconType type); - std::vector<nux::Vector4> & GetTransform(TransformIndex index); - - static void SetSkipTooltipDelay(gboolean skip_tooltip_delay); - - sigc::signal<void, LauncherIcon*> remove; - - sigc::connection needs_redraw_connection; - sigc::connection on_icon_added_connection; - sigc::connection on_icon_removed_connection; - sigc::connection on_order_changed_connection; - sigc::connection on_expo_terminated_connection; + std::vector<nux::Vector4> & GetTransform(TransformIndex index, int monitor); protected: + std::vector<nux::Point3> GetCenters(); + std::string GetName() const; void AddProperties(GVariantBuilder* builder); @@ -208,13 +201,11 @@ protected: void ResetQuirkTime(Quirk quirk); - void SetRelatedWindows(int windows); - void Remove(); void SetProgress(float progress); - void SetHasWindowOnViewport(bool val); + void SetWindowVisibleOnMonitor(bool val, int monitor); void Present(float urgency, int length); @@ -226,7 +217,7 @@ protected: virtual nux::BaseTexture* GetTextureForSize(int size) = 0; - virtual void OnCenterStabilized(nux::Point3 center) {} + virtual void OnCenterStabilized(std::vector<nux::Point3> center) {} virtual const gchar* GetRemoteUri() { @@ -276,8 +267,6 @@ protected: void OnRemoteProgressVisibleChanged(LauncherEntryRemote* remote); - Launcher* _launcher; - nux::Tooltip* _tooltip; QuicklistView* _quicklist; @@ -304,31 +293,29 @@ private: static gboolean OnPresentTimeout(gpointer data); static gboolean OnCenterTimeout(gpointer data); static gboolean OnDelayedUpdateTimeout(gpointer data); - static gboolean OnTooltipTimeout(gpointer data); void ColorForIcon(GdkPixbuf* pixbuf, nux::Color& background, nux::Color& glow); - bool _has_visible_window; - bool _quicklist_is_initialized; - bool _remote_urgent; - float _present_urgency; - float _progress; - guint _center_stabilize_handle; - guint _present_time_handle; - guint _time_delay_handle; - guint _tooltip_delay_handle; - int _related_windows; - int _sort_priority; - nux::Color _background_color; - nux::Color _glow_color; - static gboolean _skip_tooltip_delay; - - gint64 _shortcut; - - nux::Point3 _center; - nux::Point3 _last_stable; - nux::Point3 _saved_center; - IconType _icon_type; + std::vector<bool> _has_visible_window; + bool _quicklist_is_initialized; + bool _remote_urgent; + float _present_urgency; + float _progress; + guint _center_stabilize_handle; + guint _present_time_handle; + guint _time_delay_handle; + int _sort_priority; + int _last_monitor; + nux::Color _background_color; + nux::Color _glow_color; + + gint64 _shortcut; + + std::vector<nux::Point3> _center; + std::vector<nux::Point3> _last_stable; + std::vector<nux::Point3> _saved_center; + std::vector<nux::Geometry> _parent_geo; + IconType _icon_type; static GtkIconTheme* _unity_theme; @@ -338,7 +325,7 @@ private: struct timespec _quirk_times[QUIRK_LAST]; std::list<LauncherEntryRemote*> _entry_list; - std::map<TransformIndex, std::vector<nux::Vector4> > transform_map; + std::vector<std::map<TransformIndex, std::vector<nux::Vector4> > > transform_map; }; diff --git a/plugins/unityshell/src/LauncherModel.cpp b/plugins/unityshell/src/LauncherModel.cpp index ea9769bc6..fff074786 100644 --- a/plugins/unityshell/src/LauncherModel.cpp +++ b/plugins/unityshell/src/LauncherModel.cpp @@ -18,7 +18,7 @@ */ #include "LauncherModel.h" -#include "LauncherIcon.h" +#include "AbstractLauncherIcon.h" namespace unity { @@ -27,12 +27,13 @@ namespace launcher typedef struct { - LauncherIcon* icon; + AbstractLauncherIcon* icon; LauncherModel* self; } RemoveArg; LauncherModel::LauncherModel() { + selection_ = 0; } LauncherModel::~LauncherModel() @@ -44,12 +45,12 @@ LauncherModel::~LauncherModel() icon->UnReference(); } -bool LauncherModel::IconShouldShelf(LauncherIcon* icon) +bool LauncherModel::IconShouldShelf(AbstractLauncherIcon* icon) const { - return icon->Type() == LauncherIcon::TYPE_TRASH; + return icon->Type() == AbstractLauncherIcon::TYPE_TRASH; } -bool LauncherModel::CompareIcons(LauncherIcon* first, LauncherIcon* second) +bool LauncherModel::CompareIcons(AbstractLauncherIcon* first, AbstractLauncherIcon* second) { if (first->Type() < second->Type()) return true; @@ -66,31 +67,35 @@ LauncherModel::Populate() _inner.clear(); + iterator it, it2; + int i = 0; - for (auto icon : _inner_main) + for (it = main_begin(); it != main_end(); it++) { - _inner.push_back(icon); - icon->SetSortPriority(i++); + _inner.push_back(*it); + (*it)->SetSortPriority(i); + ++i; } - for (auto icon : _inner_shelf) + for (it = shelf_begin(); it != shelf_end(); it++) { - _inner.push_back(icon); - icon->SetSortPriority(i++); + _inner.push_back(*it); + (*it)->SetSortPriority(i); + ++i; } - return !std::equal(begin(), end(), copy.begin()); + return copy.size() == _inner.size() && !std::equal(begin(), end(), copy.begin()); } void -LauncherModel::AddIcon(LauncherIcon* icon) +LauncherModel::AddIcon(AbstractLauncherIcon* icon) { icon->SinkReference(); if (IconShouldShelf(icon)) - _inner_shelf.push_front(icon); + _inner_shelf.push_back(icon); else - _inner_main.push_front(icon); + _inner_main.push_back(icon); Sort(); @@ -102,15 +107,15 @@ LauncherModel::AddIcon(LauncherIcon* icon) } void -LauncherModel::RemoveIcon(LauncherIcon* icon) +LauncherModel::RemoveIcon(AbstractLauncherIcon* icon) { size_t size; - _inner_shelf.remove(icon); - _inner_main.remove(icon); + _inner_shelf.erase(std::remove(_inner_shelf.begin(), _inner_shelf.end(), icon), _inner_shelf.end()); + _inner_main.erase(std::remove(_inner_main.begin(), _inner_main.end(), icon), _inner_main.end()); size = _inner.size(); - _inner.remove(icon); + _inner.erase(std::remove(_inner.begin(), _inner.end(), icon), _inner.end()); if (size != _inner.size()) { @@ -131,7 +136,7 @@ LauncherModel::RemoveCallback(gpointer data) } void -LauncherModel::OnIconRemove(LauncherIcon* icon) +LauncherModel::OnIconRemove(AbstractLauncherIcon* icon) { RemoveArg* arg = (RemoveArg*) g_malloc0(sizeof(RemoveArg)); arg->icon = icon; @@ -149,36 +154,36 @@ LauncherModel::Save() void LauncherModel::Sort() { - _inner_shelf.sort(&LauncherModel::CompareIcons); - _inner_main.sort(&LauncherModel::CompareIcons); + std::stable_sort(_inner_shelf.begin(), _inner_shelf.end(), &LauncherModel::CompareIcons); + std::stable_sort(_inner_main.begin(), _inner_main.end(), &LauncherModel::CompareIcons); if (Populate()) order_changed.emit(); } bool -LauncherModel::IconHasSister(LauncherIcon* icon) +LauncherModel::IconHasSister(AbstractLauncherIcon* icon) const { - iterator it; - iterator end; + const_iterator it; + const_iterator end; if (icon && icon->Type() == AbstractLauncherIcon::TYPE_DEVICE) return true; if (IconShouldShelf(icon)) { - it = shelf_begin(); - end = shelf_end(); + it = _inner_shelf.begin(); + end = _inner_shelf.end(); } else { - it = main_begin(); - end = main_end(); + it = _inner_main.begin(); + end = _inner_main.end(); } for (; it != end; ++it) { - LauncherIcon* iter_icon = *it; + AbstractLauncherIcon* iter_icon = *it; if ((iter_icon != icon) && iter_icon->Type() == icon->Type()) return true; @@ -188,7 +193,7 @@ LauncherModel::IconHasSister(LauncherIcon* icon) } void -LauncherModel::ReorderAfter(LauncherIcon* icon, LauncherIcon* other) +LauncherModel::ReorderAfter(AbstractLauncherIcon* icon, AbstractLauncherIcon* other) { if (icon == other) return; @@ -218,7 +223,7 @@ LauncherModel::ReorderAfter(LauncherIcon* icon, LauncherIcon* other) } void -LauncherModel::ReorderBefore(LauncherIcon* icon, LauncherIcon* other, bool save) +LauncherModel::ReorderBefore(AbstractLauncherIcon* icon, AbstractLauncherIcon* other, bool save) { if (icon == other) return; @@ -259,7 +264,7 @@ LauncherModel::ReorderBefore(LauncherIcon* icon, LauncherIcon* other, bool save) } void -LauncherModel::ReorderSmart(LauncherIcon* icon, LauncherIcon* other, bool save) +LauncherModel::ReorderSmart(AbstractLauncherIcon* icon, AbstractLauncherIcon* other, bool save) { if (icon == other) return; @@ -313,11 +318,73 @@ LauncherModel::ReorderSmart(LauncherIcon* icon, LauncherIcon* other, bool save) } int -LauncherModel::Size() +LauncherModel::Size() const { return _inner.size(); } +AbstractLauncherIcon* LauncherModel::Selection () const +{ + return _inner[selection_]; +} + +int LauncherModel::SelectionIndex() const +{ + return selection_; +} + +void LauncherModel::SetSelection(int selection) +{ + int new_selection = std::min<int>(Size() - 1, std::max<int> (0, selection)); + + if (new_selection == selection_) + return; + + selection_ = new_selection; + selection_changed.emit(Selection()); +} + +void LauncherModel::SelectNext() +{ + int temp = selection_; + + temp++; + while (temp != selection_) + { + if (temp >= Size()) + temp = 0; + + if (_inner[temp]->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE)) + { + selection_ = temp; + selection_changed.emit(Selection()); + break; + } + temp++; + } +} + +void LauncherModel::SelectPrevious() +{ + int temp = selection_; + + temp--; + while (temp != selection_) + { + if (temp < 0) + temp = Size() - 1; + + if (_inner[temp]->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE)) + { + selection_ = temp; + selection_changed.emit(Selection()); + break; + } + temp--; + } +} + + /* iterators */ LauncherModel::iterator diff --git a/plugins/unityshell/src/LauncherModel.h b/plugins/unityshell/src/LauncherModel.h index e2113f3ea..bbf80d45e 100644 --- a/plugins/unityshell/src/LauncherModel.h +++ b/plugins/unityshell/src/LauncherModel.h @@ -22,7 +22,7 @@ #include <memory> -#include "LauncherIcon.h" +#include "AbstractLauncherIcon.h" #include <sigc++/sigc++.h> namespace unity @@ -34,27 +34,35 @@ class LauncherModel : public sigc::trackable { public: typedef std::shared_ptr<LauncherModel> Ptr; - typedef std::list<LauncherIcon*> Base; + typedef std::vector<AbstractLauncherIcon*> Base; typedef Base::iterator iterator; + typedef Base::const_iterator const_iterator; typedef Base::reverse_iterator reverse_iterator; + typedef Base::reverse_iterator const_reverse_iterator; LauncherModel(); ~LauncherModel(); - void AddIcon(LauncherIcon* icon); - void RemoveIcon(LauncherIcon* icon); + void AddIcon(AbstractLauncherIcon* icon); + void RemoveIcon(AbstractLauncherIcon* icon); void Save(); void Sort(); - int Size(); + int Size() const; - void OnIconRemove(LauncherIcon* icon); + void OnIconRemove(AbstractLauncherIcon* icon); - bool IconHasSister(LauncherIcon* icon); + bool IconHasSister(AbstractLauncherIcon* icon) const; - void ReorderAfter(LauncherIcon* icon, LauncherIcon* other); - void ReorderBefore(LauncherIcon* icon, LauncherIcon* other, bool save); + void ReorderAfter(AbstractLauncherIcon* icon, AbstractLauncherIcon* other); + void ReorderBefore(AbstractLauncherIcon* icon, AbstractLauncherIcon* other, bool save); - void ReorderSmart(LauncherIcon* icon, LauncherIcon* other, bool save); + void ReorderSmart(AbstractLauncherIcon* icon, AbstractLauncherIcon* other, bool save); + + AbstractLauncherIcon* Selection() const; + int SelectionIndex() const; + void SetSelection(int selection); + void SelectNext(); + void SelectPrevious(); iterator begin(); iterator end(); @@ -72,28 +80,25 @@ public: reverse_iterator shelf_rbegin(); reverse_iterator shelf_rend(); - sigc::signal<void, LauncherIcon*> icon_added; - sigc::signal<void, LauncherIcon*> icon_removed; + sigc::signal<void, AbstractLauncherIcon*> icon_added; + sigc::signal<void, AbstractLauncherIcon*> icon_removed; sigc::signal<void> order_changed; sigc::signal<void> saved; - - // connected to from class Launcher - sigc::connection on_icon_added_connection; - sigc::connection on_icon_removed_connection; - sigc::connection on_order_changed_connection; - + sigc::signal<void, AbstractLauncherIcon*> selection_changed; + private: Base _inner; Base _inner_shelf; Base _inner_main; + int selection_; bool Populate(); - bool IconShouldShelf(LauncherIcon* icon); + bool IconShouldShelf(AbstractLauncherIcon* icon) const; static gboolean RemoveCallback(gpointer data); - static bool CompareIcons(LauncherIcon* first, LauncherIcon* second); + static bool CompareIcons(AbstractLauncherIcon* first, AbstractLauncherIcon* second); /* Template Methods */ public: diff --git a/plugins/unityshell/src/LauncherOptions.cpp b/plugins/unityshell/src/LauncherOptions.cpp new file mode 100644 index 000000000..edf15e267 --- /dev/null +++ b/plugins/unityshell/src/LauncherOptions.cpp @@ -0,0 +1,97 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2010, 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: Jason Smith <jason.smith@canonical.com> + * Tim Penhey <tim.penhey@canonical.com> + */ + +#include "LauncherOptions.h" + +namespace unity +{ +namespace launcher +{ + +Options::Options() +{ + hide_mode.changed.connect(sigc::mem_fun (this, &Options::OnHideModeChanged)); + launch_animation.changed.connect(sigc::mem_fun (this, &Options::OnLaunchAnimationChanged)); + urgent_animation.changed.connect(sigc::mem_fun (this, &Options::OnUrgentAnimationChanged)); + auto_hide_animation.changed.connect(sigc::mem_fun (this, &Options::OnAutoHideAnimationChanged)); + backlight_mode.changed.connect(sigc::mem_fun (this, &Options::OnBacklightModeChanged)); + icon_size.changed.connect(sigc::mem_fun (this, &Options::OnIconSizeChanged)); + tile_size.changed.connect(sigc::mem_fun (this, &Options::OnTileSizeChanged)); + floating.changed.connect(sigc::mem_fun (this, &Options::OnFloatingChanged)); + background_alpha.changed.connect(sigc::mem_fun (this, &Options::OnBackgroundAlphaChanged)); + edge_decay_rate.changed.connect(sigc::mem_fun (this, &Options::OnEdgeOptionChanged)); + edge_overcome_pressure.changed.connect(sigc::mem_fun (this, &Options::OnEdgeOptionChanged)); + edge_stop_velocity.changed.connect(sigc::mem_fun (this, &Options::OnEdgeOptionChanged)); + edge_reveal_pressure.changed.connect(sigc::mem_fun (this, &Options::OnEdgeOptionChanged)); +} + +void Options::OnEdgeOptionChanged(int value) +{ + option_changed.emit(); +} + +void Options::OnHideModeChanged(LauncherHideMode value) +{ + option_changed.emit(); +} + +void Options::OnLaunchAnimationChanged(LaunchAnimation value) +{ + option_changed.emit(); +} + +void Options::OnUrgentAnimationChanged(UrgentAnimation value) +{ + option_changed.emit(); +} + +void Options::OnAutoHideAnimationChanged(AutoHideAnimation value) +{ + option_changed.emit(); +} + +void Options::OnBacklightModeChanged(BacklightMode value) +{ + option_changed.emit(); +} + +void Options::OnIconSizeChanged(int value) +{ + option_changed.emit(); +} + +void Options::OnTileSizeChanged(int value) +{ + option_changed.emit(); +} + +void Options::OnFloatingChanged(bool value) +{ + option_changed.emit(); +} + +void Options::OnBackgroundAlphaChanged(float value) +{ + option_changed.emit(); +} + + +} +} \ No newline at end of file diff --git a/plugins/unityshell/src/LauncherOptions.h b/plugins/unityshell/src/LauncherOptions.h new file mode 100644 index 000000000..bd042b7f2 --- /dev/null +++ b/plugins/unityshell/src/LauncherOptions.h @@ -0,0 +1,114 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2010 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: Jason Smith <jason.smith@canonical.com> + * Tim Penhey <tim.penhey@canonical.com> + */ + +#ifndef LAUNCHEROPTIONS_H +#define LAUNCHEROPTIONS_H + +#include <memory> +#include <vector> +#include <sigc++/sigc++.h> +#include <core/core.h> + +#include <Nux/Nux.h> + +namespace unity +{ +namespace launcher +{ + +typedef enum +{ + LAUNCHER_HIDE_NEVER, + LAUNCHER_HIDE_AUTOHIDE, + LAUNCHER_HIDE_DODGE_WINDOWS, + LAUNCHER_HIDE_DODGE_ACTIVE_WINDOW, +} LauncherHideMode; + +typedef enum +{ + LAUNCH_ANIMATION_NONE, + LAUNCH_ANIMATION_PULSE, + LAUNCH_ANIMATION_BLINK, +} LaunchAnimation; + +typedef enum +{ + URGENT_ANIMATION_NONE, + URGENT_ANIMATION_PULSE, + URGENT_ANIMATION_WIGGLE, +} UrgentAnimation; + +typedef enum +{ + FADE_OR_SLIDE, + SLIDE_ONLY, + FADE_ONLY, + FADE_AND_SLIDE, +} AutoHideAnimation; + +typedef enum +{ + BACKLIGHT_ALWAYS_ON, + BACKLIGHT_NORMAL, + BACKLIGHT_ALWAYS_OFF, + BACKLIGHT_EDGE_TOGGLE, + BACKLIGHT_NORMAL_EDGE_TOGGLE +} BacklightMode; + +class Options : public sigc::trackable +{ +public: + typedef std::shared_ptr<Options> Ptr; + + Options(); + + nux::Property<LauncherHideMode> hide_mode; + nux::Property<LaunchAnimation> launch_animation; + nux::Property<UrgentAnimation> urgent_animation; + nux::Property<AutoHideAnimation> auto_hide_animation; + nux::Property<BacklightMode> backlight_mode; + nux::Property<int> icon_size; + nux::Property<int> tile_size; + nux::Property<bool> floating; + nux::Property<float> background_alpha; + nux::Property<int> edge_decay_rate; + nux::Property<int> edge_overcome_pressure; + nux::Property<int> edge_stop_velocity; + nux::Property<int> edge_reveal_pressure; + + sigc::signal<void> option_changed; + +private: + void OnHideModeChanged(LauncherHideMode value); + void OnLaunchAnimationChanged(LaunchAnimation value); + void OnUrgentAnimationChanged(UrgentAnimation value); + void OnAutoHideAnimationChanged(AutoHideAnimation value); + void OnBacklightModeChanged(BacklightMode value); + void OnIconSizeChanged(int value); + void OnEdgeOptionChanged(int value); + void OnTileSizeChanged(int value); + void OnFloatingChanged(bool value); + void OnBackgroundAlphaChanged(float value); +}; + +} +} + +#endif // LAUNCHEROPTIONS_H diff --git a/plugins/unityshell/src/MockLauncherIcon.h b/plugins/unityshell/src/MockLauncherIcon.h index f8cba68a2..835a54197 100644 --- a/plugins/unityshell/src/MockLauncherIcon.h +++ b/plugins/unityshell/src/MockLauncherIcon.h @@ -27,6 +27,8 @@ #include <Nux/BaseWindow.h> #include <Nux/View.h> +#include <gtk/gtk.h> + #include <sigc++/sigc++.h> #include <libdbusmenu-glib/menuitem.h> @@ -45,6 +47,9 @@ public: : icon_(0) { tooltip_text = "Mock Icon"; + transform_map.resize(10); + sort_priority_ = 0; + type_ = TYPE_APPLICATION; } std::string GetName() const { return "MockLauncherIcon"; } @@ -60,7 +65,23 @@ public: return 0; } - std::vector<Window> RelatedXids () + std::vector<Window> Windows () + { + std::vector<Window> result; + + result.push_back ((100 << 16) + 200); + result.push_back ((500 << 16) + 200); + result.push_back ((300 << 16) + 200); + result.push_back ((200 << 16) + 200); + result.push_back ((300 << 16) + 200); + result.push_back ((100 << 16) + 200); + result.push_back ((300 << 16) + 200); + result.push_back ((600 << 16) + 200); + + return result; + } + + std::vector<Window> WindowsForMonitor (int monitor) { std::vector<Window> result; @@ -81,26 +102,37 @@ public: return std::string(); } - void SetSortPriority(int priority) {} + void SetSortPriority(int priority) { sort_priority_ = priority; } - bool OpenQuicklist(bool default_to_first_item = false) + bool OpenQuicklist(bool default_to_first_item = false, int monitor = -1) { return false; } - void SetCenter(nux::Point3 center) {} + void SetCenter(nux::Point3 center, int monitor, nux::Geometry geo) {} - nux::Point3 GetCenter() + nux::Point3 GetCenter(int monitor) { return nux::Point3(); } - std::vector<nux::Vector4> & GetTransform(TransformIndex index) + nux::Point3 GetSavedCenter(int monitor) + { + return nux::Point3(); + } + + void SaveCenter() {} + + std::vector<nux::Vector4> & GetTransform(TransformIndex index, int monitor) { - if (transform_map.find(index) == transform_map.end()) - transform_map[index] = std::vector<nux::Vector4> (4); + auto iter = transform_map[monitor].find(index); + if (iter == transform_map[monitor].end()) + { + auto iter2 = transform_map[monitor].insert(std::map<TransformIndex, std::vector<nux::Vector4> >::value_type(index, std::vector<nux::Vector4>(4))); + return iter2.first->second; + } - return transform_map[index]; + return iter->second; } void Activate(ActionArg arg) {} @@ -109,7 +141,7 @@ public: int SortPriority() { - return 0; + return sort_priority_; } int RelatedWindows() @@ -117,7 +149,7 @@ public: return 7; } - const bool HasWindowOnViewport() + const bool WindowVisibleOnMonitor(int monitor) { return false; } @@ -137,11 +169,15 @@ public: return 0.0f; } - bool ShowInSwitcher() + bool ShowInSwitcher(bool current) { return true; } + void InsertEntryRemote(LauncherEntryRemote* remote) {} + + void RemoveEntryRemote(LauncherEntryRemote* remote) {} + unsigned long long SwitcherPriority() { return 0; @@ -154,6 +190,8 @@ public: void SetQuirk(Quirk quirk, bool value) {} + void ResetQuirkTime(Quirk quirk) {}; + struct timespec GetQuirkTime(Quirk quirk) { timespec tv; @@ -162,7 +200,7 @@ public: IconType Type() { - return TYPE_APPLICATION; + return type_; } nux::Color BackgroundColor() @@ -263,9 +301,10 @@ private: } - std::map<TransformIndex, std::vector<nux::Vector4> > transform_map; + std::vector<std::map<TransformIndex, std::vector<nux::Vector4> > > transform_map; nux::BaseTexture* icon_; - + int sort_priority_; + IconType type_; }; } diff --git a/plugins/unityshell/src/OverlayRenderer.cpp b/plugins/unityshell/src/OverlayRenderer.cpp index f976ee073..d0cecee8c 100644 --- a/plugins/unityshell/src/OverlayRenderer.cpp +++ b/plugins/unityshell/src/OverlayRenderer.cpp @@ -277,8 +277,8 @@ void OverlayRendererImpl::Draw(nux::GraphicsEngine& gfx_context, nux::Geometry c texxform_absolute_bg.flip_v_coord = false; - texxform_absolute_bg.uoffset = (1.0f / bg_shine_texture_->GetWidth()) * (absolute_geo.x); - texxform_absolute_bg.voffset = (1.0f / bg_shine_texture_->GetHeight()) * (absolute_geo.y); + texxform_absolute_bg.uoffset = (1.0f / bg_shine_texture_->GetWidth()) * parent->x_offset; + texxform_absolute_bg.voffset = (1.0f / bg_shine_texture_->GetHeight()) * parent->y_offset; gfx_context.GetRenderStates().SetColorMask(true, true, true, false); gfx_context.GetRenderStates().SetBlend(true, GL_DST_COLOR, GL_ONE); @@ -384,8 +384,8 @@ void OverlayRendererImpl::DrawContent(nux::GraphicsEngine& gfx_context, nux::Geo rop.SrcBlend = GL_DST_COLOR; rop.DstBlend = GL_ONE; texxform_absolute_bg.flip_v_coord = false; - texxform_absolute_bg.uoffset = (1.0f / bg_shine_texture_->GetWidth()) * (absolute_geo.x); - texxform_absolute_bg.voffset = (1.0f / bg_shine_texture_->GetHeight()) * (absolute_geo.y); + texxform_absolute_bg.uoffset = (1.0f / bg_shine_texture_->GetWidth()) * parent->x_offset; + texxform_absolute_bg.voffset = (1.0f / bg_shine_texture_->GetHeight()) * parent->y_offset; nux::GetPainter().PushTextureLayer(gfx_context, bg_layer_->GetGeometry(), bg_shine_texture_, diff --git a/plugins/unityshell/src/OverlayRenderer.h b/plugins/unityshell/src/OverlayRenderer.h index ba41c22b2..f4bd624f1 100644 --- a/plugins/unityshell/src/OverlayRenderer.h +++ b/plugins/unityshell/src/OverlayRenderer.h @@ -36,6 +36,9 @@ public: // We only ever want one OverlayRenderer per view, so if you must take a pointer, take this unique one that will die // when it goes out of scope typedef std::unique_ptr<OverlayRenderer> Ptr; + + nux::Property<int> x_offset; + nux::Property<int> y_offset; OverlayRenderer(); ~OverlayRenderer(); diff --git a/plugins/unityshell/src/PanelView.cpp b/plugins/unityshell/src/PanelView.cpp index 29a502dff..acaec1889 100644 --- a/plugins/unityshell/src/PanelView.cpp +++ b/plugins/unityshell/src/PanelView.cpp @@ -182,7 +182,7 @@ void PanelView::OnDashHidden(GVariant* data, PanelView* self) void PanelView::OnDashShown(GVariant* data, PanelView* self) { - if (self->_is_primary) + if (self->_monitor == g_variant_get_int32(data)) { self->bg_effect_helper_.enabled = true; self->_dash_is_open = true; diff --git a/plugins/unityshell/src/PluginAdapter.cpp b/plugins/unityshell/src/PluginAdapter.cpp index dbc300053..82e18fd92 100644 --- a/plugins/unityshell/src/PluginAdapter.cpp +++ b/plugins/unityshell/src/PluginAdapter.cpp @@ -572,10 +572,11 @@ PluginAdapter::Lower(guint32 xid) } void -PluginAdapter::FocusWindowGroup(std::vector<Window> window_ids, FocusVisibility focus_visibility) +PluginAdapter::FocusWindowGroup(std::vector<Window> window_ids, FocusVisibility focus_visibility, int monitor) { CompPoint target_vp = m_Screen->vp(); - CompWindow* top_win = NULL; + CompWindow* top_window = NULL; + CompWindow* top_window_on_monitor = NULL; bool any_on_current = false; bool any_mapped = false; bool forced_unminimize = false; @@ -632,7 +633,9 @@ PluginAdapter::FocusWindowGroup(std::vector<Window> window_ids, FocusVisibility win->mapNum () == 0)) { bool is_mapped = win->mapNum () != 0; - top_win = win; + top_window = win; + if (monitor >= 0 && win->outputDevice() == monitor) + top_window_on_monitor = win; win->unminimize (); forced_unminimize = true; @@ -646,14 +649,18 @@ PluginAdapter::FocusWindowGroup(std::vector<Window> window_ids, FocusVisibility if (!forced_unminimize || target_vp == m_Screen->vp()) { win->raise(); - top_win = win; + top_window = win; + if (monitor >= 0 && win->outputDevice() == monitor) + top_window_on_monitor = win; } } } } - if (top_win) - top_win->activate(); + if (monitor > 0 && top_window_on_monitor) + top_window_on_monitor->activate(); + else if (top_window) + top_window->activate(); } bool diff --git a/plugins/unityshell/src/PluginAdapter.h b/plugins/unityshell/src/PluginAdapter.h index 153fe563c..8071a3a4a 100644 --- a/plugins/unityshell/src/PluginAdapter.h +++ b/plugins/unityshell/src/PluginAdapter.h @@ -128,7 +128,7 @@ public: void SetWindowIconGeometry(Window window, nux::Geometry const& geo); - void FocusWindowGroup(std::vector<Window> windows, FocusVisibility); + void FocusWindowGroup(std::vector<Window> windows, FocusVisibility, int monitor = -1); bool ScaleWindowGroup(std::vector<Window> windows, int state, bool force); bool IsScreenGrabbed(); diff --git a/plugins/unityshell/src/PointerBarrier.cpp b/plugins/unityshell/src/PointerBarrier.cpp new file mode 100644 index 000000000..d641fd5df --- /dev/null +++ b/plugins/unityshell/src/PointerBarrier.cpp @@ -0,0 +1,173 @@ +// -*- 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/>. +*/ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <X11/extensions/Xfixes.h> + +#include "PointerBarrier.h" + +namespace unity +{ +namespace ui +{ + +namespace local +{ +namespace +{ + bool is_selected_for = false; +} +} + +PointerBarrierWrapper::PointerBarrierWrapper() +{ + last_event_ = 0; + last_y_ = 0; + last_x_ = 0; + active = false; + smoothing = 100; + smoothing_count_ = 0; + smoothing_accum_ = 0; +} + +void PointerBarrierWrapper::ConstructBarrier() +{ + if (active) + return; + + Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); + + XFixesQueryExtension(dpy, &event_base_, &error_base_); + + int maj,min; + XFixesQueryVersion(dpy, &maj, &min); + + barrier = XFixesCreatePointerBarrierVelocity(dpy, + DefaultRootWindow(dpy), + x1, y1, + x2, y2, + 0, + threshold, + 0, + NULL); + + if (!local::is_selected_for) + { + XFixesSelectBarrierInput(dpy, DefaultRootWindow(dpy), 0xdeadbeef); + local::is_selected_for = true; + } + + active = true; + + nux::GraphicsDisplay::EventFilterArg event_filter; + event_filter.filter = &PointerBarrierWrapper::HandleEventWrapper; + event_filter.data = this; + + nux::GetGraphicsDisplay()->AddEventFilter(event_filter); +} + +void PointerBarrierWrapper::DestroyBarrier() +{ + if (!active) + return; + + active = false; + + Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); + XFixesDestroyPointerBarrier(dpy, barrier); + + nux::GetGraphicsDisplay()->RemoveEventFilter(this); +} + +void PointerBarrierWrapper::ReleaseBarrier(int event_id) +{ + XFixesBarrierReleasePointer (nux::GetGraphicsDisplay()->GetX11Display(), barrier, event_id); +} + +void PointerBarrierWrapper::EmitCurrentData() +{ + if (smoothing_count_ <= 0) + return; + + BarrierEvent::Ptr event (new BarrierEvent()); + event->x = last_x_; + event->y = last_y_; + event->velocity = smoothing_accum_ / smoothing_count_; + event->event_id = last_event_; + + barrier_event.emit(this, event); + + smoothing_accum_ = 0; + smoothing_count_ = 0; +} + +bool PointerBarrierWrapper::HandleEvent(XEvent xevent) +{ + if(xevent.type - event_base_ == XFixesBarrierNotify) + { + XFixesBarrierNotifyEvent *notify_event = (XFixesBarrierNotifyEvent *)&xevent; + + if (notify_event->barrier == barrier && notify_event->subtype == XFixesBarrierHitNotify) + { + if (notify_event->event_id != last_event_) + { + EmitCurrentData(); + if (smoothing_handle_) + { + g_source_remove(smoothing_handle_); + smoothing_handle_ = 0; + } + } + + last_x_ = notify_event->x; + last_y_ = notify_event->y; + last_event_ = notify_event->event_id; + smoothing_accum_ += notify_event->velocity; + smoothing_count_++; + + if (!smoothing_handle_) + { + auto smoothing_cb = [](gpointer user_data) -> gboolean + { + PointerBarrierWrapper* self = (PointerBarrierWrapper*)user_data; + self->EmitCurrentData(); + + self->smoothing_handle_ = 0; + return FALSE; + }; + + smoothing_handle_ = g_timeout_add(smoothing(), smoothing_cb, this); + } + + } + + return notify_event->barrier == barrier; + } + + return false; +} + +bool PointerBarrierWrapper::HandleEventWrapper(XEvent event, void* data) +{ + PointerBarrierWrapper* wrapper = (PointerBarrierWrapper*)data; + return wrapper->HandleEvent(event); +} + +} +} diff --git a/plugins/unityshell/src/PointerBarrier.h b/plugins/unityshell/src/PointerBarrier.h new file mode 100644 index 000000000..00761f03f --- /dev/null +++ b/plugins/unityshell/src/PointerBarrier.h @@ -0,0 +1,89 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2010 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: Jason Smith <jason.smith@canonical.com> + */ + +#ifndef UNITY_POINTERWRAPPER_H +#define UNITY_POINTERWRAPPER_H + +#include <Nux/Nux.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xfixes.h> +#include <sigc++/sigc++.h> + +namespace unity +{ +namespace ui +{ + +class BarrierEvent +{ +public: + typedef std::shared_ptr<BarrierEvent> Ptr; + + int x; + int y; + int velocity; + int event_id; +}; + +class PointerBarrierWrapper +{ +public: + typedef std::shared_ptr<PointerBarrierWrapper> Ptr; + + nux::Property<int> x1; + nux::Property<int> x2; + nux::Property<int> y1; + nux::Property<int> y2; + + nux::Property<int> threshold; + + nux::Property<bool> active; + + nux::Property<int> smoothing; + + PointerBarrierWrapper(); + + void ConstructBarrier(); + void DestroyBarrier(); + void ReleaseBarrier(int event_id); + + sigc::signal<void, PointerBarrierWrapper*, BarrierEvent::Ptr> barrier_event; + +private: + void EmitCurrentData(); + bool HandleEvent (XEvent event); + static bool HandleEventWrapper(XEvent event, void* data); + + int last_event_; + int last_x_; + int last_y_; + + int event_base_; + int error_base_; + PointerBarrier barrier; + + int smoothing_count_; + int smoothing_accum_; + guint smoothing_handle_; +}; + +} +} + +#endif \ No newline at end of file diff --git a/plugins/unityshell/src/ShortcutController.cpp b/plugins/unityshell/src/ShortcutController.cpp index 56b9e54b4..b659633ef 100644 --- a/plugins/unityshell/src/ShortcutController.cpp +++ b/plugins/unityshell/src/ShortcutController.cpp @@ -115,10 +115,12 @@ void Controller::Show() g_source_remove (show_timer_); if (enabled_) + { show_timer_ = g_timeout_add(SUPER_TAP_DURATION, &Controller::OnShowTimer, this); + model_->Fill(); + visible_ = true; + } - model_->Fill(); - visible_ = true; } gboolean Controller::OnShowTimer(gpointer data) diff --git a/plugins/unityshell/src/ShortcutView.cpp b/plugins/unityshell/src/ShortcutView.cpp index de2e39fb9..ef75e824d 100644 --- a/plugins/unityshell/src/ShortcutView.cpp +++ b/plugins/unityshell/src/ShortcutView.cpp @@ -42,19 +42,14 @@ namespace NUX_IMPLEMENT_OBJECT_TYPE(View); -View::View(NUX_FILE_LINE_DECL) - : nux::View(NUX_FILE_LINE_PARAM) +View::View() + : ui::UnityWindowView() { layout_ = new nux::VLayout(); layout_->SetPadding(50, 38); layout_->SetSpaceBetweenChildren(20); SetLayout(layout_); - background_top_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_top.png", -1, true); - background_left_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_left.png", -1, true); - background_corner_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_corner.png", -1, true); - rounding_texture_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_round_rect.png", -1, true); - std::string header = "<b>"; header += _("Keyboard Shortcuts"); header += "</b>"; @@ -77,23 +72,10 @@ View::View(NUX_FILE_LINE_DECL) // Column 2... columns_.push_back(new nux::VLayout()); columns_layout_->AddLayout(columns_[1], 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); - - bg_effect_helper_.owner = this; } View::~View() { - if (background_top_ != NULL) - background_top_->UnReference(); - - if (background_left_ != NULL) - background_left_->UnReference(); - - if (background_corner_ != NULL) - background_corner_->UnReference(); - - if (rounding_texture_ != NULL) - rounding_texture_->UnReference(); } void View::SetModel(Model::Ptr model) @@ -109,11 +91,6 @@ Model::Ptr View::GetModel() return model_; } -void View::SetupBackground(bool enabled) -{ - bg_effect_helper_.enabled = enabled; -} - nux::LinearLayout* View::CreateSectionLayout(const char* section_name) { nux::VLayout* layout = new nux::VLayout(NUX_TRACKER_LOCATION); @@ -197,19 +174,9 @@ nux::LinearLayout* View::CreateIntermediateLayout() return layout; } -void View::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) +nux::Geometry View::GetBackgroundGeometry() { - return; -} - -void View::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) -{ nux::Geometry base = GetGeometry(); - GfxContext.PushClippingRectangle(base); - - // clear region - gPainter.PaintBackground(GfxContext, base); - nux::Geometry background_geo; background_geo.width = base.width; @@ -217,165 +184,12 @@ void View::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) background_geo.x = (base.width - background_geo.width)/2; background_geo.y = (base.height - background_geo.height)/2; - // magic constant comes from texture contents (distance to cleared area) - const int internal_offset = 20; - nux::Geometry internal_clip(background_geo.x + internal_offset, - background_geo.y + internal_offset, - background_geo.width - internal_offset * 2, - background_geo.height - internal_offset * 2); - GfxContext.PushClippingRectangle(internal_clip); - - nux::Geometry geo_absolute = GetAbsoluteGeometry(); - if (BackgroundEffectHelper::blur_type != BLUR_NONE) - { - nux::Geometry blur_geo(geo_absolute.x, geo_absolute.y, base.width, base.height); - auto blur_texture = bg_effect_helper_.GetBlurRegion(blur_geo); - - if (blur_texture.IsValid()) - { - nux::TexCoordXForm texxform_blur_bg; - texxform_blur_bg.flip_v_coord = true; - texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); - texxform_blur_bg.uoffset = ((float) base.x) / geo_absolute.width; - texxform_blur_bg.voffset = ((float) base.y) / geo_absolute.height; - - nux::ROPConfig rop; - rop.Blend = false; - rop.SrcBlend = GL_ONE; - rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; - - gPainter.PushDrawTextureLayer(GfxContext, base, - blur_texture, - texxform_blur_bg, - nux::color::White, - true, - rop); - } - } - - nux::ROPConfig rop; - rop.Blend = true; - rop.SrcBlend = GL_ONE; - rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; - gPainter.PushDrawColorLayer(GfxContext, internal_clip, background_color, false, rop); - - // Make round corners - rop.Blend = true; - rop.SrcBlend = GL_ZERO; - rop.DstBlend = GL_SRC_ALPHA; - gPainter.PaintShapeCornerROP(GfxContext, - internal_clip, - nux::color::White, - nux::eSHAPE_CORNER_ROUND4, - nux::eCornerTopLeft | nux::eCornerTopRight | - nux::eCornerBottomLeft | nux::eCornerBottomRight, - true, - rop); - - GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER); - - GfxContext.PopClippingRectangle(); - GfxContext.PopClippingRectangle(); - - DrawBackground(GfxContext, background_geo); - - - layout_->ProcessDraw(GfxContext, force_draw); + return background_geo; } - -void View::DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo) -{ - int border = 30; - - GfxContext.GetRenderStates().SetBlend(TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - nux::TexCoordXForm texxform; - texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); - texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT); - - // Draw TOP-LEFT CORNER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = border; - texxform.v1 = border; - GfxContext.QRP_1Tex(geo.x, geo.y, - border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw TOP-RIGHT CORNER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = border; - texxform.v1 = border; - texxform.flip_u_coord = true; - texxform.flip_v_coord = false; - GfxContext.QRP_1Tex(geo.x + geo.width - border, geo.y, - border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw BOTTOM-LEFT CORNER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = border; - texxform.v1 = border; - texxform.flip_u_coord = false; - texxform.flip_v_coord = true; - GfxContext.QRP_1Tex(geo.x, geo.y + geo.height - border, - border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw BOTTOM-RIGHT CORNER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = border; - texxform.v1 = border; - texxform.flip_u_coord = true; - texxform.flip_v_coord = true; - GfxContext.QRP_1Tex(geo.x + geo.width - border, geo.y + geo.height - border, - border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White); - - int top_width = background_top_->GetWidth(); - int top_height = background_top_->GetHeight(); - - // Draw TOP BORDER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = top_width; - texxform.v1 = top_height; - texxform.flip_u_coord = false; - texxform.flip_v_coord = false; - GfxContext.QRP_1Tex(geo.x + border, geo.y, geo.width - border - border, border, background_top_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw BOTTOM BORDER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = top_width; - texxform.v1 = top_height; - texxform.flip_u_coord = false; - texxform.flip_v_coord = true; - GfxContext.QRP_1Tex(geo.x + border, geo.y + geo.height - border, geo.width - border - border, border, background_top_->GetDeviceTexture(), texxform, nux::color::White); - - - int left_width = background_left_->GetWidth(); - int left_height = background_left_->GetHeight(); - - // Draw LEFT BORDER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = left_width; - texxform.v1 = left_height; - texxform.flip_u_coord = false; - texxform.flip_v_coord = false; - GfxContext.QRP_1Tex(geo.x, geo.y + border, border, geo.height - border - border, background_left_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw RIGHT BORDER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = left_width; - texxform.v1 = left_height; - texxform.flip_u_coord = true; - texxform.flip_v_coord = false; - GfxContext.QRP_1Tex(geo.x + geo.width - border, geo.y + border, border, geo.height - border - border, background_left_->GetDeviceTexture(), texxform, nux::color::White); - - GfxContext.GetRenderStates().SetBlend(FALSE); +void View::DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry clip) +{ + layout_->ProcessDraw(GfxContext, force_draw); } void View::RenderColumns() diff --git a/plugins/unityshell/src/ShortcutView.h b/plugins/unityshell/src/ShortcutView.h index 2f58c4f7e..259a1f0f1 100644 --- a/plugins/unityshell/src/ShortcutView.h +++ b/plugins/unityshell/src/ShortcutView.h @@ -28,6 +28,7 @@ #include <Nux/View.h> #include <Nux/VLayout.h> +#include "UnityWindowView.h" #include "BackgroundEffectHelper.h" #include "ShortcutModel.h" @@ -36,29 +37,24 @@ namespace unity namespace shortcut { -class View : public nux::View +class View : public ui::UnityWindowView { - NUX_DECLARE_OBJECT_TYPE(View, nux::View); + NUX_DECLARE_OBJECT_TYPE(View, ui::UnityWindowView); public: typedef nux::ObjectPtr<View> Ptr; // Ctor and dtor - View(NUX_FILE_LINE_PROTO); + View(); ~View(); // Public methods void SetModel(Model::Ptr model); Model::Ptr GetModel(); - - void SetupBackground(bool enabled); - - // Properties - nux::Property<nux::Color> background_color; protected: // Protected methods - void Draw(nux::GraphicsEngine& GfxContext, bool force_draw); - void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw); + void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry clip); + nux::Geometry GetBackgroundGeometry(); private: // Private methods @@ -66,23 +62,14 @@ private: nux::LinearLayout* CreateShortKeyEntryLayout(AbstractHint* hint); nux::LinearLayout* CreateIntermediateLayout(); - void DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo); void RenderColumns(); // Private members Model::Ptr model_; - nux::BaseTexture* background_top_; - nux::BaseTexture* background_left_; - nux::BaseTexture* background_corner_; - nux::BaseTexture* rounding_texture_; - nux::VLayout* layout_; nux::HLayout* columns_layout_; std::vector<nux::VLayout*> columns_; - - BackgroundEffectHelper bg_effect_helper_; - }; } // namespace shortcut diff --git a/plugins/unityshell/src/SimpleLauncherIcon.cpp b/plugins/unityshell/src/SimpleLauncherIcon.cpp index 3731a6c40..6d04ee58e 100644 --- a/plugins/unityshell/src/SimpleLauncherIcon.cpp +++ b/plugins/unityshell/src/SimpleLauncherIcon.cpp @@ -17,12 +17,14 @@ * Authored by: Jason Smith <jason.smith@canonical.com> */ +#ifndef UNITY_SIMPLELAUNCHERICON_H +#define UNITY_SIMPLELAUNCHERICON_H + #include <NuxCore/Logger.h> #include <Nux/Nux.h> #include <Nux/BaseWindow.h> #include "SimpleLauncherIcon.h" -#include "Launcher.h" #include "PluginAdapter.h" #include "ubus-server.h" @@ -38,8 +40,8 @@ namespace nux::logging::Logger logger("unity.dash.CategoryViewGrid"); } -SimpleLauncherIcon::SimpleLauncherIcon(Launcher* IconManager) - : LauncherIcon(IconManager) +SimpleLauncherIcon::SimpleLauncherIcon() + : LauncherIcon() , icon_name("", sigc::mem_fun(this, &SimpleLauncherIcon::SetIconName)) , theme_changed_id_(0) { @@ -65,23 +67,23 @@ SimpleLauncherIcon::~SimpleLauncherIcon() g_signal_handler_disconnect(gtk_icon_theme_get_default(), theme_changed_id_); } -void SimpleLauncherIcon::OnMouseDown(int button) +void SimpleLauncherIcon::OnMouseDown(int button, int monitor) { } -void SimpleLauncherIcon::OnMouseUp(int button) +void SimpleLauncherIcon::OnMouseUp(int button, int monitor) { } -void SimpleLauncherIcon::OnMouseClick(int button) +void SimpleLauncherIcon::OnMouseClick(int button, int monitor) { } -void SimpleLauncherIcon::OnMouseEnter() +void SimpleLauncherIcon::OnMouseEnter(int monitor) { } -void SimpleLauncherIcon::OnMouseLeave() +void SimpleLauncherIcon::OnMouseLeave(int monitor) { } @@ -142,3 +144,5 @@ void SimpleLauncherIcon::OnIconThemeChanged(GtkIconTheme* icon_theme, gpointer d } // namespace launcher } // namespace unity + +#endif \ No newline at end of file diff --git a/plugins/unityshell/src/SimpleLauncherIcon.h b/plugins/unityshell/src/SimpleLauncherIcon.h index af3af5264..15479ec4c 100644 --- a/plugins/unityshell/src/SimpleLauncherIcon.h +++ b/plugins/unityshell/src/SimpleLauncherIcon.h @@ -32,7 +32,7 @@ class Launcher; class SimpleLauncherIcon : public LauncherIcon { public: - SimpleLauncherIcon(Launcher* IconManager); + SimpleLauncherIcon(); virtual ~SimpleLauncherIcon(); // override @@ -45,11 +45,11 @@ public: sigc::signal<void> activate; protected: - virtual void OnMouseDown(int button); - virtual void OnMouseUp(int button); - virtual void OnMouseClick(int button); - virtual void OnMouseEnter(); - virtual void OnMouseLeave(); + virtual void OnMouseDown(int button, int monitor); + virtual void OnMouseUp(int button, int monitor); + virtual void OnMouseClick(int button, int monitor); + virtual void OnMouseEnter(int monitor); + virtual void OnMouseLeave(int monitor); virtual void ActivateLauncherIcon(ActionArg arg); private: diff --git a/plugins/unityshell/src/SoftwareCenterLauncherIcon.cpp b/plugins/unityshell/src/SoftwareCenterLauncherIcon.cpp index 90e4a9f82..d07060404 100644 --- a/plugins/unityshell/src/SoftwareCenterLauncherIcon.cpp +++ b/plugins/unityshell/src/SoftwareCenterLauncherIcon.cpp @@ -44,8 +44,8 @@ namespace unity namespace launcher { -SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(Launcher* IconManager, BamfApplication* app, char* aptdaemon_trans_id, char* icon_path) -: BamfLauncherIcon(IconManager, app) +SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(BamfApplication* app, char* aptdaemon_trans_id, char* icon_path) +: BamfLauncherIcon(app) { _aptdaemon_trans_id = aptdaemon_trans_id; diff --git a/plugins/unityshell/src/SoftwareCenterLauncherIcon.h b/plugins/unityshell/src/SoftwareCenterLauncherIcon.h index c6f441c11..e12bc9918 100644 --- a/plugins/unityshell/src/SoftwareCenterLauncherIcon.h +++ b/plugins/unityshell/src/SoftwareCenterLauncherIcon.h @@ -40,7 +40,7 @@ class SoftwareCenterLauncherIcon : public BamfLauncherIcon { public: - SoftwareCenterLauncherIcon(Launcher* IconManager, BamfApplication* app, char* aptdaemon_trans_id, char* icon_path); + SoftwareCenterLauncherIcon(BamfApplication* app, char* aptdaemon_trans_id, char* icon_path); virtual ~SoftwareCenterLauncherIcon(); gchar* original_tooltip_text; diff --git a/plugins/unityshell/src/SpacerLauncherIcon.cpp b/plugins/unityshell/src/SpacerLauncherIcon.cpp index 98dbcca36..74d420ba2 100644 --- a/plugins/unityshell/src/SpacerLauncherIcon.cpp +++ b/plugins/unityshell/src/SpacerLauncherIcon.cpp @@ -27,8 +27,8 @@ namespace unity namespace launcher { -SpacerLauncherIcon::SpacerLauncherIcon(Launcher* IconManager) - : SimpleLauncherIcon(IconManager) +SpacerLauncherIcon::SpacerLauncherIcon() + : SimpleLauncherIcon() { SetQuirk(QUIRK_VISIBLE, true); SetQuirk(QUIRK_RUNNING, false); diff --git a/plugins/unityshell/src/SpacerLauncherIcon.h b/plugins/unityshell/src/SpacerLauncherIcon.h index 41d76ce2f..a326357aa 100644 --- a/plugins/unityshell/src/SpacerLauncherIcon.h +++ b/plugins/unityshell/src/SpacerLauncherIcon.h @@ -30,7 +30,7 @@ namespace launcher class SpacerLauncherIcon : public SimpleLauncherIcon { public: - SpacerLauncherIcon(Launcher* launcher); + SpacerLauncherIcon(); bool IsSpacer() { diff --git a/plugins/unityshell/src/SwitcherController.cpp b/plugins/unityshell/src/SwitcherController.cpp index bc3df3307..0a4e5a46e 100644 --- a/plugins/unityshell/src/SwitcherController.cpp +++ b/plugins/unityshell/src/SwitcherController.cpp @@ -45,6 +45,7 @@ Controller::Controller() timeout_length = 150; detail_on_timeout = true; detail_timeout_length = 1500; + monitor_ = 0; bg_color_ = nux::Color(0.0, 0.0, 0.0, 0.5); @@ -72,11 +73,6 @@ void Controller::OnBackgroundUpdate(GVariant* data, Controller* self) self->view_->background_color = self->bg_color_; } -bool IsOnOtherViewport (AbstractLauncherIcon* icon) -{ - return !icon->HasWindowOnViewport(); -} - void Controller::Show(ShowMode show, SortMode sort, bool reverse, std::vector<AbstractLauncherIcon*> results) { @@ -85,11 +81,6 @@ void Controller::Show(ShowMode show, SortMode sort, bool reverse, std::sort(results.begin(), results.end(), CompareSwitcherItemsPriority); } - if (show == ShowMode::CURRENT_VIEWPORT) - { - results.erase(std::remove_if(results.begin(), results.end(), IsOnOtherViewport), results.end()); - } - model_.reset(new SwitcherModel(results)); AddChild(model_.get()); model_->selection_changed.connect(sigc::mem_fun(this, &Controller::OnModelSelectionChanged)); @@ -177,6 +168,7 @@ void Controller::ConstructView() AddChild(view_.GetPointer()); view_->SetModel(model_); view_->background_color = bg_color_; + view_->monitor = monitor_; if (!view_window_) { @@ -197,9 +189,13 @@ void Controller::ConstructView() view_window_->ShowWindow(true); } -void Controller::SetWorkspace(nux::Geometry geo) +void Controller::SetWorkspace(nux::Geometry geo, int monitor) { + monitor_ = monitor; workarea_ = geo; + + if (view_) + view_->monitor = monitor_; } void Controller::Hide(bool accept_state) @@ -269,7 +265,7 @@ void Controller::Next() switch (detail_mode_) { case TAB_NEXT_WINDOW: - if (model_->detail_selection_index < model_->Selection()->RelatedXids ().size () - 1) + if (model_->detail_selection_index < model_->Selection()->Windows().size () - 1) model_->NextDetail(); else model_->Next(); @@ -324,7 +320,7 @@ SwitcherView* Controller::GetView() void Controller::SetDetail(bool value, unsigned int min_windows) { - if (value && model_->Selection()->RelatedXids().size () >= min_windows) + if (value && model_->Selection()->Windows().size () >= min_windows) { model_->detail_selection = true; detail_mode_ = TAB_NEXT_WINDOW_LOOP; @@ -409,7 +405,7 @@ void Controller::SelectFirstItem() unsigned int first_second = 0; // first icons second highest active unsigned int second_first = 0; // second icons first highest active - for (guint32 xid : first->RelatedXids()) + for (guint32 xid : first->Windows()) { unsigned int num = WindowManager::Default()->GetWindowActiveNumber(xid); @@ -424,7 +420,7 @@ void Controller::SelectFirstItem() } } - for (guint32 xid : second->RelatedXids()) + for (guint32 xid : second->Windows()) { second_first = MAX (WindowManager::Default()->GetWindowActiveNumber(xid), second_first); } diff --git a/plugins/unityshell/src/SwitcherController.h b/plugins/unityshell/src/SwitcherController.h index 81cd29dbf..1c1afe134 100644 --- a/plugins/unityshell/src/SwitcherController.h +++ b/plugins/unityshell/src/SwitcherController.h @@ -87,7 +87,7 @@ public: void SelectFirstItem(); - void SetWorkspace(nux::Geometry geo); + void SetWorkspace(nux::Geometry geo, int monitor); SwitcherView * GetView (); @@ -120,6 +120,7 @@ private: nux::BaseWindow* view_window_; nux::HLayout* main_layout_; + int monitor_; bool visible_; guint show_timer_; guint detail_timer_; diff --git a/plugins/unityshell/src/SwitcherModel.cpp b/plugins/unityshell/src/SwitcherModel.cpp index febf16c40..37f63991f 100644 --- a/plugins/unityshell/src/SwitcherModel.cpp +++ b/plugins/unityshell/src/SwitcherModel.cpp @@ -148,7 +148,7 @@ std::vector<Window> SwitcherModel::DetailXids() { std::vector<Window> results; - results = Selection()->RelatedXids (); + results = Selection()->Windows(); if (only_detail_on_viewport) { diff --git a/plugins/unityshell/src/SwitcherView.cpp b/plugins/unityshell/src/SwitcherView.cpp index eb73b7102..a75ee16bb 100644 --- a/plugins/unityshell/src/SwitcherView.cpp +++ b/plugins/unityshell/src/SwitcherView.cpp @@ -40,8 +40,8 @@ namespace switcher NUX_IMPLEMENT_OBJECT_TYPE(SwitcherView); -SwitcherView::SwitcherView(NUX_FILE_LINE_DECL) - : View(NUX_FILE_LINE_PARAM) +SwitcherView::SwitcherView() + : UnityWindowView() , target_sizes_set_(false) , redraw_handle_(0) { @@ -57,6 +57,7 @@ SwitcherView::SwitcherView(NUX_FILE_LINE_DECL) vertical_size = tile_size + 80; text_size = 15; animation_length = 250; + monitor = -1; spread_size = 3.5f; render_boxes = false; @@ -67,9 +68,6 @@ SwitcherView::SwitcherView(NUX_FILE_LINE_DECL) render_targets_.clear (); - background_top_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_top.png", -1, true); - background_left_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_left.png", -1, true); - background_corner_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_corner.png", -1, true); rounding_texture_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_round_rect.png", -1, true); text_view_ = new nux::StaticCairoText("Testing"); @@ -81,15 +79,10 @@ SwitcherView::SwitcherView(NUX_FILE_LINE_DECL) icon_size.changed.connect (sigc::mem_fun (this, &SwitcherView::OnIconSizeChanged)); tile_size.changed.connect (sigc::mem_fun (this, &SwitcherView::OnTileSizeChanged)); - - bg_effect_helper_.owner = this; } SwitcherView::~SwitcherView() { - background_top_->UnReference(); - background_left_->UnReference(); - background_corner_->UnReference(); rounding_texture_->UnReference(); text_view_->UnReference(); if (redraw_handle_ > 0) @@ -116,11 +109,7 @@ void SwitcherView::AddProperties(GVariantBuilder* builder) .add("spread-size", (float)spread_size); } -void -SwitcherView::SetupBackground() -{ - bg_effect_helper_.enabled = true; -} + LayoutWindowList SwitcherView::ExternalTargets () { @@ -196,11 +185,6 @@ SwitcherModel::Ptr SwitcherView::GetModel() return model_; } -void SwitcherView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) -{ - return; -} - RenderArg SwitcherView::CreateBaseArgForIcon(AbstractLauncherIcon* icon) { RenderArg arg; @@ -210,7 +194,7 @@ RenderArg SwitcherView::CreateBaseArgForIcon(AbstractLauncherIcon* icon) // tells the renderer to render arrows by number arg.running_on_viewport = true; - arg.window_indicators = icon->RelatedWindows(); + arg.window_indicators = icon->WindowsForMonitor(monitor).size(); if (arg.window_indicators > 1) arg.running_arrow = true; else @@ -555,104 +539,9 @@ gboolean SwitcherView::OnDrawTimeout(gpointer data) return FALSE; } -void SwitcherView::DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo) -{ - int border = 30; - - GfxContext.GetRenderStates().SetBlend (TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - nux::TexCoordXForm texxform; - texxform.SetTexCoordType (nux::TexCoordXForm::OFFSET_COORD); - texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT); - - // Draw TOP-LEFT CORNER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = border; - texxform.v1 = border; - GfxContext.QRP_1Tex (geo.x, geo.y, - border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw TOP-RIGHT CORNER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = border; - texxform.v1 = border; - texxform.flip_u_coord = true; - texxform.flip_v_coord = false; - GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y, - border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw BOTTOM-LEFT CORNER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = border; - texxform.v1 = border; - texxform.flip_u_coord = false; - texxform.flip_v_coord = true; - GfxContext.QRP_1Tex (geo.x, geo.y + geo.height - border, - border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw BOTTOM-RIGHT CORNER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = border; - texxform.v1 = border; - texxform.flip_u_coord = true; - texxform.flip_v_coord = true; - GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y + geo.height - border, - border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White); - - int top_width = background_top_->GetWidth(); - int top_height = background_top_->GetHeight(); - - // Draw TOP BORDER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = top_width; - texxform.v1 = top_height; - texxform.flip_u_coord = false; - texxform.flip_v_coord = false; - GfxContext.QRP_1Tex (geo.x + border, geo.y, geo.width - border - border, border, background_top_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw BOTTOM BORDER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = top_width; - texxform.v1 = top_height; - texxform.flip_u_coord = false; - texxform.flip_v_coord = true; - GfxContext.QRP_1Tex (geo.x + border, geo.y + geo.height - border, geo.width - border - border, border, background_top_->GetDeviceTexture(), texxform, nux::color::White); - - - int left_width = background_left_->GetWidth(); - int left_height = background_left_->GetHeight(); - - // Draw LEFT BORDER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = left_width; - texxform.v1 = left_height; - texxform.flip_u_coord = false; - texxform.flip_v_coord = false; - GfxContext.QRP_1Tex (geo.x, geo.y + border, border, geo.height - border - border, background_left_->GetDeviceTexture(), texxform, nux::color::White); - - // Draw RIGHT BORDER - texxform.u0 = 0; - texxform.v0 = 0; - texxform.u1 = left_width; - texxform.v1 = left_height; - texxform.flip_u_coord = true; - texxform.flip_v_coord = false; - GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y + border, border, geo.height - border - border, background_left_->GetDeviceTexture(), texxform, nux::color::White); - - GfxContext.GetRenderStates().SetBlend (FALSE); -} - -void SwitcherView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) +void SwitcherView::PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw) { - timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); + clock_gettime(CLOCK_MONOTONIC, ¤t_); if (!target_sizes_set_) { @@ -660,74 +549,21 @@ void SwitcherView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) target_sizes_set_ = true; } - nux::Geometry base = GetGeometry(); - GfxContext.PushClippingRectangle(base); - - // clear region - gPainter.PaintBackground(GfxContext, base); - nux::Geometry background_geo; - - last_args_ = RenderArgsFlat(background_geo, model_->SelectionIndex(), current); + last_args_ = RenderArgsFlat(background_geo, model_->SelectionIndex(), current_); last_background_ = background_geo; - // magic constant comes from texture contents (distance to cleared area) - const int internal_offset = 20; - nux::Geometry internal_clip(background_geo.x + internal_offset, - background_geo.y + internal_offset, - background_geo.width - internal_offset * 2, - background_geo.height - internal_offset * 2); - GfxContext.PushClippingRectangle(internal_clip); - - - nux::Geometry geo_absolute = GetAbsoluteGeometry (); - if (BackgroundEffectHelper::blur_type != BLUR_NONE) - { - nux::Geometry blur_geo(geo_absolute.x, geo_absolute.y, base.width, base.height); - auto blur_texture = bg_effect_helper_.GetBlurRegion(blur_geo); + icon_renderer_->PreprocessIcons(last_args_, GetGeometry()); +} - if (blur_texture.IsValid()) - { - nux::TexCoordXForm texxform_blur_bg; - texxform_blur_bg.flip_v_coord = true; - texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); - texxform_blur_bg.uoffset = ((float) base.x) / geo_absolute.width; - texxform_blur_bg.voffset = ((float) base.y) / geo_absolute.height; - - nux::ROPConfig rop; - rop.Blend = false; - rop.SrcBlend = GL_ONE; - rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; - - gPainter.PushDrawTextureLayer(GfxContext, base, - blur_texture, - texxform_blur_bg, - nux::color::White, - true, - rop); - } - } +nux::Geometry SwitcherView::GetBackgroundGeometry() +{ + return last_background_; +} - nux::ROPConfig rop; - rop.Blend = true; - rop.SrcBlend = GL_ONE; - rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; - gPainter.PushDrawColorLayer (GfxContext, internal_clip, background_color, false, rop); - - // Make round corners - rop.Blend = true; - rop.SrcBlend = GL_ZERO; - rop.DstBlend = GL_SRC_ALPHA; - gPainter.PaintShapeCornerROP(GfxContext, - internal_clip, - nux::color::White, - nux::eSHAPE_CORNER_ROUND4, - nux::eCornerTopLeft | nux::eCornerTopRight | - nux::eCornerBottomLeft | nux::eCornerBottomRight, - true, - rop); - - icon_renderer_->PreprocessIcons(last_args_, base); +void SwitcherView::DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry internal_clip) +{ + nux::Geometry base = GetGeometry(); GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER); std::list<RenderArg>::iterator it; @@ -779,6 +615,7 @@ void SwitcherView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) // render orange box that will encirlce active item(s) for (LayoutWindow::Ptr window : ExternalTargets()) { + nux::Geometry geo_absolute = GetAbsoluteGeometry(); if (window->alpha >= 1.0f) { nux::Geometry orange_box = window->result; @@ -790,15 +627,10 @@ void SwitcherView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) } } - GfxContext.PopClippingRectangle(); - GfxContext.PopClippingRectangle(); - - DrawBackground(GfxContext, background_geo); - - text_view_->SetBaseY(background_geo.y + background_geo.height - 45); + text_view_->SetBaseY(last_background_.y + last_background_.height - 45); text_view_->Draw(GfxContext, force_draw); - int ms_since_change = TimeUtil::TimeDelta(¤t, &save_time_); + int ms_since_change = TimeUtil::TimeDelta(¤t_, &save_time_); if (ms_since_change < animation_length && redraw_handle_ == 0) redraw_handle_ = g_idle_add_full (G_PRIORITY_DEFAULT, &SwitcherView::OnDrawTimeout, this, NULL); diff --git a/plugins/unityshell/src/SwitcherView.h b/plugins/unityshell/src/SwitcherView.h index 2058aaba8..f0e460fcd 100644 --- a/plugins/unityshell/src/SwitcherView.h +++ b/plugins/unityshell/src/SwitcherView.h @@ -25,6 +25,7 @@ #include "StaticCairoText.h" #include "LayoutSystem.h" #include "BackgroundEffectHelper.h" +#include "UnityWindowView.h" #include "Introspectable.h" @@ -36,6 +37,8 @@ #include <NuxCore/Property.h> + + namespace unity { namespace launcher @@ -45,13 +48,13 @@ class AbstractLauncherIcon; namespace switcher { -class SwitcherView : public debug::Introspectable, public nux::View +class SwitcherView : public debug::Introspectable, public ui::UnityWindowView { - NUX_DECLARE_OBJECT_TYPE(SwitcherView, nux::View); + NUX_DECLARE_OBJECT_TYPE(SwitcherView, ui::UnityWindowView); public: typedef nux::ObjectPtr<SwitcherView> Ptr; - SwitcherView(NUX_FILE_LINE_PROTO); + SwitcherView(); virtual ~SwitcherView(); ui::LayoutWindowList ExternalTargets (); @@ -59,8 +62,6 @@ public: void SetModel(SwitcherModel::Ptr model); SwitcherModel::Ptr GetModel(); - void SetupBackground (); - nux::Property<bool> render_boxes; nux::Property<int> border_size; nux::Property<int> flat_spacing; @@ -70,16 +71,17 @@ public: nux::Property<int> vertical_size; nux::Property<int> text_size; nux::Property<int> animation_length; + nux::Property<int> monitor; nux::Property<double> spread_size; - nux::Property<nux::Color> background_color; protected: // Introspectable methods std::string GetName() const; void AddProperties(GVariantBuilder* builder); - void Draw(nux::GraphicsEngine& GfxContext, bool force_draw); - void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw); + void PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw); + void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry clip); + nux::Geometry GetBackgroundGeometry(); ui::RenderArg InterpolateRenderArgs(ui::RenderArg const& start, ui::RenderArg const& end, float progress); nux::Geometry InterpolateBackground (nux::Geometry const& start, nux::Geometry const& end, float progress); @@ -88,8 +90,6 @@ protected: ui::RenderArg CreateBaseArgForIcon(launcher::AbstractLauncherIcon* icon); private: - void DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo); - void OnSelectionChanged(launcher::AbstractLauncherIcon* selection); void OnDetailSelectionChanged (bool detail); void OnDetailSelectionIndexChanged (unsigned int index); @@ -121,9 +121,6 @@ private: guint redraw_handle_; - nux::BaseTexture* background_top_; - nux::BaseTexture* background_left_; - nux::BaseTexture* background_corner_; nux::BaseTexture* rounding_texture_; nux::StaticCairoText* text_view_; @@ -136,11 +133,10 @@ private: ui::LayoutWindowList render_targets_; + timespec current_; timespec save_time_; bool animation_draw_; - - BackgroundEffectHelper bg_effect_helper_; }; } diff --git a/plugins/unityshell/src/TimeUtil.h b/plugins/unityshell/src/TimeUtil.h index 9f4e4fddc..ab4d109db 100644 --- a/plugins/unityshell/src/TimeUtil.h +++ b/plugins/unityshell/src/TimeUtil.h @@ -25,13 +25,44 @@ namespace unity { class TimeUtil { public: -static int TimeDelta (struct timespec const* x, struct timespec const* y); + static int TimeDelta (struct timespec const* x, struct timespec const* y) + { + return ((x->tv_sec - y->tv_sec) * 1000) + ((x->tv_nsec - y->tv_nsec) / 1000000); + } + + static void SetTimeStruct(struct timespec* timer, struct timespec* sister = 0, int sister_relation = 0) + { + struct timespec current; + clock_gettime(CLOCK_MONOTONIC, ¤t); + + if (sister) + { + int diff = TimeDelta(¤t, sister); + + if (diff < sister_relation) + { + int remove = sister_relation - diff; + SetTimeBack(¤t, remove); + } + } + + timer->tv_sec = current.tv_sec; + timer->tv_nsec = current.tv_nsec; + } + + static void SetTimeBack(struct timespec* timeref, int remove) + { + timeref->tv_sec -= remove / 1000; + remove = remove % 1000; + + if (remove > timeref->tv_nsec / 1000000) + { + timeref->tv_sec--; + timeref->tv_nsec += 1000000000; + } + timeref->tv_nsec -= remove * 1000000; + } }; -inline -int TimeUtil::TimeDelta (struct timespec const* x, struct timespec const* y) -{ - return ((x->tv_sec - y->tv_sec) * 1000) + ((x->tv_nsec - y->tv_nsec) / 1000000); -} } diff --git a/plugins/unityshell/src/TrashLauncherIcon.cpp b/plugins/unityshell/src/TrashLauncherIcon.cpp index 2c666d27e..68d6c89fd 100644 --- a/plugins/unityshell/src/TrashLauncherIcon.cpp +++ b/plugins/unityshell/src/TrashLauncherIcon.cpp @@ -32,8 +32,8 @@ namespace unity namespace launcher { -TrashLauncherIcon::TrashLauncherIcon(Launcher* IconManager) - : SimpleLauncherIcon(IconManager) +TrashLauncherIcon::TrashLauncherIcon() + : SimpleLauncherIcon() , proxy_("org.gnome.Nautilus", "/org/gnome/Nautilus", "org.gnome.Nautilus.FileOperations") { tooltip_text = _("Trash"); diff --git a/plugins/unityshell/src/TrashLauncherIcon.h b/plugins/unityshell/src/TrashLauncherIcon.h index d6b461193..f09319cc7 100644 --- a/plugins/unityshell/src/TrashLauncherIcon.h +++ b/plugins/unityshell/src/TrashLauncherIcon.h @@ -36,7 +36,7 @@ class TrashLauncherIcon : public SimpleLauncherIcon { public: - TrashLauncherIcon(Launcher* launcher); + TrashLauncherIcon(); ~TrashLauncherIcon(); virtual nux::Color BackgroundColor(); diff --git a/plugins/unityshell/src/UScreen.cpp b/plugins/unityshell/src/UScreen.cpp index 1f4ec8131..51b86c9bf 100644 --- a/plugins/unityshell/src/UScreen.cpp +++ b/plugins/unityshell/src/UScreen.cpp @@ -54,6 +54,24 @@ UScreen::GetDefault() } int +UScreen::GetMonitorWithMouse() +{ + GdkScreen* screen; + GdkDevice* device; + GdkDisplay *display; + int x; + int y; + + screen = gdk_screen_get_default(); + display = gdk_display_get_default(); + device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(display)); + + gdk_device_get_position(device, NULL, &x, &y); + + return gdk_screen_get_monitor_at_point(screen, x, y); +} + +int UScreen::GetPrimaryMonitor() { return primary_; diff --git a/plugins/unityshell/src/UScreen.h b/plugins/unityshell/src/UScreen.h index b66a8b607..bb0a60312 100644 --- a/plugins/unityshell/src/UScreen.h +++ b/plugins/unityshell/src/UScreen.h @@ -33,6 +33,7 @@ public: static UScreen* GetDefault(); int GetPrimaryMonitor(); + int GetMonitorWithMouse(); nux::Geometry& GetMonitorGeometry(int monitor); std::vector<nux::Geometry>& GetMonitors(); diff --git a/plugins/unityshell/src/UnityWindowStyle.cpp b/plugins/unityshell/src/UnityWindowStyle.cpp new file mode 100644 index 000000000..826f7669d --- /dev/null +++ b/plugins/unityshell/src/UnityWindowStyle.cpp @@ -0,0 +1,64 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2012 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: Jason Smith <jason.smith@canonical.com> + */ + +#include "UnityWindowStyle.h" + +namespace unity { +namespace ui { + +UnityWindowStyle::UnityWindowStyle() +{ + background_top_ = BaseTexturePtr(nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_top.png", -1, true)); + background_left_ = BaseTexturePtr(nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_left.png", -1, true)); + background_corner_ = BaseTexturePtr(nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_corner.png", -1, true)); +} + +UnityWindowStyle::~UnityWindowStyle() +{ + // nothing to do +} + +int UnityWindowStyle::GetBorderSize() const +{ + return 30; // as measured from textures +} + +int UnityWindowStyle::GetInternalOffset() const +{ + return 20; +} + +nux::BaseTexture* UnityWindowStyle::GetBackgroundTop() const +{ + return background_top_.GetPointer(); +} + +nux::BaseTexture* UnityWindowStyle::GetBackgroundLeft() const +{ + return background_left_.GetPointer(); +} + +nux::BaseTexture* UnityWindowStyle::GetBackgroundCorner() const +{ + return background_corner_.GetPointer(); +} + + +} +} \ No newline at end of file diff --git a/plugins/unityshell/src/UnityWindowStyle.h b/plugins/unityshell/src/UnityWindowStyle.h new file mode 100644 index 000000000..ca0a5b797 --- /dev/null +++ b/plugins/unityshell/src/UnityWindowStyle.h @@ -0,0 +1,54 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2012 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: Jason Smith <jason.smith@canonical.com> + */ + +#ifndef UNITYWINDOWSTYLE_H +#define UNITYWINDOWSTYLE_H + +#include <sigc++/sigc++.h> +#include <Nux/Nux.h> + +namespace unity { +namespace ui { + +class UnityWindowStyle +{ +public: + typedef std::shared_ptr<UnityWindowStyle> Ptr; + typedef nux::ObjectPtr<nux::BaseTexture> BaseTexturePtr; + + UnityWindowStyle(); + ~UnityWindowStyle(); + + nux::BaseTexture* GetBackgroundTop() const; + nux::BaseTexture* GetBackgroundLeft() const; + nux::BaseTexture* GetBackgroundCorner() const; + int GetBorderSize() const; + int GetInternalOffset() const; + +private: + BaseTexturePtr background_top_; + BaseTexturePtr background_left_; + BaseTexturePtr background_corner_; + +}; + +} +} + +#endif diff --git a/plugins/unityshell/src/UnityWindowView.cpp b/plugins/unityshell/src/UnityWindowView.cpp new file mode 100644 index 000000000..5f5448af8 --- /dev/null +++ b/plugins/unityshell/src/UnityWindowView.cpp @@ -0,0 +1,222 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2012 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: Jason Smith <jason.smith@canonical.com> + */ + +#include "UnityWindowView.h" + +namespace unity { +namespace ui { + +NUX_IMPLEMENT_OBJECT_TYPE(UnityWindowView); + +UnityWindowView::UnityWindowView(NUX_FILE_LINE_DECL) : View(NUX_FILE_LINE_PARAM) +{ + style = UnityWindowStyle::Ptr(new UnityWindowStyle()); + bg_helper_.owner = this; +} + +UnityWindowView::~UnityWindowView() +{ + +} + +void +UnityWindowView::SetupBackground(bool enabled) +{ + bg_helper_.enabled = enabled; +} + +void UnityWindowView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) +{ + // fixme??? +} + +void UnityWindowView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) +{ + PreDraw(GfxContext, force_draw); + + nux::Geometry base = GetGeometry(); + GfxContext.PushClippingRectangle(base); + + // clear region + gPainter.PaintBackground(GfxContext, base); + + nux::Geometry background_geo = GetBackgroundGeometry(); + int internal_offset = style()->GetInternalOffset(); + + nux::Geometry internal_clip(background_geo.x + internal_offset, + background_geo.y + internal_offset, + background_geo.width - internal_offset * 2, + background_geo.height - internal_offset * 2); + GfxContext.PushClippingRectangle(internal_clip); + + + nux::Geometry geo_absolute = GetAbsoluteGeometry (); + if (BackgroundEffectHelper::blur_type != BLUR_NONE) + { + nux::Geometry blur_geo(geo_absolute.x, geo_absolute.y, base.width, base.height); + auto blur_texture = bg_helper_.GetBlurRegion(blur_geo); + + if (blur_texture.IsValid()) + { + nux::TexCoordXForm texxform_blur_bg; + texxform_blur_bg.flip_v_coord = true; + texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); + texxform_blur_bg.uoffset = ((float) base.x) / geo_absolute.width; + texxform_blur_bg.voffset = ((float) base.y) / geo_absolute.height; + + nux::ROPConfig rop; + rop.Blend = false; + rop.SrcBlend = GL_ONE; + rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; + + gPainter.PushDrawTextureLayer(GfxContext, base, + blur_texture, + texxform_blur_bg, + nux::color::White, + true, + rop); + } + } + + nux::ROPConfig rop; + rop.Blend = true; + rop.SrcBlend = GL_ONE; + rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; + gPainter.PushDrawColorLayer (GfxContext, internal_clip, background_color, false, rop); + + // Make round corners + rop.Blend = true; + rop.SrcBlend = GL_ZERO; + rop.DstBlend = GL_SRC_ALPHA; + gPainter.PaintShapeCornerROP(GfxContext, + internal_clip, + nux::color::White, + nux::eSHAPE_CORNER_ROUND4, + nux::eCornerTopLeft | nux::eCornerTopRight | + nux::eCornerBottomLeft | nux::eCornerBottomRight, + true, + rop); + + DrawOverlay(GfxContext, force_draw, internal_clip); + + GfxContext.PopClippingRectangle(); + GfxContext.PopClippingRectangle(); + + DrawBackground(GfxContext, background_geo); + + PostDraw(GfxContext, force_draw); +} + +void UnityWindowView::DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo) +{ + int border = style()->GetBorderSize(); + + GfxContext.GetRenderStates().SetBlend (TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + nux::TexCoordXForm texxform; + texxform.SetTexCoordType (nux::TexCoordXForm::OFFSET_COORD); + texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT); + + // Draw TOP-LEFT CORNER + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = border; + texxform.v1 = border; + GfxContext.QRP_1Tex (geo.x, geo.y, + border, border, style()->GetBackgroundCorner()->GetDeviceTexture(), texxform, nux::color::White); + + // Draw TOP-RIGHT CORNER + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = border; + texxform.v1 = border; + texxform.flip_u_coord = true; + texxform.flip_v_coord = false; + GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y, + border, border, style()->GetBackgroundCorner()->GetDeviceTexture(), texxform, nux::color::White); + + // Draw BOTTOM-LEFT CORNER + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = border; + texxform.v1 = border; + texxform.flip_u_coord = false; + texxform.flip_v_coord = true; + GfxContext.QRP_1Tex (geo.x, geo.y + geo.height - border, + border, border, style()->GetBackgroundCorner()->GetDeviceTexture(), texxform, nux::color::White); + + // Draw BOTTOM-RIGHT CORNER + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = border; + texxform.v1 = border; + texxform.flip_u_coord = true; + texxform.flip_v_coord = true; + GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y + geo.height - border, + border, border, style()->GetBackgroundCorner()->GetDeviceTexture(), texxform, nux::color::White); + + int top_width = style()->GetBackgroundTop()->GetWidth(); + int top_height = style()->GetBackgroundTop()->GetHeight(); + + // Draw TOP BORDER + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = top_width; + texxform.v1 = top_height; + texxform.flip_u_coord = false; + texxform.flip_v_coord = false; + GfxContext.QRP_1Tex (geo.x + border, geo.y, geo.width - border - border, border, style()->GetBackgroundTop()->GetDeviceTexture(), texxform, nux::color::White); + + // Draw BOTTOM BORDER + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = top_width; + texxform.v1 = top_height; + texxform.flip_u_coord = false; + texxform.flip_v_coord = true; + GfxContext.QRP_1Tex (geo.x + border, geo.y + geo.height - border, geo.width - border - border, border, style()->GetBackgroundTop()->GetDeviceTexture(), texxform, nux::color::White); + + + int left_width = style()->GetBackgroundLeft()->GetWidth(); + int left_height = style()->GetBackgroundLeft()->GetHeight(); + + // Draw LEFT BORDER + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = left_width; + texxform.v1 = left_height; + texxform.flip_u_coord = false; + texxform.flip_v_coord = false; + GfxContext.QRP_1Tex (geo.x, geo.y + border, border, geo.height - border - border, style()->GetBackgroundLeft()->GetDeviceTexture(), texxform, nux::color::White); + + // Draw RIGHT BORDER + texxform.u0 = 0; + texxform.v0 = 0; + texxform.u1 = left_width; + texxform.v1 = left_height; + texxform.flip_u_coord = true; + texxform.flip_v_coord = false; + GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y + border, border, geo.height - border - border, style()->GetBackgroundLeft()->GetDeviceTexture(), texxform, nux::color::White); + + GfxContext.GetRenderStates().SetBlend (FALSE); +} + + +} +} diff --git a/plugins/unityshell/src/UnityWindowView.h b/plugins/unityshell/src/UnityWindowView.h new file mode 100644 index 000000000..f5342982b --- /dev/null +++ b/plugins/unityshell/src/UnityWindowView.h @@ -0,0 +1,65 @@ +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- +/* + * Copyright (C) 2012 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: Jason Smith <jason.smith@canonical.com> + */ + +#ifndef UNITYWINDOWVIEW_H +#define UNITYWINDOWVIEW_H + +#include "BackgroundEffectHelper.h" +#include "UnityWindowStyle.h" +#include <sigc++/sigc++.h> + +#include <Nux/Nux.h> +#include <Nux/View.h> +#include <NuxCore/ObjectPtr.h> +#include <NuxCore/Property.h> + +namespace unity { +namespace ui { + +class UnityWindowView : public nux::View +{ + NUX_DECLARE_OBJECT_TYPE(UnityWindowView, nux::View) +public: + nux::Property<nux::Color> background_color; + nux::Property<UnityWindowStyle::Ptr> style; + + UnityWindowView(NUX_FILE_LINE_PROTO); + virtual ~UnityWindowView(); + + void SetupBackground(bool enabled = true); + +protected: + void Draw(nux::GraphicsEngine& GfxContext, bool force_draw); + void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw); + + virtual void PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw) {}; + virtual void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry clip) = 0; + virtual void PostDraw(nux::GraphicsEngine& GfxContext, bool force_draw) {}; + virtual nux::Geometry GetBackgroundGeometry() = 0; + +private: + void DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo); + + BackgroundEffectHelper bg_helper_; +}; + +} +} + +#endif diff --git a/plugins/unityshell/src/WindowManager.cpp b/plugins/unityshell/src/WindowManager.cpp index 979609046..39c66de6a 100644 --- a/plugins/unityshell/src/WindowManager.cpp +++ b/plugins/unityshell/src/WindowManager.cpp @@ -103,7 +103,7 @@ class WindowManagerDummy : public WindowManager g_debug("%s", G_STRFUNC); } - void FocusWindowGroup(std::vector<Window> windows, FocusVisibility) + void FocusWindowGroup(std::vector<Window> windows, FocusVisibility, int monitor) { g_debug("%s", G_STRFUNC); } diff --git a/plugins/unityshell/src/WindowManager.h b/plugins/unityshell/src/WindowManager.h index 6d2a0809d..5663483b7 100644 --- a/plugins/unityshell/src/WindowManager.h +++ b/plugins/unityshell/src/WindowManager.h @@ -78,7 +78,7 @@ public: virtual void InitiateExpo() = 0; virtual bool IsExpoActive() = 0; - virtual void FocusWindowGroup(std::vector<Window> windows, FocusVisibility) = 0; + virtual void FocusWindowGroup(std::vector<Window> windows, FocusVisibility, int monitor = -1) = 0; virtual bool ScaleWindowGroup(std::vector<Window> windows, int state, bool force) = 0; virtual void Decorate(guint32 xid) {}; diff --git a/plugins/unityshell/src/unity-launcher-accessible.cpp b/plugins/unityshell/src/unity-launcher-accessible.cpp index e7cffcd96..7f9eacb52 100644 --- a/plugins/unityshell/src/unity-launcher-accessible.cpp +++ b/plugins/unityshell/src/unity-launcher-accessible.cpp @@ -23,7 +23,7 @@ * @see_also: Launcher * * #UnityLauncherAccessible implements the required ATK interfaces for - * #Launcher, ie: exposing the different LauncherIcon on the model as + * #Launcher, ie: exposing the different AbstractLauncherIcon on the model as * #child of the object. * */ @@ -38,7 +38,7 @@ #include "LauncherModel.h" using unity::launcher::Launcher; -using unity::launcher::LauncherIcon; +using unity::launcher::AbstractLauncherIcon; using unity::launcher::LauncherModel; /* GObject */ @@ -64,8 +64,8 @@ static gboolean unity_launcher_accessible_is_child_selected(AtkSelection* sele /* private */ static void on_selection_change_cb(UnityLauncherAccessible* launcher_accessible); -static void on_icon_added_cb(LauncherIcon* icon, UnityLauncherAccessible* self); -static void on_icon_removed_cb(LauncherIcon* icon, UnityLauncherAccessible* self); +static void on_icon_added_cb(AbstractLauncherIcon* icon, UnityLauncherAccessible* self); +static void on_icon_removed_cb(AbstractLauncherIcon* icon, UnityLauncherAccessible* self); static void on_order_change_cb(UnityLauncherAccessible* self); static void update_children_index(UnityLauncherAccessible* self); @@ -287,7 +287,7 @@ unity_launcher_accessible_ref_selection(AtkSelection* selection, gint i) { Launcher* launcher = NULL; - LauncherIcon* selected_icon = NULL; + AbstractLauncherIcon* selected_icon = NULL; nux::Object* nux_object = NULL; AtkObject* accessible_selected = NULL; @@ -315,7 +315,7 @@ static gint unity_launcher_accessible_get_selection_count(AtkSelection* selection) { Launcher* launcher = NULL; - LauncherIcon* selected_icon = NULL; + AbstractLauncherIcon* selected_icon = NULL; nux::Object* nux_object = NULL; g_return_val_if_fail(UNITY_IS_LAUNCHER_ACCESSIBLE(selection), 0); @@ -338,8 +338,8 @@ unity_launcher_accessible_is_child_selected(AtkSelection* selection, gint i) { Launcher* launcher = NULL; - LauncherIcon* icon = NULL; - LauncherIcon* selected_icon = NULL; + AbstractLauncherIcon* icon = NULL; + AbstractLauncherIcon* selected_icon = NULL; LauncherModel* launcher_model = NULL; LauncherModel::iterator it; nux::Object* nux_object = NULL; @@ -354,7 +354,7 @@ unity_launcher_accessible_is_child_selected(AtkSelection* selection, launcher_model = launcher->GetModel(); it = launcher_model->begin(); std::advance(it, i); - icon = dynamic_cast<LauncherIcon*>(*it); + icon = dynamic_cast<AbstractLauncherIcon*>(*it); selected_icon = launcher->GetSelectedMenuIcon(); @@ -372,7 +372,7 @@ static void on_selection_change_cb(UnityLauncherAccessible* launcher_accessible) static void -on_icon_added_cb(LauncherIcon* icon, +on_icon_added_cb(AbstractLauncherIcon* icon, UnityLauncherAccessible* self) { AtkObject* icon_accessible = NULL; @@ -396,7 +396,7 @@ on_icon_added_cb(LauncherIcon* icon, } static void -on_icon_removed_cb(LauncherIcon* icon, +on_icon_removed_cb(AbstractLauncherIcon* icon, UnityLauncherAccessible* self) { AtkObject* icon_accessible = NULL; diff --git a/plugins/unityshell/src/unity-switcher-accessible.cpp b/plugins/unityshell/src/unity-switcher-accessible.cpp index e49ccbf22..a61fcfbd7 100644 --- a/plugins/unityshell/src/unity-switcher-accessible.cpp +++ b/plugins/unityshell/src/unity-switcher-accessible.cpp @@ -391,7 +391,7 @@ create_children(UnitySwitcherAccessible* self) SwitcherView* switcher = NULL; SwitcherModel::Ptr switcher_model; SwitcherModel::iterator it; - LauncherIcon* child = NULL; + AbstractLauncherIcon* child = NULL; AtkObject* child_accessible = NULL; nux_object = nux_object_accessible_get_object(NUX_OBJECT_ACCESSIBLE(self)); @@ -406,7 +406,7 @@ create_children(UnitySwitcherAccessible* self) for (it = switcher_model->begin(); it != switcher_model->end(); it++) { - child = dynamic_cast<LauncherIcon*>(*it); + child = dynamic_cast<AbstractLauncherIcon*>(*it); child_accessible = unity_launcher_icon_accessible_new(child); atk_object_set_parent(child_accessible, ATK_OBJECT(self)); self->priv->children = g_slist_append(self->priv->children, diff --git a/plugins/unityshell/src/unitya11ytests.cpp b/plugins/unityshell/src/unitya11ytests.cpp index 9ffbd122c..70bf6bb7b 100644 --- a/plugins/unityshell/src/unitya11ytests.cpp +++ b/plugins/unityshell/src/unitya11ytests.cpp @@ -224,7 +224,7 @@ a11y_unit_test_launcher_connection(void) g_debug("[a11y] Launcher accessible created correctly"); } - launcher_icon = new SimpleLauncherIcon(launcher); + launcher_icon = new SimpleLauncherIcon(); launcher_icon->SinkReference(); launcher_icon_accessible = unity_a11y_get_accessible(launcher_icon); diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp index bc948351d..2d0f81913 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -52,6 +52,7 @@ #include "unitya11y.h" +#include "ubus-server.h" #include "UBusMessages.h" #include "UScreen.h" @@ -66,6 +67,7 @@ COMPIZ_PLUGIN_20090315(unityshell, unity::UnityPluginVTable); namespace unity { +using namespace launcher; using launcher::AbstractLauncherIcon; using launcher::Launcher; using ui::KeyboardUtil; @@ -104,10 +106,7 @@ UnityScreen::UnityScreen(CompScreen* screen) , needsRelayout(false) , _in_paint(false) , relayoutSourceId(0) - , _edge_trigger_handle(0) , _redraw_handle(0) - , _edge_pointerY(0) - , _escape_action(nullptr) , newFocusedWindow(nullptr) , doShellRepaint(false) , allowWindowPaint(false) @@ -238,7 +237,6 @@ UnityScreen::UnityScreen(CompScreen* screen) debugger = new unity::debug::DebugDBusInterface(this, this->screen); - _edge_timeout = optionGetLauncherRevealEdgeTimeout (); _in_paint = false; #ifndef USE_GLES @@ -286,8 +284,6 @@ UnityScreen::UnityScreen(CompScreen* screen) optionSetExecuteCommandInitiate(boost::bind(&UnityScreen::executeCommand, this, _1, _2, _3)); optionSetPanelFirstMenuInitiate(boost::bind(&UnityScreen::showPanelFirstMenuKeyInitiate, this, _1, _2, _3)); optionSetPanelFirstMenuTerminate(boost::bind(&UnityScreen::showPanelFirstMenuKeyTerminate, this, _1, _2, _3)); - optionSetLauncherRevealEdgeInitiate(boost::bind(&UnityScreen::launcherRevealEdgeInitiate, this, _1, _2, _3)); - optionSetLauncherRevealEdgeTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); optionSetAutomaximizeValueNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); optionSetAltTabTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); optionSetAltTabBiasViewportNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); @@ -311,6 +307,10 @@ UnityScreen::UnityScreen(CompScreen* screen) optionSetLauncherSwitcherPrevInitiate(boost::bind(&UnityScreen::launcherSwitcherPrevInitiate, this, _1, _2, _3)); optionSetLauncherSwitcherForwardTerminate(boost::bind(&UnityScreen::launcherSwitcherTerminate, this, _1, _2, _3)); + optionSetStopVelocityNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); + optionSetRevealPressureNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); + optionSetOvercomePressureNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); + optionSetDecayRateNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); optionSetShowMinimizedWindowsNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); ubus_manager_.RegisterInterest(UBUS_LAUNCHER_START_KEY_NAV, @@ -319,9 +319,6 @@ UnityScreen::UnityScreen(CompScreen* screen) ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_NAV, sigc::mem_fun(this, &UnityScreen::OnLauncherEndKeyNav)); - ubus_manager_.RegisterInterest(UBUS_QUICKLIST_END_KEY_NAV, - sigc::mem_fun(this, &UnityScreen::OnQuicklistEndKeyNav)); - g_idle_add_full (G_PRIORITY_DEFAULT, &UnityScreen::initPluginActions, this, NULL); super_keypressed_ = false; @@ -337,6 +334,7 @@ UnityScreen::UnityScreen(CompScreen* screen) ubus_manager_.RegisterInterest(UBUS_PLACE_VIEW_SHOWN, [&](GVariant * args) { dash_is_open_ = true; + dash_monitor_ = g_variant_get_int32(args); RaiseInputWindows(); }); ubus_manager_.RegisterInterest(UBUS_PLACE_VIEW_HIDDEN, [&](GVariant * args) { dash_is_open_ = false; }); @@ -441,25 +439,6 @@ void UnityScreen::CreateSuperNewAction(char shortcut, bool use_shift, bool use_n _shortcut_actions.push_back(action); } -void UnityScreen::EnableCancelAction(bool enabled, int modifiers) -{ - if (enabled) - { - /* Create a new keybinding for the Escape key and the current modifiers */ - CompAction::KeyBinding binding(9, modifiers); - - _escape_action = CompActionPtr(new CompAction()); - _escape_action->setKey(binding); - - screen->addAction(_escape_action.get()); - } - else if (!enabled && _escape_action.get()) - { - screen->removeAction(_escape_action.get()); - _escape_action = nullptr; - } -} - void UnityScreen::nuxPrologue() { #ifndef USE_GLES @@ -517,14 +496,6 @@ void UnityScreen::nuxEpilogue() glDisable(GL_SCISSOR_TEST); } -void UnityScreen::OnLauncherHiddenChanged() -{ - if (launcher_controller_->launcher().Hidden()) - screen->addAction(&optionGetLauncherRevealEdge()); - else - screen->removeAction(&optionGetLauncherRevealEdge()); -} - void UnityScreen::paintPanelShadow(const GLMatrix& matrix) { #ifndef USE_GLES @@ -553,7 +524,22 @@ void UnityScreen::paintPanelShadow(const GLMatrix& matrix) vc[2] = y1; vc[3] = y2; - if (!dash_is_open_ && panel_controller_->opacity() > 0.0f) + // compiz doesn't use the same method of tracking monitors as our toolkit + // we need to make sure we properly associate with the right monitor + int current_monitor = -1; + auto monitors = UScreen::GetDefault()->GetMonitors(); + int i = 0; + for (auto monitor : monitors) + { + if (monitor.x == output->x() && monitor.y == output->y()) + { + current_monitor = i; + break; + } + i++; + } + + if (!(dash_is_open_ && current_monitor == dash_monitor_) && panel_controller_->opacity() > 0.0f) { foreach(GLTexture * tex, _shadow_texture) { @@ -615,7 +601,22 @@ void UnityScreen::paintPanelShadow(const GLMatrix& matrix) vc[2] = y1; vc[3] = y2; - if (!dash_is_open_ && panel_controller_->opacity() > 0.0f) + // compiz doesn't use the same method of tracking monitors as our toolkit + // we need to make sure we properly associate with the right monitor + int current_monitor = -1; + auto monitors = UScreen::GetDefault()->GetMonitors(); + int i = 0; + for (auto monitor : monitors) + { + if (monitor.x == output->x() && monitor.y == output->y()) + { + current_monitor = i; + break; + } + i++; + } + + if (!(dash_is_open_ && current_monitor == dash_monitor_) && panel_controller_->opacity() > 0.0f) { foreach(GLTexture * tex, _shadow_texture) { @@ -844,6 +845,25 @@ void UnityWindow::paintThumbnail (nux::Geometry const& bounding, float alpha) geo.height); } +void UnityScreen::EnableCancelAction(bool enabled, int modifiers) +{ + if (enabled) + { + /* Create a new keybinding for the Escape key and the current modifiers */ + CompAction::KeyBinding binding(9, modifiers); + + _escape_action = CompActionPtr(new CompAction()); + _escape_action->setKey(binding); + + screen->addAction(_escape_action.get()); + } + else if (!enabled && _escape_action.get()) + { + screen->removeAction(_escape_action.get()); + _escape_action = nullptr; + } +} + void UnityScreen::enterShowDesktopMode () { for (CompWindow *w : screen->windows ()) @@ -1275,7 +1295,6 @@ void UnityScreen::damageNuxRegions() void UnityScreen::handleEvent(XEvent* event) { bool skip_other_plugins = false; - Launcher& launcher = launcher_controller_->launcher(); switch (event->type) { case FocusIn: @@ -1288,13 +1307,13 @@ void UnityScreen::handleEvent(XEvent* event) cScreen->damageScreen(); // evil hack #endif if (_key_nav_mode_requested) - launcher.startKeyNavMode(); + launcher_controller_->KeyNavGrab(); _key_nav_mode_requested = false; break; case ButtonPress: if (super_keypressed_) { - launcher.KeySwitcherCancel(); + launcher_controller_->KeyNavTerminate(false); EnableCancelAction(false); } break; @@ -1313,7 +1332,7 @@ void UnityScreen::handleEvent(XEvent* event) { g_idle_add([] (gpointer data) -> gboolean { auto self = static_cast<UnityScreen*>(data); - if (!self->launcher_controller_->launcher().KeySwitcherIsActive()) + if (!self->launcher_controller_->KeyNavIsActive()) { self->shortcut_controller_->SetEnabled(false); self->shortcut_controller_->Hide(); @@ -1321,13 +1340,9 @@ void UnityScreen::handleEvent(XEvent* event) return FALSE; }, this); - skip_other_plugins = launcher.CheckSuperShortcutPressed(screen->dpy(), key_sym, event->xkey.keycode, event->xkey.state, key_string); + skip_other_plugins = launcher_controller_->HandleLauncherKeyEvent(screen->dpy(), key_sym, event->xkey.keycode, event->xkey.state, key_string); if (!skip_other_plugins) - { skip_other_plugins = dash_controller_->CheckShortcutActivation(key_string); - if (skip_other_plugins) - launcher.SetLatestShortcut(key_string[0]); - } } } break; @@ -1433,14 +1448,14 @@ bool UnityScreen::showLauncherKeyInitiate(CompAction* action, action->setState(action->state() | CompAction::StateTermKey); super_keypressed_ = true; - launcher_controller_->launcher().StartKeyShowLauncher(); + launcher_controller_->HandleLauncherKeyPress(); EnsureSuperKeybindings (); if (!shortcut_controller_->Visible() && shortcut_controller_->IsEnabled()) { static nux::Geometry last_geo; UScreen* uscreen = UScreen::GetDefault(); - int primary_monitor = uscreen->GetPrimaryMonitor(); + int primary_monitor = uscreen->GetMonitorWithMouse(); auto monitor_geo = uscreen->GetMonitorGeometry(primary_monitor); int width = 970; @@ -1472,11 +1487,16 @@ bool UnityScreen::showLauncherKeyTerminate(CompAction* action, if (state & CompAction::StateCancel) return false; + bool accept_state = (state & CompAction::StateCancel) == 0; + super_keypressed_ = false; - launcher_controller_->launcher().EndKeyShowLauncher(); + launcher_controller_->KeyNavTerminate(accept_state); + launcher_controller_->HandleLauncherKeyRelease(); + EnableCancelAction(false); shortcut_controller_->SetEnabled(enable_shortcut_overlay_); shortcut_controller_->Hide(); + action->setState (action->state() & (unsigned)~(CompAction::StateTermKey)); return false; } @@ -1501,67 +1521,6 @@ bool UnityScreen::showPanelFirstMenuKeyTerminate(CompAction* action, return false; } -gboolean UnityScreen::OnEdgeTriggerTimeout(gpointer data) -{ - UnityScreen* self = reinterpret_cast<UnityScreen*>(data); - - if (pointerX <= 1) - { - if (pointerY <= 24) - return true; - - if (abs(pointerY - self->_edge_pointerY) <= 5) - { - self->launcher_controller_->launcher().EdgeRevealTriggered(pointerX, pointerY); - } - else - { - /* We are still in the edge, but moving in Y, maybe we need another chance */ - - if (abs(pointerY - self->_edge_pointerY) > 20) - { - /* We're quite far from the first hit spot, let's wait again */ - self->_edge_pointerY = pointerY; - return true; - } - else - { - /* We're quite near to the first hit spot, so we can reduce our timeout */ - self->_edge_pointerY = pointerY; - g_source_remove(self->_edge_trigger_handle); - self->_edge_trigger_handle = g_timeout_add(self->_edge_timeout/2, - &UnityScreen::OnEdgeTriggerTimeout, - self); - return false; - } - } - } - - self->_edge_trigger_handle = 0; - return false; -} - -bool UnityScreen::launcherRevealEdgeInitiate(CompAction* action, - CompAction::State state, - CompOption::Vector& options) -{ - if (screen->grabbed()) - return false; - - if (_edge_trigger_handle) - g_source_remove(_edge_trigger_handle); - - if (pointerX <= 1) - { - _edge_pointerY = pointerY; - _edge_trigger_handle = g_timeout_add(_edge_timeout, - &UnityScreen::OnEdgeTriggerTimeout, - this); - } - - return false; -} - void UnityScreen::SendExecuteCommand() { ubus_manager_.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST, @@ -1576,20 +1535,10 @@ bool UnityScreen::executeCommand(CompAction* action, return false; } -void UnityScreen::restartLauncherKeyNav() -{ - // set input-focus on launcher-window and start key-nav mode - if (newFocusedWindow != NULL) - { - newFocusedWindow->moveInputFocusTo(); - launcher_controller_->launcher().startKeyNavMode(); - } -} - void UnityScreen::startLauncherKeyNav() { // get CompWindow* of launcher-window - newFocusedWindow = screen->findWindow(launcher_controller_->launcher_input_window_id()); + newFocusedWindow = screen->findWindow(launcher_controller_->KeyNavLauncherInputWindowId()); // check if currently focused window isn't the launcher-window if (newFocusedWindow != screen->findWindow(screen->activeWindow())) @@ -1624,8 +1573,6 @@ bool UnityScreen::altTabInitiateCommon(CompAction *action, if (!grab_index_) return false; - std::vector<unity::launcher::AbstractLauncherIcon*> results = launcher_controller_->GetAltTabIcons(); - screen->addAction(&optionGetAltTabRight()); screen->addAction(&optionGetAltTabDetailStart()); screen->addAction(&optionGetAltTabDetailStop()); @@ -1637,12 +1584,19 @@ bool UnityScreen::altTabInitiateCommon(CompAction *action, switcher_controller_->SetWorkspace(nux::Geometry(screen->outputDevs()[device].x1() + 100, screen->outputDevs()[device].y1() + 100, screen->outputDevs()[device].width() - 200, - screen->outputDevs()[device].height() - 200)); + screen->outputDevs()[device].height() - 200), device); switcher::ShowMode show_mode = optionGetAltTabBiasViewport() ? switcher::ShowMode::CURRENT_VIEWPORT : switcher::ShowMode::ALL; RaiseInputWindows(); - switcher_controller_->Show(show_mode, switcher::SortMode::FOCUS_ORDER, false, results); + + int show_monitor = (show_mode == switcher::ShowMode::CURRENT_VIEWPORT) ? device : -1; + + std::vector<unity::launcher::AbstractLauncherIcon*> results = launcher_controller_->GetAltTabIcons(show_monitor); + + if (!(results.size() == 1 && results[0]->Type() == AbstractLauncherIcon::IconType::TYPE_BEGIN)) + switcher_controller_->Show(show_mode, switcher::SortMode::FOCUS_ORDER, false, results); + return true; } @@ -1731,47 +1685,32 @@ bool UnityScreen::altTabPrevWindowInitiate(CompAction* action, CompAction::State bool UnityScreen::launcherSwitcherForwardInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options) { - Launcher& launcher = launcher_controller_->launcher(); - - if (!launcher.KeySwitcherIsActive()) + if (!launcher_controller_->KeyNavIsActive()) { + launcher_controller_->KeyNavActivate(); EnableCancelAction(true, action->key().modifiers()); - launcher.KeySwitcherActivate(); } else { - launcher.KeySwitcherNext(); + launcher_controller_->KeyNavNext(); } action->setState(action->state() | CompAction::StateTermKey); return false; } - bool UnityScreen::launcherSwitcherPrevInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options) { - launcher_controller_->launcher().KeySwitcherPrevious(); + launcher_controller_->KeyNavPrevious(); return false; } - bool UnityScreen::launcherSwitcherTerminate(CompAction* action, CompAction::State state, CompOption::Vector& options) { - Launcher& launcher = launcher_controller_->launcher(); - - if (launcher.KeySwitcherIsActive()) - { - if (state & CompAction::StateCancel) - { - launcher.KeySwitcherCancel(); - } - else - { - launcher.KeySwitcherTerminate(); - } - - EnableCancelAction(false); - } + bool accept_state = (state & CompAction::StateCancel) == 0; + launcher_controller_->KeyNavTerminate(accept_state); + EnableCancelAction(false); + action->setState (action->state() & (unsigned)~(CompAction::StateTermKey)); return false; } @@ -1795,11 +1734,6 @@ void UnityScreen::OnLauncherEndKeyNav(GVariant* data) PluginAdapter::Default ()->restoreInputFocus (); } -void UnityScreen::OnQuicklistEndKeyNav(GVariant* data) -{ - restartLauncherKeyNav(); -} - gboolean UnityScreen::initPluginActions(gpointer data) { CompPlugin* p = CompPlugin::find("expo"); @@ -2163,7 +2097,7 @@ void UnityWindow::windowNotify(CompWindowNotify n) if (us->dash_is_open_) { - lw = screen->findWindow(us->launcher_controller_->launcher_input_window_id()); + lw = screen->findWindow(us->launcher_controller_->LauncherWindowId(0)); lw->moveInputFocusTo(); } } @@ -2211,81 +2145,51 @@ void UnityWindow::resizeNotify(int x, int y, int w, int h) CompPoint UnityWindow::tryNotIntersectUI(CompPoint& pos) { UnityScreen* us = UnityScreen::get(screen); - Launcher& launcher = us->launcher_controller_->launcher(); - nux::Geometry geo = launcher.GetAbsoluteGeometry(); - CompRegion allowedWorkArea (screen->workArea ()); - CompRect launcherGeo(geo.x, geo.y, geo.width, geo.height); - CompRegion wRegion (window->borderRect ()); - CompRegion intRegion; - - wRegion.translate (pos.x () - wRegion.boundingRect ().x (), - pos.y () - wRegion.boundingRect ().y ()); + auto window_geo = window->borderRect (); + nux::Geometry target_monitor; + nux::Point result(pos.x(), pos.y()); - /* subtract launcher and panel geometries from allowed workarea */ - if (!launcher.Hidden()) + // seriously why does compiz not track monitors XRandR style??? + auto monitors = UScreen::GetDefault()->GetMonitors(); + for (auto monitor : monitors) { - switch (launcher.GetHideMode()) + if (monitor.IsInside(result)) { - case Launcher::LAUNCHER_HIDE_DODGE_WINDOWS: - case Launcher::LAUNCHER_HIDE_DODGE_ACTIVE_WINDOW: - allowedWorkArea -= launcherGeo; - break; - - default: - break; + target_monitor = monitor; + break; } } - for (nux::Geometry &g : us->panel_controller_->GetGeometries ()) + auto launchers = us->launcher_controller_->launchers(); + for (auto launcher : launchers) { - CompRect pg (g.x, g.y, g.width, g.height); - allowedWorkArea -= pg; - } - - /* Invert allowed work area */ - allowedWorkArea = CompRegion (screen->workArea ()) - allowedWorkArea; - - /* Now intersect the window region with the allowed work area - * region, such that it splits up into a number of rects */ - intRegion = wRegion.intersected (allowedWorkArea); - - if (intRegion.rects ().size () > 1) - { - /* Now find the largest rect, this will be the area that we want to move to */ - CompRect largest; - - for (CompRect &r : intRegion.rects ()) + nux::Geometry geo = launcher->GetAbsoluteGeometry(); + + if (launcher->Hidden() || launcher->GetHideMode() == LAUNCHER_HIDE_NEVER || launcher->GetHideMode() == LAUNCHER_HIDE_AUTOHIDE) + continue; + + if (geo.IsInside(result)) { - if (r.area () > largest.area ()) - largest = r; + if (geo.x + geo.width + 1 + window_geo.width() < target_monitor.x + target_monitor.width) + { + result.x = geo.x + geo.width + 1; + } } + } - /* Now pad the largest rect with the other rectangles that - * were intersecting, padding the opposite side to the one - * that they are currently on on the large rect - */ - - intRegion -= largest; - - for (CompRect &r : intRegion.rects ()) + for (nux::Geometry &geo : us->panel_controller_->GetGeometries ()) + { + if (geo.IsInside(result)) { - if (r.x1 () > largest.x2 ()) - largest.setX (largest.x () - r.width ()); - else if (r.x2 () < largest.x ()) - largest.setWidth (largest.width () + r.width ()); - - if (r.y1 () > largest.y2 ()) - largest.setY (largest.y () - r.height ()); - else if (r.y2 () < largest.y ()) - largest.setWidth (largest.height () + r.height ()); + if (geo.y + geo.height + window_geo.height() < target_monitor.y + target_monitor.height) + { + result.y = geo.y + geo.height; + } } - - pos = largest.pos (); } - if (launcherGeo.contains(pos)) - pos.setX(launcherGeo.x() + launcherGeo.width() + 1); - + pos.setX(result.x); + pos.setY(result.y); return pos; } @@ -2349,7 +2253,7 @@ void UnityScreen::onRedrawRequested() void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num) { // Note: perhaps we should put the options here into the controller. - Launcher& launcher = launcher_controller_->launcher(); + unity::launcher::Options::Ptr launcher_options = launcher_controller_->options(); switch (num) { case UnityshellOptions::BackgroundColor: @@ -2366,16 +2270,16 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num) break; } case UnityshellOptions::LauncherHideMode: - launcher.SetHideMode((Launcher::LauncherHideMode) optionGetLauncherHideMode()); + launcher_options->hide_mode = (unity::launcher::LauncherHideMode) optionGetLauncherHideMode(); break; case UnityshellOptions::BacklightMode: - launcher.SetBacklightMode((Launcher::BacklightMode) optionGetBacklightMode()); + launcher_options->backlight_mode = (unity::launcher::BacklightMode) optionGetBacklightMode(); break; case UnityshellOptions::LaunchAnimation: - launcher.SetLaunchAnimation((Launcher::LaunchAnimation) optionGetLaunchAnimation()); + launcher_options->launch_animation = (unity::launcher::LaunchAnimation) optionGetLaunchAnimation(); break; case UnityshellOptions::UrgentAnimation: - launcher.SetUrgentAnimation((Launcher::UrgentAnimation) optionGetUrgentAnimation()); + launcher_options->urgent_animation = (unity::launcher::UrgentAnimation) optionGetUrgentAnimation(); break; case UnityshellOptions::PanelOpacity: panel_controller_->SetOpacity(optionGetPanelOpacity()); @@ -2395,13 +2299,15 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num) optionGetMenusDiscoveryFadeout()); break; case UnityshellOptions::LauncherOpacity: - launcher.SetBackgroundAlpha(optionGetLauncherOpacity()); + launcher_options->background_alpha = optionGetLauncherOpacity(); break; case UnityshellOptions::IconSize: { CompPlugin *p = CompPlugin::find ("expo"); - launcher.SetIconSize(optionGetIconSize() + 6, optionGetIconSize()); + launcher_options->icon_size = optionGetIconSize(); + launcher_options->tile_size = optionGetIconSize() + 6; + dash_controller_->launcher_width = optionGetIconSize() + 18; if (p) @@ -2423,7 +2329,7 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num) break; } case UnityshellOptions::AutohideAnimation: - launcher.SetAutoHideAnimation((Launcher::AutoHideAnimation) optionGetAutohideAnimation()); + launcher_options->auto_hide_animation = (unity::launcher::AutoHideAnimation) optionGetAutohideAnimation(); break; case UnityshellOptions::DashBlurExperimental: BackgroundEffectHelper::blur_type = (unity::BlurType)optionGetDashBlurExperimental(); @@ -2434,9 +2340,6 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num) case UnityshellOptions::DevicesOption: unity::DevicesSettings::GetDefault().SetDevicesOption((unity::DevicesSettings::DevicesOption) optionGetDevicesOption()); break; - case UnityshellOptions::LauncherRevealEdgeTimeout: - _edge_timeout = optionGetLauncherRevealEdgeTimeout(); - break; case UnityshellOptions::AltTabTimeout: switcher_controller_->detail_on_timeout = optionGetAltTabTimeout(); case UnityshellOptions::AltTabBiasViewport: @@ -2454,6 +2357,18 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num) case UnityshellOptions::ShowDesktopIcon: launcher_controller_->SetShowDesktopIcon(optionGetShowDesktopIcon()); break; + case UnityshellOptions::DecayRate: + launcher_options->edge_decay_rate = optionGetDecayRate() * 100; + break; + case UnityshellOptions::OvercomePressure: + launcher_options->edge_overcome_pressure = optionGetOvercomePressure() * 100; + break; + case UnityshellOptions::StopVelocity: + launcher_options->edge_stop_velocity = optionGetStopVelocity() * 100; + break; + case UnityshellOptions::RevealPressure: + launcher_options->edge_reveal_pressure = optionGetRevealPressure() * 100; + break; default: break; } @@ -2556,12 +2471,7 @@ void UnityScreen::initLauncher() { Timer timer; launcher_controller_.reset(new launcher::Controller(screen->dpy())); - primary_monitor_.changed.connect(sigc::mem_fun(launcher_controller_.get(), - &launcher::Controller::PrimaryMonitorGeometryChanged)); - - Launcher& launcher = launcher_controller_->launcher(); - launcher.hidden_changed.connect(sigc::mem_fun(this, &UnityScreen::OnLauncherHiddenChanged)); - AddChild(&launcher); + AddChild(launcher_controller_.get()); switcher_controller_.reset(new switcher::Controller()); AddChild(switcher_controller_.get()); @@ -2589,13 +2499,7 @@ void UnityScreen::initLauncher() AddChild(dash_controller_.get()); - launcher.SetHideMode(Launcher::LAUNCHER_HIDE_DODGE_WINDOWS); - launcher.SetLaunchAnimation(Launcher::LAUNCH_ANIMATION_PULSE); - launcher.SetUrgentAnimation(Launcher::URGENT_ANIMATION_WIGGLE); - ScheduleRelayout(0); - - OnLauncherHiddenChanged(); } void UnityScreen::InitHints() diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h index 18d95ed31..0b05ef4f4 100644 --- a/plugins/unityshell/src/unityshell.h +++ b/plugins/unityshell/src/unityshell.h @@ -187,7 +187,6 @@ public: bool executeCommand(CompAction* action, CompAction::State state, CompOption::Vector& options); bool setKeyboardFocusKeyInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options); - bool launcherRevealEdgeInitiate(CompAction* action, CompAction::State state, CompOption::Vector& options); bool altTabInitiateCommon(CompAction* action, CompAction::State state, @@ -248,16 +247,13 @@ private: static void initUnity(nux::NThread* thread, void* InitData); static void OnStartKeyNav(GVariant* data, void* value); static void OnExitKeyNav(GVariant* data, void* value); - static gboolean OnEdgeTriggerTimeout(gpointer data); static gboolean OnRedrawTimeout(gpointer data); void startLauncherKeyNav(); void restartLauncherKeyNav(); - void OnLauncherHiddenChanged(); void OnDashRealized (); - void OnQuicklistEndKeyNav(GVariant* data); void OnLauncherStartKeyNav(GVariant* data); void OnLauncherEndKeyNav(GVariant* data); @@ -285,16 +281,12 @@ private: bool needsRelayout; bool _in_paint; guint32 relayoutSourceId; - guint _edge_timeout; - guint _edge_trigger_handle; guint32 _redraw_handle; - gint _edge_pointerY; - typedef std::shared_ptr<CompAction> CompActionPtr; typedef std::vector<CompActionPtr> ShortcutActions; ShortcutActions _shortcut_actions; - CompActionPtr _escape_action; bool super_keypressed_; + CompActionPtr _escape_action; /* keyboard-nav mode */ CompWindow* newFocusedWindow; @@ -325,6 +317,7 @@ private: UBusManager ubus_manager_; bool dash_is_open_; + int dash_monitor_; CompScreen::GrabHandle grab_index_; CompWindowList fullscreen_windows_; bool painting_tray_; diff --git a/plugins/unityshell/unityshell.xml.in b/plugins/unityshell/unityshell.xml.in index 8a12f90a1..6de5a413a 100644 --- a/plugins/unityshell/unityshell.xml.in +++ b/plugins/unityshell/unityshell.xml.in @@ -42,20 +42,6 @@ <options> <group> <_short>Behaviour</_short> - <option name="launcher_reveal_edge" type="edge"> - <_short>Reveal Mode</_short> - <_long>From which edge should the launcher reveal.</_long> - <default> - <edge name="Left"/> - </default> - </option> - <option name="launcher_reveal_edge_timeout" type="int"> - <_short>Edge Reveal Timeout</_short> - <_long>How long (in ms) wait before revealing the launcher when the mouse pointer is touching the edge.</_long> - <min>1</min> - <max>1000</max> - <default>150</default> - </option> <option name="launcher_hide_mode" type="int"> <_short>Hide Launcher</_short> <_long>Make the launcher hide automatically after some time of inactivity: always or just when the focussed window is not over the launcher</_long> @@ -282,6 +268,38 @@ <max>64</max> <precision>1</precision> </option> + <option name="reveal_pressure" type="int"> + <_short>Launcher Reveal Pressure</_short> + <_long>Amount of mouse pressure required to reveal launcher</_long> + <default>80</default> + <min>1</min> + <max>1000</max> + <precision>1</precision> + </option> + <option name="overcome_pressure" type="int"> + <_short>Launcher Edge Stop Overcome Pressure</_short> + <_long>Amount of mouse pressure required to push into the next monitor</_long> + <default>75</default> + <min>1</min> + <max>1000</max> + <precision>1</precision> + </option> + <option name="decay_rate" type="int"> + <_short>Pressure Decay Rate</_short> + <_long>The rate at which mouse pressure decays</_long> + <default>75</default> + <min>1</min> + <max>1000</max> + <precision>1</precision> + </option> + <option name="stop_velocity" type="int"> + <_short>Edge Stop Velocity</_short> + <_long>The maximum velocity at which the mouse will still be stoped</_long> + <default>100</default> + <min>1</min> + <max>1000</max> + <precision>1</precision> + </option> <option name="autohide_animation" type="int"> <_short>Hide Animation</_short> <_long>Animation played when the launcher is showing or hiding</_long> diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 80a738161..c7e2bd3f9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -110,6 +110,7 @@ if (GTEST_FOUND AND # The actual test executable (xless) - do not put anything that requires X in here add_executable(test-gtest-xless test_animator.cpp + test_launcher_model.cpp test_glib_object.cpp test_glib_object_utils.cpp test_glib_object_utils.h @@ -138,6 +139,8 @@ if (GTEST_FOUND AND ${UNITY_SRC}/FavoriteStore.h ${UNITY_SRC}/FavoriteStoreGSettings.cpp ${UNITY_SRC}/FavoriteStoreGSettings.h + ${UNITY_SRC}/LauncherModel.cpp + ${UNITY_SRC}/LauncherModel.h ${UNITY_SRC}/FavoriteStorePrivate.cpp ${UNITY_SRC}/FavoriteStorePrivate.h ${UNITY_SRC}/MockLauncherIcon.h diff --git a/tests/autopilot/autopilot/emulators/X11.py b/tests/autopilot/autopilot/emulators/X11.py index ecf57db1e..f543301e2 100644 --- a/tests/autopilot/autopilot/emulators/X11.py +++ b/tests/autopilot/autopilot/emulators/X11.py @@ -23,6 +23,7 @@ from Xlib import X from Xlib import XK from Xlib.display import Display from Xlib.ext.xtest import fake_input +import gtk.gdk _PRESSED_KEYS = [] _DISPLAY = Display() @@ -232,15 +233,15 @@ class Mouse(object): self.release(button) def move(self, x, y, animate=True): - """Moves mouse to location (x, y).""" - def perform_move(x, y): - fake_input(_DISPLAY, X.MotionNotify, x=x, y=y) + '''Moves mouse to location (x, y)''' + def perform_move(x, y, sync): + fake_input(_DISPLAY, X.MotionNotify, sync, X.CurrentTime, X.NONE, x=x, y=y) _DISPLAY.sync() sleep(0.001) if not animate: - perform_move(x, y) - + perform_move(x, y, False) + dest_x, dest_y = x, y curr_x, curr_y = self.position() @@ -249,20 +250,20 @@ class Mouse(object): dx = float(curr_x - dest_x) slope = dy/dx if dx > 0 else 0 yint = curr_y - (slope * curr_x) - xscale = 1 if dest_x > curr_x else -1 - + xscale = 10 if dest_x > curr_x else -10 + while (int(curr_x) != dest_x): - curr_x += xscale; - curr_y = int(slope * curr_x + yint) if curr_y > 0 else dest_y - - perform_move(curr_x, curr_y) - + target_x = min(curr_x + xscale, dest_x) if dest_x > curr_x else max(curr_x + xscale, dest_x) + perform_move(target_x - curr_x, 0, True) + curr_x = target_x; + if (curr_y != dest_y): - yscale = 1 if dest_y > curr_y else -1 + yscale = 10 if dest_y > curr_y else -10 while (curr_y != dest_y): - curr_y += yscale - perform_move(curr_x, curr_y) - + target_y = min(curr_y + yscale, dest_y) if dest_y > curr_y else max(curr_y + yscale, dest_y) + perform_move(0, target_y - curr_y, True) + curr_y = target_y + def position(self): """Returns the current position of the mouse pointer.""" coord = _DISPLAY.screen().root.query_pointer()._data @@ -273,3 +274,31 @@ class Mouse(object): self.move(16, 13, animate=False) self.click() self.move(800, 500, animate=False) + + +class ScreenGeometry: + """Get details about screen geometry.""" + + def __init__(self): + self._default_screen = gtk.gdk.screen_get_default() + + def get_num_monitors(self): + """Get the number of monitors attached to the PC.""" + return self._default_screen.get_n_monitors() + + def get_monitor_geometry(self, monitor_number): + """Get the geometry for a particular monitor. + + Returns a tuple containing (x,y,width,height). + + """ + if monitor_number >= self.get_num_monitors(): + raise ValueError('Specified monitor number is out of range.') + return tuple(self._default_screen.get_monitor_geometry(monitor_number)) + + def move_mouse_to_monitor(self, monitor_number): + """Move the mouse to the center of the specified monitor.""" + geo = self.get_monitor_geometry(monitor_number) + x = geo[0] + (geo[2]/2) + y = geo[1] + (geo[3]/2) + Mouse().move(x,y, False) #dont animate this or it might not get there due to barriers diff --git a/tests/autopilot/autopilot/emulators/unity.py b/tests/autopilot/autopilot/emulators/unity.py index 09feb4f65..8ef847d1b 100644 --- a/tests/autopilot/autopilot/emulators/unity.py +++ b/tests/autopilot/autopilot/emulators/unity.py @@ -55,66 +55,107 @@ class Launcher(Unity): def __init__(self): super(Launcher, self).__init__() # set up base launcher vars - state = self.__get_state() - self.icon_width = int(state['icon-size']) - - self.reveal_pos = (0, 120) - self.hide_pos = (self.icon_width *2, 120) - + self.x = 0 + self.y = 120 + self.width = 0 + self.height = 0 self.show_timeout = 1 self.hide_timeout = 1 + self.grabbed = False - - def move_mouse_to_reveal_pos(self): - """Move the mouse to the launcher reveal position.""" - self._mouse.move(*self.reveal_pos) + def move_mouse_to_right_of_launcher(self, monitor): + (x, y, w, h) = self.launcher_geometry(monitor) + self._mouse.move(x + w + 10, y + h / 2, False) sleep(self.show_timeout) - def move_mouse_outside_of_boundry(self): - """Move the mouse outside the launcher.""" - self._mouse.move(*self.hide_pos) - sleep(self.hide_timeout) + def reveal_launcher(self, monitor): + (x, y, w, h) = self.launcher_geometry(monitor) + self._mouse.move(x - 1200, y + h / 2) + sleep(self.show_timeout) - def is_showing(self): - """Is the launcher showing?""" - state = self.__get_state() + def grab_switcher(self): + self._keyboard.press_and_release('Alt+F1') + self.grabbed = True + + def switcher_enter_quicklist(self): + if self.grabbed: + self._keyboard.press_and_release('Right') + + def switcher_exit_quicklist(self): + if self.grabbed: + self._keyboard.press_and_release('Left') + + def start_switcher(self): + self._keyboard.press('Super+Tab') + self._keyboard.release('Tab') + + def end_switcher(self, cancel): + if cancel: + self._keyboard.press_and_release('Escape') + if self.grabbed != True: + self._keyboard.release('Super') + else: + if self.grabbed: + self._keyboard.press_and_release('\n') + else: + self._keyboard.release('Super') + self.grabbed = False + + def switcher_next(self): + if self.grabbed: + self._keyboard.press_and_release('Down') + else: + self._keyboard.press_and_release('Tab') + + def switcher_prev(self): + if self.grabbed: + self._keyboard.press_and_release('Up') + else: + self._keyboard.press_and_release('Shift+Tab') + + def quicklist_open(self, monitor): + state = self.__get_state(monitor) + return bool(state['quicklist-open']) + + def is_showing(self, monitor): + state = self.__get_state(monitor) return not bool(state['hidden']) - def __get_state(self): - # get the state for the 'launcher' piece - return super(Launcher, self).get_state('/Unity/Launcher')[0] + def key_nav_is_active(self): + state = self.__get_controller_state() + return bool(state['key_nav_is_active']) - def get_launcher_icons(self): - """Get a list of launcher icons in this launcher.""" - icons = self.get_state("//Launcher/LauncherIcon") - return [LauncherIcon(icon_dict) for icon_dict in icons] + def key_nav_monitor(self): + state = self.__get_controller_state() + return int(state['key_nav_launcher_monitor']) - def click_launcher_icon(self, icon, button=1): - """Move the mouse over the launcher icon, and click it.""" - self.move_mouse_to_reveal_pos() - self._mouse.move(icon.x, icon.y + (self.icon_width / 2)) - self._mouse.click(button) - self.move_mouse_outside_of_boundry() + def key_nav_is_grabbed(self): + state = self.__get_controller_state() + return bool(state['key_nav_is_grabbed']) + def key_nav_selection(self): + state = self.__get_controller_state() + return int(state['key_nav_selection']) -class LauncherIcon: - """Holds information about a launcher icon. + def launcher_geometry(self, monitor): + state = self.__get_state(monitor); + x = int(state['x']) + y = int(state['y']) + width = int(state['width']) + height = int(state['height']) + return (x, y, width, height) - Do not instantiate an instance of this class yourself. Instead, use the - appropriate methods in the Launcher class instead. + def num_launchers(self): + return len(super(Launcher, self).get_state('/Unity/LauncherController/Launcher')) + + def __get_controller_state(self): + return super(Launcher, self).get_state('/Unity/LauncherController')[0] + + def __get_state(self, monitor): + # get the state for the 'launcher' piece + return super(Launcher, self).get_state('/Unity/LauncherController/Launcher[monitor=%s]' % (monitor))[0] - """ - def __init__(self, icon_dict): - self.tooltip_text = icon_dict['tooltip-text'] - self.x = icon_dict['x'] - self.y = icon_dict['y'] - self.num_windows = icon_dict['related-windows'] - self.visible = icon_dict['quirk-visible'] - self.active = icon_dict['quirk-active'] - self.running = icon_dict['quirk-running'] - self.presented = icon_dict['quirk-presented'] - self.urgent = icon_dict['quirk-urgent'] class Switcher(Unity): """Interact with the Unity switcher.""" @@ -161,67 +202,71 @@ class Switcher(Unity): self._keyboard.press_and_release('Shift+`') def __get_icon(self, index): - return self.__get_model()['Children'][index][1][0] + import ipdb; ipdb.set_trace() + return self.get_state('/Unity/SwitcherController/SwitcherModel')[0]['children-of-men'][index][1][0] - @property - def current_icon(self): - """Get the currently-selected icon.""" - if not self.get_is_visible: - return None - model = self.__get_model() - sel_idx = self.get_selection_index() + def get_icon_name(self, index): + return self.__get_icon(index)['tooltip-text'] + + def get_icon_desktop_file(self, index): try: - return LauncherIcon(model['Children'][sel_idx][1]) - except KeyError: + return self.__get_icon(index)['desktop-file'] + except: return None def get_model_size(self): - return len(self.__get_model()['Children']) + return len(self.get_state('/Unity/SwitcherController/SwitcherModel')[0]['children-of-men']) def get_selection_index(self): - return int(self.__get_model()['selection-index']) + return int(self.get_state('/Unity/SwitcherController/SwitcherModel')[0]['selection-index']) def get_last_selection_index(self): - return bool(self.__get_model()['last-selection-index']) + return bool(self.get_state('/Unity/SwitcherController/SwitcherModel')[0]['last-selection-index']) def get_is_visible(self): - return bool(self.__get_controller()['visible']) - - def __get_model(self): - return self.get_state('/Unity/SwitcherController/SwitcherModel')[0] - - def __get_controller(self): - return self.set_state('/unity/SwitcherController')[0] + return bool(self.get_state('/Unity/SwitcherController')[0]['visible']) class Dash(Unity): - """An emulator class that makes it easier to interact with the unity dash.""" - - def __init__(self): - self.plugin = Plugin(global_context, "unityshell") - self.setting = Setting(self.plugin, "show_launcher") - super(Dash, self).__init__() - - def toggle_reveal(self): - """Reveals the dash if it's currently hidden, hides it otherwise.""" - self._keyboard.press_and_release('Super') - sleep(1) - - def ensure_visible(self): - """Ensures the dash is visible.""" - if not self.get_is_visible(): - self.toggle_reveal(); - - def ensure_hidden(self): - """Ensures the dash is hidden.""" - if self.get_is_visible(): - self.toggle_reveal(); - - def get_is_visible(self): - """Is the dash visible?""" + """ + An emulator class that makes it easier to interact with the unity dash. + """ + + def __init__(self): + self.plugin = Plugin(global_context, "unityshell") + self.setting = Setting(self.plugin, "show_launcher") + super(Dash, self).__init__() + + def toggle_reveal(self): + """ + Reveals the dash if it's currently hidden, hides it otherwise. + """ + self._keyboard.press_and_release("Super") + sleep(1) + + def ensure_visible(self): + """ + Ensures the dash is visible. + """ + if not self.get_is_visible(): + self.toggle_reveal(); + + def ensure_hidden(self): + """ + Ensures the dash is hidden. + """ + if self.get_is_visible(): + self.toggle_reveal(); + + def get_is_visible(self): + """ + Is the dash visible? + """ return bool(self.get_state("/Unity/DashController")[0]["visible"]) - def get_search_string(self): - """Return the current dash search bar search string.""" + def get_search_string(self): + """ + Return the current dash search bar search string. + """ return unicode(self.get_state("//SearchBar")[0]['search_string']) def get_current_lens(self): diff --git a/tests/autopilot/autopilot/tests/test_launcher.py b/tests/autopilot/autopilot/tests/test_launcher.py index 58f78b509..0c972d38b 100644 --- a/tests/autopilot/autopilot/tests/test_launcher.py +++ b/tests/autopilot/autopilot/tests/test_launcher.py @@ -1,8 +1,12 @@ from testtools import TestCase +from testtools.matchers import Equals +from testtools.matchers import LessThan from autopilot.emulators.unity import Launcher from autopilot.glibrunner import GlibRunner +from time import sleep + class LauncherTests(TestCase): """Test the launcher.""" run_test_with = GlibRunner @@ -11,10 +15,85 @@ class LauncherTests(TestCase): super(LauncherTests, self).setUp() self.server = Launcher() + def test_launcher_switcher_ungrabbed(self): + """Tests basic key nav integration without keyboard grabs""" + sleep(.5) + + self.server.start_switcher() + sleep(.5) + + self.assertThat(self.server.key_nav_is_active(), Equals(True)) + self.assertThat(self.server.key_nav_is_grabbed(), Equals(False)) + self.assertThat(self.server.key_nav_selection(), Equals(0)) + + self.server.switcher_next() + sleep(.5) + self.assertThat(0, LessThan(self.server.key_nav_selection())) + + self.server.switcher_prev() + sleep(.5) + self.assertThat(self.server.key_nav_selection(), Equals(0)) + + self.server.end_switcher(True) + sleep(.5) + self.assertThat(self.server.key_nav_is_active(), Equals(False)) + + def test_launcher_switcher_grabbed(self): + """Tests basic key nav integration via keyboard grab""" + sleep(.5) + + self.server.grab_switcher() + sleep(.5) + + self.assertThat(self.server.key_nav_is_active(), Equals(True)) + self.assertThat(self.server.key_nav_is_grabbed(), Equals(True)) + self.assertThat(self.server.key_nav_selection(), Equals(0)) + + self.server.switcher_next() + sleep(.5) + self.assertThat(0, LessThan(self.server.key_nav_selection())) + + self.server.switcher_prev() + sleep(.5) + self.assertThat(self.server.key_nav_selection(), Equals(0)) + + self.server.end_switcher(True) + sleep(.5) + self.assertThat(self.server.key_nav_is_active(), Equals(False)) + + def test_launcher_switcher_quicklist_interaction(self): + """Tests that the key nav opens and closes quicklists properly and regrabs afterwards""" + self.server.move_mouse_to_right_of_launcher(0) + sleep(.5) + + self.server.grab_switcher() + sleep(.5) + + self.assertThat(self.server.key_nav_is_active(), Equals(True)) + self.assertThat(self.server.key_nav_is_grabbed(), Equals(True)) + + self.server.switcher_next() + sleep(.5) + + self.server.switcher_enter_quicklist() + sleep(.5) + self.assertThat(self.server.quicklist_open(0), Equals(True)) + self.server.switcher_exit_quicklist() + sleep(.5) + + self.assertThat(self.server.quicklist_open(0), Equals(False)) + self.assertThat(self.server.key_nav_is_active(), Equals(True)) + self.assertThat(self.server.key_nav_is_grabbed(), Equals(True)) + + self.server.end_switcher(True) + sleep(.5) + self.assertThat(self.server.key_nav_is_active(), Equals(False)) + def test_reveal_on_mouse_to_edge(self): - """Test that we can reveal the launcher with the mouse.""" - self.server.move_mouse_outside_of_boundry() - self.server.move_mouse_to_reveal_pos() - self.assertTrue(self.server.is_showing()) - self.server.move_mouse_outside_of_boundry() - self.assertFalse(self.server.is_showing()) + """Tests reeal of launchers by mouse pressure""" + num_launchers = self.server.num_launchers() + + for x in range(num_launchers): + self.server.move_mouse_to_right_of_launcher(x) + self.server.reveal_launcher(x) + self.assertThat(self.server.is_showing(x), Equals(True)) diff --git a/tests/test_launcher_model.cpp b/tests/test_launcher_model.cpp new file mode 100644 index 000000000..e64d3b9d6 --- /dev/null +++ b/tests/test_launcher_model.cpp @@ -0,0 +1,216 @@ +/* + * Copyright 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 warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY 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 + * version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Jason Smith <jason.smith@canonical.com> + * + */ + +#include <gtest/gtest.h> + +#include "LauncherModel.h" +#include "MockLauncherIcon.h" +#include "AbstractLauncherIcon.h" + +#include <vector> + + +using namespace unity::launcher; + +namespace +{ + +class EventListener +{ + public: + EventListener() + { + icon_added = false; + icon_removed = false; + } + + void OnIconAdded (AbstractLauncherIcon* icon) + { + icon_added = true; + } + + void OnIconRemoved (AbstractLauncherIcon* icon) + { + icon_removed = true; + } + + bool icon_added; + bool icon_removed; +}; +//bool seen_result; + +TEST(TestLauncherModel, TestConstructor) +{ + LauncherModel::Ptr model(new LauncherModel()); + EXPECT_EQ(model->Size(), 0); +} + +TEST(TestLauncherModel, TestAdd) +{ + AbstractLauncherIcon* first = new MockLauncherIcon(); + LauncherModel::Ptr model(new LauncherModel()); + + EXPECT_EQ(model->Size(), 0); + model->AddIcon(first); + EXPECT_EQ(model->Size(), 1); +} + +TEST(TestLauncherModel, TestRemove) +{ + AbstractLauncherIcon* first = new MockLauncherIcon(); + LauncherModel::Ptr model(new LauncherModel()); + + EXPECT_EQ(model->Size(), 0); + model->AddIcon(first); + EXPECT_EQ(model->Size(), 1); + model->RemoveIcon(first); + EXPECT_EQ(model->Size(), 0); +} + +TEST(TestLauncherModel, TestAddSignal) +{ + AbstractLauncherIcon* first = new MockLauncherIcon(); + LauncherModel::Ptr model(new LauncherModel()); + + EventListener *listener = new EventListener(); + + model->icon_added.connect(sigc::mem_fun(listener, &EventListener::OnIconAdded)); + model->AddIcon(first); + EXPECT_EQ(listener->icon_added, true); + + delete listener; +} + +TEST(TestLauncherModel, TestRemoveSignal) +{ + AbstractLauncherIcon* first = new MockLauncherIcon(); + LauncherModel::Ptr model(new LauncherModel()); + + EventListener *listener = new EventListener(); + + model->icon_removed.connect(sigc::mem_fun(listener, &EventListener::OnIconRemoved)); + model->AddIcon(first); + EXPECT_EQ(listener->icon_removed, false); + model->RemoveIcon(first); + EXPECT_EQ(listener->icon_removed, true); + + delete listener; +} + +TEST(TestLauncherModel, TestSort) +{ + AbstractLauncherIcon* first = new MockLauncherIcon(); + AbstractLauncherIcon* second = new MockLauncherIcon(); + AbstractLauncherIcon* third = new MockLauncherIcon(); + AbstractLauncherIcon* fourth = new MockLauncherIcon(); + + LauncherModel::Ptr model(new LauncherModel()); + + third->SetSortPriority(0); + model->AddIcon(third); + + first->SetSortPriority(-1); + model->AddIcon(first); + + fourth->SetSortPriority(2); + model->AddIcon(fourth); + + second->SetSortPriority(0); + model->AddIcon(second); + + LauncherModel::iterator it; + it = model->begin(); + + EXPECT_EQ(first, *it); + it++; + EXPECT_EQ(second, *it); + it++; + EXPECT_EQ(third, *it); + it++; + EXPECT_EQ(fourth, *it); +} + +TEST(TestLauncherModel, TestReorderBefore) +{ + AbstractLauncherIcon* first = new MockLauncherIcon(); + AbstractLauncherIcon* second = new MockLauncherIcon(); + AbstractLauncherIcon* third = new MockLauncherIcon(); + AbstractLauncherIcon* fourth = new MockLauncherIcon(); + + LauncherModel::Ptr model(new LauncherModel()); + + first->SetSortPriority(0); + second->SetSortPriority(1); + third->SetSortPriority(2); + fourth->SetSortPriority(3); + + model->AddIcon(first); + model->AddIcon(second); + model->AddIcon(third); + model->AddIcon(fourth); + + model->ReorderBefore(third, second, false); + + LauncherModel::iterator it; + it = model->begin(); + + EXPECT_EQ(first, *it); + it++; + EXPECT_EQ(third, *it); + it++; + EXPECT_EQ(second, *it); + it++; + EXPECT_EQ(fourth, *it); +} + +TEST(TestLauncherModel, TestReorderSmart) +{ + AbstractLauncherIcon* first = new MockLauncherIcon(); + AbstractLauncherIcon* second = new MockLauncherIcon(); + AbstractLauncherIcon* third = new MockLauncherIcon(); + AbstractLauncherIcon* fourth = new MockLauncherIcon(); + + LauncherModel::Ptr model(new LauncherModel()); + + first->SetSortPriority(0); + second->SetSortPriority(1); + third->SetSortPriority(2); + fourth->SetSortPriority(3); + + model->AddIcon(first); + model->AddIcon(second); + model->AddIcon(third); + model->AddIcon(fourth); + + model->ReorderSmart(third, second, false); + + LauncherModel::iterator it; + it = model->begin(); + + EXPECT_EQ(first, *it); + it++; + EXPECT_EQ(third, *it); + it++; + EXPECT_EQ(second, *it); + it++; + EXPECT_EQ(fourth, *it); +} + +} |
