summaryrefslogtreecommitdiff
diff options
-rw-r--r--CMakeLists.txt4
-rw-r--r--UnityCore/CMakeLists.txt2
-rw-r--r--UnityCore/GLibSignal-inl.h272
-rw-r--r--UnityCore/GLibSignal.cpp11
-rw-r--r--UnityCore/GLibSignal.h271
-rw-r--r--UnityCore/unity-core.pc.cmake2
-rw-r--r--dash/DashController.cpp5
-rw-r--r--dash/DashView.cpp31
-rw-r--r--dash/PlacesVScrollBar.h2
-rw-r--r--dash/ResultRendererHorizontalTile.h2
-rw-r--r--dash/ResultRendererTile.h2
-rw-r--r--dash/ResultView.cpp2
-rw-r--r--dash/ResultView.h2
-rw-r--r--dash/ResultViewGrid.cpp2
-rw-r--r--hud/HudButton.cpp31
-rw-r--r--hud/HudButton.h10
-rw-r--r--hud/HudView.cpp44
-rw-r--r--hud/HudView.h4
-rw-r--r--launcher/AbstractLauncherIcon.h1
-rw-r--r--launcher/FavoriteStoreGSettings.cpp25
-rw-r--r--launcher/Launcher.cpp11
-rw-r--r--launcher/Launcher.h4
-rw-r--r--launcher/LauncherController.cpp16
-rw-r--r--launcher/LauncherIcon.cpp3
-rw-r--r--launcher/LauncherModel.cpp2
-rw-r--r--launcher/LauncherModel.h2
-rw-r--r--launcher/QuicklistMenuItem.h2
-rw-r--r--launcher/QuicklistMenuItemCheckmark.h2
-rw-r--r--launcher/QuicklistMenuItemLabel.h2
-rw-r--r--launcher/QuicklistMenuItemRadio.h2
-rw-r--r--launcher/QuicklistMenuItemSeparator.h2
-rw-r--r--launcher/QuicklistView.cpp225
-rw-r--r--launcher/QuicklistView.h8
-rw-r--r--launcher/SwitcherController.cpp13
-rw-r--r--launcher/SwitcherController.h2
-rw-r--r--launcher/SwitcherModel.cpp2
-rw-r--r--panel/PanelController.cpp15
-rw-r--r--panel/PanelController.h1
-rw-r--r--panel/PanelIndicatorEntryView.h2
-rw-r--r--panel/PanelView.cpp4
-rw-r--r--panel/PanelView.h2
-rw-r--r--panel/WindowButtons.cpp7
-rw-r--r--plugins/unity-mt-grab-handles/CMakeLists.txt2
-rw-r--r--plugins/unityshell/src/DebugDBusInterface.cpp19
-rw-r--r--plugins/unityshell/src/XPathQueryPart.cpp32
-rw-r--r--plugins/unityshell/src/compizminimizedwindowhandler.h1
-rw-r--r--plugins/unityshell/src/unityshell.cpp348
-rw-r--r--plugins/unityshell/src/unityshell.h23
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/autopilot/unity/emulators/__init__.py9
-rw-r--r--tests/autopilot/unity/emulators/dash.py13
-rw-r--r--tests/autopilot/unity/emulators/hud.py30
-rw-r--r--tests/autopilot/unity/emulators/icons.py2
-rw-r--r--tests/autopilot/unity/emulators/launcher.py50
-rw-r--r--tests/autopilot/unity/emulators/panel.py2
-rw-r--r--tests/autopilot/unity/emulators/quicklist.py2
-rw-r--r--tests/autopilot/unity/emulators/shortcut_hint.py2
-rw-r--r--tests/autopilot/unity/emulators/switcher.py2
-rw-r--r--tests/autopilot/unity/emulators/tooltip.py8
-rw-r--r--tests/autopilot/unity/emulators/unity.py12
-rw-r--r--tests/autopilot/unity/emulators/window_manager.py3
-rw-r--r--tests/autopilot/unity/tests/__init__.py26
-rw-r--r--tests/autopilot/unity/tests/launcher/__init__.py59
-rw-r--r--tests/autopilot/unity/tests/launcher/test_capture.py113
-rw-r--r--tests/autopilot/unity/tests/launcher/test_icon_behavior.py208
-rw-r--r--tests/autopilot/unity/tests/launcher/test_keynav.py191
-rw-r--r--tests/autopilot/unity/tests/launcher/test_reveal.py87
-rw-r--r--tests/autopilot/unity/tests/launcher/test_shortcut.py55
-rw-r--r--tests/autopilot/unity/tests/launcher/test_switcher.py168
-rw-r--r--tests/autopilot/unity/tests/launcher/test_visual.py76
-rw-r--r--tests/autopilot/unity/tests/test_dash.py36
-rw-r--r--tests/autopilot/unity/tests/test_hud.py36
-rw-r--r--tests/autopilot/unity/tests/test_launcher.py851
-rw-r--r--tests/autopilot/unity/tests/test_panel.py15
-rw-r--r--tests/autopilot/unity/tests/test_quicklist.py30
-rw-r--r--tests/autopilot/unity/tests/test_shortcut_hint.py85
-rw-r--r--tests/autopilot/unity/tests/test_switcher.py20
-rw-r--r--tests/test_glib_signals.cpp65
-rw-r--r--tests/test_hud_controller.cpp3
-rw-r--r--tests/test_im_text_entry.cpp65
-rw-r--r--tests/test_introspection.cpp61
-rw-r--r--tests/test_keyboard_util.cpp115
-rw-r--r--tools/CMakeLists.txt2
-rwxr-xr-xtools/build-compiz-glib2
-rwxr-xr-xtools/migrate_favorites.py292
-rwxr-xr-xtools/unity.cmake3
-rw-r--r--unity-shared/CMakeLists.txt1
-rw-r--r--unity-shared/CairoTexture.h2
-rw-r--r--unity-shared/DashStyle.cpp4
-rw-r--r--unity-shared/IMTextEntry.cpp107
-rw-r--r--unity-shared/IMTextEntry.h24
-rw-r--r--unity-shared/IconRenderer.cpp2
-rw-r--r--unity-shared/IconTexture.h2
-rw-r--r--unity-shared/Introspectable.cpp6
-rw-r--r--unity-shared/Introspectable.h4
-rw-r--r--unity-shared/KeyboardUtil.cpp (renamed from plugins/unityshell/src/KeyboardUtil.cpp)52
-rw-r--r--unity-shared/KeyboardUtil.h (renamed from plugins/unityshell/src/KeyboardUtil.h)19
-rw-r--r--unity-shared/PanelStyle.cpp2
-rw-r--r--unity-shared/PluginAdapterCompiz.cpp12
-rw-r--r--unity-shared/SearchBar.cpp3
-rw-r--r--unity-shared/SearchBar.h2
-rw-r--r--unity-shared/StaticCairoText.cpp2
-rw-r--r--unity-shared/UBusMessages.h4
103 files changed, 2131 insertions, 2397 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e86aae33a..bc034a517 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -127,7 +127,9 @@ endif (DISABLE_MAINTAINER_CFLAGS)
#
# Compiz Plugins
#
-set (UNITY_PLUGIN_DEPS "compiz;nux-2.0>=2.0.0;libbamf3;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib-0.4;x11;libstartup-notification-1.0;gthread-2.0;indicator3-0.4>=0.4.90;atk;unity-misc>=0.4.0;gconf-2.0;libutouch-geis;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;gnome-desktop-3.0;xfixes")
+
+set (UNITY_PLUGIN_DEPS "compiz;nux-3.0>=3.0.0;libbamf3;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib-0.4;x11;libstartup-notification-1.0;gthread-2.0;indicator3-0.4>=0.4.90;atk;unity-misc>=0.4.0;gconf-2.0;libutouch-geis;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;xfixes")
+
find_package (PkgConfig)
pkg_check_modules (CACHED_UNITY_DEPS REQUIRED ${UNITY_PLUGIN_DEPS})
add_subdirectory(unity-shared)
diff --git a/UnityCore/CMakeLists.txt b/UnityCore/CMakeLists.txt
index aa6a573a0..962c5475c 100644
--- a/UnityCore/CMakeLists.txt
+++ b/UnityCore/CMakeLists.txt
@@ -1,5 +1,5 @@
find_package (PkgConfig)
-pkg_check_modules (CORE_DEPS REQUIRED glib-2.0 gio-2.0 dee-1.0 sigc++-2.0 nux-core-2.0 gdk-pixbuf-2.0 unity)
+pkg_check_modules (CORE_DEPS REQUIRED glib-2.0 gio-2.0 dee-1.0 sigc++-2.0 nux-core-3.0 gdk-pixbuf-2.0 unity)
execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} unity --variable lensesdir OUTPUT_VARIABLE _lensesdir OUTPUT_STRIP_TRAILING_WHITESPACE)
diff --git a/UnityCore/GLibSignal-inl.h b/UnityCore/GLibSignal-inl.h
index 2a8f1baad..0f3e7a9b5 100644
--- a/UnityCore/GLibSignal-inl.h
+++ b/UnityCore/GLibSignal-inl.h
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
-* Copyright (C) 2011 Canonical Ltd
+* Copyright (C) 2011-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
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Neil Jagdish patel <neil.patel@canonical.com>
+* Marco Trevisan <marco.trevisan@canonical.com>
*/
#ifndef UNITY_GLIB_SIGNAL_INL_H
@@ -25,274 +26,27 @@ namespace unity
namespace glib
{
-template <typename R, typename G>
-Signal0<R, G>::Signal0()
-{}
-
-template <typename R, typename G>
-void Signal0<R, G>::Connect(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- object_ = reinterpret_cast<GObject*>(object);
- name_ = signal_name;
- callback_ = callback;
- connection_id_ = g_signal_connect(object, signal_name.c_str(),
- G_CALLBACK(Callback), this);
-}
-
-template <typename R, typename G>
-R Signal0<R, G>::Callback(G object, Signal0* self)
-{
- return self->callback_(object);
-}
-
-template <typename R, typename G, typename T>
-Signal1<R, G, T>::Signal1()
-{}
-
-template <typename R, typename G, typename T>
-void Signal1<R, G, T>::Connect(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- object_ = reinterpret_cast<GObject*>(object);
- name_ = signal_name;
- callback_ = callback;
- connection_id_ = g_signal_connect(object, signal_name.c_str(),
- G_CALLBACK(Callback), this);
-}
-
-template <typename R, typename G, typename T>
-R Signal1<R, G, T>::Callback(G object, T data1, Signal1* self)
-{
- return self->callback_(object, data1);
-}
-
-template <typename R, typename G, typename T1, typename T2>
-Signal2<R, G, T1, T2>::Signal2()
-{}
-
-template <typename R, typename G, typename T1, typename T2>
-void Signal2<R, G, T1, T2>::Connect(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- object_ = reinterpret_cast<GObject*>(object);
- name_ = signal_name;
- callback_ = callback;
- connection_id_ = g_signal_connect(object, signal_name.c_str(),
- G_CALLBACK(Callback), this);
-}
-
-template <typename R, typename G, typename T1, typename T2>
-R Signal2<R, G, T1, T2>::Callback(G object,
- T1 data1,
- T2 data2,
- Signal2* self)
-{
- return self->callback_(object, data1, data2);
-}
-
-template <typename R, typename G, typename T1, typename T2, typename T3>
-Signal3<R, G, T1, T2, T3>::Signal3()
-{}
-
-template <typename R, typename G, typename T1, typename T2, typename T3>
-void Signal3<R, G, T1, T2, T3>::Connect(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- object_ = reinterpret_cast<GObject*>(object);
- name_ = signal_name;
- callback_ = callback;
- connection_id_ = g_signal_connect(object, signal_name.c_str(),
- G_CALLBACK(Callback), this);
-}
-
-template <typename R, typename G, typename T1, typename T2, typename T3>
-R Signal3<R, G, T1, T2, T3>::Callback(G object,
- T1 data1,
- T2 data2,
- T3 data3,
- Signal3* self)
+template <typename R, typename G, typename... Ts>
+Signal<R, G, Ts...>::Signal(G object, std::string const& signal_name,
+ SignalCallback const& callback)
{
- return self->callback_(object, data1, data2, data3);
+ Connect(object, signal_name, callback);
}
-template <typename R, typename G, typename T1, typename T2, typename T3, typename T4>
-Signal4<R, G, T1, T2, T3, T4>::Signal4()
-{}
-
-template <typename R, typename G, typename T1, typename T2, typename T3, typename T4>
-void Signal4<R, G, T1, T2, T3, T4>::Connect(G object,
- std::string const& signal_name,
- SignalCallback callback)
+template <typename R, typename G, typename... Ts>
+void Signal<R, G, Ts...>::Connect(G object, std::string const& signal_name,
+ SignalCallback const& callback)
{
object_ = reinterpret_cast<GObject*>(object);
name_ = signal_name;
callback_ = callback;
- connection_id_ = g_signal_connect(object, signal_name.c_str(),
- G_CALLBACK(Callback), this);
+ connection_id_ = g_signal_connect(object, signal_name.c_str(), G_CALLBACK(Callback), this);
}
-template <typename R, typename G, typename T1, typename T2, typename T3, typename T4>
-R Signal4<R, G, T1, T2, T3, T4>::Callback(G object,
- T1 data1,
- T2 data2,
- T3 data3,
- T4 data4,
- Signal4* self)
-{
- return self->callback_(object, data1, data2, data3, data4);
-}
-
-
-template < typename R, typename G, typename T1, typename T2,
- typename T3, typename T4, typename T5 >
-Signal5<R, G, T1, T2, T3, T4, T5>::Signal5()
-{}
-
-template < typename R, typename G, typename T1, typename T2,
- typename T3, typename T4, typename T5 >
-void Signal5<R, G, T1, T2, T3, T4, T5>::Connect(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- object_ = reinterpret_cast<GObject*>(object);
- name_ = signal_name;
- callback_ = callback;
- connection_id_ = g_signal_connect(object, signal_name.c_str(),
- G_CALLBACK(Callback), this);
-}
-
-template < typename R, typename G, typename T1, typename T2,
- typename T3, typename T4, typename T5 >
-R Signal5<R, G, T1, T2, T3, T4, T5>::Callback(G object,
- T1 data1,
- T2 data2,
- T3 data3,
- T4 data4,
- T5 data5,
- Signal5* self)
-{
- return self->callback_(object, data1, data2, data3, data4, data5);
-}
-
-template < typename R, typename G, typename T1, typename T2,
- typename T3, typename T4, typename T5 , typename T6 >
-Signal6<R, G, T1, T2, T3, T4, T5, T6>::Signal6()
-{}
-
-template < typename R, typename G, typename T1, typename T2,
- typename T3, typename T4, typename T5 , typename T6 >
-void Signal6<R, G, T1, T2, T3, T4, T5, T6>::Connect(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- object_ = reinterpret_cast<GObject*>(object);
- name_ = signal_name;
- callback_ = callback;
- connection_id_ = g_signal_connect(object, signal_name.c_str(),
- G_CALLBACK(Callback), this);
-}
-
-template < typename R, typename G, typename T1, typename T2,
- typename T3, typename T4, typename T5, typename T6 >
-R Signal6<R, G, T1, T2, T3, T4, T5, T6>::Callback(G object,
- T1 data1,
- T2 data2,
- T3 data3,
- T4 data4,
- T5 data5,
- T6 data6,
- Signal6* self)
-{
- return self->callback_(object, data1, data2, data3, data4, data5, data6);
-}
-
-template<typename R, typename G>
-Signal<R, G>::Signal()
-{}
-
-template<typename R, typename G>
-Signal<R, G>::Signal(G object, std::string const& signal_name, SignalCallback callback)
-{
- this->Connect(object, signal_name, callback);
-}
-
-template<typename R, typename G, typename T1>
-Signal<R, G, T1>::Signal()
-{}
-
-template<typename R, typename G, typename T1>
-Signal<R, G, T1>::Signal(G object, std::string const& signal_name, SignalCallback callback)
-{
- this->Connect(object, signal_name, callback);
-}
-
-template<typename R, typename G, typename T1, typename T2>
-Signal<R, G, T1, T2>::Signal()
-{}
-
-template<typename R, typename G, typename T1, typename T2>
-Signal<R, G, T1, T2>::Signal(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- this->Connect(object, signal_name, callback);
-}
-
-template<typename R, typename G, typename T1, typename T2, typename T3>
-Signal<R, G, T1, T2, T3>::Signal()
-{}
-
-template<typename R, typename G, typename T1, typename T2, typename T3>
-Signal<R, G, T1, T2, T3>::Signal(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- this->Connect(object, signal_name, callback);
-}
-
-template<typename R, typename G, typename T1, typename T2, typename T3, typename T4>
-Signal<R, G, T1, T2, T3, T4>::Signal()
-{}
-
-template<typename R, typename G, typename T1, typename T2, typename T3, typename T4>
-Signal<R, G, T1, T2, T3, T4>::Signal(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- this->Connect(object, signal_name, callback);
-}
-
-template < typename R, typename G, typename T1, typename T2, typename T3, typename T4,
- typename T5 >
-Signal<R, G, T1, T2, T3, T4, T5>::Signal()
-{}
-
-template < typename R, typename G, typename T1, typename T2, typename T3, typename T4,
- typename T5 >
-Signal<R, G, T1, T2, T3, T4, T5>::Signal(G object,
- std::string const& signal_name,
- SignalCallback callback)
-{
- this->Connect(object, signal_name, callback);
-}
-
-template < typename R, typename G, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6 >
-Signal<R, G, T1, T2, T3, T4, T5, T6>::Signal()
-{}
-
-template < typename R, typename G, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6 >
-Signal<R, G, T1, T2, T3, T4, T5, T6>::Signal(G object,
- std::string const& signal_name,
- SignalCallback callback)
+template <typename R, typename G, typename... Ts>
+R Signal<R, G, Ts...>::Callback(G object, Ts... vs, Signal* self)
{
- this->Connect(object, signal_name, callback);
+ return self->callback_(object, vs...);
}
}
diff --git a/UnityCore/GLibSignal.cpp b/UnityCore/GLibSignal.cpp
index b191d8b9c..d2942aec2 100644
--- a/UnityCore/GLibSignal.cpp
+++ b/UnityCore/GLibSignal.cpp
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
-* Copyright (C) 2011 Canonical Ltd
+* Copyright (C) 2011-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
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Neil Jagdish patel <neil.patel@canonical.com>
+* Marco Trevisan <marco.trevisan@canonical.com>
*/
#include "GLibSignal.h"
@@ -63,8 +64,12 @@ SignalManager::SignalManager()
// opportunity for random bugs, it also made the API bad.
void SignalManager::Add(SignalBase* signal)
{
- SignalBase::Ptr s(signal);
- connections_.push_back(s);
+ Add(SignalBase::Ptr(signal));
+}
+
+void SignalManager::Add(SignalBase::Ptr const& signal)
+{
+ connections_.push_back(signal);
}
// This uses void* to keep in line with the g_signal* functions
diff --git a/UnityCore/GLibSignal.h b/UnityCore/GLibSignal.h
index c1004a886..b498888bb 100644
--- a/UnityCore/GLibSignal.h
+++ b/UnityCore/GLibSignal.h
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
-* Copyright (C) 2011 Canonical Ltd
+* Copyright (C) 2011-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
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+* Marco Trevisan <marco.trevisan@canonical.com>
*/
#ifndef UNITY_GLIB_SIGNAL_H
@@ -22,8 +23,8 @@
#include <string>
#include <vector>
+#include <memory>
#include <boost/noncopyable.hpp>
-#include <boost/shared_ptr.hpp>
#include <glib-object.h>
#include <sigc++/sigc++.h>
@@ -32,14 +33,11 @@ namespace unity
namespace glib
{
-using sigc::nil;
-
-class SignalBase
+class SignalBase : boost::noncopyable
{
public:
- typedef boost::shared_ptr<SignalBase> Ptr;
+ typedef std::shared_ptr<SignalBase> Ptr;
- SignalBase();
virtual ~SignalBase();
void Disconnect();
@@ -48,257 +46,58 @@ public:
std::string const& name() const;
protected:
+ SignalBase();
+
GObject* object_;
guint32 connection_id_;
std::string name_;
};
-template <typename R, typename G>
-class Signal0 : public SignalBase
-{
-public:
- typedef sigc::slot<R, G> SignalCallback;
-
- Signal0();
-
- void Connect(G Object,
- std::string const& signal_name,
- SignalCallback cb);
-private:
- static R Callback(G object, Signal0* self);
-private:
- SignalCallback callback_;
-};
-
-template <typename R, typename G, typename T>
-class Signal1 : public SignalBase
-{
-public:
- typedef sigc::slot<R, G, T> SignalCallback;
-
- Signal1();
-
- void Connect(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-private:
- static R Callback(G object, T data1, Signal1* self);
-private:
- SignalCallback callback_;
-};
-
-template <typename R, typename G, typename T1, typename T2>
-class Signal2 : public SignalBase
-{
-public:
- typedef sigc::slot<R, G, T1, T2> SignalCallback;
-
- Signal2();
-
- void Connect(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-private:
- static R Callback(G Object,
- T1 data1,
- T2 data2,
- Signal2* self);
-private:
- SignalCallback callback_;
-};
-
-template <typename R, typename G, typename T1, typename T2, typename T3>
-class Signal3 : public SignalBase
-{
-public:
- typedef sigc::slot<R, G, T1, T2, T3> SignalCallback;
-
- Signal3();
-
- void Connect(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-private:
- static R Callback(G Object,
- T1 data1,
- T2 data2,
- T3 data3,
- Signal3* self);
-private:
- SignalCallback callback_;
-};
-
-template <typename R, typename G, typename T1, typename T2, typename T3, typename T4>
-class Signal4 : public SignalBase
+template <typename R, typename G, typename... Ts>
+class Signal : public SignalBase
{
public:
- typedef sigc::slot<R, G, T1, T2, T3, T4> SignalCallback;
-
- Signal4();
+/* Versions of GCC prior to 4.7 doesn't support the Ts... expansion, we can
+ * workaround this issue using the trick below.
+ * See GCC bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35722 */
+#if !defined(__GNUC__) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 7)
+ typedef sigc::slot<R, G, Ts...> SignalCallback;
+#else
+ template<template <typename...> class T, typename... params>
+ struct expand_variadic {
+ typedef T<params...> type;
+ };
- void Connect(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-private:
- static R Callback(G Object,
- T1 data1,
- T2 data2,
- T3 data3,
- T4 data4,
- Signal4* self);
-private:
- SignalCallback callback_;
-};
+ typedef typename expand_variadic<sigc::slot, R, G, Ts...>::type SignalCallback;
+#endif
-template < typename R, typename G, typename T1, typename T2,
- typename T3, typename T4, typename T5 >
-class Signal5 : public SignalBase
-{
-public:
- typedef sigc::slot<R, G, T1, T2, T3, T4, T5> SignalCallback;
+ inline Signal() {};
+ inline Signal(G object, std::string const& signal_name, SignalCallback const& callback);
- Signal5();
+ inline void Connect(G Object, std::string const& signal_name, SignalCallback const& callback);
- void Connect(G Object,
- std::string const& signal_name,
- SignalCallback callback);
private:
- static R Callback(G Object,
- T1 data1,
- T2 data2,
- T3 data3,
- T4 data4,
- T5 data5,
- Signal5* self);
-private:
- SignalCallback callback_;
-};
-
-template < typename R, typename G, typename T1, typename T2,
- typename T3, typename T4, typename T5, typename T6 >
-class Signal6 : public SignalBase
-{
-public:
- typedef sigc::slot<R, G, T1, T2, T3, T4, T5, T6> SignalCallback;
+ static R Callback(G Object, Ts... vs, Signal* self);
- Signal6();
-
- void Connect(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-private:
- static R Callback(G Object,
- T1 data1,
- T2 data2,
- T3 data3,
- T4 data4,
- T5 data5,
- T6 data6,
- Signal6* self);
-private:
SignalCallback callback_;
};
-template < typename R, typename G,
- typename T1 = nil, typename T2 = nil,
- typename T3 = nil, typename T4 = nil,
- typename T5 = nil, typename T6 = nil >
-class Signal : public Signal6<R, G, T1, T2, T3, T4, T5, T6>
-{
-public:
- typedef sigc::slot<R, G, T1, T2, T3, T4, T5, T6> SignalCallback;
-
- inline Signal();
- inline Signal(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-};
-
-template <typename R, typename G>
-class Signal<R, G, nil, nil, nil, nil, nil, nil> : public Signal0<R, G>
-{
-public:
- typedef sigc::slot<R, G> SignalCallback;
-
- inline Signal();
- inline Signal(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-};
-
-template <typename R, typename G, typename T1>
-class Signal<R, G, T1, nil, nil, nil, nil, nil> : public Signal1<R, G, T1>
-{
-public:
- typedef sigc::slot<R, G, T1> SignalCallback;
-
- inline Signal();
- inline Signal(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-};
-
-template <typename R, typename G, typename T1, typename T2>
-class Signal<R, G, T1, T2, nil, nil, nil, nil> : public Signal2<R, G, T1, T2>
+class SignalManager : boost::noncopyable
{
public:
- typedef sigc::slot<R, G, T1, T2> SignalCallback;
-
- inline Signal();
- inline Signal(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-};
-
-template <typename R, typename G, typename T1, typename T2, typename T3>
-class Signal<R, G, T1, T2, T3, nil, nil, nil> : public Signal3<R, G, T1, T2 , T3>
-{
-public:
- typedef sigc::slot<R, G, T1, T2, T3> SignalCallback;
-
- inline Signal();
- inline Signal(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-};
-
-template <typename R, typename G, typename T1, typename T2, typename T3, typename T4>
-class Signal<R, G, T1, T2, T3, T4, nil, nil>
- : public Signal4<R, G, T1, T2 , T3, T4>
-{
-public:
- typedef sigc::slot<R, G, T1, T2, T3, T4> SignalCallback;
-
- inline Signal();
- inline Signal(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-};
-
-template <typename R, typename G, typename T1, typename T2, typename T3, typename T4, typename T5>
-class Signal<R, G, T1, T2, T3, T4, T5, nil>
- : public Signal5<R, G, T1, T2 , T3, T4, T5>
-{
-public:
- typedef sigc::slot<R, G, T1, T2, T3, T4, T5> SignalCallback;
-
- inline Signal();
- inline Signal(G Object,
- std::string const& signal_name,
- SignalCallback callback);
-};
-
-class SignalManager : public boost::noncopyable
-{
-public:
- typedef std::vector<SignalBase::Ptr> ConnectionVector;
-
SignalManager();
void Add(SignalBase* signal);
+ void Add(SignalBase::Ptr const& signal);
+ template <typename R, typename G, typename... Ts>
+ void Add(G object, std::string const& signal_name, typename Signal<R, G, Ts...>::SignalCallback const& callback)
+ {
+ Add(std::make_shared<Signal<R, G, Ts...>>(object, signal_name, callback));
+ }
+
void Disconnect(void* object, std::string const& signal_name = "");
-private:
- ConnectionVector connections_;
+protected:
+ std::vector<SignalBase::Ptr> connections_;
};
}
diff --git a/UnityCore/unity-core.pc.cmake b/UnityCore/unity-core.pc.cmake
index 66e389236..251209154 100644
--- a/UnityCore/unity-core.pc.cmake
+++ b/UnityCore/unity-core.pc.cmake
@@ -9,4 +9,4 @@ Description: Core objects and utilities for Unity implementations
Version: @VERSION@
Libs: -L${libdir} -lunity-core-@UNITY_API_VERSION@
Cflags: -I${includedir}/Unity-@UNITY_API_VERSION@
-Requires: glib-2.0 gio-2.0 sigc++-2.0 nux-core-2.0 dee-1.0
+Requires: glib-2.0 gio-2.0 sigc++-2.0 nux-core-3.0 dee-1.0
diff --git a/dash/DashController.cpp b/dash/DashController.cpp
index 4b611a715..eae21622a 100644
--- a/dash/DashController.cpp
+++ b/dash/DashController.cpp
@@ -80,7 +80,7 @@ void Controller::SetupWindow()
window_->ShowWindow(false);
window_->SetOpacity(0.0f);
window_->mouse_down_outside_pointer_grab_area.connect(sigc::mem_fun(this, &Controller::OnMouseDownOutsideWindow));
-
+
/* FIXME - first time we load our windows there is a race that causes the input window not to actually get input, this side steps that by causing an input window show and hide before we really need it. */
auto plugin_adapter = PluginAdapter::Default();
plugin_adapter->saveInputFocus ();
@@ -337,6 +337,9 @@ gboolean Controller::CheckShortcutActivation(const char* key_string)
std::string lens_id = view_->GetIdForShortcutActivation(std::string(key_string));
if (lens_id != "")
{
+ if (PluginAdapter::Default()->IsScaleActive())
+ PluginAdapter::Default()->TerminateScale();
+
GVariant* args = g_variant_new("(sus)", lens_id.c_str(), dash::GOTO_DASH_URI, "");
OnActivateRequest(args);
g_variant_unref(args);
diff --git a/dash/DashView.cpp b/dash/DashView.cpp
index e84a3e726..afa1f729f 100644
--- a/dash/DashView.cpp
+++ b/dash/DashView.cpp
@@ -30,6 +30,7 @@
#include <UnityCore/RadioOptionFilter.h>
#include "unity-shared/DashStyle.h"
+#include "unity-shared/KeyboardUtil.h"
#include "unity-shared/UnitySettings.h"
#include "unity-shared/UBusMessages.h"
@@ -761,16 +762,17 @@ void DashView::ProcessDndEnter()
ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
}
-Area* DashView::FindKeyFocusArea(unsigned int key_symbol,
- unsigned long x11_key_code,
- unsigned long special_keys_state)
+nux::Area* DashView::FindKeyFocusArea(unsigned int key_symbol,
+ unsigned long x11_key_code,
+ unsigned long special_keys_state)
{
// Do what nux::View does, but if the event isn't a key navigation,
// designate the text entry to process it.
+ using namespace nux;
+ nux::KeyNavDirection direction = KEY_NAV_NONE;
bool ctrl = (special_keys_state & NUX_STATE_CTRL);
- nux::KeyNavDirection direction = KEY_NAV_NONE;
switch (x11_key_code)
{
case NUX_VK_UP:
@@ -801,14 +803,13 @@ Area* DashView::FindKeyFocusArea(unsigned int key_symbol,
case NUX_VK_F4:
// Maybe we should not do it here, but it needs to be checked where
// we are able to know if alt is pressed.
- if (special_keys_state & NUX_STATE_ALT)
+ if (special_keys_state == NUX_STATE_ALT)
{
ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
}
break;
default:
direction = KEY_NAV_NONE;
- break;
}
// We should not do it here, but I really don't want to make DashView
@@ -816,7 +817,7 @@ Area* DashView::FindKeyFocusArea(unsigned int key_symbol,
// DashView::KeyNavIteration.
nux::InputArea* focus_area = nux::GetWindowCompositor().GetKeyFocusArea();
- if (key_symbol == nux::NUX_KEYDOWN && !search_bar_->im_preedit)
+ if (direction != KEY_NAV_NONE && key_symbol == nux::NUX_KEYDOWN && !search_bar_->im_preedit)
{
std::list<nux::Area*> tabs;
for (auto category : active_lens_view_->categories())
@@ -891,7 +892,18 @@ Area* DashView::FindKeyFocusArea(unsigned int key_symbol,
}
}
- if (direction == KEY_NAV_NONE || search_bar_->im_preedit)
+ bool search_key = false;
+
+ if (direction == KEY_NAV_NONE)
+ {
+ if (ui::KeyboardUtil::IsPrintableKeySymbol(x11_key_code) ||
+ ui::KeyboardUtil::IsMoveKeySymbol(x11_key_code))
+ {
+ search_key = true;
+ }
+ }
+
+ if (search_key || search_bar_->im_preedit)
{
// then send the event to the search entry
return search_bar_->text_entry();
@@ -900,7 +912,8 @@ Area* DashView::FindKeyFocusArea(unsigned int key_symbol,
{
return next_object_to_key_focus_area_->FindKeyFocusArea(key_symbol, x11_key_code, special_keys_state);
}
- return NULL;
+
+ return nullptr;
}
}
diff --git a/dash/PlacesVScrollBar.h b/dash/PlacesVScrollBar.h
index 54d0b3da7..11bace179 100644
--- a/dash/PlacesVScrollBar.h
+++ b/dash/PlacesVScrollBar.h
@@ -25,7 +25,7 @@
#include <Nux/ScrollView.h>
#include <Nux/BaseWindow.h>
#include <Nux/VScrollBar.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
class PlacesVScrollBar : public nux::VScrollBar
{
diff --git a/dash/ResultRendererHorizontalTile.h b/dash/ResultRendererHorizontalTile.h
index d7c68238b..deda4bd71 100644
--- a/dash/ResultRendererHorizontalTile.h
+++ b/dash/ResultRendererHorizontalTile.h
@@ -29,7 +29,7 @@
#include <NuxCore/Object.h>
#include <NuxCore/Property.h>
#include <Nux/TextureArea.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include "ResultRendererTile.h"
diff --git a/dash/ResultRendererTile.h b/dash/ResultRendererTile.h
index 54a21faf2..165b60653 100644
--- a/dash/ResultRendererTile.h
+++ b/dash/ResultRendererTile.h
@@ -30,7 +30,7 @@
#include <NuxCore/ObjectPtr.h>
#include <NuxCore/Property.h>
#include <Nux/TextureArea.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include "unity-shared/IconLoader.h"
#include "ResultRenderer.h"
diff --git a/dash/ResultView.cpp b/dash/ResultView.cpp
index 8c22866e7..5350fc579 100644
--- a/dash/ResultView.cpp
+++ b/dash/ResultView.cpp
@@ -142,7 +142,7 @@ void ResultView::AddProperties(GVariantBuilder* builder)
.add("expanded", expanded);
}
-debug::Introspectable::IntrospectableList const& ResultView::GetIntrospectableChildren()
+debug::Introspectable::IntrospectableList ResultView::GetIntrospectableChildren()
{
ClearIntrospectableWrappers();
diff --git a/dash/ResultView.h b/dash/ResultView.h
index 1cc339b82..224d11637 100644
--- a/dash/ResultView.h
+++ b/dash/ResultView.h
@@ -61,7 +61,7 @@ public:
std::string GetName() const;
void AddProperties(GVariantBuilder* builder);
- IntrospectableList const& GetIntrospectableChildren();
+ IntrospectableList GetIntrospectableChildren();
protected:
virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
diff --git a/dash/ResultViewGrid.cpp b/dash/ResultViewGrid.cpp
index 2fc07cdf0..173c26c3c 100644
--- a/dash/ResultViewGrid.cpp
+++ b/dash/ResultViewGrid.cpp
@@ -23,7 +23,7 @@
#include <Nux/Nux.h>
#include <NuxCore/Logger.h>
#include <Nux/VLayout.h>
-#include <NuxImage/GdkGraphics.h>
+#include <NuxGraphics/GdkGraphics.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
diff --git a/hud/HudButton.cpp b/hud/HudButton.cpp
index 138407f30..13159eba7 100644
--- a/hud/HudButton.cpp
+++ b/hud/HudButton.cpp
@@ -28,7 +28,7 @@
#include <Nux/Nux.h>
#include <Nux/HLayout.h>
#include <NuxCore/Logger.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <NuxGraphics/NuxGraphics.h>
#include <UnityCore/GLibWrapper.h>
#include <UnityCore/Variant.h>
@@ -52,10 +52,13 @@ namespace unity
namespace hud
{
+NUX_IMPLEMENT_OBJECT_TYPE(HudButton);
+
HudButton::HudButton(NUX_FILE_LINE_DECL)
: nux::Button(NUX_FILE_LINE_PARAM)
, is_rounded(false)
, is_focused_(false)
+ , skip_draw_(true)
{
hlayout_ = new nux::HLayout(NUX_TRACKER_LOCATION);
hlayout_->SetLeftAndRightPadding(hlayout_left_padding, -1);
@@ -105,7 +108,7 @@ void HudButton::RedrawTheme(nux::Geometry const& geom, cairo_t* cr, nux::ButtonV
bool HudButton::AcceptKeyNavFocus()
{
- // The button will not receive the keyboard focus. The keyboard focus is always to remain with the
+ // The button will not receive the keyboard focus. The keyboard focus is always to remain with the
// text entry in the hud.
return false;
}
@@ -130,7 +133,11 @@ long HudButton::ComputeContentSize()
void HudButton::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
{
+ if (skip_draw_)
+ return;
+
nux::Geometry const& geo = GetGeometry();
+ GfxContext.PushClippingRectangle(geo);
gPainter.PaintBackground(GfxContext, geo);
// set up our texture mode
@@ -170,12 +177,21 @@ void HudButton::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
nux::color::White);
GfxContext.GetRenderStates().SetBlend(alpha, src, dest);
+
+ GfxContext.PopClippingRectangle();
}
void HudButton::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
{
+ if (skip_draw_)
+ return;
+
if (IsFullRedraw())
+ {
+ GfxContext.PushClippingRectangle(GetGeometry());
hlayout_->ProcessDraw(GfxContext, force_draw);
+ GfxContext.PopClippingRectangle();
+ }
}
void HudButton::SetQuery(Query::Ptr query)
@@ -188,7 +204,7 @@ void HudButton::SetQuery(Query::Ptr query)
hlayout_->Clear();
for (auto item : items)
{
- nux::StaticCairoText* text = new nux::StaticCairoText(item.first.c_str());
+ nux::StaticCairoText* text = new nux::StaticCairoText(item.first);
text->SetTextColor(nux::Color(1.0f, 1.0f, 1.0f, item.second ? 1.0f : 0.5f));
text->SetFont(button_font);
hlayout_->AddView(text, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
@@ -200,6 +216,12 @@ Query::Ptr HudButton::GetQuery()
return query_;
}
+void HudButton::SetSkipDraw(bool skip_draw)
+{
+ skip_draw_ = skip_draw;
+}
+
+
// Introspectable
std::string HudButton::GetName() const
{
@@ -209,7 +231,8 @@ std::string HudButton::GetName() const
void HudButton::AddProperties(GVariantBuilder* builder)
{
variant::BuilderWrapper(builder)
- .add("label", label());
+ .add("label", label())
+ .add("focused", fake_focused());
}
} // namespace hud
diff --git a/hud/HudButton.h b/hud/HudButton.h
index 555f5ab38..9ccf43d14 100644
--- a/hud/HudButton.h
+++ b/hud/HudButton.h
@@ -38,8 +38,8 @@ namespace hud
class HudButton : public nux::Button, public unity::debug::Introspectable
{
- typedef nux::ObjectPtr<nux::BaseTexture> BaseTexturePtr;
- typedef std::unique_ptr<nux::CairoWrapper> NuxCairoPtr;
+ NUX_DECLARE_OBJECT_TYPE(HudButton, nux::Button);
+
public:
typedef nux::ObjectPtr<HudButton> Ptr;
@@ -48,6 +48,8 @@ public:
void SetQuery(Query::Ptr query);
std::shared_ptr<Query> GetQuery();
+ void SetSkipDraw(bool skip_draw);
+
nux::Property<std::string> label;
nux::Property<bool> is_rounded;
nux::Property<bool> fake_focused;
@@ -65,9 +67,13 @@ protected:
void RedrawTheme(nux::Geometry const& geom, cairo_t* cr, nux::ButtonVisualState faked_state);
private:
+ typedef std::unique_ptr<nux::CairoWrapper> NuxCairoPtr;
+
Query::Ptr query_;
nux::Geometry cached_geometry_;
+
bool is_focused_;
+ bool skip_draw_;
NuxCairoPtr prelight_;
NuxCairoPtr active_;
diff --git a/hud/HudView.cpp b/hud/HudView.cpp
index 6c0e02531..d45a741a0 100644
--- a/hud/HudView.cpp
+++ b/hud/HudView.cpp
@@ -27,6 +27,8 @@
#include <Nux/HLayout.h>
#include <Nux/VLayout.h>
+#include "unity-shared/Introspectable.h"
+
#include "unity-shared/UBusMessages.h"
#include "unity-shared/DashStyle.h"
@@ -116,10 +118,6 @@ View::View()
View::~View()
{
- for (auto button = buttons_.begin(); button != buttons_.end(); button++)
- {
- RemoveChild((*button).GetPointer());
- }
}
void View::ProcessGrowShrink()
@@ -149,6 +147,11 @@ void View::ProcessGrowShrink()
current_height_ = new_height;
}
+ for (auto button : buttons_)
+ {
+ button->SetSkipDraw((button->GetAbsoluteY() + button->GetBaseHeight()) > (GetAbsoluteY() + current_height_));
+ }
+
QueueDraw();
if (diff > grow_anim_length + pause_before_grow_length)
@@ -238,6 +241,8 @@ void View::SetQueries(Hud::Queries queries)
HudButton::Ptr button(new HudButton());
buttons_.push_front(button);
+ button->SetMinimumWidth(content_width);
+ button->SetMaximumWidth(content_width);
button->SetQuery(query);
button_views_->AddView(button.GetPointer(), 0, nux::MINOR_POSITION_LEFT);
@@ -250,12 +255,11 @@ void View::SetQueries(Hud::Queries queries)
query_activated.emit(dynamic_cast<HudButton*>(area)->GetQuery());
});
- button->key_nav_focus_change.connect([&](nux::Area* area, bool recieving, KeyNavDirection direction){
+ button->key_nav_focus_change.connect([&](nux::Area* area, bool recieving, nux::KeyNavDirection direction){
if (recieving)
query_selected.emit(dynamic_cast<HudButton*>(area)->GetQuery());
});
- button->SetMinimumWidth(content_width);
++found_items;
}
@@ -350,7 +354,7 @@ void View::SetupViews()
{
dash::Style& style = dash::Style::Instance();
- nux::VLayout* super_layout = new nux::VLayout();
+ nux::VLayout* super_layout = new nux::VLayout();
layout_ = new nux::HLayout();
{
// fill layout with icon
@@ -398,7 +402,7 @@ void View::OnSearchChanged(std::string const& search_string)
{
button->fake_focused = false;
}
-
+
if (!buttons_.empty())
buttons_.back()->fake_focused = true;
}
@@ -417,7 +421,9 @@ void View::OnKeyDown (unsigned long event_type, unsigned long keysym,
void View::OnMouseButtonDown(int x, int y, unsigned long button, unsigned long key)
{
- if (!content_geo_.IsPointInside(x, y))
+ nux::Geometry current_geo(content_geo_);
+ current_geo.height = current_height_;
+ if (!current_geo.IsPointInside(x, y))
{
ubus.SendMessage(UBUS_HUD_CLOSE_REQUEST);
}
@@ -457,7 +463,7 @@ void View::DrawContent(nux::GraphicsEngine& gfx_context, bool force_draw)
x += content_width - 1;
nux::GetPainter().Draw2DLine(gfx_context, x, y, x, y + height, nux::color::White * 0.13);
}
-
+
GetLayout()->ProcessDraw(gfx_context, force_draw);
nux::GetPainter().PopBackgroundStack();
}
@@ -500,6 +506,18 @@ void View::AddProperties(GVariantBuilder* builder)
.add("num_buttons", num_buttons);
}
+debug::Introspectable::IntrospectableList View::GetIntrospectableChildren()
+{
+ introspectable_children_.clear();
+ introspectable_children_.merge(debug::Introspectable::GetIntrospectableChildren());
+ for (auto button: buttons_)
+ {
+ introspectable_children_.push_front(button.GetPointer());
+ }
+
+ return introspectable_children_;
+}
+
bool View::InspectKeyEvent(unsigned int eventType,
unsigned int key_sym,
const char* character)
@@ -573,6 +591,12 @@ nux::Area* View::FindKeyFocusArea(unsigned int event_type,
// Not sure if Enter should be a navigation key
direction = nux::KEY_NAV_ENTER;
break;
+ case NUX_VK_F4:
+ if (special_keys_state == nux::NUX_STATE_ALT)
+ {
+ ubus.SendMessage(UBUS_HUD_CLOSE_REQUEST);
+ }
+ break;
default:
direction = nux::KEY_NAV_NONE;
break;
diff --git a/hud/HudView.h b/hud/HudView.h
index ca1e1a6f4..8e654b49f 100644
--- a/hud/HudView.h
+++ b/hud/HudView.h
@@ -61,7 +61,7 @@ public:
void AboutToHide();
void SetWindowGeometry(nux::Geometry const& absolute_geo, nux::Geometry const& geo);
-
+
protected:
virtual Area* FindKeyFocusArea(unsigned int event_type,
unsigned long x11_key_code,
@@ -87,6 +87,7 @@ private:
std::string GetName() const;
void AddProperties(GVariantBuilder* builder);
+ IntrospectableList GetIntrospectableChildren();
private:
UBusManager ubus;
@@ -94,6 +95,7 @@ private:
nux::ObjectPtr<nux::Layout> content_layout_;
nux::ObjectPtr<nux::VLayout> button_views_;
std::list<HudButton::Ptr> buttons_;
+ IntrospectableList introspectable_children_;
//FIXME - replace with dash search bar once modifications to dash search bar land
SearchBar::Ptr search_bar_;
diff --git a/launcher/AbstractLauncherIcon.h b/launcher/AbstractLauncherIcon.h
index a419a4974..1f4341536 100644
--- a/launcher/AbstractLauncherIcon.h
+++ b/launcher/AbstractLauncherIcon.h
@@ -218,6 +218,7 @@ public:
sigc::signal<void, AbstractLauncherIcon::Ptr> needs_redraw;
sigc::signal<void, AbstractLauncherIcon::Ptr> remove;
+ sigc::signal<void, nux::ObjectPtr<nux::View>> tooltip_visible;
sigc::signal<void> visibility_changed;
sigc::connection needs_redraw_connection;
diff --git a/launcher/FavoriteStoreGSettings.cpp b/launcher/FavoriteStoreGSettings.cpp
index 2467b94ab..fe900099b 100644
--- a/launcher/FavoriteStoreGSettings.cpp
+++ b/launcher/FavoriteStoreGSettings.cpp
@@ -44,7 +44,6 @@ namespace
nux::logging::Logger logger("unity.favorites");
const char* SETTINGS_NAME = "com.canonical.Unity.Launcher";
-const char* LATEST_SETTINGS_MIGRATION = "3.2.10";
void on_settings_updated(GSettings* settings,
const gchar* key,
@@ -68,30 +67,6 @@ FavoriteStoreGSettings::FavoriteStoreGSettings(GSettingsBackend* backend)
void FavoriteStoreGSettings::Init()
{
- /* migrate the favorites if needed and ignore errors */
- glib::String latest_migration_update(g_settings_get_string(
- settings_, "favorite-migration"));
- if (latest_migration_update.Str() < LATEST_SETTINGS_MIGRATION)
- {
- glib::Error error;
- std::string cmd(PREFIXDIR);
- cmd += "/lib/unity/migrate_favorites.py";
-
- glib::String output;
-
- g_spawn_command_line_sync(cmd.c_str(),
- &output,
- NULL,
- NULL,
- &error);
- if (error)
- {
- LOG_WARN(logger) << "WARNING: Unable to run the migrate favorites "
- << "tools successfully: " << error
- << ".\n\tThe output was:" << output;
- }
- }
-
g_signal_connect(settings_, "changed", G_CALLBACK(on_settings_updated), this);
Refresh();
}
diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp
index 7123c4ed9..b83bae24a 100644
--- a/launcher/Launcher.cpp
+++ b/launcher/Launcher.cpp
@@ -1520,6 +1520,11 @@ bool Launcher::IsBackLightModeToggles() const
}
}
+nux::ObjectPtr<nux::View> Launcher::GetActiveTooltip() const
+{
+ return _active_tooltip;
+}
+
void Launcher::SetActionState(LauncherActionState actionstate)
{
if (_launcher_action_state == actionstate)
@@ -1681,6 +1686,7 @@ void Launcher::OnIconAdded(AbstractLauncherIcon::Ptr icon)
EnsureAnimation();
icon->needs_redraw.connect(sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
+ icon->tooltip_visible.connect(sigc::mem_fun(this, &Launcher::OnTooltipVisible));
}
void Launcher::OnIconRemoved(AbstractLauncherIcon::Ptr icon)
@@ -1757,6 +1763,11 @@ void Launcher::OnIconNeedsRedraw(AbstractLauncherIcon::Ptr icon)
EnsureAnimation();
}
+void Launcher::OnTooltipVisible(nux::ObjectPtr<nux::View> view)
+{
+ _active_tooltip = view;
+}
+
void Launcher::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
{
diff --git a/launcher/Launcher.h b/launcher/Launcher.h
index 77ac52fbe..aee8f95a6 100644
--- a/launcher/Launcher.h
+++ b/launcher/Launcher.h
@@ -96,6 +96,8 @@ public:
return _parent;
};
+ nux::ObjectPtr<nux::View> GetActiveTooltip() const; // nullptr = no tooltip
+
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);
@@ -269,6 +271,7 @@ private:
void OnOrderChanged();
void OnIconNeedsRedraw(AbstractLauncherIcon::Ptr icon);
+ void OnTooltipVisible(nux::ObjectPtr<nux::View> view);
void OnOverlayHidden(GVariant* data);
void OnOverlayShown(GVariant* data);
@@ -311,6 +314,7 @@ private:
LauncherModel::Ptr _model;
nux::BaseWindow* _parent;
+ nux::ObjectPtr<nux::View> _active_tooltip;
QuicklistView* _active_quicklist;
nux::HLayout* m_Layout;
diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp
index 2886ad1e7..ad7168fcd 100644
--- a/launcher/LauncherController.cpp
+++ b/launcher/LauncherController.cpp
@@ -196,7 +196,6 @@ public:
LauncherList launchers;
- glib::Source::UniquePtr activate_idle_;
glib::Object<BamfMatcher> matcher_;
glib::Signal<void, BamfMatcher*, BamfView*> view_opened_signal_;
glib::SourceManager sources_;
@@ -373,6 +372,9 @@ void Controller::Impl::OnWindowFocusChanged (guint32 xid)
{
static bool keynav_first_focus = false;
+ if (parent_->IsOverlayOpen())
+ keynav_first_focus = false;
+
if (keynav_first_focus)
{
keynav_first_focus = false;
@@ -1098,7 +1100,6 @@ void Controller::Impl::ReceiveMouseDownOutsideArea(int x, int y, unsigned long b
void Controller::KeyNavGrab()
{
- pimpl->ubus.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
pimpl->launcher_grabbed = true;
KeyNavActivate();
pimpl->keyboard_launcher_->GrabKeyboard();
@@ -1197,12 +1198,13 @@ void Controller::KeyNavTerminate(bool activate)
g_variant_new_boolean(pimpl->keynav_restore_window_));
}
- pimpl->activate_idle_.reset(new glib::Idle([activate, this] () {
- if (activate)
+ if (activate)
+ {
+ pimpl->sources_.Add(std::make_shared<glib::Idle>([this] {
pimpl->model_->Selection()->Activate(ActionArg(ActionArg::LAUNCHER, 0));
-
- return false;
- }));
+ return false;
+ }));
+ }
pimpl->launcher_keynav = false;
if (!pimpl->launcher_open)
diff --git a/launcher/LauncherIcon.cpp b/launcher/LauncherIcon.cpp
index a17db19b0..d0f02dd6b 100644
--- a/launcher/LauncherIcon.cpp
+++ b/launcher/LauncherIcon.cpp
@@ -513,6 +513,7 @@ LauncherIcon::ShowTooltip()
LoadTooltip();
_tooltip->ShowTooltipWithTipAt(tip_x, tip_y);
_tooltip->ShowWindow(!tooltip_text().empty());
+ tooltip_visible.emit(_tooltip);
}
void
@@ -534,6 +535,7 @@ void LauncherIcon::RecvMouseLeave(int monitor)
if (_tooltip)
_tooltip->ShowWindow(false);
+ tooltip_visible.emit(nux::ObjectPtr<nux::View>(nullptr));
}
bool LauncherIcon::OpenQuicklist(bool select_first_item, int monitor)
@@ -653,6 +655,7 @@ void LauncherIcon::HideTooltip()
{
if (_tooltip)
_tooltip->ShowWindow(false);
+ tooltip_visible.emit(nux::ObjectPtr<nux::View>(nullptr));
}
bool
diff --git a/launcher/LauncherModel.cpp b/launcher/LauncherModel.cpp
index c3f0f9f38..8e8d6e504 100644
--- a/launcher/LauncherModel.cpp
+++ b/launcher/LauncherModel.cpp
@@ -44,7 +44,7 @@ void LauncherModel::AddProperties(GVariantBuilder* builder)
.add("selection", selection_);
}
-unity::debug::Introspectable::IntrospectableList const& LauncherModel::GetIntrospectableChildren()
+unity::debug::Introspectable::IntrospectableList LauncherModel::GetIntrospectableChildren()
{
introspection_results_.clear();
diff --git a/launcher/LauncherModel.h b/launcher/LauncherModel.h
index de3e33867..e6295b6cf 100644
--- a/launcher/LauncherModel.h
+++ b/launcher/LauncherModel.h
@@ -84,7 +84,7 @@ public:
sigc::signal<void> saved;
sigc::signal<void, AbstractLauncherIcon::Ptr> selection_changed;
- IntrospectableList const& GetIntrospectableChildren();
+ IntrospectableList GetIntrospectableChildren();
protected:
// Introspectable methods
std::string GetName() const;
diff --git a/launcher/QuicklistMenuItem.h b/launcher/QuicklistMenuItem.h
index 25b108634..6a0291428 100644
--- a/launcher/QuicklistMenuItem.h
+++ b/launcher/QuicklistMenuItem.h
@@ -26,7 +26,7 @@
#include <Nux/Nux.h>
#include <Nux/View.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
diff --git a/launcher/QuicklistMenuItemCheckmark.h b/launcher/QuicklistMenuItemCheckmark.h
index 39a31f334..bc5046415 100644
--- a/launcher/QuicklistMenuItemCheckmark.h
+++ b/launcher/QuicklistMenuItemCheckmark.h
@@ -23,7 +23,7 @@
#include <Nux/Nux.h>
#include <Nux/View.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include "QuicklistMenuItem.h"
diff --git a/launcher/QuicklistMenuItemLabel.h b/launcher/QuicklistMenuItemLabel.h
index 421c9ac64..58ce6e2f2 100644
--- a/launcher/QuicklistMenuItemLabel.h
+++ b/launcher/QuicklistMenuItemLabel.h
@@ -23,7 +23,7 @@
#include <Nux/Nux.h>
#include <Nux/View.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include "QuicklistMenuItem.h"
diff --git a/launcher/QuicklistMenuItemRadio.h b/launcher/QuicklistMenuItemRadio.h
index e75a17ad5..e50be8509 100644
--- a/launcher/QuicklistMenuItemRadio.h
+++ b/launcher/QuicklistMenuItemRadio.h
@@ -22,7 +22,7 @@
#include <Nux/Nux.h>
#include <Nux/View.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include "QuicklistMenuItem.h"
diff --git a/launcher/QuicklistMenuItemSeparator.h b/launcher/QuicklistMenuItemSeparator.h
index 50987a120..ce1dd8948 100644
--- a/launcher/QuicklistMenuItemSeparator.h
+++ b/launcher/QuicklistMenuItemSeparator.h
@@ -22,7 +22,7 @@
#include <Nux/Nux.h>
#include <Nux/View.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include "QuicklistMenuItem.h"
diff --git a/launcher/QuicklistView.cpp b/launcher/QuicklistView.cpp
index fd88737c4..125554966 100644
--- a/launcher/QuicklistView.cpp
+++ b/launcher/QuicklistView.cpp
@@ -27,7 +27,7 @@
#include <Nux/Button.h>
#include <NuxGraphics/GraphicsEngine.h>
#include <Nux/TextureArea.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <UnityCore/Variant.h>
#include "unity-shared/CairoTexture.h"
@@ -101,8 +101,6 @@ QuicklistView::QuicklistView()
_item_layout = new nux::VLayout(TEXT(""), NUX_TRACKER_LOCATION);
_vlayout->AddLayout(_item_layout, 0);
- _default_item_layout = new nux::VLayout(TEXT(""), NUX_TRACKER_LOCATION);
- _vlayout->AddLayout(_default_item_layout, 0);
_vlayout->AddLayout(_bottom_space, 0);
_vlayout->SetMinimumWidth(140);
@@ -306,10 +304,7 @@ QuicklistView::RecvKeyPressed(unsigned long eventType,
case NUX_KP_ENTER:
if (IsMenuItemSelectable(_current_item_index))
{
- dbusmenu_menuitem_handle_event(GetNthItems(_current_item_index)->_menuItem,
- "clicked",
- NULL,
- 0);
+ ActivateItem(GetNthItems(_current_item_index));
Hide();
}
break;
@@ -321,22 +316,13 @@ QuicklistView::RecvKeyPressed(unsigned long eventType,
QuicklistView::~QuicklistView()
{
- std::list<QuicklistMenuItem*>::iterator it;
- for (it = _item_list.begin(); it != _item_list.end(); it++)
+ for (auto item : _item_list)
{
// Remove from introspection
- RemoveChild(*it);
- (*it)->UnReference();
+ RemoveChild(item);
+ item->UnReference();
}
- for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
- {
- // Remove from introspection
- RemoveChild(*it);
- (*it)->UnReference();
- }
-
- _default_item_list.clear();
_item_list.clear();
}
@@ -353,7 +339,7 @@ void QuicklistView::ShowQuicklistWithTipAt(int anchor_tip_x, int anchor_tip_y)
if (!_enable_quicklist_for_testing)
{
- if ((_item_list.size() != 0) || (_default_item_list.size() != 0))
+ if ((_item_list.size() != 0))
{
int offscreen_size = GetBaseY() +
GetBaseHeight() -
@@ -434,17 +420,10 @@ void QuicklistView::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw)
gfxContext.PushClippingRectangle(base);
- std::list<QuicklistMenuItem*>::iterator it;
- for (it = _item_list.begin(); it != _item_list.end(); it++)
- {
- if ((*it)->GetVisible())
- (*it)->ProcessDraw(gfxContext, forceDraw);
- }
-
- for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
+ for (auto item : _item_list)
{
- if ((*it)->GetVisible())
- (*it)->ProcessDraw(gfxContext, forceDraw);
+ if (item->GetVisible())
+ item->ProcessDraw(gfxContext, forceDraw);
}
gfxContext.PopClippingRectangle();
@@ -458,40 +437,20 @@ void QuicklistView::PreLayoutManagement()
int MaxItemWidth = 0;
int TotalItemHeight = 0;
- std::list<QuicklistMenuItem*>::iterator it;
- for (it = _item_list.begin(); it != _item_list.end(); it++)
- {
- // Make sure item is in layout if it should be
- if (!(*it)->GetVisible())
- {
- _item_layout->RemoveChildObject(*it);
- continue;
- }
- else if (!(*it)->GetParentObject())
- _item_layout->AddView(*it, 1, nux::eCenter, nux::eFull);
-
- int textWidth = 0;
- int textHeight = 0;
- (*it)->GetTextExtents(textWidth, textHeight);
- if (textWidth > MaxItemWidth)
- MaxItemWidth = textWidth;
- TotalItemHeight += textHeight;
- }
-
- for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
+ for (auto item : _item_list)
{
// Make sure item is in layout if it should be
- if (!(*it)->GetVisible())
+ if (!item->GetVisible())
{
- _default_item_layout->RemoveChildObject(*it);
+ _item_layout->RemoveChildObject(item);
continue;
}
- else if (!(*it)->GetParentObject())
- _default_item_layout->AddView(*it, 1, nux::eCenter, nux::eFull);
+ else if (!item->GetParentObject())
+ _item_layout->AddView(item, 1, nux::eCenter, nux::eFull);
int textWidth = 0;
int textHeight = 0;
- (*it)->GetTextExtents(textWidth, textHeight);
+ item->GetTextExtents(textWidth, textHeight);
if (textWidth > MaxItemWidth)
MaxItemWidth = textWidth;
TotalItemHeight += textHeight;
@@ -513,7 +472,6 @@ void QuicklistView::PreLayoutManagement()
}
_item_layout->SetMinimumWidth(MaxItemWidth);
- _default_item_layout->SetMinimumWidth(MaxItemWidth);
BaseWindow::PreLayoutManagement();
}
@@ -527,27 +485,15 @@ long QuicklistView::PostLayoutManagement(long LayoutResult)
int x = _padding + _anchor_width + _corner_radius + _offset_correction;
int y = _padding + _corner_radius + _offset_correction;
- std::list<QuicklistMenuItem*>::iterator it;
- for (it = _item_list.begin(); it != _item_list.end(); it++)
+ for (auto item : _item_list)
{
- if (!(*it)->GetVisible())
+ if (!item->GetVisible())
continue;
- (*it)->SetBaseX(x);
- (*it)->SetBaseY(y);
+ item->SetBaseX(x);
+ item->SetBaseY(y);
- y += (*it)->GetBaseHeight();
- }
-
- for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
- {
- if (!(*it)->GetVisible())
- continue;
-
- (*it)->SetBaseX(x);
- (*it)->SetBaseY(y);
-
- y += (*it)->GetBaseHeight();
+ y += item->GetBaseHeight();
}
// We must correct the width of line separators. The rendering of the separator can be smaller than the width of the
@@ -555,21 +501,10 @@ long QuicklistView::PostLayoutManagement(long LayoutResult)
// only after MaxItemWidth is computed in QuicklistView::PreLayoutManagement.
// The setting of the separator width is done here after the Layout cycle for this widget is over. The width of the separator
// has bee set correctly during the layout cycle, but the cairo rendering still need to be adjusted.
- int separator_width = nux::Max<int>(_default_item_layout->GetBaseWidth(), _item_layout->GetBaseWidth());
-
- for (it = _item_list.begin(); it != _item_list.end(); it++)
- {
- QuicklistMenuItem* item = (QuicklistMenuItem*)(*it);
- if (item->GetVisible() && item->CairoSurfaceWidth() != separator_width)
- {
- // Compute textures of the item.
- item->UpdateTexture();
- }
- }
+ int separator_width = _item_layout->GetBaseWidth();
- for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
+ for (auto item : _item_list)
{
- QuicklistMenuItem* item = (QuicklistMenuItem*)(*it);
if (item->GetVisible() && item->CairoSurfaceWidth() != separator_width)
{
// Compute textures of the item.
@@ -605,41 +540,31 @@ void QuicklistView::RecvItemMouseClick(QuicklistMenuItem* item, int x, int y)
void QuicklistView::CheckAndEmitItemSignal(int x, int y)
{
nux::Geometry geo;
- std::list<QuicklistMenuItem*>::iterator it;
- for (it = _item_list.begin(); it != _item_list.end(); it++)
+ for (auto item : _item_list)
{
- if (!(*it)->GetVisible())
+ if (!item->GetVisible())
continue;
- geo = (*it)->GetGeometry();
+ geo = item->GetGeometry();
geo.width = _item_layout->GetBaseWidth();
if (geo.IsPointInside(x, y))
{
// An action is performed: send the signal back to the application
- if ((*it)->_menuItem)
- {
- dbusmenu_menuitem_handle_event((*it)->_menuItem, "clicked", NULL, 0);
- }
+ ActivateItem(item);
}
}
+}
- for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
+void QuicklistView::ActivateItem(QuicklistMenuItem* item)
+{
+ if (item && item->_menuItem)
{
- if (!(*it)->GetVisible())
- continue;
-
- geo = (*it)->GetGeometry();
- geo.width = _default_item_layout->GetBaseWidth();
+ ubus_server_send_message(ubus_server_get_default(),
+ UBUS_PLACE_VIEW_CLOSE_REQUEST,
+ NULL);
- if (geo.IsPointInside(x, y))
- {
- // An action is performed: send the signal back to the application
- if ((*it)->_menuItem)
- {
- dbusmenu_menuitem_handle_event((*it)->_menuItem, "clicked", NULL, 0);
- }
- }
+ dbusmenu_menuitem_handle_event(item->_menuItem, "clicked", NULL, 0);
}
}
@@ -659,30 +584,23 @@ void QuicklistView::RecvItemMouseRelease(QuicklistMenuItem* item, int x, int y)
void QuicklistView::CancelItemsPrelightStatus()
{
- std::list<QuicklistMenuItem*>::iterator it;
- for (it = _item_list.begin(); it != _item_list.end(); it++)
+ for (auto item : _item_list)
{
- (*it)->_prelight = false;
- }
-
- for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
- {
- (*it)->_prelight = false;
+ item->_prelight = false;
}
}
void QuicklistView::RecvItemMouseDrag(QuicklistMenuItem* item, int x, int y)
{
nux::Geometry geo;
-
- for (auto it : _item_list)
+ for (auto item : _item_list)
{
- int item_index = GetItemIndex(it);
+ int item_index = GetItemIndex(item);
if (!IsMenuItemSelectable(item_index))
continue;
- geo = it->GetGeometry();
+ geo = item->GetGeometry();
geo.width = _item_layout->GetBaseWidth();
if (geo.IsPointInside(x + item->GetBaseX(), y + item->GetBaseY()))
@@ -690,22 +608,6 @@ void QuicklistView::RecvItemMouseDrag(QuicklistMenuItem* item, int x, int y)
SelectItem(item_index);
}
}
-
- for (auto it : _default_item_list)
- {
- int item_index = GetItemIndex(it);
-
- if (!IsMenuItemSelectable(item_index))
- continue;
-
- geo = it->GetGeometry();
- geo.width = _default_item_layout->GetBaseWidth();
-
- if (geo.IsPointInside(x + item->GetBaseX(), y + item->GetBaseY()))
- {
- SelectItem(item_index);
- }
- }
}
void QuicklistView::RecvItemMouseEnter(QuicklistMenuItem* item)
@@ -765,26 +667,17 @@ void QuicklistView::RecvMouseDownOutsideOfQuicklist(int x, int y, unsigned long
void QuicklistView::RemoveAllMenuItem()
{
- std::list<QuicklistMenuItem*>::iterator it;
- for (it = _item_list.begin(); it != _item_list.end(); it++)
+ for (auto item : _item_list)
{
// Remove from introspection
- RemoveChild(*it);
- (*it)->UnReference();
+ RemoveChild(item);
+ item->UnReference();
}
- for (it = _default_item_list.begin(); it != _default_item_list.end(); it++)
- {
- // Remove from introspection
- RemoveChild(*it);
- (*it)->UnReference();
- }
_item_list.clear();
- _default_item_list.clear();
_item_layout->Clear();
- _default_item_layout->Clear();
_cairo_text_has_changed = true;
nux::GetWindowThread()->QueueObjectLayout(this);
}
@@ -819,7 +712,7 @@ void QuicklistView::RenderQuicklistView()
int QuicklistView::GetNumItems()
{
- return _item_list.size() + _default_item_list.size();
+ return _item_list.size();
}
QuicklistMenuItem* QuicklistView::GetNthItems(int index)
@@ -827,24 +720,10 @@ QuicklistMenuItem* QuicklistView::GetNthItems(int index)
if (index < (int)_item_list.size())
{
int i = 0;
- std::list<QuicklistMenuItem*>::iterator it;
- for (i = 0, it = _item_list.begin(); it != _item_list.end(); i++, it++)
+ for (auto item : _item_list)
{
- if (i == index)
- return *it;
- }
- }
-
- if (index < (int)_item_list.size() + (int)_default_item_list.size())
- {
- int i = 0;
- if (_item_list.size() > 0)
- i = _item_list.size() - 1;
- std::list<QuicklistMenuItem*>::iterator it;
- for (it = _default_item_list.begin(); it != _default_item_list.end(); i++, it++)
- {
- if (i == index)
- return *it;
+ if (i++ == index)
+ return item;
}
}
@@ -863,14 +742,6 @@ int QuicklistView::GetItemIndex(QuicklistMenuItem* item)
return index;
}
- for (auto it : _default_item_list)
- {
- ++index;
-
- if (it == item)
- return index;
- }
-
return index;
}
@@ -1304,7 +1175,7 @@ void QuicklistView::UpdateTexture()
if (!_enable_quicklist_for_testing)
{
- if (!_item_list.empty() || !_default_item_list.empty())
+ if (!_item_list.empty())
{
int offscreen_size = GetBaseY() +
height -
@@ -1500,7 +1371,7 @@ QuicklistView::GetSelectedMenuItem()
return GetNthItems(_current_item_index);
}
-debug::Introspectable::IntrospectableList const& QuicklistView::GetIntrospectableChildren()
+debug::Introspectable::IntrospectableList QuicklistView::GetIntrospectableChildren()
{
_introspectable_children.clear();
for (auto item: _item_list)
diff --git a/launcher/QuicklistView.h b/launcher/QuicklistView.h
index 49674aa33..6f2cac675 100644
--- a/launcher/QuicklistView.h
+++ b/launcher/QuicklistView.h
@@ -25,7 +25,7 @@
#include <Nux/BaseWindow.h>
#include <NuxGraphics/GraphicsEngine.h>
#include <Nux/TextureArea.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
@@ -71,7 +71,7 @@ public:
// Introspection
std::string GetName() const;
void AddProperties(GVariantBuilder* builder);
- IntrospectableList const& GetIntrospectableChildren();
+ IntrospectableList GetIntrospectableChildren();
void EnableQuicklistForTesting(bool enable_testing);
@@ -131,6 +131,8 @@ private:
//! Check the mouse up event sent by an item. Detect the item where the mous is and emit the appropriate signal.
void CheckAndEmitItemSignal(int x, int y);
+ void ActivateItem(QuicklistMenuItem* item);
+
void SelectItem(int index);
bool IsMenuItemSelectable(int index);
@@ -157,7 +159,6 @@ private:
nux::HLayout* _hlayout;
nux::VLayout* _vlayout;
nux::VLayout* _item_layout;
- nux::VLayout* _default_item_layout;
nux::SpaceLayout* _left_space; //!< Space from the left of the widget to the left of the text.
nux::SpaceLayout* _right_space; //!< Space from the right of the text to the right of the widget.
nux::SpaceLayout* _top_space; //!< Space from the left of the widget to the left of the text.
@@ -166,7 +167,6 @@ private:
bool _cairo_text_has_changed;
void UpdateTexture();
std::list<QuicklistMenuItem*> _item_list;
- std::list<QuicklistMenuItem*> _default_item_list;
// used by keyboard/a11y-navigation
int _current_item_index;
diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp
index f96bd6040..f91289d47 100644
--- a/launcher/SwitcherController.cpp
+++ b/launcher/SwitcherController.cpp
@@ -159,8 +159,11 @@ void Controller::ShowView()
ConstructView();
+ ubus_manager_.SendMessage(UBUS_SWITCHER_START, NULL);
+
if (view_window_) {
view_window_->ShowWindow(true);
+ view_window_->PushToFront();
view_window_->SetOpacity(1.0f);
}
}
@@ -179,6 +182,7 @@ void Controller::ConstructWindow()
view_window_->SetLayout(main_layout_);
view_window_->SetBackgroundColor(nux::Color(0x00000000));
view_window_->SetGeometry(workarea_);
+ view_window_->EnableInputWindow(true, "Switcher", false, false);
}
}
@@ -240,6 +244,8 @@ void Controller::Hide(bool accept_state)
}
}
+ ubus_manager_.SendMessage(UBUS_SWITCHER_END, g_variant_new_boolean(!accept_state));
+
sources_.Remove(VIEW_CONSTRUCT_IDLE);
sources_.Remove(SHOW_TIMEOUT);
sources_.Remove(DETAIL_TIMEOUT);
@@ -254,6 +260,8 @@ void Controller::Hide(bool accept_state)
{
view_window_->SetOpacity(0.0f);
view_window_->ShowWindow(false);
+ view_window_->PushToBack();
+ view_window_->EnableInputWindow(false);
}
ubus_manager_.SendMessage(UBUS_SWITCHER_SHOWN, g_variant_new("(bi)", false, monitor_));
@@ -385,6 +393,11 @@ LayoutWindowList Controller::ExternalRenderTargets()
return view_->ExternalTargets();
}
+guint Controller::GetSwitcherInputWindowId() const
+{
+ return view_window_->GetInputWindowId();
+}
+
bool Controller::CompareSwitcherItemsPriority(AbstractLauncherIcon::Ptr first,
AbstractLauncherIcon::Ptr second)
{
diff --git a/launcher/SwitcherController.h b/launcher/SwitcherController.h
index 32f385f27..5f8015c36 100644
--- a/launcher/SwitcherController.h
+++ b/launcher/SwitcherController.h
@@ -90,6 +90,8 @@ public:
ui::LayoutWindowList ExternalRenderTargets ();
+ guint GetSwitcherInputWindowId() const;
+
protected:
// Introspectable methods
std::string GetName() const;
diff --git a/launcher/SwitcherModel.cpp b/launcher/SwitcherModel.cpp
index e3c26f138..600c2fea8 100644
--- a/launcher/SwitcherModel.cpp
+++ b/launcher/SwitcherModel.cpp
@@ -171,7 +171,7 @@ SwitcherModel::DetailSelectionWindow ()
if (detail_selection_index > DetailXids().size() - 1)
return 0;
-
+
return DetailXids()[detail_selection_index];
}
diff --git a/panel/PanelController.cpp b/panel/PanelController.cpp
index f947fe74b..460a61ee8 100644
--- a/panel/PanelController.cpp
+++ b/panel/PanelController.cpp
@@ -49,6 +49,7 @@ public:
void QueueRedraw();
std::vector<Window> GetTrayXids() const;
+ std::vector<nux::View*> GetPanelViews() const;
std::vector<nux::Geometry> GetGeometries() const;
// NOTE: nux::Property maybe?
@@ -106,6 +107,15 @@ std::vector<Window> Controller::Impl::GetTrayXids() const
return xids;
}
+std::vector<nux::View*> Controller::Impl::GetPanelViews() const
+{
+ std::vector<nux::View*> views;
+ views.reserve(windows_.size());
+ for (auto window: windows_)
+ views.push_back(ViewForWindow(window));
+ return views;
+}
+
std::vector<nux::Geometry> Controller::Impl::GetGeometries() const
{
std::vector<nux::Geometry> geometries;
@@ -325,6 +335,11 @@ std::vector<Window> Controller::GetTrayXids() const
return pimpl->GetTrayXids();
}
+std::vector<nux::View*> Controller::GetPanelViews() const
+{
+ return pimpl->GetPanelViews();
+}
+
std::vector<nux::Geometry> Controller::GetGeometries() const
{
return pimpl->GetGeometries();
diff --git a/panel/PanelController.h b/panel/PanelController.h
index 282d232eb..2c8a9c1bc 100644
--- a/panel/PanelController.h
+++ b/panel/PanelController.h
@@ -41,6 +41,7 @@ public:
void QueueRedraw();
std::vector<Window> GetTrayXids() const;
+ std::vector<nux::View*> GetPanelViews() const;
std::vector<nux::Geometry> GetGeometries() const;
// NOTE: nux::Property maybe?
diff --git a/panel/PanelIndicatorEntryView.h b/panel/PanelIndicatorEntryView.h
index 949e8681c..dcf3dd5a0 100644
--- a/panel/PanelIndicatorEntryView.h
+++ b/panel/PanelIndicatorEntryView.h
@@ -23,7 +23,7 @@
#include <Nux/TextureArea.h>
#include <Nux/View.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <NuxGraphics/GraphicsEngine.h>
#include <UnityCore/IndicatorEntry.h>
diff --git a/panel/PanelView.cpp b/panel/PanelView.cpp
index 3ced1322f..14f24752d 100644
--- a/panel/PanelView.cpp
+++ b/panel/PanelView.cpp
@@ -24,8 +24,8 @@
#include <Nux/Layout.h>
#include <Nux/WindowCompositor.h>
-#include <NuxImage/CairoGraphics.h>
-#include <NuxImage/ImageSurface.h>
+#include <NuxGraphics/CairoGraphics.h>
+#include <NuxGraphics/ImageSurface.h>
#include <NuxCore/Logger.h>
#include <UnityCore/GLibWrapper.h>
diff --git a/panel/PanelView.h b/panel/PanelView.h
index 8f45ec884..9dac92ea1 100644
--- a/panel/PanelView.h
+++ b/panel/PanelView.h
@@ -26,7 +26,7 @@
#include <Nux/View.h>
#include <Nux/TextureArea.h>
#include <NuxGraphics/GraphicsEngine.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <gdk/gdkx.h>
#include <UnityCore/DBusIndicators.h>
diff --git a/panel/WindowButtons.cpp b/panel/WindowButtons.cpp
index d7bcd32f3..9788989bf 100644
--- a/panel/WindowButtons.cpp
+++ b/panel/WindowButtons.cpp
@@ -506,7 +506,7 @@ void WindowButtons::OnOverlayShown(GVariant* data)
glib::String overlay_identity;
gboolean can_maximise = FALSE;
gint32 overlay_monitor = 0;
- g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
+ g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
&overlay_identity, &can_maximise, &overlay_monitor);
if (overlay_monitor != monitor_)
@@ -539,6 +539,9 @@ void WindowButtons::OnOverlayShown(GVariant* data)
if (button->GetType() == panel::WindowButtonType::MAXIMIZE)
maximize_button = button;
+ if (button->GetType() == panel::WindowButtonType::MINIMIZE)
+ button->SetEnabled(false);
+
button->SetOverlayOpen(true);
}
}
@@ -574,7 +577,7 @@ void WindowButtons::OnOverlayHidden(GVariant* data)
glib::String overlay_identity;
gboolean can_maximise = FALSE;
gint32 overlay_monitor = 0;
- g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
+ g_variant_get(data, UBUS_OVERLAY_FORMAT_STRING,
&overlay_identity, &can_maximise, &overlay_monitor);
if (overlay_monitor != monitor_)
diff --git a/plugins/unity-mt-grab-handles/CMakeLists.txt b/plugins/unity-mt-grab-handles/CMakeLists.txt
index 9e5a65f4a..3020cf6a3 100644
--- a/plugins/unity-mt-grab-handles/CMakeLists.txt
+++ b/plugins/unity-mt-grab-handles/CMakeLists.txt
@@ -2,4 +2,4 @@ find_package (Compiz REQUIRED)
include (CompizPlugin)
-compiz_plugin (unitymtgrabhandles PKGDEPS nux-2.0>=2.0.0 PLUGINDEPS composite opengl CFLAGSADD -std=c++0x)
+compiz_plugin (unitymtgrabhandles PKGDEPS nux-3.0>=3.0.0 PLUGINDEPS composite opengl CFLAGSADD -std=c++0x)
diff --git a/plugins/unityshell/src/DebugDBusInterface.cpp b/plugins/unityshell/src/DebugDBusInterface.cpp
index 9d7a24971..42e55de39 100644
--- a/plugins/unityshell/src/DebugDBusInterface.cpp
+++ b/plugins/unityshell/src/DebugDBusInterface.cpp
@@ -60,13 +60,17 @@ const char* DebugDBusInterface::DBUS_DEBUG_OBJECT_PATH = "/com/canonical/Unity/D
const gchar DebugDBusInterface::introspection_xml[] =
" <node>"
- " <interface name='com.canonical.Unity.Debug.Introspection'>"
+ " <interface name='com.canonical.Autopilot.Introspection'>"
""
" <method name='GetState'>"
" <arg type='s' name='piece' direction='in' />"
- " <arg type='aa{sv}' name='state' direction='out' />"
+ " <arg type='a(sv)' name='state' direction='out' />"
" </method>"
""
+ " </interface>"
+ ""
+ " <interface name='com.canonical.Unity.Debug.Logging'>"
+ ""
" <method name='StartLogToFile'>"
" <arg type='s' name='file_path' direction='in' />"
" </method>"
@@ -223,14 +227,17 @@ GVariant* GetState(std::string const& query)
// process the XPath query:
std::list<Introspectable*> parts = GetIntrospectableNodesFromQuery(query, _parent_introspectable);
GVariantBuilder builder;
- g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
-
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("a(sv)"));
+ if (parts.empty())
+ {
+ LOG_WARNING(logger) << "Query '" << query << "' Did not match anything.";
+ }
for (Introspectable *node : parts)
{
- g_variant_builder_add_value(&builder, node->Introspect());
+ g_variant_builder_add(&builder, "(sv)", node->GetName().c_str(), node->Introspect());
}
- return g_variant_new("(aa{sv})", &builder);
+ return g_variant_new("(a(sv))", &builder);
}
void StartLogToFile(std::string const& file_path)
diff --git a/plugins/unityshell/src/XPathQueryPart.cpp b/plugins/unityshell/src/XPathQueryPart.cpp
index cf3026733..a42a65c34 100644
--- a/plugins/unityshell/src/XPathQueryPart.cpp
+++ b/plugins/unityshell/src/XPathQueryPart.cpp
@@ -41,12 +41,12 @@ XPathQueryPart::XPathQueryPart(std::string const& query_part)
{
std::vector<std::string> part_pieces;
boost::algorithm::split(part_pieces, query_part, boost::algorithm::is_any_of("[]="));
- // Boost's split() implementation does not match it's documentation! According to the
- // docs, it's not supposed to add empty strings, but it does, which is a PITA. This
+ // Boost's split() implementation does not match it's documentation! According to the
+ // docs, it's not supposed to add empty strings, but it does, which is a PITA. This
// next line removes them:
- part_pieces.erase( std::remove_if( part_pieces.begin(),
- part_pieces.end(),
- boost::bind( &std::string::empty, _1 ) ),
+ part_pieces.erase( std::remove_if( part_pieces.begin(),
+ part_pieces.end(),
+ boost::bind( &std::string::empty, _1 ) ),
part_pieces.end());
if (part_pieces.size() == 1)
{
@@ -71,7 +71,7 @@ bool XPathQueryPart::Matches(Introspectable* node) const
bool matches = false;
if (param_name_ == "")
{
- matches = node->GetName() == node_name_;
+ matches = (node_name_ == "*" || node->GetName() == node_name_);
}
else
{
@@ -85,9 +85,9 @@ bool XPathQueryPart::Matches(Introspectable* node) const
if (prop_value != NULL)
{
GVariantClass prop_val_type = g_variant_classify(prop_value);
- // it'd be nice to be able to do all this with one method. However, the booleans need
+ // it'd be nice to be able to do all this with one method. However, the booleans need
// special treatment, and I can't figure out how to group all the integer types together
- // without resorting to template functions.... and we all know what happens when you
+ // without resorting to template functions.... and we all know what happens when you
// start doing that...
switch (prop_val_type)
{
@@ -116,7 +116,7 @@ bool XPathQueryPart::Matches(Introspectable* node) const
std::stringstream stream(param_value_);
int val; // changing this to guchar causes problems.
stream >> val;
- matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
+ matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
val == g_variant_get_byte(prop_value);
}
break;
@@ -125,7 +125,7 @@ bool XPathQueryPart::Matches(Introspectable* node) const
std::stringstream stream(param_value_);
gint16 val;
stream >> val;
- matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
+ matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
val == g_variant_get_int16(prop_value);
}
break;
@@ -134,8 +134,8 @@ bool XPathQueryPart::Matches(Introspectable* node) const
std::stringstream stream(param_value_);
guint16 val;
stream >> val;
- matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
- val == g_variant_get_uint16(prop_value);
+ matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
+ val == g_variant_get_uint16(prop_value);
}
break;
case G_VARIANT_CLASS_INT32:
@@ -143,7 +143,7 @@ bool XPathQueryPart::Matches(Introspectable* node) const
std::stringstream stream(param_value_);
gint32 val;
stream >> val;
- matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
+ matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
val == g_variant_get_int32(prop_value);
}
break;
@@ -152,7 +152,7 @@ bool XPathQueryPart::Matches(Introspectable* node) const
std::stringstream stream(param_value_);
guint32 val;
stream >> val;
- matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
+ matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
val == g_variant_get_uint32(prop_value);
}
break;
@@ -161,7 +161,7 @@ bool XPathQueryPart::Matches(Introspectable* node) const
std::stringstream stream(param_value_);
gint64 val;
stream >> val;
- matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
+ matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
val == g_variant_get_int64(prop_value);
}
break;
@@ -170,7 +170,7 @@ bool XPathQueryPart::Matches(Introspectable* node) const
std::stringstream stream(param_value_);
guint64 val;
stream >> val;
- matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
+ matches = (stream.rdstate() & (stream.badbit|stream.failbit)) == 0 &&
val == g_variant_get_uint64(prop_value);
}
break;
diff --git a/plugins/unityshell/src/compizminimizedwindowhandler.h b/plugins/unityshell/src/compizminimizedwindowhandler.h
index a53e9f815..4befd16f0 100644
--- a/plugins/unityshell/src/compizminimizedwindowhandler.h
+++ b/plugins/unityshell/src/compizminimizedwindowhandler.h
@@ -104,6 +104,7 @@ compiz::CompizMinimizedWindowHandler<Screen, Window>::CompizMinimizedWindowHandl
template <typename Screen, typename Window>
compiz::CompizMinimizedWindowHandler<Screen, Window>::~CompizMinimizedWindowHandler ()
{
+ minimizingWindows.remove (priv->mWindow);
minimizedWindows.remove (this);
}
diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp
index bd273603f..169b5224f 100644
--- a/plugins/unityshell/src/unityshell.cpp
+++ b/plugins/unityshell/src/unityshell.cpp
@@ -100,7 +100,6 @@ const unsigned int SCROLL_DOWN_BUTTON = 6;
const unsigned int SCROLL_UP_BUTTON = 7;
const std::string RELAYOUT_TIMEOUT = "relayout-timeout";
-const std::string REDRAW_IDLE = "redraw-idle";
} // namespace local
} // anon namespace
@@ -118,6 +117,7 @@ UnityScreen::UnityScreen(CompScreen* screen)
, super_keypressed_(false)
, newFocusedWindow(nullptr)
, doShellRepaint(false)
+ , didShellRepaint(false)
, allowWindowPaint(false)
, damaged(false)
, _key_nav_mode_requested(false)
@@ -131,6 +131,7 @@ UnityScreen::UnityScreen(CompScreen* screen)
, hud_keypress_time_(0)
, panel_texture_has_changed_(true)
, paint_panel_(false)
+ , scale_just_activated_(false)
{
Timer timer;
gfloat version;
@@ -353,6 +354,12 @@ UnityScreen::UnityScreen(CompScreen* screen)
ubus_manager_.RegisterInterest(UBUS_LAUNCHER_END_KEY_SWTICHER,
sigc::mem_fun(this, &UnityScreen::OnLauncherEndKeyNav));
+ ubus_manager_.RegisterInterest(UBUS_SWITCHER_START,
+ sigc::mem_fun(this, &UnityScreen::OnSwitcherStart));
+
+ ubus_manager_.RegisterInterest(UBUS_SWITCHER_END,
+ sigc::mem_fun(this, &UnityScreen::OnSwitcherEnd));
+
auto init_plugins_cb = sigc::mem_fun(this, &UnityScreen::initPluginActions);
sources_.Add(std::make_shared<glib::Idle>(init_plugins_cb, glib::Source::Priority::DEFAULT));
@@ -902,6 +909,7 @@ void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transfo
}
doShellRepaint = false;
+ didShellRepaint = true;
damaged = false;
}
@@ -1204,7 +1212,15 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
{
bool ret;
- doShellRepaint = true;
+ /*
+ * Very important!
+ * Don't waste GPU and CPU rendering the shell on every frame if you don't
+ * need to. Doing so on every frame causes Nux to hog the GPU and slow down
+ * ALL rendering. (LP: #988079)
+ */
+ bool force = forcePaintOnTop() || PluginAdapter::Default()->IsExpoActive();
+ doShellRepaint = force || !(region.isEmpty() || wt->GetDrawList().empty());
+
allowWindowPaint = true;
_last_output = output;
paint_panel_ = false;
@@ -1220,13 +1236,21 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
* attempts to bind it will only increment
* its bind reference so make sure that
* you always unbind as much as you bind */
- _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
+ if (doShellRepaint)
+ _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
#endif
+ // CompRegion has no clear() method. So this is the fastest alternative.
+ aboveShell = CompRegion();
+ nuxRegion = CompRegion();
+
/* glPaintOutput is part of the opengl plugin, so we need the GLScreen base class. */
ret = gScreen->glPaintOutput(attrib, transform, region, output, mask);
#ifndef USE_MODERN_COMPIZ_GL
+ if (doShellRepaint && !force && aboveShell.contains(*output))
+ doShellRepaint = false;
+
if (doShellRepaint)
paintDisplay(region, transform, mask);
#endif
@@ -1279,16 +1303,32 @@ void UnityScreen::preparePaint(int ms)
for (ShowdesktopHandlerWindowInterface *wi : ShowdesktopHandler::animating_windows)
wi->HandleAnimations (ms);
+ // Workaround Nux bug LP: #1014610:
if (damaged)
{
damaged = false;
- damageNuxRegions();
+ nuxDamageCompiz();
}
+ compizDamageNux(cScreen->currentDamage());
+
+ didShellRepaint = false;
}
void UnityScreen::donePaint()
{
+ /*
+ * It's only safe to clear the draw list if drawing actually occurred
+ * (i.e. the shell was not obscured behind a fullscreen window).
+ * If you clear the draw list and drawing has not occured then you'd be
+ * left with all your views thinking they're queued for drawing still and
+ * would refuse to redraw when you return from fullscreen.
+ * I think this is a Nux bug. ClearDrawList should ideally also mark all
+ * the queued views as draw_cmd_queued_=false.
+ */
+ if (didShellRepaint)
+ wt->ClearDrawList();
+
std::list <ShowdesktopHandlerWindowInterface *> remove_windows;
for (ShowdesktopHandlerWindowInterface *wi : ShowdesktopHandler::animating_windows)
@@ -1309,42 +1349,100 @@ void UnityScreen::donePaint()
cScreen->donePaint ();
}
-/* Grab changed nux regions and add damage rects for them */
-void UnityScreen::damageNuxRegions()
+void UnityScreen::compizDamageNux(CompRegion const& damage)
{
- CompRegion nux_damage;
-
- if (damaged)
+ if (!launcher_controller_)
return;
- std::vector<nux::Geometry> dirty = wt->GetDrawList();
+ CompRect::vector const& rects(damage.rects());
+ for (const CompRect &r : rects)
+ {
+ nux::Geometry geo(r.x(), r.y(), r.width(), r.height());
+ BackgroundEffectHelper::ProcessDamage(geo);
+ }
+
+ auto launchers = launcher_controller_->launchers();
+ for (auto launcher : launchers)
+ {
+ if (!launcher->Hidden())
+ {
+ nux::Geometry geo = launcher->GetAbsoluteGeometry();
+ CompRegion launcher_region(geo.x, geo.y, geo.width, geo.height);
+ if (damage.intersects(launcher_region))
+ launcher->QueueDraw();
+ nux::ObjectPtr<nux::View> tooltip = launcher->GetActiveTooltip();
+ if (!tooltip.IsNull())
+ {
+ nux::Geometry tip = tooltip->GetAbsoluteGeometry();
+ CompRegion tip_region(tip.x, tip.y, tip.width, tip.height);
+ if (damage.intersects(tip_region))
+ tooltip->QueueDraw();
+ }
+ }
+ }
+
+ std::vector<nux::View*> const& panels(panel_controller_->GetPanelViews());
+ for (nux::View* view : panels)
+ {
+ nux::Geometry geo = view->GetAbsoluteGeometry();
+ CompRegion panel_region(geo.x, geo.y, geo.width, geo.height);
+ if (damage.intersects(panel_region))
+ view->QueueDraw();
+ }
+
+ QuicklistManager* qm = QuicklistManager::Default();
+ if (qm)
+ {
+ QuicklistView* view = qm->Current();
+ if (view)
+ {
+ nux::Geometry geo = view->GetAbsoluteGeometry();
+ CompRegion quicklist_region(geo.x, geo.y, geo.width, geo.height);
+ if (damage.intersects(quicklist_region))
+ view->QueueDraw();
+ }
+ }
+}
+
+/* Grab changed nux regions and add damage rects for them */
+void UnityScreen::nuxDamageCompiz()
+{
+ // Workaround Nux bug LP: #1014610 (unbounded DrawList growth)
+ // Also, ensure we don't dereference null *controller_ on startup.
+ if (damaged || !launcher_controller_ || !dash_controller_)
+ return;
damaged = true;
- for (std::vector<nux::Geometry>::iterator it = dirty.begin(), end = dirty.end();
- it != end; ++it)
+ CompRegion nux_damage;
+
+ std::vector<nux::Geometry> const& dirty = wt->GetDrawList();
+ for (auto geo : dirty)
+ nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
+
+ if (launcher_controller_->IsOverlayOpen())
{
- nux::Geometry const& geo = *it;
+ nux::BaseWindow* dash_window = dash_controller_->window();
+ nux::Geometry const& geo = dash_window->GetAbsoluteGeometry();
nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
}
- nux::Geometry geo = wt->GetWindowCompositor().GetTooltipMainWindowGeometry();
- nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
-
- geo = lastTooltipArea;
- nux_damage += CompRegion(lastTooltipArea.x, lastTooltipArea.y,
- lastTooltipArea.width, lastTooltipArea.height);
+ auto launchers = launcher_controller_->launchers();
+ for (auto launcher : launchers)
+ {
+ if (!launcher->Hidden())
+ {
+ nux::ObjectPtr<nux::View> tooltip = launcher->GetActiveTooltip();
+ if (!tooltip.IsNull())
+ {
+ nux::Geometry const& g = tooltip->GetAbsoluteGeometry();
+ nux_damage += CompRegion(g.x, g.y, g.width, g.height);
+ }
+ }
+ }
- /*
- * Avoid Nux damaging Nux as recommended by smspillaz. Though I don't
- * believe it would be harmful or significantly expensive right now.
- */
cScreen->damageRegionSetEnabled(this, false);
cScreen->damageRegion(nux_damage);
cScreen->damageRegionSetEnabled(this, true);
-
- wt->ClearDrawList();
-
- lastTooltipArea = geo;
}
/* handle X Events */
@@ -1362,8 +1460,14 @@ void UnityScreen::handleEvent(XEvent* event)
#ifndef USE_MODERN_COMPIZ_GL
cScreen->damageScreen(); // evil hack
#endif
- if (_key_nav_mode_requested && !launcher_controller_->IsOverlayOpen())
+ if (_key_nav_mode_requested)
+ {
+ if (launcher_controller_->IsOverlayOpen())
+ {
+ dash_controller_->HideDash();
+ }
launcher_controller_->KeyNavGrab();
+ }
_key_nav_mode_requested = false;
break;
case ButtonPress:
@@ -1394,6 +1498,19 @@ void UnityScreen::handleEvent(XEvent* event)
break;
case KeyPress:
{
+ if (super_keypressed_)
+ {
+ /* We need an idle to postpone this action, after the current event
+ * has been processed */
+ sources_.Add(std::make_shared<glib::Idle>([&]() {
+ shortcut_controller_->SetEnabled(false);
+ shortcut_controller_->Hide();
+ EnableCancelAction(CancelActionTarget::SHORTCUT_HINT, false);
+
+ return false;
+ }));
+ }
+
KeySym key_sym;
char key_string[2];
int result = XLookupString(&(event->xkey), key_string, 2, &key_sym, 0);
@@ -1421,21 +1538,6 @@ void UnityScreen::handleEvent(XEvent* event)
if (super_keypressed_)
{
- if (key_sym != XK_Escape || (key_sym == XK_Escape && !launcher_controller_->KeyNavIsActive()))
- {
- /* We need an idle to postpone this action, after the current event
- * has been processed */
- sources_.Add(std::make_shared<glib::Idle>([&]() {
- if (!launcher_controller_->KeyNavIsActive())
- {
- shortcut_controller_->SetEnabled(false);
- shortcut_controller_->Hide();
- EnableCancelAction(CancelActionTarget::SHORTCUT_HINT, false);
- }
- return false;
- }));
- }
-
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);
@@ -1504,13 +1606,7 @@ void UnityScreen::handleEvent(XEvent* event)
void UnityScreen::damageRegion(const CompRegion &region)
{
- const CompRect::vector &rects(region.rects());
- for (const CompRect &r : rects)
- {
- nux::Geometry geo(r.x(), r.y(), r.width(), r.height());
- BackgroundEffectHelper::ProcessDamage(geo);
- }
-
+ compizDamageNux(region);
cScreen->damageRegion(region);
}
@@ -1526,6 +1622,11 @@ void UnityScreen::handleCompizEvent(const char* plugin,
ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
}
+ if (PluginAdapter::Default()->IsScaleActive() && g_strcmp0(plugin, "scale") == 0)
+ {
+ scale_just_activated_ = true;
+ }
+
screen->handleCompizEvent(plugin, event, option);
}
@@ -1573,6 +1674,18 @@ bool UnityScreen::showLauncherKeyTerminate(CompAction* action,
LOG_DEBUG(logger) << "Super released: " << (was_tap ? "tapped" : "released");
int when = options[7].value().i(); // XEvent time in millisec
+ // hack...if the scale just wasn't activated AND the 'when' time is within time to start the
+ // dash then assume was_tap is also true, since the ScalePlugin doesn't accept that state...
+ if (PluginAdapter::Default()->IsScaleActive() && !scale_just_activated_ && launcher_controller_->AboutToShowDash(true, when))
+ {
+ PluginAdapter::Default()->TerminateScale();
+ was_tap = true;
+ }
+ else if (scale_just_activated_)
+ {
+ scale_just_activated_ = false;
+ }
+
if (hud_controller_->IsVisible() && launcher_controller_->AboutToShowDash(was_tap, when))
hud_controller_->HideHud();
@@ -1629,6 +1742,12 @@ void UnityScreen::SendExecuteCommand()
{
hud_controller_->HideHud();
}
+
+ if (PluginAdapter::Default()->IsScaleActive())
+ {
+ PluginAdapter::Default()->TerminateScale();
+ }
+
ubus_manager_.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST,
g_variant_new("(sus)", "commands.lens", 0, ""));
}
@@ -1641,26 +1760,6 @@ bool UnityScreen::executeCommand(CompAction* action,
return true;
}
-void UnityScreen::startLauncherKeyNav()
-{
- // get CompWindow* of launcher-window
- newFocusedWindow = screen->findWindow(launcher_controller_->KeyNavLauncherInputWindowId());
-
- // check if currently focused window isn't the launcher-window
- if (newFocusedWindow != screen->findWindow(screen->activeWindow()))
- PluginAdapter::Default()->saveInputFocus();
-
- // set input-focus on launcher-window and start key-nav mode
- if (newFocusedWindow)
- {
- // Put the launcher BaseWindow at the top of the BaseWindow stack. The
- // input focus coming from the XinputWindow will be processed by the
- // launcher BaseWindow only. Then the Launcher BaseWindow will decide
- // which View will get the input focus.
- launcher_controller_->PushToFront();
- newFocusedWindow->moveInputFocusTo();
- }
-}
bool UnityScreen::setKeyboardFocusKeyInitiate(CompAction* action,
CompAction::State state,
@@ -1904,11 +2003,31 @@ bool UnityScreen::launcherSwitcherTerminate(CompAction* action, CompAction::Stat
void UnityScreen::OnLauncherStartKeyNav(GVariant* data)
{
- startLauncherKeyNav();
+ // Put the launcher BaseWindow at the top of the BaseWindow stack. The
+ // input focus coming from the XinputWindow will be processed by the
+ // launcher BaseWindow only. Then the Launcher BaseWindow will decide
+ // which View will get the input focus.
+ if (SaveInputThenFocus(launcher_controller_->KeyNavLauncherInputWindowId()))
+ launcher_controller_->PushToFront();
}
void UnityScreen::OnLauncherEndKeyNav(GVariant* data)
{
+ RestoreWindow(data);
+}
+
+void UnityScreen::OnSwitcherStart(GVariant* data)
+{
+ SaveInputThenFocus(switcher_controller_->GetSwitcherInputWindowId());
+}
+
+void UnityScreen::OnSwitcherEnd(GVariant* data)
+{
+ RestoreWindow(data);
+}
+
+void UnityScreen::RestoreWindow(GVariant* data)
+{
bool preserve_focus = false;
if (data)
@@ -1922,6 +2041,24 @@ void UnityScreen::OnLauncherEndKeyNav(GVariant* data)
PluginAdapter::Default ()->restoreInputFocus ();
}
+bool UnityScreen::SaveInputThenFocus(const guint xid)
+{
+ // get CompWindow*
+ newFocusedWindow = screen->findWindow(xid);
+
+ // check if currently focused window isn't it self
+ if (xid != screen->activeWindow())
+ PluginAdapter::Default()->saveInputFocus();
+
+ // set input-focus on window
+ if (newFocusedWindow)
+ {
+ newFocusedWindow->moveInputFocusTo();
+ return true;
+ }
+ return false;
+}
+
bool UnityScreen::ShowHud()
{
if (switcher_controller_->Visible())
@@ -2122,14 +2259,6 @@ bool isNuxWindow (CompWindow* value)
return false;
}
-const CompWindowList& UnityScreen::getWindowPaintList()
-{
- CompWindowList& pl = _withRemovedNuxWindows = cScreen->getWindowPaintList();
- pl.remove_if(isNuxWindow);
-
- return pl;
-}
-
void UnityScreen::RaiseInputWindows()
{
std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
@@ -2154,6 +2283,35 @@ bool UnityWindow::glPaint(const GLWindowPaintAttrib& attrib,
const CompRegion& region,
unsigned int mask)
{
+ /*
+ * The occlusion pass tests windows from TOP to BOTTOM. That's opposite to
+ * the actual painting loop.
+ */
+ if (isNuxWindow(window))
+ {
+ if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
+ {
+ uScreen->nuxRegion += window->geometry();
+ uScreen->nuxRegion -= uScreen->aboveShell;
+ }
+ return false; // Ensure nux windows are never painted by compiz
+ }
+ else if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
+ {
+ static const unsigned int nonOcclusionBits =
+ PAINT_WINDOW_TRANSLUCENT_MASK |
+ PAINT_WINDOW_TRANSFORMED_MASK |
+ PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
+ if (!(mask & nonOcclusionBits))
+ // And I've been advised to test other things, but they don't work:
+ // && (attrib.opacity == OPAQUE)) <-- Doesn't work; Only set in glDraw
+ // && !window->alpha() <-- Doesn't work; Opaque windows often have alpha
+ {
+ uScreen->aboveShell += window->geometry();
+ uScreen->aboveShell -= uScreen->nuxRegion;
+ }
+ }
+
GLWindowPaintAttrib wAttrib = attrib;
if (mMinimizeHandler)
@@ -2212,7 +2370,17 @@ bool UnityWindow::glDraw(const GLMatrix& matrix,
}
}
- if (uScreen->doShellRepaint && !uScreen->forcePaintOnTop ())
+ /*
+ * Paint the shell in *roughly* the compiz stacking order. This is only
+ * approximate because we're painting all the nux windows as soon as we find
+ * the bottom-most nux window (from bottom to top).
+ * But remember to avoid painting the shell if it's within the aboveShell
+ * region.
+ */
+ if (uScreen->doShellRepaint &&
+ !uScreen->forcePaintOnTop () &&
+ !uScreen->aboveShell.contains(window->geometry())
+ )
{
std::vector<Window> const& xwns = nux::XInputWindow::NativeHandleList();
unsigned int size = xwns.size();
@@ -2527,25 +2695,7 @@ void UnityScreen::initUnity(nux::NThread* thread, void* InitData)
void UnityScreen::onRedrawRequested()
{
- // disable blur updates so we dont waste perf. This can stall the blur during animations
- // but ensures a smooth animation.
- if (_in_paint)
- {
- if (!sources_.GetSource(local::REDRAW_IDLE))
- {
- auto redraw_idle(std::make_shared<glib::Idle>(glib::Source::Priority::DEFAULT));
- sources_.Add(redraw_idle, local::REDRAW_IDLE);
-
- redraw_idle->Run([&]() {
- onRedrawRequested();
- return false;
- });
- }
- }
- else
- {
- damageNuxRegions();
- }
+ nuxDamageCompiz();
}
/* Handle option changes and plug that into nux windows */
diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h
index a93e570ff..eb0851515 100644
--- a/plugins/unityshell/src/unityshell.h
+++ b/plugins/unityshell/src/unityshell.h
@@ -133,9 +133,6 @@ public:
CompOutput*,
unsigned int);
- /* Pop our InputOutput windows from the paint list */
- const CompWindowList& getWindowPaintList();
-
/* handle X11 events */
void handleEvent(XEvent*);
@@ -212,7 +209,10 @@ private:
bool initPluginActions();
void initLauncher();
- void damageNuxRegions();
+
+ void compizDamageNux(CompRegion const& region);
+ void nuxDamageCompiz();
+
void onRedrawRequested();
void Relayout();
@@ -220,7 +220,6 @@ private:
static void OnStartKeyNav(GVariant* data, void* value);
static void OnExitKeyNav(GVariant* data, void* value);
- void startLauncherKeyNav();
void restartLauncherKeyNav();
void OnDashRealized ();
@@ -228,6 +227,12 @@ private:
void OnLauncherStartKeyNav(GVariant* data);
void OnLauncherEndKeyNav(GVariant* data);
+ void OnSwitcherStart(GVariant* data);
+ void OnSwitcherEnd(GVariant* data);
+
+ void RestoreWindow(GVariant* data);
+ bool SaveInputThenFocus(const guint xid);
+
void InitHints();
void OnPanelStyleChanged();
@@ -255,7 +260,6 @@ private:
bool enable_shortcut_overlay_;
GestureEngine gesture_engine_;
- nux::Geometry lastTooltipArea;
bool needsRelayout;
bool _in_paint;
bool super_keypressed_;
@@ -272,11 +276,14 @@ private:
/* handle paint order */
bool doShellRepaint;
+ bool didShellRepaint;
bool allowWindowPaint;
bool damaged;
bool _key_nav_mode_requested;
CompOutput* _last_output;
- CompWindowList _withRemovedNuxWindows;
+
+ CompRegion nuxRegion;
+ CompRegion aboveShell;
nux::Property<nux::Geometry> primary_monitor_;
@@ -306,6 +313,8 @@ private:
bool paint_panel_;
nux::ObjectPtr<nux::IOpenGLBaseTexture> panel_texture_;
+ bool scale_just_activated_;
+
#ifndef USE_MODERN_COMPIZ_GL
ScreenEffectFramebufferObject::GLXGetProcAddressProc glXGetProcAddressP;
#endif
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 894bdcf4c..0cea996e3 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -209,6 +209,7 @@ if (GTEST_SRC_DIR AND
test_icon_loader.cpp
test_im_text_entry.cpp
test_hud_view.cpp
+ test_keyboard_util.cpp
test_resultviewgrid.cpp
test_single_monitor_launcher_icon.cpp
test_switcher_controller.cpp
@@ -270,6 +271,7 @@ if (GTEST_SRC_DIR AND
${CMAKE_SOURCE_DIR}/unity-shared/Introspectable.cpp
${CMAKE_SOURCE_DIR}/unity-shared/IntrospectableWrappers.cpp
${CMAKE_SOURCE_DIR}/unity-shared/JSONParser.cpp
+ ${CMAKE_SOURCE_DIR}/unity-shared/KeyboardUtil.cpp
${CMAKE_SOURCE_DIR}/unity-shared/OverlayRenderer.cpp
${CMAKE_SOURCE_DIR}/unity-shared/PanelStyle.cpp
${CMAKE_SOURCE_DIR}/unity-shared/PluginAdapterStandalone.cpp
diff --git a/tests/autopilot/unity/emulators/__init__.py b/tests/autopilot/unity/emulators/__init__.py
index 1f7b6e36f..48f4966a5 100644
--- a/tests/autopilot/unity/emulators/__init__.py
+++ b/tests/autopilot/unity/emulators/__init__.py
@@ -8,3 +8,12 @@
#
"""A collection of Unity-specific emulators."""
+
+
+from autopilot.introspection.dbus import DBusIntrospectionObject
+
+
+class UnityIntrospectionObject(DBusIntrospectionObject):
+
+ DBUS_SERVICE = "com.canonical.Unity"
+ DBUS_OBJECT = "/com/canonical/Unity/Debug"
diff --git a/tests/autopilot/unity/emulators/dash.py b/tests/autopilot/unity/emulators/dash.py
index 807886a34..f7d315b65 100644
--- a/tests/autopilot/unity/emulators/dash.py
+++ b/tests/autopilot/unity/emulators/dash.py
@@ -9,14 +9,11 @@
from __future__ import absolute_import
-from autopilot.introspection.unity import (
- get_state_by_path,
- make_introspection_object,
- UnityIntrospectionObject,
- )
+from autopilot.introspection.dbus import make_introspection_object
from autopilot.emulators.X11 import Keyboard, Mouse
from autopilot.keybindings import KeybindingsHelper
+from unity.emulators import UnityIntrospectionObject
import logging
@@ -294,9 +291,9 @@ class FilterBar(UnityIntrospectionObject):
and for some reason the FilterBar stuff is bundled in the SearchBar.
"""
- state_info = get_state_by_path("//DashView/SearchBar")
- assert(len(state_info) == 1)
- return make_introspection_object(("SearchBar", state_info[0]))
+ searchbar_state = self.get_state_by_path("//DashView/SearchBar")
+ assert(len(searchbar_state) == 1)
+ return make_introspection_object(searchbar_state[0])
class FilterExpanderLabel(UnityIntrospectionObject):
diff --git a/tests/autopilot/unity/emulators/hud.py b/tests/autopilot/unity/emulators/hud.py
index e0c7d7656..59c99bc04 100644
--- a/tests/autopilot/unity/emulators/hud.py
+++ b/tests/autopilot/unity/emulators/hud.py
@@ -9,9 +9,11 @@
from __future__ import absolute_import
-from autopilot.introspection.unity import UnityIntrospectionObject
from autopilot.keybindings import KeybindingsHelper
+from HTMLParser import HTMLParser
+import re
+from unity.emulators import UnityIntrospectionObject
from unity.emulators.dash import SearchBar
from unity.emulators.icons import HudEmbeddedIcon, HudLauncherIcon
@@ -106,6 +108,19 @@ class Hud(KeybindingsHelper):
return 0
@property
+ def hud_buttons(self):
+ """Returns a list of current HUD buttons."""
+ return self.view.hud_buttons
+
+ @property
+ def selected_hud_button(self):
+ try:
+ [button] = filter(lambda x: x.focused, self.hud_buttons)
+ return button
+ except IndexError:
+ raise RuntimeError("No HUD buttons found, is hud active?")
+
+ @property
def num_buttons(self):
view = self.controller.get_hud_view()
if view:
@@ -123,6 +138,10 @@ class HudView(UnityIntrospectionObject):
return self.get_children_by_type(SearchBar)[0]
@property
+ def hud_buttons(self):
+ return self.get_children_by_type(HudButton)
+
+ @property
def geometry(self):
return (self.x, self.y, self.width, self.height)
@@ -133,3 +152,12 @@ class HudController(UnityIntrospectionObject):
def get_hud_view(self):
views = self.get_children_by_type(HudView)
return views[0] if views else None
+
+class HudButton(UnityIntrospectionObject):
+ """Proxy object for the hud buttons."""
+
+ @property
+ def label_no_formatting(self):
+ """Returns the label text with the formatting removed."""
+ htmlparser = HTMLParser()
+ return htmlparser.unescape(re.sub("<[^>]*>", "", self.label))
diff --git a/tests/autopilot/unity/emulators/icons.py b/tests/autopilot/unity/emulators/icons.py
index 5c084dc44..7097b5a82 100644
--- a/tests/autopilot/unity/emulators/icons.py
+++ b/tests/autopilot/unity/emulators/icons.py
@@ -9,7 +9,7 @@
from __future__ import absolute_import
-from autopilot.introspection.unity import UnityIntrospectionObject
+from unity.emulators import UnityIntrospectionObject
from unity.emulators.quicklist import Quicklist
from unity.emulators.tooltip import ToolTip
diff --git a/tests/autopilot/unity/emulators/launcher.py b/tests/autopilot/unity/emulators/launcher.py
index b31305c35..a0742df20 100644
--- a/tests/autopilot/unity/emulators/launcher.py
+++ b/tests/autopilot/unity/emulators/launcher.py
@@ -12,7 +12,6 @@ from __future__ import absolute_import
from autopilot.emulators.dbus_handler import session_bus
from autopilot.emulators.X11 import Mouse, ScreenGeometry
from autopilot.keybindings import KeybindingsHelper
-from autopilot.introspection.unity import UnityIntrospectionObject
from autopilot.utilities import get_compiz_option
import dbus
import logging
@@ -20,6 +19,7 @@ from math import floor
from testtools.matchers import NotEquals
from time import sleep
+from unity.emulators import UnityIntrospectionObject
from unity.emulators.icons import BFBLauncherIcon, BamfLauncherIcon, SimpleLauncherIcon
logger = logging.getLogger(__name__)
@@ -169,6 +169,52 @@ class Launcher(UnityIntrospectionObject, KeybindingsHelper):
if self.hidemode == 1:
self.is_showing.wait_for(False)
+ def keyboard_select_icon(self, **kwargs):
+ """Using either keynav mode or the switcher, select an icon in the launcher.
+
+ The desired mode (keynav or switcher) must be started already before
+ calling this methods or a RuntimeError will be raised.
+
+ This method won't activate the icon, it will only select it.
+
+ Icons are selected by passing keyword argument filters to this method.
+ For example:
+
+ >>> launcher.keyboard_select_icon(tooltip_text="Calculator")
+
+ ...will select the *first* icon that has a 'tooltip_text' attribute equal
+ to 'Calculator'. If an icon is missing the attribute, it is treated as
+ not matching.
+
+ If no icon is found, this method will raise a ValueError.
+
+ """
+
+ if not self.in_keynav_mode and not self.in_switcher_mode:
+ raise RuntimeError("Launcher must be in keynav or switcher mode")
+
+ [launcher_model] = LauncherModel.get_all_instances()
+ all_icons = launcher_model.get_launcher_icons()
+ logger.debug("all_icons = %r", [i.tooltip_text for i in all_icons])
+ for icon in all_icons:
+ # can't iterate over the model icons directly since some are hidden
+ # from the user.
+ if not icon.visible:
+ continue
+ logger.debug("Selected icon = %s", icon.tooltip_text)
+ matches = True
+ for arg,val in kwargs.iteritems():
+ if not hasattr(icon, arg) or getattr(icon, arg, None) != val:
+ matches = False
+ break
+ if matches:
+ return
+ if self.in_keynav_mode:
+ self.key_nav_next()
+ elif self.in_switcher_mode:
+ self.switcher_next()
+ raise ValueError("No icon found that matches: %r", kwargs)
+
def key_nav_start(self):
"""Start keyboard navigation mode by pressing Alt+F1."""
self._screen.move_mouse_to_monitor(self.monitor)
@@ -264,7 +310,7 @@ class Launcher(UnityIntrospectionObject, KeybindingsHelper):
`icon` must be an instance of SimpleLauncherIcon or it's descendants.
"""
if not isinstance(icon, SimpleLauncherIcon):
- raise TypeError("icon must be a LauncherIcon")
+ raise TypeError("icon must be a LauncherIcon, not %s" % type(icon))
logger.debug("Clicking launcher icon %r on monitor %d with mouse button %d",
icon, self.monitor, button)
diff --git a/tests/autopilot/unity/emulators/panel.py b/tests/autopilot/unity/emulators/panel.py
index 275549f95..2b0d69254 100644
--- a/tests/autopilot/unity/emulators/panel.py
+++ b/tests/autopilot/unity/emulators/panel.py
@@ -12,10 +12,10 @@ from __future__ import absolute_import
import logging
from time import sleep
-from autopilot.introspection.unity import UnityIntrospectionObject
from autopilot.emulators.X11 import Mouse
from autopilot.keybindings import KeybindingsHelper
+from unity.emulators import UnityIntrospectionObject
logger = logging.getLogger(__name__)
diff --git a/tests/autopilot/unity/emulators/quicklist.py b/tests/autopilot/unity/emulators/quicklist.py
index fafab3dc5..c4cbe55b4 100644
--- a/tests/autopilot/unity/emulators/quicklist.py
+++ b/tests/autopilot/unity/emulators/quicklist.py
@@ -11,9 +11,9 @@ from __future__ import absolute_import
import logging
-from autopilot.introspection.unity import UnityIntrospectionObject
from autopilot.emulators.X11 import Mouse
+from unity.emulators import UnityIntrospectionObject
logger = logging.getLogger(__name__)
diff --git a/tests/autopilot/unity/emulators/shortcut_hint.py b/tests/autopilot/unity/emulators/shortcut_hint.py
index dcff2d214..279b4f108 100644
--- a/tests/autopilot/unity/emulators/shortcut_hint.py
+++ b/tests/autopilot/unity/emulators/shortcut_hint.py
@@ -11,9 +11,9 @@ from __future__ import absolute_import
import logging
-from autopilot.introspection.unity import UnityIntrospectionObject
from autopilot.keybindings import KeybindingsHelper
+from unity.emulators import UnityIntrospectionObject
logger = logging.getLogger(__name__)
diff --git a/tests/autopilot/unity/emulators/switcher.py b/tests/autopilot/unity/emulators/switcher.py
index 9491802ad..7525f137b 100644
--- a/tests/autopilot/unity/emulators/switcher.py
+++ b/tests/autopilot/unity/emulators/switcher.py
@@ -12,9 +12,9 @@ from __future__ import absolute_import
import logging
from autopilot.emulators.X11 import Mouse
-from autopilot.introspection.unity import UnityIntrospectionObject
from autopilot.keybindings import KeybindingsHelper
+from unity.emulators import UnityIntrospectionObject
# even though we don't use these directly, we need to make sure they've been
# imported so the classes contained are registered with the introspection API.
from unity.emulators.icons import *
diff --git a/tests/autopilot/unity/emulators/tooltip.py b/tests/autopilot/unity/emulators/tooltip.py
index 60d165460..17c3740a3 100644
--- a/tests/autopilot/unity/emulators/tooltip.py
+++ b/tests/autopilot/unity/emulators/tooltip.py
@@ -7,13 +7,9 @@
# by the Free Software Foundation.
#
-import logging
-from time import sleep
+from __future__ import absolute_import
-from autopilot.introspection.unity import UnityIntrospectionObject
-
-
-logger = logging.getLogger(__name__)
+from unity.emulators import UnityIntrospectionObject
class ToolTip(UnityIntrospectionObject):
diff --git a/tests/autopilot/unity/emulators/unity.py b/tests/autopilot/unity/emulators/unity.py
index 912dc3f57..69ecab582 100644
--- a/tests/autopilot/unity/emulators/unity.py
+++ b/tests/autopilot/unity/emulators/unity.py
@@ -15,20 +15,20 @@ from dbus import Interface
# acquire the debugging dbus object
UNITY_BUS_NAME = 'com.canonical.Unity'
DEBUG_PATH = '/com/canonical/Unity/Debug'
-INTROSPECTION_IFACE = 'com.canonical.Unity.Debug.Introspection'
+LOGGING_IFACE = 'com.canonical.Unity.Debug.Logging'
_debug_proxy_obj = session_bus.get_object(UNITY_BUS_NAME, DEBUG_PATH)
-_introspection_iface = Interface(_debug_proxy_obj, INTROSPECTION_IFACE)
+_logging_iface = Interface(_debug_proxy_obj, LOGGING_IFACE)
def start_log_to_file(file_path):
"""Instruct Unity to start logging to the given file."""
- _introspection_iface.StartLogToFile(file_path)
+ _logging_iface.StartLogToFile(file_path)
def reset_logging():
"""Instruct Unity to stop logging to a file."""
- _introspection_iface.ResetLogging()
+ _logging_iface.ResetLogging()
def set_log_severity(component, severity):
@@ -39,7 +39,7 @@ def set_log_severity(component, severity):
'severity' is the severity name (like 'DEBUG', 'INFO' etc.)
"""
- _introspection_iface.SetLogSeverity(component, severity)
+ _logging_iface.SetLogSeverity(component, severity)
def log_unity_message(severity, message):
@@ -53,5 +53,5 @@ def log_unity_message(severity, message):
test, use the python logging framework instead.
"""
- _introspection_iface.LogMessage(severity, message)
+ _logging_iface.LogMessage(severity, message)
diff --git a/tests/autopilot/unity/emulators/window_manager.py b/tests/autopilot/unity/emulators/window_manager.py
index ceebda3cd..9c0f02a9f 100644
--- a/tests/autopilot/unity/emulators/window_manager.py
+++ b/tests/autopilot/unity/emulators/window_manager.py
@@ -11,7 +11,8 @@ from __future__ import absolute_import
import logging
from autopilot.keybindings import KeybindingsHelper
-from autopilot.introspection.unity import UnityIntrospectionObject
+
+from unity.emulators import UnityIntrospectionObject
logger = logging.getLogger(__name__)
diff --git a/tests/autopilot/unity/tests/__init__.py b/tests/autopilot/unity/tests/__init__.py
index 14fbbebc5..e24e19a19 100644
--- a/tests/autopilot/unity/tests/__init__.py
+++ b/tests/autopilot/unity/tests/__init__.py
@@ -10,8 +10,10 @@
from __future__ import absolute_import
+from autopilot.matchers import Eventually
from autopilot.testcase import AutopilotTestCase
from dbus import DBusException
+from logging import getLogger
import os
from tempfile import mktemp
from testtools.content import text_content
@@ -31,6 +33,8 @@ from unity.emulators.unity import (
)
+log = getLogger(__name__)
+
class UnityTestCase(AutopilotTestCase):
"""Unity test case base class, with improvments specific to Unity tests."""
@@ -57,31 +61,49 @@ class UnityTestCase(AutopilotTestCase):
"""
well_behaved = True
reasons = []
+ log.info("Checking system state for badly behaving test...")
# Have we switched workspace?
if self.workspace.current_workspace != self._initial_workspace_num:
well_behaved = False
reasons.append("The test changed the active workspace from %d to %d." \
% (self._initial_workspace_num, self.workspace.current_workspace))
+ log.warning("Test changed the active workspace, changing it back...")
self.workspace.switch_to(self._initial_workspace_num)
# Have we left the dash open?
if self.dash.visible:
well_behaved = False
reasons.append("The test left the dash open.")
+ log.warning("Test left the dash open, closing it...")
self.dash.ensure_hidden()
# ... or the hud?
if self.hud.visible:
well_behaved = False
reasons.append("The test left the hud open.")
+ log.warning("Test left the hud open, closing it...")
self.hud.ensure_hidden()
# Are we in show desktop mode?
if self.window_manager.showdesktop_active:
well_behaved = False
reasons.append("The test left the system in show_desktop mode.")
+ log.warning("Test left the system in show desktop mode, exiting it...")
self.window_manager.leave_show_desktop()
+ for launcher in self.launcher.get_launchers():
+ if launcher.in_keynav_mode:
+ well_behaved = False
+ reasons.append("The test left the launcher keynav mode enabled.")
+ log.warning("Test left the launcher in keynav mode, exiting it...")
+ launcher.key_nav_cancel()
+ if launcher.in_switcher_mode:
+ well_behaved = False
+ reasons.append("The test left the launcher in switcher mode.")
+ log.warning("Test left the launcher in switcher mode, exiting it...")
+ launcher.switcher_cancel()
if not well_behaved:
self.fail("/n".join(reasons))
+ else:
+ log.info("Test was well behaved.")
@property
def dash(self):
@@ -170,3 +192,7 @@ class UnityTestCase(AutopilotTestCase):
raise ValueError("Log level '%s' must be one of: %r" % (level, valid_levels))
set_log_severity(component, level)
+ def assertNumberWinsIsEventually(self, app, num):
+ """Asserts that 'app' eventually has 'num' wins. Waits up to 10 seconds."""
+
+ self.assertThat(lambda: len(app.get_windows()), Eventually(Equals(num)))
diff --git a/tests/autopilot/unity/tests/launcher/__init__.py b/tests/autopilot/unity/tests/launcher/__init__.py
new file mode 100644
index 000000000..8f7602d92
--- /dev/null
+++ b/tests/autopilot/unity/tests/launcher/__init__.py
@@ -0,0 +1,59 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Author: Thomi Richards
+#
+# 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.
+
+"""Autopilot test case class for all Launcher tests"""
+
+from autopilot.emulators.X11 import ScreenGeometry
+from autopilot.testcase import multiply_scenarios
+
+from unity.tests import UnityTestCase
+
+
+def _make_scenarios():
+ """Make scenarios for launcher test cases based on the number of configured
+ monitors.
+ """
+ screen_geometry = ScreenGeometry()
+ num_monitors = screen_geometry.get_num_monitors()
+
+ # it doesn't make sense to set only_primary when we're running in a single-monitor setup.
+ if num_monitors == 1:
+ return [('Single Monitor', {'launcher_monitor': 0, 'only_primary': False})]
+
+ monitor_scenarios = [('Monitor %d' % (i), {'launcher_monitor': i}) for i in range(num_monitors)]
+ launcher_mode_scenarios = [('launcher_on_primary', {'only_primary': True}),
+ ('launcher on all', {'only_primary': False})]
+ return multiply_scenarios(monitor_scenarios, launcher_mode_scenarios)
+
+
+class LauncherTestCase(UnityTestCase):
+ """A base class for all launcher tests that uses scenarios to run on
+ each launcher (for multi-monitor setups).
+ """
+ scenarios = _make_scenarios()
+
+ def setUp(self):
+ super(LauncherTestCase, self).setUp()
+ self.screen_geo = ScreenGeometry()
+ self.set_unity_log_level("unity.launcher", "DEBUG")
+ self.addCleanup(self.set_unity_log_level, "unity.launcher", "INFO")
+
+ self.set_unity_option('num_launchers', int(self.only_primary))
+ self.launcher_instance = self.get_launcher()
+
+ if self.only_primary:
+ try:
+ old_primary_screen = self.screen_geo.get_primary_monitor()
+ self.screen_geo.set_primary_monitor(self.launcher_monitor)
+ self.addCleanup(self.screen_geo.set_primary_monitor, old_primary_screen)
+ except ScreenGeometry.BlacklistedDriverError:
+ self.skipTest("Impossible to set the monitor %d as primary" % self.launcher_monitor)
+
+ def get_launcher(self):
+ """Get the launcher for the current scenario."""
+ return self.launcher.get_launcher_for_monitor(self.launcher_monitor)
diff --git a/tests/autopilot/unity/tests/launcher/test_capture.py b/tests/autopilot/unity/tests/launcher/test_capture.py
new file mode 100644
index 000000000..a6f4b602e
--- /dev/null
+++ b/tests/autopilot/unity/tests/launcher/test_capture.py
@@ -0,0 +1,113 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Authors: Thomi Richards,
+# Marco Trevisan (Treviño)
+#
+# 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.
+
+from __future__ import absolute_import
+
+from autopilot.emulators.X11 import ScreenGeometry
+from autopilot.matchers import Eventually
+import logging
+from testtools.matchers import Equals, LessThan, GreaterThan
+from time import sleep
+
+from unity.tests import UnityTestCase
+
+logger = logging.getLogger(__name__)
+
+
+class LauncherCaptureTests(UnityTestCase):
+ """Test the launchers ability to capture/not capture the mouse."""
+
+ screen_geo = ScreenGeometry()
+
+ def setUp(self):
+ super(LauncherCaptureTests, self).setUp()
+
+ if self.screen_geo.get_num_monitors() <= 1:
+ self.skipTest("This test requires two or more monitors.")
+
+ self.set_unity_option('launcher_capture_mouse', True)
+ self.set_unity_option('num_launchers', 0)
+ self.setHideMode(0)
+
+ def setHideMode(self, mode):
+ self.set_unity_option('launcher_hide_mode', mode)
+ launcher = self.launcher.get_launcher_for_monitor(0)
+ self.assertThat(launcher.hidemode, Eventually(Equals(mode)))
+
+ def leftMostMonitor(self):
+ x1, y1, width, height = self.screen_geo.get_monitor_geometry(0)
+ x2, y2, width, height = self.screen_geo.get_monitor_geometry(1)
+
+ if x1 < x2:
+ return 0
+ return 1
+
+ def rightMostMonitor(self):
+ # TODO: This will break setups with 3 or more monitors.
+ return 1 - self.leftMostMonitor()
+
+
+ def test_launcher_captures_while_sticky_and_revealed(self):
+ """Tests that the launcher captures the mouse when moving between monitors
+ while revealed.
+ """
+ x, y, width, height = self.screen_geo.get_monitor_geometry(self.rightMostMonitor())
+ self.mouse.move(x + width / 2, y + height / 2, False)
+ self.mouse.move(x - width / 2, y + height / 2, True, 5, .002)
+
+ x_fin, y_fin = self.mouse.position()
+ # The launcher should have held the mouse a little bit
+ self.assertThat(x_fin, GreaterThan(x - width / 2))
+
+ def test_launcher_not_capture_while_not_sticky_and_revealed(self):
+ """Tests that the launcher doesn't captures the mouse when moving between monitors
+ while revealed and stick is off.
+ """
+
+ self.set_unity_option('launcher_capture_mouse', False)
+
+ x, y, width, height = self.screen_geo.get_monitor_geometry(self.rightMostMonitor())
+ self.mouse.move(x + width / 2, y + height / 2, False)
+ self.mouse.move(x - width / 2, y + height / 2, True, 5, .002)
+
+ x_fin, y_fin = self.mouse.position()
+ # The launcher should have held the mouse a little bit
+ self.assertThat(x_fin, Equals(x - width / 2))
+
+ def test_launcher_not_capture_while_not_sticky_and_hidden_moving_right(self):
+ """Tests that the launcher doesn't capture the mouse when moving between monitors
+ while hidden and sticky is off.
+ """
+
+ self.set_unity_option('launcher_capture_mouse', False)
+ self.setHideMode(1)
+
+ x, y, width, height = self.screen_geo.get_monitor_geometry(self.leftMostMonitor())
+ self.mouse.move(x + width / 2, y + height / 2, False)
+ sleep(1.5)
+ self.mouse.move(x + width * 1.5, y + height / 2, True, 5, .002)
+
+ x_fin, y_fin = self.mouse.position()
+ # The launcher should have held the mouse a little bit
+ self.assertThat(x_fin, Equals(x + width * 1.5))
+
+ def test_launcher_capture_while_sticky_and_hidden_moving_right(self):
+ """Tests that the launcher captures the mouse when moving between monitors
+ while hidden.
+ """
+ self.setHideMode(1)
+
+ x, y, width, height = self.screen_geo.get_monitor_geometry(self.leftMostMonitor())
+ self.mouse.move(x + width / 2, y + height / 2, False)
+ sleep(1.5)
+ self.mouse.move(x + width * 1.5, y + height / 2, True, 5, .002)
+
+ x_fin, y_fin = self.mouse.position()
+ # The launcher should have held the mouse a little bit
+ self.assertThat(x_fin, LessThan(x + width * 1.5))
diff --git a/tests/autopilot/unity/tests/launcher/test_icon_behavior.py b/tests/autopilot/unity/tests/launcher/test_icon_behavior.py
new file mode 100644
index 000000000..1e996a6c3
--- /dev/null
+++ b/tests/autopilot/unity/tests/launcher/test_icon_behavior.py
@@ -0,0 +1,208 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Authors: Thomi Richards,
+# Marco Trevisan (Treviño)
+#
+# 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.
+
+from __future__ import absolute_import
+
+from autopilot.matchers import Eventually
+from autopilot.testcase import multiply_scenarios
+import logging
+from testtools.matchers import Equals, NotEquals
+from time import sleep
+
+from unity.emulators.launcher import IconDragType
+from unity.tests.launcher import LauncherTestCase, _make_scenarios
+
+logger = logging.getLogger(__name__)
+
+
+class LauncherIconsTests(LauncherTestCase):
+ """Test the launcher icons interactions"""
+
+ def setUp(self):
+ super(LauncherIconsTests, self).setUp()
+ self.set_unity_option('launcher_hide_mode', 0)
+
+ def test_bfb_tooltip_disappear_when_dash_is_opened(self):
+ """Tests that the bfb tooltip disappear when the dash is opened."""
+ bfb = self.launcher.model.get_bfb_icon()
+ self.mouse.move(bfb.center_x, bfb.center_y)
+
+ self.dash.ensure_visible()
+ self.addCleanup(self.dash.ensure_hidden)
+
+ self.assertThat(bfb.get_tooltip().active, Eventually(Equals(False)))
+
+ def test_bfb_tooltip_is_disabled_when_dash_is_open(self):
+ """Tests the that bfb tooltip is disabled when the dash is open."""
+ self.dash.ensure_visible()
+ self.addCleanup(self.dash.ensure_hidden)
+
+ bfb = self.launcher.model.get_bfb_icon()
+ self.mouse.move(bfb.center_x, bfb.center_y)
+
+ self.assertThat(bfb.get_tooltip().active, Eventually(Equals(False)))
+
+ def test_shift_click_opens_new_application_instance(self):
+ """Shift+Clicking MUST open a new instance of an already-running application."""
+ app = self.start_app("Calculator")
+ desktop_id = app.desktop_file
+ icon = self.launcher.model.get_icon_by_desktop_id(desktop_id)
+ launcher_instance = self.launcher.get_launcher_for_monitor(0)
+
+ self.keyboard.press("Shift")
+ self.addCleanup(self.keyboard.release, "Shift")
+ launcher_instance.click_launcher_icon(icon)
+
+ self.assertNumberWinsIsEventually(app, 2)
+
+ def test_launcher_activate_last_focused_window(self):
+ """Activating a launcher icon must raise only the last focused instance
+ of that application.
+
+ """
+
+ mahj = self.start_app("Mahjongg")
+ [mah_win1] = mahj.get_windows()
+ self.assertTrue(mah_win1.is_focused)
+
+ calc = self.start_app("Calculator")
+ [calc_win] = calc.get_windows()
+ self.assertTrue(calc_win.is_focused)
+
+ self.start_app("Mahjongg")
+ # Sleeping due to the start_app only waiting for the bamf model to be
+ # updated with the application. Since the app has already started,
+ # and we are just waiting on a second window, however a defined sleep
+ # here is likely to be problematic.
+ # TODO: fix bamf emulator to enable waiting for new windows.
+ sleep(1)
+ [mah_win2] = [w for w in mahj.get_windows() if w.x_id != mah_win1.x_id]
+ self.assertTrue(mah_win2.is_focused)
+ self.assertVisibleWindowStack([mah_win2, calc_win, mah_win1])
+
+ mahj_icon = self.launcher.model.get_icon_by_desktop_id(mahj.desktop_file)
+ calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file)
+
+ self.launcher_instance.click_launcher_icon(calc_icon)
+ sleep(1)
+ self.assertTrue(calc_win.is_focused)
+ self.assertVisibleWindowStack([calc_win, mah_win2, mah_win1])
+
+ self.launcher_instance.click_launcher_icon(mahj_icon)
+ sleep(1)
+ self.assertTrue(mah_win2.is_focused)
+ self.assertVisibleWindowStack([mah_win2, calc_win, mah_win1])
+
+ self.keybinding("window/minimize")
+ sleep(1)
+
+ self.assertTrue(mah_win2.is_hidden)
+ self.assertTrue(calc_win.is_focused)
+ self.assertVisibleWindowStack([calc_win, mah_win1])
+
+ self.launcher_instance.click_launcher_icon(mahj_icon)
+ sleep(1)
+ self.assertTrue(mah_win1.is_focused)
+ self.assertTrue(mah_win2.is_hidden)
+ self.assertVisibleWindowStack([mah_win1, calc_win])
+
+ def test_clicking_icon_twice_initiates_spread(self):
+ """This tests shows that when you click on a launcher icon twice,
+ when an application window is focused, the spread is initiated.
+ """
+ calc = self.start_app("Calculator")
+ [calc_win1] = calc.get_windows()
+ self.assertTrue(calc_win1.is_focused)
+
+ self.start_app("Calculator")
+ # Sleeping due to the start_app only waiting for the bamf model to be
+ # updated with the application. Since the app has already started,
+ # and we are just waiting on a second window, however a defined sleep
+ # here is likely to be problematic.
+ # TODO: fix bamf emulator to enable waiting for new windows.
+ sleep(1)
+ [calc_win2] = [w for w in calc.get_windows() if w.x_id != calc_win1.x_id]
+
+ self.assertVisibleWindowStack([calc_win2, calc_win1])
+ self.assertTrue(calc_win2.is_focused)
+
+ calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file)
+ self.addCleanup(self.keybinding, "spread/cancel")
+ self.launcher_instance.click_launcher_icon(calc_icon)
+
+ self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
+ self.assertThat(self.window_manager.scale_active_for_group, Eventually(Equals(True)))
+
+ def test_icon_shows_on_quick_application_reopen(self):
+ """Icons must stay on launcher when an application is quickly closed/reopened."""
+ calc = self.start_app("Calculator")
+ desktop_file = calc.desktop_file
+ calc_icon = self.launcher.model.get_icon_by_desktop_id(desktop_file)
+ self.assertThat(calc_icon.visible, Eventually(Equals(True)))
+
+ self.close_all_app("Calculator")
+ calc = self.start_app("Calculator")
+ sleep(2)
+
+ calc_icon = self.launcher.model.get_icon_by_desktop_id(desktop_file)
+ self.assertThat(calc_icon, NotEquals(None))
+ self.assertThat(calc_icon.visible, Eventually(Equals(True)))
+
+
+class LauncherDragIconsBehavior(LauncherTestCase):
+ """Tests dragging icons around the Launcher."""
+
+ scenarios = multiply_scenarios(_make_scenarios(),
+ [
+ ('inside', {'drag_type': IconDragType.INSIDE}),
+ ('outside', {'drag_type': IconDragType.OUTSIDE}),
+ ])
+
+ def ensure_calc_icon_not_in_launcher(self):
+ """Wait until the launcher model updates and removes the calc icon."""
+ refresh_fn = lambda: self.launcher.model.get_icon_by_desktop_id("gcalctool.desktop")
+ self.assertThat(refresh_fn, Eventually(Equals(None)))
+
+ def test_can_drag_icon_below_bfb(self):
+ """Application icons must be draggable to below the BFB."""
+
+ self.ensure_calc_icon_not_in_launcher()
+ calc = self.start_app("Calculator")
+ calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file)
+
+ bfb_icon_position = 0
+ self.launcher_instance.drag_icon_to_position(calc_icon,
+ bfb_icon_position,
+ self.drag_type)
+ moved_icon = self.launcher.model.\
+ get_launcher_icons_for_monitor(self.launcher_monitor)[1]
+ self.assertThat(moved_icon.id, Equals(calc_icon.id))
+
+ def test_can_drag_icon_above_window_switcher(self):
+ """Application icons must be dragable to above the workspace switcher icon."""
+
+ self.ensure_calc_icon_not_in_launcher()
+ calc = self.start_app("Calculator")
+ calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file)
+
+ # Move a known icon to the top as it needs to be more than 2 icon
+ # spaces away for this test to actually do anything
+ bfb_icon_position = 0
+ self.launcher_instance.drag_icon_to_position(calc_icon,
+ bfb_icon_position,
+ self.drag_type)
+ sleep(1)
+ switcher_pos = -2
+ self.launcher_instance.drag_icon_to_position(calc_icon,
+ switcher_pos,
+ self.drag_type)
+
+ moved_icon = self.launcher.model.\
+ get_launcher_icons_for_monitor(self.launcher_monitor)[-3]
+ self.assertThat(moved_icon.id, Equals(calc_icon.id))
diff --git a/tests/autopilot/unity/tests/launcher/test_keynav.py b/tests/autopilot/unity/tests/launcher/test_keynav.py
new file mode 100644
index 000000000..b65f262b9
--- /dev/null
+++ b/tests/autopilot/unity/tests/launcher/test_keynav.py
@@ -0,0 +1,191 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Authors: Thomi Richards,
+# Marco Trevisan (Treviño)
+#
+# 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.
+
+from __future__ import absolute_import
+
+from autopilot.matchers import Eventually
+import logging
+from testtools.matchers import Equals, GreaterThan
+
+from unity.tests.launcher import LauncherTestCase
+
+logger = logging.getLogger(__name__)
+
+
+class LauncherKeyNavTests(LauncherTestCase):
+ """Test the launcher key navigation"""
+
+ def start_keynav_with_cleanup_cancel(self):
+ """Start keynav mode safely.
+
+ This adds a cleanup action that cancels keynav mode at the end of the
+ test if it's still running (but does nothing otherwise).
+
+ """
+ self.launcher_instance.key_nav_start()
+ self.addCleanup(self.safe_quit_keynav)
+
+ def safe_quit_keynav(self):
+ """Quit the keynav mode if it's engaged."""
+ if self.launcher.key_nav_is_active:
+ self.launcher_instance.key_nav_cancel()
+
+ def test_launcher_keynav_initiate(self):
+ """Tests we can initiate keyboard navigation on the launcher."""
+ self.start_keynav_with_cleanup_cancel()
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
+ self.assertThat(self.launcher.key_nav_is_grabbed, Eventually(Equals(True)))
+
+ def test_launcher_keynav_cancel(self):
+ """Test that we can exit keynav mode."""
+ self.launcher_instance.key_nav_start()
+ self.launcher_instance.key_nav_cancel()
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
+ self.assertThat(self.launcher.key_nav_is_grabbed, Eventually(Equals(False)))
+
+ def test_launcher_keynav_cancel_resume_focus(self):
+ """Test that ending the launcher keynav resume the focus."""
+ calc = self.start_app("Calculator")
+ self.assertTrue(calc.is_active)
+
+ self.start_keynav_with_cleanup_cancel()
+ self.assertFalse(calc.is_active)
+
+ self.launcher_instance.key_nav_cancel()
+ self.assertTrue(calc.is_active)
+
+ def test_launcher_keynav_starts_at_index_zero(self):
+ """Test keynav mode starts at index 0."""
+ self.start_keynav_with_cleanup_cancel()
+ self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
+
+ def test_launcher_keynav_forward(self):
+ """Must be able to move forwards while in keynav mode."""
+ self.start_keynav_with_cleanup_cancel()
+ self.launcher_instance.key_nav_next()
+ # The launcher model has hidden items, so the keynav indexes do not
+ # increase by 1 each time. This test was failing because the 2nd icon
+ # had an index of 2, not 1 as expected. The best we can do here is to
+ # make sure that the index has increased. This opens us to the
+ # possibility that the launcher really is skipping forward more than one
+ # icon at a time, but we can't do much about that.
+ self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(0)))
+
+ def test_launcher_keynav_prev_works(self):
+ """Must be able to move backwards while in keynav mode."""
+ self.start_keynav_with_cleanup_cancel()
+ self.launcher_instance.key_nav_next()
+ self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(0)))
+ self.launcher_instance.key_nav_prev()
+ self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
+
+ def test_launcher_keynav_cycling_forward(self):
+ """Launcher keynav must loop through icons when cycling forwards"""
+ self.start_keynav_with_cleanup_cancel()
+ prev_icon = 0
+ for icon in range(1, self.launcher.model.num_launcher_icons()):
+ self.launcher_instance.key_nav_next()
+ # FIXME We can't directly check for selection/icon number equalty
+ # since the launcher model also contains "hidden" icons that aren't
+ # shown, so the selection index can increment by more than 1.
+ self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(prev_icon)))
+ prev_icon = self.launcher.key_nav_selection
+
+ self.launcher_instance.key_nav_next()
+ self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
+
+ def test_launcher_keynav_cycling_backward(self):
+ """Launcher keynav must loop through icons when cycling backwards"""
+ self.start_keynav_with_cleanup_cancel()
+ self.launcher_instance.key_nav_prev()
+ # FIXME We can't directly check for self.launcher.num_launcher_icons - 1
+ self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(1)))
+
+ def test_launcher_keynav_can_open_and_close_quicklist(self):
+ """Tests that we can open and close a quicklist from keynav mode."""
+ self.start_keynav_with_cleanup_cancel()
+ self.launcher_instance.key_nav_next()
+ self.launcher_instance.key_nav_enter_quicklist()
+ self.assertThat(self.launcher_instance.quicklist_open, Eventually(Equals(True)))
+ self.launcher_instance.key_nav_exit_quicklist()
+ self.assertThat(self.launcher_instance.quicklist_open, Eventually(Equals(False)))
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
+ self.assertThat(self.launcher.key_nav_is_grabbed, Eventually(Equals(True)))
+
+ def test_launcher_keynav_mode_toggles(self):
+ """Tests that keynav mode toggles with Alt+F1."""
+ # was initiated in setup.
+ self.start_keynav_with_cleanup_cancel()
+ self.keybinding("launcher/keynav")
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
+
+ def test_launcher_keynav_activate_keep_focus(self):
+ """Activating a running launcher icon must focus it."""
+ calc = self.start_app("Calculator")
+ mahjongg = self.start_app("Mahjongg")
+ self.assertTrue(mahjongg.is_active)
+ self.assertFalse(calc.is_active)
+
+ self.start_keynav_with_cleanup_cancel()
+
+ self.launcher_instance.keyboard_select_icon(tooltip_text=calc.name)
+ self.launcher_instance.key_nav_activate()
+
+ self.assertTrue(calc.is_active)
+ self.assertFalse(mahjongg.is_active)
+
+ def test_launcher_keynav_expo_focus(self):
+ """When entering expo mode from KeyNav the Desktop must get focus."""
+ self.start_keynav_with_cleanup_cancel()
+
+ self.launcher_instance.keyboard_select_icon(tooltip_text="Workspace Switcher")
+ self.launcher_instance.key_nav_activate()
+ self.addCleanup(self.keybinding, "expo/cancel")
+
+ self.assertThat(self.panels.get_active_panel().title, Eventually(Equals("Ubuntu Desktop")))
+
+ def test_launcher_keynav_expo_exit_on_esc(self):
+ """Esc should quit expo when entering it from KeyNav."""
+ self.start_keynav_with_cleanup_cancel()
+
+ self.launcher_instance.keyboard_select_icon(tooltip_text="Workspace Switcher")
+ self.launcher_instance.key_nav_activate()
+
+ self.keyboard.press_and_release("Escape")
+ self.assertThat(self.window_manager.expo_active, Eventually(Equals(False)))
+
+ def test_launcher_keynav_alt_tab_quits(self):
+ """Tests that alt+tab exits keynav mode."""
+ self.start_keynav_with_cleanup_cancel()
+
+ self.keybinding("switcher/reveal_normal")
+ self.addCleanup(self.switcher.terminate)
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
+
+ def test_launcher_keynav_alt_grave_quits(self):
+ """Tests that alt+` exits keynav mode."""
+ self.start_keynav_with_cleanup_cancel()
+ # Can't use switcher emulat here since the switcher won't appear.
+ self.keybinding("switcher/reveal_details")
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
+
+ def test_launcher_keynav_cancel_doesnt_activate_icon(self):
+ """This tests when canceling keynav the current icon doesnt activate."""
+ self.start_keynav_with_cleanup_cancel()
+ self.keyboard.press_and_release("Escape")
+ self.assertThat(self.dash.visible, Eventually(Equals(False)))
+
+ def test_alt_f1_closes_dash(self):
+ """This test when Alt+F1 is activated it must close the dash."""
+ self.dash.ensure_visible()
+
+ self.start_keynav_with_cleanup_cancel()
+
+ self.assertThat(self.dash.visible, Equals(False))
+ self.assertThat(self.launcher.key_nav_is_active, Equals(True))
diff --git a/tests/autopilot/unity/tests/launcher/test_reveal.py b/tests/autopilot/unity/tests/launcher/test_reveal.py
new file mode 100644
index 000000000..745424b3d
--- /dev/null
+++ b/tests/autopilot/unity/tests/launcher/test_reveal.py
@@ -0,0 +1,87 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Authors: Thomi Richards,
+# Marco Trevisan (Treviño)
+#
+# 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.
+
+from __future__ import absolute_import
+
+from autopilot.matchers import Eventually
+import logging
+from testtools.matchers import Equals, GreaterThan
+from time import sleep
+
+from unity.tests.launcher import LauncherTestCase
+
+logger = logging.getLogger(__name__)
+
+
+class LauncherRevealTests(LauncherTestCase):
+ """Test the launcher reveal behavior when in autohide mode."""
+
+ def setUp(self):
+ super(LauncherRevealTests, self).setUp()
+ # these automatically reset to the original value, as implemented in AutopilotTestCase
+ self.set_unity_option('launcher_capture_mouse', True)
+ self.set_unity_option('launcher_hide_mode', 1)
+ launcher = self.get_launcher()
+ self.assertThat(launcher.hidemode, Eventually(Equals(1)))
+
+ def test_launcher_keyboard_reveal_works(self):
+ """Revealing launcher with keyboard must work."""
+ self.launcher_instance.keyboard_reveal_launcher()
+ self.addCleanup(self.launcher_instance.keyboard_unreveal_launcher)
+ self.assertThat(self.launcher_instance.is_showing, Eventually(Equals(True)))
+
+ def test_reveal_on_mouse_to_edge(self):
+ """Tests reveal of launchers by mouse pressure."""
+ self.launcher_instance.move_mouse_to_right_of_launcher()
+ self.launcher_instance.mouse_reveal_launcher()
+ self.assertThat(self.launcher_instance.is_showing, Eventually(Equals(True)))
+
+ def test_reveal_with_mouse_under_launcher(self):
+ """The Launcher must hide properly if the mouse is under the launcher."""
+
+ self.launcher_instance.move_mouse_over_launcher()
+ # we can't use "launcher_instance.keyboard_reveal_launcher()"
+ # since it moves the mouse out of the way, invalidating the test.
+ self.keybinding_hold("launcher/reveal")
+ sleep(1)
+ self.keybinding_release("launcher/reveal")
+ self.assertThat(self.launcher_instance.is_showing, Eventually(Equals(False)))
+
+ def test_reveal_does_not_hide_again(self):
+ """Tests reveal of launchers by mouse pressure to ensure it doesn't
+ automatically hide again.
+ """
+ self.launcher_instance.move_mouse_to_right_of_launcher()
+ self.launcher_instance.mouse_reveal_launcher()
+ self.assertThat(self.launcher_instance.is_showing, Eventually(Equals(True)))
+
+ def test_launcher_does_not_reveal_with_mouse_down(self):
+ """Launcher must not reveal if have mouse button 1 down."""
+ self.screen_geo.move_mouse_to_monitor(self.launcher_instance.monitor)
+ self.mouse.press(1)
+ self.addCleanup(self.mouse.release, 1)
+ #FIXME: This is really bad API. it says reveal but it's expected to fail. bad bad bad!!
+ self.launcher_instance.mouse_reveal_launcher()
+ # Need a sleep here otherwise this test would pass even if the code failed.
+ # THis test needs to be rewritten...
+ sleep(5)
+ self.assertThat(self.launcher_instance.is_showing, Equals(False))
+
+ def test_new_icon_has_the_shortcut(self):
+ """New icons should have an associated shortcut"""
+ if self.launcher.model.num_bamf_launcher_icons() >= 10:
+ self.skip("There are already more than 9 icons in the launcher")
+
+ desktop_file = self.KNOWN_APPS['Calculator']['desktop-file']
+ if self.launcher.model.get_icon_by_desktop_id(desktop_file) != None:
+ self.skip("Calculator icon is already on the launcher.")
+
+ self.start_app('Calculator')
+ icon = self.launcher.model.get_icon_by_desktop_id(desktop_file)
+ self.assertThat(icon.shortcut, GreaterThan(0))
diff --git a/tests/autopilot/unity/tests/launcher/test_shortcut.py b/tests/autopilot/unity/tests/launcher/test_shortcut.py
new file mode 100644
index 000000000..8747b5723
--- /dev/null
+++ b/tests/autopilot/unity/tests/launcher/test_shortcut.py
@@ -0,0 +1,55 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Authors: Thomi Richards,
+# Marco Trevisan (Treviño)
+#
+# 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.
+
+from __future__ import absolute_import
+
+from autopilot.matchers import Eventually
+import logging
+from testtools.matchers import Equals
+from time import sleep
+
+from unity.tests.launcher import LauncherTestCase
+
+logger = logging.getLogger(__name__)
+
+
+class LauncherShortcutTests(LauncherTestCase):
+ """Tests for the shortcut hint window."""
+
+ def setUp(self):
+ super(LauncherShortcutTests, self).setUp()
+ self.launcher_instance.keyboard_reveal_launcher()
+ self.addCleanup(self.launcher_instance.keyboard_unreveal_launcher)
+ sleep(2)
+
+ def test_launcher_keyboard_reveal_shows_shortcut_hints(self):
+ """Launcher icons must show shortcut hints after revealing with keyboard."""
+ self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(True)))
+
+ def test_launcher_switcher_keeps_shorcuts(self):
+ """Initiating launcher switcher after showing shortcuts must not hide shortcuts"""
+ self.launcher_instance.switcher_start()
+ self.addCleanup(self.launcher_instance.switcher_cancel)
+
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
+ self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(True)))
+
+ def test_launcher_switcher_next_keeps_shortcuts(self):
+ """Launcher switcher next action must keep shortcuts after they've been shown."""
+ self.launcher_instance.switcher_start()
+ self.addCleanup(self.launcher_instance.switcher_cancel)
+ self.launcher_instance.switcher_next()
+ self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(True)))
+
+ def test_launcher_switcher_prev_keeps_shortcuts(self):
+ """Launcher switcher prev action must keep shortcuts after they've been shown."""
+ self.launcher_instance.switcher_start()
+ self.addCleanup(self.launcher_instance.switcher_cancel)
+ self.launcher_instance.switcher_prev()
+ self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(True)))
diff --git a/tests/autopilot/unity/tests/launcher/test_switcher.py b/tests/autopilot/unity/tests/launcher/test_switcher.py
new file mode 100644
index 000000000..786826f12
--- /dev/null
+++ b/tests/autopilot/unity/tests/launcher/test_switcher.py
@@ -0,0 +1,168 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Authors: Thomi Richards,
+# Marco Trevisan (Treviño)
+#
+# 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.
+
+from __future__ import absolute_import
+
+from autopilot.matchers import Eventually
+
+import logging
+from testtools.matchers import Equals, NotEquals, GreaterThan
+from time import sleep
+
+from unity.tests.launcher import LauncherTestCase
+
+
+logger = logging.getLogger(__name__)
+
+
+class LauncherSwitcherTests(LauncherTestCase):
+ """ Tests the functionality of the launcher's switcher capability"""
+
+ def start_switcher_with_cleanup_cancel(self):
+ """Start switcher mode safely.
+
+ This adds a cleanup action that cancels keynav mode at the end of the
+ test if it's still running (but does nothing otherwise).
+
+ """
+ self.launcher_instance.switcher_start()
+ self.addCleanup(self.safe_quit_switcher)
+
+ def safe_quit_switcher(self):
+ """Quit the keynav mode if it's engaged."""
+ if self.launcher.key_nav_is_active:
+ self.launcher_instance.switcher_cancel()
+
+ def test_launcher_switcher_cancel(self):
+ """Test that ending the launcher switcher actually works."""
+ self.launcher_instance.switcher_start()
+ self.launcher_instance.switcher_cancel()
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
+
+ def test_launcher_switcher_cancel_resume_focus(self):
+ """Test that ending the launcher switcher resume the focus."""
+ self.close_all_app("Calculator")
+ calc = self.start_app("Calculator")
+ self.assertTrue(calc.is_active)
+
+ self.start_switcher_with_cleanup_cancel()
+ sleep(.5)
+ self.assertFalse(calc.is_active)
+
+ self.launcher_instance.switcher_cancel()
+ sleep(.5)
+ self.assertTrue(calc.is_active)
+
+ def test_launcher_switcher_starts_at_index_zero(self):
+ """Test that starting the Launcher switcher puts the keyboard focus on item 0."""
+ self.start_switcher_with_cleanup_cancel()
+
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
+ self.assertThat(self.launcher.key_nav_is_grabbed, Eventually(Equals(False)))
+ self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
+
+ def test_launcher_switcher_next(self):
+ """Moving to the next launcher item while switcher is activated must work."""
+ self.start_switcher_with_cleanup_cancel()
+ self.launcher_instance.switcher_next()
+ # The launcher model has hidden items, so the keynav indexes do not
+ # increase by 1 each time. This test was failing because the 2nd icon
+ # had an index of 2, not 1 as expected. The best we can do here is to
+ # make sure that the index has increased. This opens us to the
+ # possibility that the launcher really is skipping forward more than one
+ # icon at a time, but we can't do much about that.
+ self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(0)))
+
+ def test_launcher_switcher_prev(self):
+ """Moving to the previous launcher item while switcher is activated must work."""
+ self.start_switcher_with_cleanup_cancel()
+ self.launcher_instance.switcher_prev()
+ self.assertThat(self.launcher.key_nav_selection, Eventually(NotEquals(0)))
+
+ def test_launcher_switcher_down(self):
+ """Pressing the down arrow key while switcher is activated must work."""
+ self.start_switcher_with_cleanup_cancel()
+ self.launcher_instance.switcher_down()
+ # The launcher model has hidden items, so the keynav indexes do not
+ # increase by 1 each time. This test was failing because the 2nd icon
+ # had an index of 2, not 1 as expected. The best we can do here is to
+ # make sure that the index has increased. This opens us to the
+ # possibility that the launcher really is skipping forward more than one
+ # icon at a time, but we can't do much about that.
+ self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(0)))
+
+ def test_launcher_switcher_up(self):
+ """Pressing the up arrow key while switcher is activated must work."""
+ self.start_switcher_with_cleanup_cancel()
+ self.launcher_instance.switcher_up()
+ self.assertThat(self.launcher.key_nav_selection, Eventually(NotEquals(0)))
+
+ def test_launcher_switcher_next_doesnt_show_shortcuts(self):
+ """Moving forward in launcher switcher must not show launcher shortcuts."""
+ self.start_switcher_with_cleanup_cancel()
+ self.launcher_instance.switcher_next()
+ # sleep so that the shortcut timeout could be triggered
+ sleep(2)
+ self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(False)))
+
+ def test_launcher_switcher_prev_doesnt_show_shortcuts(self):
+ """Moving backward in launcher switcher must not show launcher shortcuts."""
+ self.start_switcher_with_cleanup_cancel()
+ self.launcher_instance.switcher_prev()
+ # sleep so that the shortcut timeout could be triggered
+ sleep(2)
+ self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(False)))
+
+ def test_launcher_switcher_cycling_forward(self):
+ """Launcher Switcher must loop through icons when cycling forwards"""
+ self.start_switcher_with_cleanup_cancel()
+ prev_icon = 0
+ num_icons = self.launcher.model.num_launcher_icons()
+ logger.info("This launcher has %d icons", num_icons)
+ for icon in range(1, num_icons):
+ self.launcher_instance.switcher_next()
+ # FIXME We can't directly check for selection/icon number equalty
+ # since the launcher model also contains "hidden" icons that aren't
+ # shown, so the selection index can increment by more than 1.
+ self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(prev_icon)))
+ prev_icon = self.launcher.key_nav_selection
+
+ self.launcher_instance.switcher_next()
+ self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
+
+ def test_launcher_switcher_cycling_backward(self):
+ """Launcher Switcher must loop through icons when cycling backwards"""
+ self.start_switcher_with_cleanup_cancel()
+ self.launcher_instance.switcher_prev()
+ # FIXME We can't directly check for self.launcher.num_launcher_icons - 1
+ self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(1)))
+
+ def test_launcher_switcher_activate_keep_focus(self):
+ """Activating a running launcher icon should focus the application."""
+ calc = self.start_app("Calculator")
+ mahjongg = self.start_app("Mahjongg")
+ self.assertTrue(mahjongg.is_active)
+ self.assertFalse(calc.is_active)
+
+ self.start_switcher_with_cleanup_cancel()
+
+ self.launcher_instance.keyboard_select_icon(tooltip_text=calc.name)
+ self.launcher_instance.switcher_activate()
+
+ self.assertThat(lambda: calc.is_active, Eventually(Equals(True)))
+ self.assertThat(lambda: mahjongg.is_active, Eventually(Equals(False)))
+
+ def test_launcher_switcher_using_shorcuts(self):
+ """Using some other shortcut while switcher is active must cancel switcher."""
+ self.start_switcher_with_cleanup_cancel()
+ self.keyboard.press_and_release("s")
+ sleep(.25)
+ self.keyboard.press_and_release("Escape")
+ sleep(.25)
+ self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
diff --git a/tests/autopilot/unity/tests/launcher/test_visual.py b/tests/autopilot/unity/tests/launcher/test_visual.py
new file mode 100644
index 000000000..6b1fd7805
--- /dev/null
+++ b/tests/autopilot/unity/tests/launcher/test_visual.py
@@ -0,0 +1,76 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Authors: Thomi Richards,
+# Marco Trevisan (Treviño)
+#
+# 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.
+
+from __future__ import absolute_import
+
+from autopilot.matchers import Eventually
+import logging
+from testtools.matchers import Equals
+from time import sleep
+
+from unity.emulators.icons import BFBLauncherIcon
+from unity.tests.launcher import LauncherTestCase
+
+logger = logging.getLogger(__name__)
+
+
+class LauncherVisualTests(LauncherTestCase):
+ """Tests for visual aspects of the launcher (icon saturation etc.)."""
+
+ def test_keynav_from_dash_saturates_icons(self):
+ """Starting super+tab switcher from the dash must resaturate launcher icons.
+
+ Tests fix for bug #913569.
+ """
+ bfb = self.launcher.model.get_bfb_icon()
+ self.mouse.move(bfb.center_x, bfb.center_y)
+ self.dash.ensure_visible()
+ sleep(1)
+ # We can't use 'launcher_instance.switcher_start()' since it moves the mouse.
+ self.keybinding_hold_part_then_tap("launcher/switcher")
+ self.addCleanup(self.keybinding_release, "launcher/switcher")
+ self.addCleanup(self.keybinding, "launcher/switcher/exit")
+
+ self.keybinding_tap("launcher/switcher/next")
+ for icon in self.launcher.model.get_launcher_icons():
+ self.assertThat(icon.desaturated, Eventually(Equals(False)))
+
+ def test_opening_dash_desaturates_icons(self):
+ """Opening the dash must desaturate all the launcher icons."""
+ self.dash.ensure_visible()
+ self.addCleanup(self.dash.ensure_hidden)
+
+ for icon in self.launcher.model.get_launcher_icons():
+ if isinstance(icon, BFBLauncherIcon):
+ self.assertThat(icon.desaturated, Eventually(Equals(False)))
+ else:
+ self.assertThat(icon.desaturated, Eventually(Equals(True)))
+
+ def test_opening_dash_with_mouse_over_launcher_keeps_icon_saturation(self):
+ """Opening dash with mouse over launcher must not desaturate icons."""
+ launcher_instance = self.get_launcher()
+ x,y,w,h = launcher_instance.geometry
+ self.mouse.move(x + w/2, y + h/2)
+ sleep(.5)
+ self.dash.ensure_visible()
+ self.addCleanup(self.dash.ensure_hidden)
+ for icon in self.launcher.model.get_launcher_icons():
+ self.assertThat(icon.desaturated, Eventually(Equals(False)))
+
+ def test_mouse_over_with_dash_open_desaturates_icons(self):
+ """Moving mouse over launcher with dash open must saturate icons."""
+ launcher_instance = self.get_launcher()
+ self.dash.ensure_visible()
+ self.addCleanup(self.dash.ensure_hidden)
+ sleep(.5)
+ x,y,w,h = launcher_instance.geometry
+ self.mouse.move(x + w/2, y + h/2)
+ sleep(.5)
+ for icon in self.launcher.model.get_launcher_icons():
+ self.assertThat(icon.desaturated, Eventually(Equals(False)))
diff --git a/tests/autopilot/unity/tests/test_dash.py b/tests/autopilot/unity/tests/test_dash.py
index b15a9df47..4a1581b24 100644
--- a/tests/autopilot/unity/tests/test_dash.py
+++ b/tests/autopilot/unity/tests/test_dash.py
@@ -70,6 +70,30 @@ class DashRevealTests(DashTestCase):
self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
self.assertThat(self.dash.visible, Eventually(Equals(False)))
+ def test_dash_opens_when_in_spread(self):
+ """This test shows the dash opens when in spread mode."""
+ self.keybinding("spread/start")
+ self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
+
+ self.dash.ensure_visible()
+ self.assertThat(self.dash.visible, Eventually(Equals(True)))
+
+ def test_command_lens_opens_when_in_spread(self):
+ """This test shows the command lens opens when in spread mode."""
+ self.keybinding("spread/start")
+ self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
+
+ self.dash.reveal_command_lens()
+ self.assertThat(self.dash.active_lens, Eventually(Equals('commands.lens')))
+
+ def test_lens_opens_when_in_spread(self):
+ """This test shows that any lens opens when in spread mode."""
+ self.keybinding("spread/start")
+ self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
+
+ self.dash.reveal_application_lens()
+ self.assertThat(self.dash.active_lens, Eventually(Equals('applications.lens')))
+
class DashSearchInputTests(DashTestCase):
"""Test features involving input to the dash search"""
@@ -247,16 +271,6 @@ class DashKeyNavTests(DashTestCase):
category = lens.get_focused_category()
self.assertIsNot(category, None)
- def test_alt_f1_disabled(self):
- """This test that Alt+F1 is disabled when the dash is opened."""
- self.dash.ensure_visible()
- # can't use launcher emulator since we'll fail to start keynav:
- self.keybinding("launcher/keynav")
- # can't use Eventually here - sleep long enough for the launcher controller
- # to react to the keypress (well, hopefully not)
- sleep(5)
- self.assertThat(self.launcher.key_nav_is_active, Equals(False))
-
class DashClipboardTests(DashTestCase):
"""Test the Unity clipboard"""
@@ -514,7 +528,7 @@ class CategoryHeaderTests(DashTestCase):
self.mouse.move(self.dash.view.x + self.dash.view.width / 2,
category.header_y + category.header_height / 2)
- self.mouse.click()
+ self.mouse.click()
self.assertThat(category.is_expanded, Eventually(Equals(not is_expanded)))
self.mouse.click()
diff --git a/tests/autopilot/unity/tests/test_hud.py b/tests/autopilot/unity/tests/test_hud.py
index f4e4fc68c..cc190dd4b 100644
--- a/tests/autopilot/unity/tests/test_hud.py
+++ b/tests/autopilot/unity/tests/test_hud.py
@@ -180,7 +180,9 @@ class HudBehaviorTests(HudTestsBase):
self.hud.ensure_visible()
self.keyboard.type("undo")
- self.assertThat(self.hud.search_string, Eventually(Equals("undo")))
+ hud_query_check = lambda: self.hud.selected_hud_button.label_no_formatting
+ self.assertThat(hud_query_check,
+ Eventually(Equals("Edit > Undo")))
self.keyboard.press_and_release('Return')
self.assertThat(self.hud.visible, Eventually(Equals(False)))
self.keyboard.press_and_release("Ctrl+s")
@@ -244,6 +246,38 @@ class HudBehaviorTests(HudTestsBase):
self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
self.assertThat(self.hud.visible, Eventually(Equals(False)))
+ def test_hud_closes_click_outside_geo_shrunk(self):
+ """
+ Clicking outside the hud when it is shurnk will make it close.
+ Shurnk is when the hud has no results and is much smaller then normal.
+ """
+
+ self.hud.ensure_visible()
+ (x,y,w,h) = self.hud.view.geometry
+ self.mouse.move(w/2, h-50)
+ self.mouse.click()
+
+ self.assertThat(self.hud.visible, Eventually(Equals(False)))
+
+ def test_hud_closes_click_outside_geo(self):
+ """Clicking outside of the hud will make it close."""
+
+ self.hud.ensure_visible()
+ self.keyboard.type("Test")
+
+ (x,y,w,h) = self.hud.view.geometry
+ self.mouse.move(w/2, h+50)
+ self.mouse.click()
+
+ self.assertThat(self.hud.visible, Eventually(Equals(False)))
+
+ def test_alt_f4_close_hud(self):
+ """Hud must close on alt+F4."""
+ self.hud.ensure_visible()
+ self.keyboard.press_and_release("Alt+F4")
+ self.assertThat(self.hud.visible, Eventually(Equals(False)))
+
+
class HudLauncherInteractionsTests(HudTestsBase):
launcher_modes = [('Launcher autohide', {'launcher_autohide': False}),
diff --git a/tests/autopilot/unity/tests/test_launcher.py b/tests/autopilot/unity/tests/test_launcher.py
deleted file mode 100644
index 8232b9dce..000000000
--- a/tests/autopilot/unity/tests/test_launcher.py
+++ /dev/null
@@ -1,851 +0,0 @@
-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
-# Copyright 2012 Canonical
-# Authors: Thomi Richards,
-# Marco Trevisan (Treviño)
-#
-# 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.
-
-from __future__ import absolute_import
-
-from autopilot.emulators.X11 import ScreenGeometry
-from autopilot.matchers import Eventually
-from autopilot.testcase import multiply_scenarios
-import logging
-from testtools.matchers import Equals, NotEquals, LessThan, GreaterThan
-from time import sleep
-
-from unity.emulators.icons import BFBLauncherIcon
-from unity.emulators.launcher import IconDragType
-from unity.tests import UnityTestCase
-
-logger = logging.getLogger(__name__)
-
-def _make_scenarios():
- """Make scenarios for launcher test cases based on the number of configured
- monitors.
- """
- screen_geometry = ScreenGeometry()
- num_monitors = screen_geometry.get_num_monitors()
-
- # it doesn't make sense to set only_primary when we're running in a single-monitor setup.
- if num_monitors == 1:
- return [('Single Monitor', {'launcher_monitor': 0, 'only_primary': False})]
-
- monitor_scenarios = [('Monitor %d' % (i), {'launcher_monitor': i}) for i in range(num_monitors)]
- launcher_mode_scenarios = [('launcher_on_primary', {'only_primary': True}),
- ('launcher on all', {'only_primary': False})]
- return multiply_scenarios(monitor_scenarios, launcher_mode_scenarios)
-
-
-class LauncherTestCase(UnityTestCase):
- """A base class for all launcher tests that uses scenarios to run on
- each launcher (for multi-monitor setups).
- """
- scenarios = _make_scenarios()
-
- def setUp(self):
- super(LauncherTestCase, self).setUp()
- self.screen_geo = ScreenGeometry()
- self.set_unity_log_level("unity.launcher", "DEBUG")
- self.addCleanup(self.set_unity_log_level, "unity.launcher", "INFO")
-
- self.set_unity_option('num_launchers', int(self.only_primary))
- self.launcher_instance = self.get_launcher()
-
- if self.only_primary:
- try:
- old_primary_screen = self.screen_geo.get_primary_monitor()
- self.screen_geo.set_primary_monitor(self.launcher_monitor)
- self.addCleanup(self.screen_geo.set_primary_monitor, old_primary_screen)
- except ScreenGeometry.BlacklistedDriverError:
- self.skipTest("Impossible to set the monitor %d as primary" % self.launcher_monitor)
-
- def get_launcher(self):
- """Get the launcher for the current scenario."""
- return self.launcher.get_launcher_for_monitor(self.launcher_monitor)
-
-
-class LauncherSwitcherTests(LauncherTestCase):
- """ Tests the functionality of the launcher's switcher capability"""
-
- def start_switcher_with_cleanup_cancel(self):
- """Start the launcher switcher and add a cleanup action to cancel it."""
- self.launcher_instance.switcher_start()
- self.addCleanup(self.safe_quit_switcher)
-
- def safe_quit_switcher(self):
- """Quit the keynav mode if it's engaged."""
- if self.launcher.key_nav_is_active:
- self.launcher_instance.switcher_cancel()
-
- def test_launcher_switcher_cancel(self):
- """Test that ending the launcher switcher actually works."""
- self.launcher_instance.switcher_start()
- self.launcher_instance.switcher_cancel()
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
-
- def test_launcher_switcher_cancel_resume_focus(self):
- """Test that ending the launcher switcher resume the focus."""
- # TODO either remove this test from the class or don't initiate the
- # switcher in setup.
- self.close_all_app("Calculator")
- calc = self.start_app("Calculator")
- self.assertTrue(calc.is_active)
-
- self.start_switcher_with_cleanup_cancel()
- sleep(.5)
- self.assertFalse(calc.is_active)
-
- self.launcher_instance.switcher_cancel()
- sleep(.5)
- self.assertTrue(calc.is_active)
-
- def test_launcher_switcher_starts_at_index_zero(self):
- """Test that starting the Launcher switcher puts the keyboard focus on item 0."""
- self.start_switcher_with_cleanup_cancel()
-
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
- self.assertThat(self.launcher.key_nav_is_grabbed, Eventually(Equals(False)))
- self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
-
- def test_launcher_switcher_next(self):
- """Moving to the next launcher item while switcher is activated must work."""
- self.start_switcher_with_cleanup_cancel()
- self.launcher_instance.switcher_next()
- # The launcher model has hidden items, so the keynav indexes do not
- # increase by 1 each time. This test was failing because the 2nd icon
- # had an index of 2, not 1 as expected. The best we can do here is to
- # make sure that the index has increased. This opens us to the
- # possibility that the launcher really is skipping forward more than one
- # icon at a time, but we can't do much about that.
- self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(0)))
-
- def test_launcher_switcher_prev(self):
- """Moving to the previous launcher item while switcher is activated must work."""
- self.start_switcher_with_cleanup_cancel()
- self.launcher_instance.switcher_prev()
- self.assertThat(self.launcher.key_nav_selection, Eventually(NotEquals(0)))
-
- def test_launcher_switcher_down(self):
- """Pressing the down arrow key while switcher is activated must work."""
- self.start_switcher_with_cleanup_cancel()
- self.launcher_instance.switcher_down()
- # The launcher model has hidden items, so the keynav indexes do not
- # increase by 1 each time. This test was failing because the 2nd icon
- # had an index of 2, not 1 as expected. The best we can do here is to
- # make sure that the index has increased. This opens us to the
- # possibility that the launcher really is skipping forward more than one
- # icon at a time, but we can't do much about that.
- self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(0)))
-
- def test_launcher_switcher_up(self):
- """Pressing the up arrow key while switcher is activated must work."""
- self.start_switcher_with_cleanup_cancel()
- self.launcher_instance.switcher_up()
- self.assertThat(self.launcher.key_nav_selection, Eventually(NotEquals(0)))
-
- def test_launcher_switcher_next_doesnt_show_shortcuts(self):
- """Moving forward in launcher switcher must not show launcher shortcuts."""
- self.start_switcher_with_cleanup_cancel()
- self.launcher_instance.switcher_next()
- # sleep so that the shortcut timeout could be triggered
- sleep(2)
- self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(False)))
-
- def test_launcher_switcher_prev_doesnt_show_shortcuts(self):
- """Moving backward in launcher switcher must not show launcher shortcuts."""
- self.start_switcher_with_cleanup_cancel()
- self.launcher_instance.switcher_prev()
- # sleep so that the shortcut timeout could be triggered
- sleep(2)
- self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(False)))
-
- def test_launcher_switcher_cycling_forward(self):
- """Launcher Switcher must loop through icons when cycling forwards"""
- self.start_switcher_with_cleanup_cancel()
- prev_icon = 0
- num_icons = self.launcher.model.num_launcher_icons()
- logger.info("This launcher has %d icons", num_icons)
- for icon in range(1, num_icons):
- self.launcher_instance.switcher_next()
- # FIXME We can't directly check for selection/icon number equalty
- # since the launcher model also contains "hidden" icons that aren't
- # shown, so the selection index can increment by more than 1.
- self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(prev_icon)))
- prev_icon = self.launcher.key_nav_selection
-
- self.launcher_instance.switcher_next()
- self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
-
- def test_launcher_switcher_cycling_backward(self):
- """Launcher Switcher must loop through icons when cycling backwards"""
- self.start_switcher_with_cleanup_cancel()
- self.launcher_instance.switcher_prev()
- # FIXME We can't directly check for self.launcher.num_launcher_icons - 1
- self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(1)))
-
- def test_launcher_switcher_activate_keep_focus(self):
- """Activating a running launcher icon should focus the application."""
- calc = self.start_app("Calculator")
- mahjongg = self.start_app("Mahjongg")
- self.assertTrue(mahjongg.is_active)
- self.assertFalse(calc.is_active)
-
- self.start_switcher_with_cleanup_cancel()
-
- found = False
- for icon in self.launcher.model.get_launcher_icons_for_monitor(self.launcher_monitor):
- if (icon.tooltip_text == calc.name):
- found = True
- self.launcher_instance.switcher_activate()
- break
- else:
- self.launcher_instance.switcher_next()
-
- if not found:
- self.addCleanup(self.launcher_instance.switcher_cancel)
-
- self.assertTrue(found)
- # TODO - we need to extend the Eventually() matcher to work on regular
- # attributes too, at which point we can stop writing ugly stuff in our
- # tests like this:
- for i in range(10):
- if calc.is_active and not mahjongg.is_active:
- break
- sleep(1)
-
- self.assertTrue(calc.is_active)
- self.assertFalse(mahjongg.is_active)
-
- def test_launcher_switcher_using_shorcuts(self):
- """Using some other shortcut while switcher is active must cancel switcher."""
- self.start_switcher_with_cleanup_cancel()
- self.keyboard.press_and_release("s")
- sleep(.25)
- self.keyboard.press_and_release("Escape")
- sleep(.25)
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
-
-
-class LauncherShortcutTests(LauncherTestCase):
- """Tests for the shortcut hint window."""
-
- def setUp(self):
- super(LauncherShortcutTests, self).setUp()
- self.launcher_instance.keyboard_reveal_launcher()
- self.addCleanup(self.launcher_instance.keyboard_unreveal_launcher)
- sleep(2)
-
- def test_launcher_keyboard_reveal_shows_shortcut_hints(self):
- """Launcher icons must show shortcut hints after revealing with keyboard."""
- self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(True)))
-
- def test_launcher_switcher_keeps_shorcuts(self):
- """Initiating launcher switcher after showing shortcuts must not hide shortcuts"""
- self.launcher_instance.switcher_start()
- self.addCleanup(self.launcher_instance.switcher_cancel)
-
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
- self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(True)))
-
- def test_launcher_switcher_next_keeps_shortcuts(self):
- """Launcher switcher next action must keep shortcuts after they've been shown."""
- self.launcher_instance.switcher_start()
- self.addCleanup(self.launcher_instance.switcher_cancel)
- self.launcher_instance.switcher_next()
- self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(True)))
-
- def test_launcher_switcher_prev_keeps_shortcuts(self):
- """Launcher switcher prev action must keep shortcuts after they've been shown."""
- self.launcher_instance.switcher_start()
- self.addCleanup(self.launcher_instance.switcher_cancel)
- self.launcher_instance.switcher_prev()
- self.assertThat(self.launcher_instance.shortcuts_shown, Eventually(Equals(True)))
-
-
-class LauncherKeyNavTests(LauncherTestCase):
- """Test the launcher key navigation"""
-
- def start_keynav_with_cleanup_cancel(self):
- self.launcher_instance.key_nav_start()
- self.addCleanup(self.safe_quit_keynav)
-
- def safe_quit_keynav(self):
- """Quit the keynav mode if it's engaged."""
- if self.launcher.key_nav_is_active:
- self.launcher_instance.key_nav_cancel()
-
- def test_launcher_keynav_initiate(self):
- """Tests we can initiate keyboard navigation on the launcher."""
- self.start_keynav_with_cleanup_cancel()
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
- self.assertThat(self.launcher.key_nav_is_grabbed, Eventually(Equals(True)))
-
- def test_launcher_keynav_cancel(self):
- """Test that we can exit keynav mode."""
- self.launcher_instance.key_nav_start()
- self.launcher_instance.key_nav_cancel()
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
- self.assertThat(self.launcher.key_nav_is_grabbed, Eventually(Equals(False)))
-
- def test_launcher_keynav_cancel_resume_focus(self):
- """Test that ending the launcher keynav resume the focus."""
- calc = self.start_app("Calculator")
- self.assertTrue(calc.is_active)
-
- self.start_keynav_with_cleanup_cancel()
- self.assertFalse(calc.is_active)
-
- self.launcher_instance.key_nav_cancel()
- self.assertTrue(calc.is_active)
-
- def test_launcher_keynav_starts_at_index_zero(self):
- """Test keynav mode starts at index 0."""
- self.start_keynav_with_cleanup_cancel()
- self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
-
- def test_launcher_keynav_forward(self):
- """Must be able to move forwards while in keynav mode."""
- self.start_keynav_with_cleanup_cancel()
- self.launcher_instance.key_nav_next()
- # The launcher model has hidden items, so the keynav indexes do not
- # increase by 1 each time. This test was failing because the 2nd icon
- # had an index of 2, not 1 as expected. The best we can do here is to
- # make sure that the index has increased. This opens us to the
- # possibility that the launcher really is skipping forward more than one
- # icon at a time, but we can't do much about that.
- self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(0)))
-
- def test_launcher_keynav_prev_works(self):
- """Must be able to move backwards while in keynav mode."""
- self.start_keynav_with_cleanup_cancel()
- self.launcher_instance.key_nav_next()
- self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(0)))
- self.launcher_instance.key_nav_prev()
- self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
-
- def test_launcher_keynav_cycling_forward(self):
- """Launcher keynav must loop through icons when cycling forwards"""
- self.start_keynav_with_cleanup_cancel()
- prev_icon = 0
- for icon in range(1, self.launcher.model.num_launcher_icons()):
- self.launcher_instance.key_nav_next()
- # FIXME We can't directly check for selection/icon number equalty
- # since the launcher model also contains "hidden" icons that aren't
- # shown, so the selection index can increment by more than 1.
- self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(prev_icon)))
- prev_icon = self.launcher.key_nav_selection
-
- self.launcher_instance.key_nav_next()
- self.assertThat(self.launcher.key_nav_selection, Eventually(Equals(0)))
-
- def test_launcher_keynav_cycling_backward(self):
- """Launcher keynav must loop through icons when cycling backwards"""
- self.start_keynav_with_cleanup_cancel()
- self.launcher_instance.key_nav_prev()
- # FIXME We can't directly check for self.launcher.num_launcher_icons - 1
- self.assertThat(self.launcher.key_nav_selection, Eventually(GreaterThan(1)))
-
- def test_launcher_keynav_can_open_and_close_quicklist(self):
- """Tests that we can open and close a quicklist from keynav mode."""
- self.start_keynav_with_cleanup_cancel()
- self.launcher_instance.key_nav_next()
- self.launcher_instance.key_nav_enter_quicklist()
- self.assertThat(self.launcher_instance.quicklist_open, Eventually(Equals(True)))
- self.launcher_instance.key_nav_exit_quicklist()
- self.assertThat(self.launcher_instance.quicklist_open, Eventually(Equals(False)))
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
- self.assertThat(self.launcher.key_nav_is_grabbed, Eventually(Equals(True)))
-
- def test_launcher_keynav_mode_toggles(self):
- """Tests that keynav mode toggles with Alt+F1."""
- # was initiated in setup.
- self.start_keynav_with_cleanup_cancel()
- self.keybinding("launcher/keynav")
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
-
- def test_launcher_keynav_activate_keep_focus(self):
- """Activating a running launcher icon must focus it."""
- calc = self.start_app("Calculator")
- mahjongg = self.start_app("Mahjongg")
- self.assertTrue(mahjongg.is_active)
- self.assertFalse(calc.is_active)
-
- self.start_keynav_with_cleanup_cancel()
-
- found = False
- for icon in self.launcher.model.get_launcher_icons_for_monitor(self.launcher_monitor):
- if (icon.tooltip_text == calc.name):
- found = True
- self.launcher_instance.key_nav_activate()
- break
- else:
- self.launcher_instance.key_nav_next()
-
- sleep(.5)
-
- self.assertTrue(found)
- self.assertTrue(calc.is_active)
- self.assertFalse(mahjongg.is_active)
-
- def test_launcher_keynav_expo_focus(self):
- """When entering expo mode from KeyNav the Desktop must get focus."""
- self.start_keynav_with_cleanup_cancel()
-
- for icon in self.launcher.model.get_launcher_icons_for_monitor(self.launcher_monitor):
- if (icon.tooltip_text == "Workspace Switcher"):
- self.launcher_instance.key_nav_activate()
- break
- self.launcher_instance.key_nav_next()
-
- self.assertThat(self.panels.get_active_panel().title, Eventually(Equals("Ubuntu Desktop")))
-
- def test_launcher_keynav_expo_exit_on_esc(self):
- """Esc should quit expo when entering it from KeyNav."""
- self.start_keynav_with_cleanup_cancel()
-
- for icon in self.launcher.model.get_launcher_icons_for_monitor(self.launcher_monitor):
- if (icon.tooltip_text == "Workspace Switcher"):
- self.launcher_instance.key_nav_activate()
- break
- self.launcher_instance.key_nav_next()
-
- self.keyboard.press_and_release("Escape")
- self.assertThat(self.window_manager.expo_active, Eventually(Equals(False)))
-
- def test_launcher_keynav_alt_tab_quits(self):
- """Tests that alt+tab exits keynav mode."""
- self.start_keynav_with_cleanup_cancel()
-
- self.keybinding("switcher/reveal_normal")
- self.addCleanup(self.switcher.terminate)
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
-
- def test_launcher_keynav_alt_grave_quits(self):
- """Tests that alt+` exits keynav mode."""
- self.start_keynav_with_cleanup_cancel()
- # Can't use switcher emulat here since the switcher won't appear.
- self.keybinding("switcher/reveal_details")
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
-
- def test_launcher_keynav_cancel_doesnt_activate_icon(self):
- """This tests when canceling keynav the current icon doesnt activate."""
- self.start_keynav_with_cleanup_cancel()
- self.keyboard.press_and_release("Escape")
- self.assertThat(self.dash.visible, Eventually(Equals(False)))
-
-class LauncherIconsBehaviorTests(LauncherTestCase):
- """Test the launcher icons interactions"""
-
- def test_launcher_activate_last_focused_window(self):
- """This tests shows that when you activate a launcher icon only the last
- focused instance of that application is rasied.
-
- This is tested by opening 2 Mahjongg and a Calculator.
- Then we activate the Calculator launcher icon.
- Then we actiavte the Mahjongg launcher icon.
- Then we minimize the focused applications.
- This should give focus to the next window on the stack.
- Then we activate the Mahjongg launcher icon
- This should bring to focus the non-minimized window.
- If only 1 instance is raised then the Calculator gets the focus.
- If ALL the instances are raised then the second Mahjongg gets the focus.
-
- """
- mahj = self.start_app("Mahjongg")
- [mah_win1] = mahj.get_windows()
- self.assertTrue(mah_win1.is_focused)
-
- calc = self.start_app("Calculator")
- [calc_win] = calc.get_windows()
- self.assertTrue(calc_win.is_focused)
-
- self.start_app("Mahjongg")
- # Sleeping due to the start_app only waiting for the bamf model to be
- # updated with the application. Since the app has already started,
- # and we are just waiting on a second window, however a defined sleep
- # here is likely to be problematic.
- # TODO: fix bamf emulator to enable waiting for new windows.
- sleep(1)
- [mah_win2] = [w for w in mahj.get_windows() if w.x_id != mah_win1.x_id]
- self.assertTrue(mah_win2.is_focused)
- self.assertVisibleWindowStack([mah_win2, calc_win, mah_win1])
-
- mahj_icon = self.launcher.model.get_icon_by_desktop_id(mahj.desktop_file)
- calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file)
-
- self.launcher_instance.click_launcher_icon(calc_icon)
- sleep(1)
- self.assertTrue(calc_win.is_focused)
- self.assertVisibleWindowStack([calc_win, mah_win2, mah_win1])
-
- self.launcher_instance.click_launcher_icon(mahj_icon)
- sleep(1)
- self.assertTrue(mah_win2.is_focused)
- self.assertVisibleWindowStack([mah_win2, calc_win, mah_win1])
-
- self.keybinding("window/minimize")
- sleep(1)
-
- self.assertTrue(mah_win2.is_hidden)
- self.assertTrue(calc_win.is_focused)
- self.assertVisibleWindowStack([calc_win, mah_win1])
-
- self.launcher_instance.click_launcher_icon(mahj_icon)
- sleep(1)
- self.assertTrue(mah_win1.is_focused)
- self.assertTrue(mah_win2.is_hidden)
- self.assertVisibleWindowStack([mah_win1, calc_win])
-
- def test_icon_shows_on_quick_application_reopen(self):
- """Icons should stay on launcher when an application is quickly closed/reopened."""
- calc = self.start_app("Calculator")
- desktop_file = calc.desktop_file
- calc_icon = self.launcher.model.get_icon_by_desktop_id(desktop_file)
- self.assertThat(calc_icon.visible, Eventually(Equals(True)))
-
- self.close_all_app("Calculator")
- calc = self.start_app("Calculator")
- sleep(2)
-
- calc_icon = self.launcher.model.get_icon_by_desktop_id(desktop_file)
- self.assertThat(calc_icon, NotEquals(None))
- self.assertThat(calc_icon.visible, Eventually(Equals(True)))
-
-
-class LauncherDragIconsBehavior(LauncherTestCase):
- """Tests interation with dragging icons with the Launcher"""
-
- scenarios = multiply_scenarios(_make_scenarios(),
- [
- ('inside', {'drag_type': IconDragType.INSIDE}),
- ('outside', {'drag_type': IconDragType.OUTSIDE}),
- ])
-
- def ensure_calc_icon_not_in_launcher(self):
- while 1:
- icon = self.launcher.model.get_icon_by_desktop_id("gcalctool.desktop")
- if not icon:
- break
- sleep(1)
-
- def test_can_drag_icon_below_bfb(self):
- """Application icons must be draggable to below the BFB."""
-
- self.ensure_calc_icon_not_in_launcher()
- calc = self.start_app("Calculator")
- calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file)
-
- bfb_icon_position = 0
- self.launcher_instance.drag_icon_to_position(calc_icon,
- bfb_icon_position,
- self.drag_type)
- moved_icon = self.launcher.model.\
- get_launcher_icons_for_monitor(self.launcher_monitor)[1]
- self.assertThat(moved_icon.id, Equals(calc_icon.id))
-
- def test_can_drag_icon_above_window_switcher(self):
- """Launcher icons must be dragable to above the workspace switcher icon."""
-
- self.ensure_calc_icon_not_in_launcher()
- calc = self.start_app("Calculator")
- calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file)
-
- # Move a known icon to the top as it needs to be more than 2 icon
- # spaces away for this test to actually do anything
- bfb_icon_position = 0
- self.launcher_instance.drag_icon_to_position(calc_icon,
- bfb_icon_position,
- self.drag_type)
- sleep(1)
- switcher_pos = -2
- self.launcher_instance.drag_icon_to_position(calc_icon,
- switcher_pos,
- self.drag_type)
-
- moved_icon = self.launcher.model.\
- get_launcher_icons_for_monitor(self.launcher_monitor)[-3]
- self.assertThat(moved_icon.id, Equals(calc_icon.id))
-
-
-class LauncherRevealTests(LauncherTestCase):
- """Test the launcher reveal behavior when in autohide mode."""
-
- def setUp(self):
- super(LauncherRevealTests, self).setUp()
- # these automatically reset to the original value, as implemented in AutopilotTestCase
- self.set_unity_option('launcher_capture_mouse', True)
- self.set_unity_option('launcher_hide_mode', 1)
- launcher = self.get_launcher()
- self.assertThat(launcher.hidemode, Eventually(Equals(1)))
-
- def test_launcher_keyboard_reveal_works(self):
- """Revealing launcher with keyboard must work."""
- self.launcher_instance.keyboard_reveal_launcher()
- self.addCleanup(self.launcher_instance.keyboard_unreveal_launcher)
- self.assertThat(self.launcher_instance.is_showing, Eventually(Equals(True)))
-
- def test_reveal_on_mouse_to_edge(self):
- """Tests reveal of launchers by mouse pressure."""
- self.launcher_instance.move_mouse_to_right_of_launcher()
- self.launcher_instance.mouse_reveal_launcher()
- self.assertThat(self.launcher_instance.is_showing, Eventually(Equals(True)))
-
- def test_reveal_with_mouse_under_launcher(self):
- """Tests that the launcher hides properly if the
- mouse is under the launcher when it is revealed.
- """
- self.launcher_instance.move_mouse_over_launcher()
- # we can't use "launcher_instance.keyboard_reveal_launcher()"
- # since it moves the mouse out of the way, invalidating the test.
- self.keybinding_hold("launcher/reveal")
- sleep(1)
- self.keybinding_release("launcher/reveal")
- self.assertThat(self.launcher_instance.is_showing, Eventually(Equals(False)))
-
- def test_reveal_does_not_hide_again(self):
- """Tests reveal of launchers by mouse pressure to ensure it doesn't
- automatically hide again.
- """
- self.launcher_instance.move_mouse_to_right_of_launcher()
- self.launcher_instance.mouse_reveal_launcher()
- self.assertThat(self.launcher_instance.is_showing, Eventually(Equals(True)))
-
- def test_launcher_does_not_reveal_with_mouse_down(self):
- """Launcher must not reveal if have mouse button 1 down."""
- self.screen_geo.move_mouse_to_monitor(self.launcher_instance.monitor)
- self.mouse.press(1)
- self.addCleanup(self.mouse.release, 1)
- #FIXME: This is really bad API. it says reveal but it's expected to fail. bad bad bad!!
- self.launcher_instance.mouse_reveal_launcher()
- # Need a sleep here otherwise this test would pass even if the code failed.
- # THis test needs to be rewritten...
- sleep(5)
- self.assertThat(self.launcher_instance.is_showing, Equals(False))
-
- def test_new_icon_has_the_shortcut(self):
- """New icons should have an associated shortcut"""
- if self.launcher.model.num_bamf_launcher_icons() >= 10:
- self.skip("There are already more than 9 icons in the launcher")
-
- desktop_file = self.KNOWN_APPS['Calculator']['desktop-file']
- if self.launcher.model.get_icon_by_desktop_id(desktop_file) != None:
- self.skip("Calculator icon is already on the launcher.")
-
- self.start_app('Calculator')
- icon = self.launcher.model.get_icon_by_desktop_id(desktop_file)
- self.assertThat(icon.shortcut, GreaterThan(0))
-
-
-class LauncherVisualTests(LauncherTestCase):
- """Tests for visual aspects of the launcher (icon saturation etc.)."""
-
- def test_keynav_from_dash_saturates_icons(self):
- """Starting super+tab switcher from the dash must resaturate launcher icons.
-
- Tests fix for bug #913569.
- """
- bfb = self.launcher.model.get_bfb_icon()
- self.mouse.move(bfb.center_x, bfb.center_y)
- self.dash.ensure_visible()
- sleep(1)
- # We can't use 'launcher_instance.switcher_start()' since it moves the mouse.
- self.keybinding_hold_part_then_tap("launcher/switcher")
- self.addCleanup(self.keybinding_release, "launcher/switcher")
- self.addCleanup(self.keybinding, "launcher/switcher/exit")
-
- self.keybinding_tap("launcher/switcher/next")
- for icon in self.launcher.model.get_launcher_icons():
- self.assertThat(icon.desaturated, Eventually(Equals(False)))
-
- def test_opening_dash_desaturates_icons(self):
- """Opening the dash must desaturate all the launcher icons."""
- self.dash.ensure_visible()
- self.addCleanup(self.dash.ensure_hidden)
-
- for icon in self.launcher.model.get_launcher_icons():
- if isinstance(icon, BFBLauncherIcon):
- self.assertThat(icon.desaturated, Eventually(Equals(False)))
- else:
- self.assertThat(icon.desaturated, Eventually(Equals(True)))
-
- def test_opening_dash_with_mouse_over_launcher_keeps_icon_saturation(self):
- """Opening dash with mouse over launcher must not desaturate icons."""
- launcher_instance = self.get_launcher()
- x,y,w,h = launcher_instance.geometry
- self.mouse.move(x + w/2, y + h/2)
- sleep(.5)
- self.dash.ensure_visible()
- self.addCleanup(self.dash.ensure_hidden)
- for icon in self.launcher.model.get_launcher_icons():
- self.assertThat(icon.desaturated, Eventually(Equals(False)))
-
- def test_mouse_over_with_dash_open_desaturates_icons(self):
- """Moving mouse over launcher with dash open must saturate icons."""
- launcher_instance = self.get_launcher()
- self.dash.ensure_visible()
- self.addCleanup(self.dash.ensure_hidden)
- sleep(.5)
- x,y,w,h = launcher_instance.geometry
- self.mouse.move(x + w/2, y + h/2)
- sleep(.5)
- for icon in self.launcher.model.get_launcher_icons():
- self.assertThat(icon.desaturated, Eventually(Equals(False)))
-
-
-class LauncherCaptureTests(UnityTestCase):
- """Test the launchers ability to capture/not capture the mouse."""
-
- screen_geo = ScreenGeometry()
-
- def setHideMode(self, mode):
- launcher = self.launcher.get_launcher_for_monitor(0)
- self.assertThat(launcher.hidemode, Eventually(Equals(mode)))
-
- def leftMostMonitor(self):
- x1, y1, width, height = self.screen_geo.get_monitor_geometry(0)
- x2, y2, width, height = self.screen_geo.get_monitor_geometry(1)
-
- if x1 < x2:
- return 0
- return 1
-
- def rightMostMonitor(self):
- return 1 - self.leftMostMonitor()
-
- def setUp(self):
- super(LauncherCaptureTests, self).setUp()
- self.set_unity_option('launcher_capture_mouse', True)
- self.set_unity_option('launcher_hide_mode', 0)
- self.set_unity_option('num_launchers', 0)
- self.setHideMode(0)
-
- def test_launcher_captures_while_sticky_and_revealed(self):
- """Tests that the launcher captures the mouse when moving between monitors
- while revealed.
- """
- if self.screen_geo.get_num_monitors() <= 1:
- self.skipTest("Cannot run this test with a single monitor configured.")
-
- x, y, width, height = self.screen_geo.get_monitor_geometry(self.rightMostMonitor())
- self.mouse.move(x + width / 2, y + height / 2, False)
- self.mouse.move(x - width / 2, y + height / 2, True, 5, .002)
-
- x_fin, y_fin = self.mouse.position()
- # The launcher should have held the mouse a little bit
- self.assertThat(x_fin, GreaterThan(x - width / 2))
-
- def test_launcher_not_capture_while_not_sticky_and_revealed(self):
- """Tests that the launcher doesn't captures the mouse when moving between monitors
- while revealed and stick is off.
- """
- if self.screen_geo.get_num_monitors() <= 1:
- self.skipTest("Cannot run this test with a single monitor configured.")
-
- self.set_unity_option('launcher_capture_mouse', False)
-
- x, y, width, height = self.screen_geo.get_monitor_geometry(self.rightMostMonitor())
- self.mouse.move(x + width / 2, y + height / 2, False)
- self.mouse.move(x - width / 2, y + height / 2, True, 5, .002)
-
- x_fin, y_fin = self.mouse.position()
- # The launcher should have held the mouse a little bit
- self.assertThat(x_fin, Equals(x - width / 2))
-
- def test_launcher_not_capture_while_not_sticky_and_hidden_moving_right(self):
- """Tests that the launcher doesn't capture the mouse when moving between monitors
- while hidden and sticky is off.
- """
- if self.screen_geo.get_num_monitors() <= 1:
- self.skipTest("Cannot run this test with a single monitor configured.")
-
- self.set_unity_option('launcher_hide_mode', 1)
- self.set_unity_option('launcher_capture_mouse', False)
-
- self.setHideMode(1)
-
- x, y, width, height = self.screen_geo.get_monitor_geometry(self.leftMostMonitor())
- self.mouse.move(x + width / 2, y + height / 2, False)
- sleep(1.5)
- self.mouse.move(x + width * 1.5, y + height / 2, True, 5, .002)
-
- x_fin, y_fin = self.mouse.position()
- # The launcher should have held the mouse a little bit
- self.assertThat(x_fin, Equals(x + width * 1.5))
-
- def test_launcher_capture_while_sticky_and_hidden_moving_right(self):
- """Tests that the launcher captures the mouse when moving between monitors
- while hidden.
- """
- if self.screen_geo.get_num_monitors() <= 1:
- self.skipTest("Cannot run this test with a single monitor configured.")
-
- self.set_unity_option('launcher_hide_mode', 1)
-
- self.setHideMode(1)
-
- x, y, width, height = self.screen_geo.get_monitor_geometry(self.leftMostMonitor())
- self.mouse.move(x + width / 2, y + height / 2, False)
- sleep(1.5)
- self.mouse.move(x + width * 1.5, y + height / 2, True, 5, .002)
-
- x_fin, y_fin = self.mouse.position()
- # The launcher should have held the mouse a little bit
- self.assertThat(x_fin, LessThan(x + width * 1.5))
-
-
-class LauncherTooltipTests(UnityTestCase):
- """Test the launcher tooltips"""
-
- def setUp(self):
- super(LauncherTooltipTests, self).setUp()
- self.set_unity_option('launcher_hide_mode', 0)
-
- def test_bfb_tooltip_disappear_when_dash_is_opened(self):
- """Tests that the bfb tooltip disappear when the dash is opened."""
- bfb = self.launcher.model.get_bfb_icon()
- self.mouse.move(bfb.center_x, bfb.center_y)
-
- self.dash.ensure_visible()
- self.addCleanup(self.dash.ensure_hidden)
-
- self.assertThat(bfb.get_tooltip().active, Eventually(Equals(False)))
-
- def test_bfb_tooltip_is_disabled_when_dash_is_open(self):
- """Tests the that bfb tooltip is disabled when the dash is open."""
- self.dash.ensure_visible()
- self.addCleanup(self.dash.ensure_hidden)
-
- bfb = self.launcher.model.get_bfb_icon()
- self.mouse.move(bfb.center_x, bfb.center_y)
-
- self.assertThat(bfb.get_tooltip().active, Eventually(Equals(False)))
-
-
-class LauncherIconTests(UnityTestCase):
- """Tests for the launcher icons."""
-
- def assertNumberWinsIsEventually(self, app, num):
- """Asserts that 'app' eventually has 'num' wins. Waits up to 10 seconds."""
- for i in range(10):
- wins = app.get_windows()
- if len(wins) == num:
- return
- sleep(1)
-
- self.assertThat(len(app.get_windows()), Equals(num))
-
- def test_shift_click_opens_new_application_instance(self):
- """Shift+Clicking MUST open a new instance of an already-running application."""
- app = self.start_app("Calculator")
- desktop_id = app.desktop_file
- icon = self.launcher.model.get_icon_by_desktop_id(desktop_id)
- launcher_instance = self.launcher.get_launcher_for_monitor(0)
-
- self.keyboard.press("Shift")
- self.addCleanup(self.keyboard.release, "Shift")
- launcher_instance.click_launcher_icon(icon)
-
- self.assertNumberWinsIsEventually(app, 2)
diff --git a/tests/autopilot/unity/tests/test_panel.py b/tests/autopilot/unity/tests/test_panel.py
index bdcadde94..68a9f13ee 100644
--- a/tests/autopilot/unity/tests/test_panel.py
+++ b/tests/autopilot/unity/tests/test_panel.py
@@ -10,6 +10,7 @@ from __future__ import absolute_import
from autopilot.emulators.X11 import ScreenGeometry
from autopilot.emulators.bamf import BamfWindow
+from autopilot.matchers import Eventually
import logging
import os
from testtools.matchers import Equals, GreaterThan, NotEquals
@@ -360,10 +361,6 @@ class PanelWindowButtonsTests(PanelTestsBase):
self.assertTrue(text_win.is_hidden)
- icon = self.launcher.model.get_icon_by_desktop_id(text_win.application.desktop_file)
- launcher = self.launcher.get_launcher_for_monitor(self.panel_monitor)
- launcher.click_launcher_icon(icon)
-
def test_window_buttons_minimize_follows_fitts_law(self):
"""Tests that the 'Minimize' button is conform to Fitts's Law.
@@ -482,14 +479,13 @@ class PanelWindowButtonsTests(PanelTestsBase):
"""Tests that the 'Minimize' button is disabled for the dash."""
self.dash.ensure_visible()
self.addCleanup(self.dash.ensure_hidden)
- sleep(.5)
button = self.panel.window_buttons.minimize
button.mouse_click()
sleep(.5)
- self.assertFalse(button.enabled)
- self.assertTrue(self.dash.visible)
+ self.assertThat(button.enabled, Eventually(Equals(False)))
+ self.assertThat(self.dash.visible, Eventually(Equals(True)))
def test_window_buttons_maximization_buttons_works_for_dash(self):
"""'Maximize' and 'Restore' buttons (when both enabled) must work as expected."""
@@ -715,9 +711,8 @@ class PanelMenuTests(PanelTestsBase):
# TODO: This doesn't test what it says on the tin. Setting MENUPROXY to ''
# just makes the menu appear inside the app. That's fine, but it's not
# what is described in the docstring or test id.
- old_env = os.environ["UBUNTU_MENUPROXY"]
- os.putenv("UBUNTU_MENUPROXY", "")
- self.addCleanup(os.putenv, "UBUNTU_MENUPROXY", old_env)
+ self.patch_environment("UBUNTU_MENUPROXY", "")
+
calc_win = self.open_new_application_window("Calculator")
sleep(1)
diff --git a/tests/autopilot/unity/tests/test_quicklist.py b/tests/autopilot/unity/tests/test_quicklist.py
index bdaec248d..f3a0d49b7 100644
--- a/tests/autopilot/unity/tests/test_quicklist.py
+++ b/tests/autopilot/unity/tests/test_quicklist.py
@@ -140,6 +140,22 @@ class QuicklistActionTests(UnityTestCase):
self.assertThat(self.window_manager.scale_active, Eventually(Equals(True)))
self.assertThat(self.window_manager.scale_active_for_group, Eventually(Equals(True)))
+ def test_quicklist_item_triggered_closes_dash(self):
+ """When any quicklist item is triggered it must close the dash."""
+
+ calc = self.start_app("Calculator")
+ [calc_win] = calc.get_windows()
+ self.assertTrue(calc_win.is_focused)
+
+ self.dash.ensure_visible()
+
+ calc_icon = self.launcher.model.get_icon_by_desktop_id(calc.desktop_file)
+ calc_ql = self.open_quicklist_for_icon(calc_icon)
+
+ self.keyboard.press_and_release("Down")
+ self.keyboard.press_and_release("Enter")
+ self.assertThat(self.dash.visible, Eventually(Equals(False)))
+
class QuicklistKeyNavigationTests(UnityTestCase):
"""Tests for the quicklist key navigation."""
@@ -169,17 +185,13 @@ class QuicklistKeyNavigationTests(UnityTestCase):
self.ql_launcher.key_nav_start()
self.addCleanup(self.ql_launcher.key_nav_cancel)
- for icon in self.launcher.model.get_launcher_icons():
- if icon.tooltip_text != self.ql_app.name:
- self.ql_launcher.key_nav_next()
- else:
- self.keybinding("launcher/keynav/open-quicklist")
- self.addCleanup(self.keybinding, "launcher/keynav/close-quicklist")
- break
+ self.ql_launcher.keyboard_select_icon(tooltip_text=self.ql_app.name)
+ self.keybinding("launcher/keynav/open-quicklist")
+ self.addCleanup(self.keybinding, "launcher/keynav/close-quicklist")
+ self.assertThat(self.ql_launcher_icon.get_quicklist, Eventually(NotEquals(None)))
self.quicklist = self.ql_launcher_icon.get_quicklist()
- self.assertThat(self.quicklist, NotEquals(None))
- self.assertThat(self.quicklist.selected_item, NotEquals(None))
+ self.assertThat(lambda: self.quicklist.selected_item, Eventually(NotEquals(None)))
def test_keynav_selects_first_item_when_unselected(self):
"""Home key MUST select the first selectable item in a quicklist."""
diff --git a/tests/autopilot/unity/tests/test_shortcut_hint.py b/tests/autopilot/unity/tests/test_shortcut_hint.py
index ad3acb2fb..4a0d32eb6 100644
--- a/tests/autopilot/unity/tests/test_shortcut_hint.py
+++ b/tests/autopilot/unity/tests/test_shortcut_hint.py
@@ -104,6 +104,13 @@ class ShortcutHintInteractionsTests(BaseShortcutHintTests):
self.keybinding_tap("expo/start")
self.addCleanup(self.keybinding, "expo/cancel")
+ def test_shortcut_hint_hide_pressing_modifiers(self):
+ """Pressing a modifer key must hide the shortcut hint."""
+ self.shortcut_hint.ensure_visible()
+ self.addCleanup(self.shortcut_hint.ensure_hidden)
+
+ self.keyboard.press('Control')
+
self.assertThat(self.shortcut_hint.visible, Eventually(Equals(False)))
def test_launcher_switcher_next_doesnt_show_shortcut_hint(self):
@@ -133,84 +140,6 @@ class ShortcutHintInteractionsTests(BaseShortcutHintTests):
self.assertThat(self.shortcut_hint.visible, Equals(False))
- def test_launcher_switcher_next_keeps_shortcut_hint(self):
- """Super+Tab switcher cycling forwards must not dispel an already-showing
- shortcut hint.
-
- """
- show_timeout = self.shortcut_hint.get_show_timeout()
- self.shortcut_hint.ensure_visible()
- self.addCleanup(self.shortcut_hint.ensure_hidden)
-
- self.keybinding("launcher/switcher/next")
- self.addCleanup(self.keyboard.press_and_release, "Escape")
-
- self.assertThat(self.launcher.key_nav_is_active, Equals(True))
-
- self.keybinding("launcher/switcher/next")
- sleep(show_timeout * 2)
- self.assertThat(self.shortcut_hint.visible, Equals(True))
-
- def test_launcher_switcher_prev_keeps_shortcut_hint(self):
- """Super+Tab switcher cycling backwards must not dispel an already-showing
- shortcut hint.
-
- """
- show_timeout = self.shortcut_hint.get_show_timeout()
- self.shortcut_hint.ensure_visible()
- self.addCleanup(self.shortcut_hint.ensure_visible)
-
- self.keybinding("launcher/switcher/next")
- self.addCleanup(self.keyboard.press_and_release, "Escape")
- self.assertThat(self.launcher.key_nav_is_active, Equals(True))
-
- self.keybinding("launcher/switcher/prev")
- self.keybinding("launcher/switcher/prev")
- sleep(show_timeout * 2)
- self.assertThat(self.shortcut_hint.visible, Equals(True))
-
- def test_launcher_switcher_cancel_doesnt_hide_shortcut_hint(self):
- """Cancelling the launcher switcher (by Escape) must not hide the
- shortcut hint view.
-
- """
- self.shortcut_hint.ensure_visible()
- self.addCleanup(self.shortcut_hint.ensure_hidden)
-
- self.keybinding("launcher/switcher/next")
- # NOTE: This will generate an extra Escape keypress if the test passes,
- # but that's better than the alternative...
- self.addCleanup(self.keybinding, "launcher/switcher/exit")
-
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
- self.assertThat(self.shortcut_hint.visible, Equals(True))
-
- self.keyboard.press_and_release("Escape")
-
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
- self.assertThat(self.shortcut_hint.visible, Equals(True))
-
- def test_launcher_switcher_and_shortcut_hint_escaping(self):
- """Cancelling the launcher switcher (by Escape) should not hide the
- shortcut hint view, an extra keypress is needed.
-
- """
- self.shortcut_hint.ensure_visible()
- self.addCleanup(self.shortcut_hint.ensure_hidden)
-
- self.keybinding("launcher/switcher/next")
-
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(True)))
- self.assertThat(self.shortcut_hint.visible, Equals(True))
-
- self.keyboard.press_and_release("Escape")
-
- self.assertThat(self.launcher.key_nav_is_active, Eventually(Equals(False)))
- self.assertThat(self.shortcut_hint.visible, Equals(True))
-
- self.keyboard.press_and_release("Escape")
- self.assertThat(self.shortcut_hint.visible, Eventually(Equals(False)))
-
def test_launcher_icons_hints_show_with_shortcut_hint(self):
"""When the shortcut hint is shown also the launcer's icons hints should
be shown.
diff --git a/tests/autopilot/unity/tests/test_switcher.py b/tests/autopilot/unity/tests/test_switcher.py
index 5f044d0ed..c16a52f3d 100644
--- a/tests/autopilot/unity/tests/test_switcher.py
+++ b/tests/autopilot/unity/tests/test_switcher.py
@@ -52,10 +52,10 @@ class SwitcherTests(SwitcherTestCase):
"""Starting switcher in details mode must show the focused window title."""
app = self.start_app("Text Editor")
sleep(1)
- self.switcher.initiate(SwitcherMode.DETAIL)
- self.addCleanup(self.switcher.terminate)
[title] = [w.title for w in app.get_windows() if w.is_focused]
+ self.switcher.initiate(SwitcherMode.DETAIL)
+ self.addCleanup(self.switcher.terminate)
self.assertThat(self.switcher.controller.view.label, Eventually(Equals(title)))
@@ -190,6 +190,22 @@ class SwitcherTests(SwitcherTestCase):
self.addCleanup(self.switcher.terminate)
self.assertThat(self.switcher.controller.monitor, Eventually(Equals(monitor)))
+ def test_switcher_alt_f4_is_disabled(self):
+ """Tests that alt+f4 does not work while switcher is active."""
+
+ app = self.start_app("Text Editor")
+ sleep(1)
+
+ self.switcher.initiate(SwitcherMode.DETAIL)
+ self.addCleanup(self.switcher.terminate)
+
+ self.keyboard.press_and_release("Alt+F4")
+ [win] = [w for w in app.get_windows()]
+
+ # Need the sleep to allow the window time to close, for jenkins!
+ sleep(10)
+ self.assertThat(win.is_valid, Equals(True))
+
class SwitcherWindowsManagementTests(SwitcherTestCase):
"""Test the switcher window management."""
diff --git a/tests/test_glib_signals.cpp b/tests/test_glib_signals.cpp
index 7c8f210ca..e3f0fa34c 100644
--- a/tests/test_glib_signals.cpp
+++ b/tests/test_glib_signals.cpp
@@ -115,26 +115,22 @@ protected:
char arg6_;
};
+class MockSignalManager : public SignalManager
+{
+public:
+ std::vector<SignalBase::Ptr> GetConnections() const { return connections_; }
+};
+
TEST_F(TestGLibSignals, TestConstructions)
{
- SignalBase base;
-
- Signal0<void, TestSignals*> signal0;
- Signal1<void, TestSignals*, string> signal1;
- Signal2<void, TestSignals*, string, int> signal2;
- Signal3<void, TestSignals*, string, int, float> signal3;
- Signal4<void, TestSignals*, string, int, float, double> signal4;
- Signal5<void, TestSignals*, string, int, float, double, gboolean> signal5;
- Signal6<gboolean, TestSignals*, string, int, float, double, gboolean, char> signal6;
-
- Signal<void, TestSignals*> signal00;
- Signal<void, TestSignals*, string> signal01;
- Signal<void, TestSignals*, string, int> signal02;
- Signal<void, TestSignals*, string, int, float> signal03;
- Signal<void, TestSignals*, string, int, float, double> signal04;
- Signal<void, TestSignals*, string, int, float, double, gboolean> signal05;
- Signal<gboolean, TestSignals*, string, int, float, double, gboolean, char> signal06;
+ Signal<void, TestSignals*> signal0;
+ Signal<void, TestSignals*, string> signal1;
+ Signal<void, TestSignals*, string, int> signal2;
+ Signal<void, TestSignals*, string, int, float> signal3;
+ Signal<void, TestSignals*, string, int, float, double> signal4;
+ Signal<void, TestSignals*, string, int, float, double, gboolean> signal5;
+ Signal<gboolean, TestSignals*, string, int, float, double, gboolean, char> signal6;
}
TEST_F(TestGLibSignals, TestSignal0)
@@ -282,12 +278,13 @@ TEST_F(TestGLibSignals, TestCleanDestruction)
TEST_F(TestGLibSignals, TestManagerConstruction)
{
- SignalManager manager;
+ MockSignalManager manager;
+ EXPECT_TRUE(manager.GetConnections().empty());
}
TEST_F(TestGLibSignals, TestManagerAddition)
{
- SignalManager manager;
+ MockSignalManager manager;
manager.Add(new Signal<void, TestSignals*>(test_signals_,
"signal0",
@@ -310,11 +307,34 @@ TEST_F(TestGLibSignals, TestManagerAddition)
manager.Add(new Signal<gboolean, TestSignals*, const char*, int, float, double, gboolean, char>(test_signals_,
"signal6",
sigc::mem_fun(this, &TestGLibSignals::Signal6Callback)));
+
+ EXPECT_EQ(manager.GetConnections().size(), 7);
+}
+
+TEST_F(TestGLibSignals, TestManagerAdditionTemplate)
+{
+ MockSignalManager manager;
+
+ manager.Add<void, TestSignals*>(test_signals_, "signal0",
+ sigc::mem_fun(this, &TestGLibSignals::Signal0Callback));
+ manager.Add<void, TestSignals*, const char*>(test_signals_, "signal1",
+ sigc::mem_fun(this, &TestGLibSignals::Signal1Callback));
+ manager.Add<void, TestSignals*, const char*, int>(test_signals_, "signal2",
+ sigc::mem_fun(this, &TestGLibSignals::Signal2Callback));
+ manager.Add<void, TestSignals*, const char*, int, float>(test_signals_, "signal3",
+ sigc::mem_fun(this, &TestGLibSignals::Signal3Callback));
+ manager.Add<void, TestSignals*, const char*, int, float, double>(test_signals_, "signal4",
+ sigc::mem_fun(this, &TestGLibSignals::Signal4Callback));
+ manager.Add<void, TestSignals*, const char*, int, float, double, gboolean>(test_signals_, "signal5",
+ sigc::mem_fun(this, &TestGLibSignals::Signal5Callback));
+ manager.Add<gboolean, TestSignals*, const char*, int, float, double, gboolean, char>(test_signals_, "signal6", sigc::mem_fun(this, &TestGLibSignals::Signal6Callback));
+
+ EXPECT_EQ(manager.GetConnections().size(), 7);
}
TEST_F(TestGLibSignals, TestManagerConnection)
{
- SignalManager manager;
+ MockSignalManager manager;
manager.Add(new Signal<void, TestSignals*>(test_signals_,
"signal0",
@@ -330,9 +350,8 @@ TEST_F(TestGLibSignals, TestManagerConnection)
EXPECT_TRUE(signal1_received_);
gboolean ret = FALSE;
- manager.Add(new Signal<gboolean, TestSignals*, const char*, int, float, double, gboolean, char>(test_signals_,
- "signal6",
- sigc::mem_fun(this, &TestGLibSignals::Signal6Callback)));
+ manager.Add<gboolean, TestSignals*, const char*, int, float, double, gboolean, char>(test_signals_, "signal6",
+ sigc::mem_fun(this, &TestGLibSignals::Signal6Callback));
g_signal_emit_by_name(test_signals_, "signal6", "test", 100, 1.0f, 100.00, FALSE, 'x', &ret);
EXPECT_TRUE(signal6_received_);
EXPECT_TRUE(ret);
diff --git a/tests/test_hud_controller.cpp b/tests/test_hud_controller.cpp
index 5ee7b7989..6bd379fe2 100644
--- a/tests/test_hud_controller.cpp
+++ b/tests/test_hud_controller.cpp
@@ -59,7 +59,7 @@ public:
virtual void SetUp()
{
view = new MockHudView;
- controller.reset(new hud::Controller([&view]{ return view.GetPointer(); }));
+ controller.reset(new hud::Controller([this]{ return view.GetPointer(); }));
}
Settings unity_settings;
@@ -73,6 +73,7 @@ public:
TEST_F(TestHudController, TestHideHud)
{
controller->ShowHud();
+ Utils::WaitForTimeout(1);
EXPECT_CALL(*view, ResetToDefault())
.Times(1);
diff --git a/tests/test_im_text_entry.cpp b/tests/test_im_text_entry.cpp
index d10125e36..2c5457119 100644
--- a/tests/test_im_text_entry.cpp
+++ b/tests/test_im_text_entry.cpp
@@ -24,6 +24,7 @@
using namespace testing;
using namespace unity;
+using namespace nux;
namespace
{
@@ -48,14 +49,15 @@ public:
class MockTextEntry : public IMTextEntry
{
public:
- MOCK_METHOD1(InsertText, void(std::string const&));
- MOCK_METHOD0(Cut, void());
- MOCK_METHOD0(Copy, void());
- MOCK_METHOD1(Paste, void(bool));
+ MOCK_METHOD0(CutClipboard, void());
+ MOCK_METHOD0(CopyClipboard, void());
+ MOCK_METHOD0(PasteClipboard, void());
+ MOCK_METHOD0(PastePrimaryClipboard, void());
- bool TryHandleSpecial(nux::Event const& event)
+ bool InspectKeyEvent(nux::Event const& event)
{
- return IMTextEntry::TryHandleSpecial(event);
+ key_down.emit(event.type, event.GetKeySym(), event.GetKeyState(), nullptr, 0);
+ return IMTextEntry::InspectKeyEvent(event);
}
};
@@ -66,8 +68,8 @@ TEST(TestIMTextEntry, CopyCtrlC)
TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_c);
- EXPECT_CALL(text_entry, Copy());
- EXPECT_FALSE(text_entry.TryHandleSpecial(event));
+ EXPECT_CALL(text_entry, CopyClipboard());
+ EXPECT_TRUE(text_entry.InspectKeyEvent(event));
}
TEST(TestIMTextEntry, CopyCtrlIns)
@@ -76,8 +78,8 @@ TEST(TestIMTextEntry, CopyCtrlIns)
TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_INSERT);
- EXPECT_CALL(text_entry, Copy());
- EXPECT_FALSE(text_entry.TryHandleSpecial(event));
+ EXPECT_CALL(text_entry, CopyClipboard());
+ EXPECT_TRUE(text_entry.InspectKeyEvent(event));
}
TEST(TestIMTextEntry, PasteCtrlV)
@@ -86,8 +88,8 @@ TEST(TestIMTextEntry, PasteCtrlV)
TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_v);
- EXPECT_CALL(text_entry, Paste(false));
- EXPECT_FALSE(text_entry.TryHandleSpecial(event));
+ EXPECT_CALL(text_entry, PasteClipboard());
+ EXPECT_TRUE(text_entry.InspectKeyEvent(event));
}
TEST(TestIMTextEntry, PasteShiftIns)
@@ -96,8 +98,8 @@ TEST(TestIMTextEntry, PasteShiftIns)
TestEvent event(KEY_MODIFIER_SHIFT, NUX_VK_INSERT);
- EXPECT_CALL(text_entry, Paste(false));
- EXPECT_FALSE(text_entry.TryHandleSpecial(event));
+ EXPECT_CALL(text_entry, PasteClipboard());
+ EXPECT_TRUE(text_entry.InspectKeyEvent(event));
}
TEST(TestIMTextEntry, CutCtrlX)
@@ -106,8 +108,8 @@ TEST(TestIMTextEntry, CutCtrlX)
TestEvent event(KEY_MODIFIER_CTRL, NUX_VK_x);
- EXPECT_CALL(text_entry, Cut());
- EXPECT_FALSE(text_entry.TryHandleSpecial(event));
+ EXPECT_CALL(text_entry, CutClipboard());
+ EXPECT_TRUE(text_entry.InspectKeyEvent(event));
}
TEST(TestIMTextEntry, CutShiftDel)
@@ -116,8 +118,8 @@ TEST(TestIMTextEntry, CutShiftDel)
TestEvent event(KEY_MODIFIER_SHIFT, NUX_VK_DELETE);
- EXPECT_CALL(text_entry, Cut());
- EXPECT_FALSE(text_entry.TryHandleSpecial(event));
+ EXPECT_CALL(text_entry, CutClipboard());
+ EXPECT_TRUE(text_entry.InspectKeyEvent(event));
}
TEST(TestIMTextEntry, CtrlMoveKeys)
@@ -125,16 +127,16 @@ TEST(TestIMTextEntry, CtrlMoveKeys)
MockTextEntry text_entry;
TestEvent left(KEY_MODIFIER_CTRL, NUX_VK_LEFT);
- EXPECT_TRUE(text_entry.TryHandleSpecial(left));
+ EXPECT_TRUE(text_entry.InspectKeyEvent(left));
TestEvent right(KEY_MODIFIER_CTRL, NUX_VK_RIGHT);
- EXPECT_TRUE(text_entry.TryHandleSpecial(right));
+ EXPECT_TRUE(text_entry.InspectKeyEvent(right));
TestEvent home(KEY_MODIFIER_CTRL, NUX_VK_HOME);
- EXPECT_TRUE(text_entry.TryHandleSpecial(home));
+ EXPECT_TRUE(text_entry.InspectKeyEvent(home));
TestEvent end(KEY_MODIFIER_CTRL, NUX_VK_END);
- EXPECT_TRUE(text_entry.TryHandleSpecial(end));
+ EXPECT_TRUE(text_entry.InspectKeyEvent(end));
}
TEST(TestIMTextEntry, CtrlDeleteKeys)
@@ -142,10 +144,10 @@ TEST(TestIMTextEntry, CtrlDeleteKeys)
MockTextEntry text_entry;
TestEvent del(KEY_MODIFIER_CTRL, NUX_VK_DELETE);
- EXPECT_TRUE(text_entry.TryHandleSpecial(del));
+ EXPECT_TRUE(text_entry.InspectKeyEvent(del));
TestEvent backspace(KEY_MODIFIER_CTRL, NUX_VK_BACKSPACE);
- EXPECT_TRUE(text_entry.TryHandleSpecial(backspace));
+ EXPECT_TRUE(text_entry.InspectKeyEvent(backspace));
}
TEST(TestIMTextEntry, CtrlA)
@@ -153,7 +155,7 @@ TEST(TestIMTextEntry, CtrlA)
MockTextEntry text_entry;
TestEvent selectall(KEY_MODIFIER_CTRL, NUX_VK_a);
- EXPECT_TRUE(text_entry.TryHandleSpecial(selectall));
+ EXPECT_TRUE(text_entry.InspectKeyEvent(selectall));
}
TEST(TestIMTextEntry, CtrlKeybindings)
@@ -165,15 +167,10 @@ TEST(TestIMTextEntry, CtrlKeybindings)
NUX_VK_HOME, NUX_VK_END,
NUX_VK_BACKSPACE, NUX_VK_DELETE };
- for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym)
+ for (auto keysym : allowed_keys)
{
- bool should_be_handled = false;
-
- if (std::find(allowed_keys.begin(), allowed_keys.end(), keysym) != allowed_keys.end())
- should_be_handled = true;
-
TestEvent event(KEY_MODIFIER_CTRL, keysym);
- EXPECT_EQ(text_entry.TryHandleSpecial(event), should_be_handled);
+ EXPECT_TRUE(text_entry.InspectKeyEvent(event));
}
}
@@ -184,7 +181,7 @@ TEST(TestIMTextEntry, AltKeybindings)
for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym)
{
TestEvent event(KEY_MODIFIER_ALT, keysym);
- EXPECT_FALSE(text_entry.TryHandleSpecial(event));
+ EXPECT_FALSE(text_entry.InspectKeyEvent(event));
}
}
@@ -195,7 +192,7 @@ TEST(TestIMTextEntry, SuperKeybindings)
for (unsigned long keysym = 0; keysym < XK_VoidSymbol; ++keysym)
{
TestEvent event(KEY_MODIFIER_SUPER, keysym);
- EXPECT_FALSE(text_entry.TryHandleSpecial(event));
+ EXPECT_FALSE(text_entry.InspectKeyEvent(event));
}
}
diff --git a/tests/test_introspection.cpp b/tests/test_introspection.cpp
index a88cbbe90..53b9f626a 100644
--- a/tests/test_introspection.cpp
+++ b/tests/test_introspection.cpp
@@ -94,12 +94,12 @@ protected:
};
-TEST_F(TestIntrospection, TestTest)
+TEST_F(TestIntrospection, TestTest)
{
ASSERT_STREQ("Unity", root_->GetName().c_str());
}
-TEST_F(TestIntrospection, TestVariousRootQueries)
+TEST_F(TestIntrospection, TestVariousRootQueries)
{
std::list<Introspectable*> results;
std::string query;
@@ -108,7 +108,7 @@ TEST_F(TestIntrospection, TestVariousRootQueries)
ASSERT_EQ(1, results.size());
EXPECT_STREQ("Unity", results.front()->GetName().c_str());
- query = "/";
+ query = "/";
results = GetIntrospectableNodesFromQuery(query, root_.get());
ASSERT_EQ(1, results.size());
EXPECT_STREQ("Unity", results.front()->GetName().c_str());
@@ -119,6 +119,37 @@ TEST_F(TestIntrospection, TestVariousRootQueries)
EXPECT_STREQ("Unity", results.front()->GetName().c_str());
}
+TEST_F(TestIntrospection, TestAsteriskWildcard)
+{
+ std::list<Introspectable*> results;
+ std::string query = "/Unity/*";
+
+ results = GetIntrospectableNodesFromQuery(query, root_.get());
+ ASSERT_EQ(2, results.size());
+
+ for(auto p : results)
+ {
+ ASSERT_TRUE(
+ p->GetName() == "DashController" ||
+ p->GetName() == "PanelController"
+ );
+ }
+}
+
+TEST_F(TestIntrospection, TestRelativeAsteriskWildcard)
+{
+ std::list<Introspectable*> results;
+ std::string query = "//DashController/*";
+
+ results = GetIntrospectableNodesFromQuery(query, root_.get());
+ ASSERT_EQ(3, results.size());
+
+ for(auto p : results)
+ {
+ ASSERT_TRUE(p->GetName() == "Foo");
+ }
+}
+
TEST_F(TestIntrospection, TestAbsoluteQueries)
{
std::list<Introspectable*> results;
@@ -136,14 +167,14 @@ TEST_F(TestIntrospection, TestMalformedRelativeQueries)
results = GetIntrospectableNodesFromQuery(query, root_.get());
ASSERT_EQ(1, results.size());
- EXPECT_STREQ("Unity", results.front()->GetName().c_str());
+ EXPECT_STREQ("Unity", results.front()->GetName().c_str());
query = "Foo";
results = GetIntrospectableNodesFromQuery(query, root_.get());
ASSERT_EQ(3, results.size());
for(auto p : results)
{
- EXPECT_STREQ("Foo", p->GetName().c_str());
+ EXPECT_STREQ("Foo", p->GetName().c_str());
}
}
@@ -154,14 +185,14 @@ TEST_F(TestIntrospection, TestSimpleRelativeQueries)
results = GetIntrospectableNodesFromQuery(query, root_.get());
ASSERT_EQ(1, results.size());
- EXPECT_STREQ("Unity", results.front()->GetName().c_str());
+ EXPECT_STREQ("Unity", results.front()->GetName().c_str());
query = "//Foo";
results = GetIntrospectableNodesFromQuery(query, root_.get());
ASSERT_EQ(3, results.size());
for(auto p : results)
{
- EXPECT_STREQ("Foo", p->GetName().c_str());
+ EXPECT_STREQ("Foo", p->GetName().c_str());
}
}
@@ -174,7 +205,7 @@ TEST_F(TestIntrospection, TestComplexRelativeQueries)
ASSERT_EQ(3, results.size());
for(auto p : results)
{
- EXPECT_STREQ("Foo", p->GetName().c_str());
+ EXPECT_STREQ("Foo", p->GetName().c_str());
}
}
@@ -185,7 +216,7 @@ TEST_F(TestIntrospection, TestQueriesWithNoResults)
results = GetIntrospectableNodesFromQuery(query, root_.get());
ASSERT_EQ(0, results.size());
-
+
query = "DoesNotEverExist";
results = GetIntrospectableNodesFromQuery(query, root_.get());
ASSERT_EQ(0, results.size());
@@ -211,7 +242,7 @@ TEST_F(TestIntrospection, TestQueriesWithParams)
ASSERT_EQ(3, results.size());
for(auto p : results)
{
- EXPECT_STREQ("Foo", p->GetName().c_str());
+ EXPECT_STREQ("Foo", p->GetName().c_str());
}
// make sure param queries work with descendant nodes as well:
@@ -219,7 +250,7 @@ TEST_F(TestIntrospection, TestQueriesWithParams)
ASSERT_EQ(3, results.size());
for(auto p : results)
{
- EXPECT_STREQ("Foo", p->GetName().c_str());
+ EXPECT_STREQ("Foo", p->GetName().c_str());
}
}
@@ -259,7 +290,7 @@ TEST_F(TestIntrospection, TestQueryTypeBool)
TEST_F(TestIntrospection, TestQueryTypeInt)
{
std::list<Introspectable*> results;
-
+
// these should all select the root Unity node:
std::list<std::string> queries = {"/Unity[BytePropertyPos=12]",
"/Unity[Int16PropertyPos=1012]",
@@ -291,7 +322,7 @@ TEST_F(TestIntrospection, TestQueryTypeInt)
{
results = GetIntrospectableNodesFromQuery(query, root_.get());
ASSERT_EQ(0, results.size());
- }
+ }
}
TEST_F(TestIntrospection, TestMalformedQueries)
@@ -320,6 +351,6 @@ TEST_F(TestIntrospection, TestMalformedQueries)
for (std::string query : queries)
{
results = GetIntrospectableNodesFromQuery(query, root_.get());
- ASSERT_EQ(0, results.size()) << "Failing query: " << query;
+ ASSERT_EQ(0, results.size()) << "Failing query: " << query;
}
-} \ No newline at end of file
+}
diff --git a/tests/test_keyboard_util.cpp b/tests/test_keyboard_util.cpp
new file mode 100644
index 000000000..cc61e336e
--- /dev/null
+++ b/tests/test_keyboard_util.cpp
@@ -0,0 +1,115 @@
+// -*- 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: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
+ */
+
+#include <gtest/gtest.h>
+#include <algorithm>
+
+#include "KeyboardUtil.h"
+
+using namespace unity::ui;
+
+namespace
+{
+
+void test_key(KeyboardUtil const& key_util, Display* x_display, const char* key)
+{
+ unsigned int above_keycode = key_util.GetKeycodeAboveKeySymbol(XStringToKeysym(key));
+ KeySym above_keysym = XkbKeycodeToKeysym(x_display, above_keycode, 0, 1);
+ EXPECT_NE(above_keysym, NoSymbol);
+}
+
+TEST(TestKeyboardUtil, AboveKeySymbol)
+{
+ Display* x_display = XOpenDisplay(NULL);
+
+ KeyboardUtil key_util(x_display);
+ test_key(key_util, x_display, "Tab");
+ test_key(key_util, x_display, "Shift_R");
+ test_key(key_util, x_display, "Control_L");
+ test_key(key_util, x_display, "space");
+ test_key(key_util, x_display, "comma");
+ test_key(key_util, x_display, "a");
+ test_key(key_util, x_display, "b");
+ test_key(key_util, x_display, "c");
+ test_key(key_util, x_display, "d");
+ test_key(key_util, x_display, "e");
+ test_key(key_util, x_display, "f");
+ test_key(key_util, x_display, "g");
+ test_key(key_util, x_display, "h");
+ test_key(key_util, x_display, "i");
+ test_key(key_util, x_display, "j");
+ test_key(key_util, x_display, "k");
+ test_key(key_util, x_display, "l");
+ test_key(key_util, x_display, "m");
+ test_key(key_util, x_display, "n");
+ test_key(key_util, x_display, "o");
+ test_key(key_util, x_display, "p");
+ test_key(key_util, x_display, "k");
+ test_key(key_util, x_display, "r");
+ test_key(key_util, x_display, "s");
+ test_key(key_util, x_display, "t");
+ test_key(key_util, x_display, "u");
+ test_key(key_util, x_display, "v");
+ test_key(key_util, x_display, "w");
+ test_key(key_util, x_display, "x");
+ test_key(key_util, x_display, "y");
+ test_key(key_util, x_display, "z");
+}
+
+TEST(TestKeyboardUtil, PrintableKeySymbols)
+{
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_Delete));
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_BackSpace));
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_space));
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_3));
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_v));
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_1));
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_ntilde));
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_0));
+ EXPECT_TRUE(KeyboardUtil::IsPrintableKeySymbol(XK_exclam));
+
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_F1));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Select));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Hyper_R));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Control_L));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Shift_L));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Super_L));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Print));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Insert));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Num_Lock));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_Caps_Lock));
+ EXPECT_FALSE(KeyboardUtil::IsPrintableKeySymbol(XK_ISO_Level3_Shift));
+}
+
+TEST(TestKeyboardUtil, MoveKeySymbols)
+{
+ std::vector<KeySym> move_symbols { XK_Home, XK_Left, XK_Up, XK_Right, XK_Down,
+ XK_Prior, XK_Page_Up, XK_Next, XK_Page_Down,
+ XK_End, XK_Begin };
+
+ for (KeySym sym = 0; sym < XK_VoidSymbol; ++sym)
+ {
+ if (std::find(move_symbols.begin(), move_symbols.end(), sym) != move_symbols.end())
+ EXPECT_TRUE(KeyboardUtil::IsMoveKeySymbol(sym));
+ else
+ EXPECT_FALSE(KeyboardUtil::IsMoveKeySymbol(sym));
+ }
+}
+
+} // Namespace
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 523e56f65..24dfc2280 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,7 +1,7 @@
#
# Some unity tools
#
-install(FILES makebootchart.py migrate_favorites.py PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/unity/)
+install(FILES makebootchart.py PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/unity/)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/unity.cmake ${CMAKE_BINARY_DIR}/bin/unity)
install(FILES ${CMAKE_BINARY_DIR}/bin/unity PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
diff --git a/tools/build-compiz-glib b/tools/build-compiz-glib
index e7453e287..474fd1934 100755
--- a/tools/build-compiz-glib
+++ b/tools/build-compiz-glib
@@ -23,7 +23,7 @@ PREFIX=$HOME/staging/
PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig
LD_LIBRARY_PATH=$PREFIX/lib
# These are the dependencies for ubuntu. This script should work on other distros provided the dependencies are met
-DEPENDENCIES="git-core cmake libcairo2-dev librsvg2-dev libglib2.0-dev libpng12-dev libdbus-1-dev libboost-dev libboost-serialization-dev libxml2-dev libgl1-mesa-dev libglu1-mesa-dev libwnck-dev libgconf2-dev libx11-xcb-dev libxslt1-dev libnotify-dev libprotobuf-dev libmetacity-dev libgnome-window-settings-dev libgnome-desktop-dev gnome-control-center-dev intltool cython python2.6-dev"
+DEPENDENCIES="git-core cmake libcairo2-dev librsvg2-dev libglib2.0-dev libpng12-dev libdbus-1-dev libboost-dev libboost-serialization-dev libxml2-dev libgl1-mesa-dev libglu1-mesa-dev libwnck-dev libgconf2-dev libx11-xcb-dev libxslt1-dev libnotify-dev libprotobuf-dev libmetacity-dev libgnome-window-settings-dev gnome-control-center-dev intltool cython python2.6-dev"
COMPONENTS=(core libcompizconfig compizconfig-python ccsm compizconfig-backend-gconf plugins-main plugins-extra plugins-unsupported)
echo "Installing dependencies..."
diff --git a/tools/migrate_favorites.py b/tools/migrate_favorites.py
deleted file mode 100755
index 2ec45bd65..000000000
--- a/tools/migrate_favorites.py
+++ /dev/null
@@ -1,292 +0,0 @@
-#!/usr/bin/python
-# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
-# Copyright 2010 Canonical
-# Author: Didier Roche
-#
-# 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.
-
-import sys
-
-try:
- import datetime
- import gconf
- import glob
- import gobject
- from gobject import GError
- import os
- import subprocess
- from xdg import BaseDirectory
-except ImportError, e:
- print "No migration because of a missing python module: %s" % e
- sys.exit (1)
-
-LAST_MIGRATION = '3.2.10'
-
-def get_log_file():
- ''' open the log file and return it '''
-
- data_path = "%s/unity" % BaseDirectory.xdg_cache_home
- if not os.path.isdir(data_path):
- os.makedirs(data_path)
- try:
- return open("%s/migration_script.log" % data_path, "a")
- except (IOError, OSError), e:
- print "Can't put log in %s, will print those manually. Error is: %s" % (data_path, e)
- return None
-
-def migrating_chapter_log(name, apps_list, migration_list, log_file):
- '''Log migration of new launchers'''
-
- log(" + Migration for %s.\n Current app list is: %s\n Candidates are: %s" % (name, apps_list, migration_list), log_file)
-
-
-def log(message, log_file):
- ''' log if log_file present'''
- if log_file:
- log_file.write("%s\n" % message)
- else:
- print message
-
-def get_desktop_dir():
- ''' no python binding from xdg to get the desktop directory? '''
-
- possible_desktop_folder = None
- try:
- for line in file('%s/user-dirs.dirs' % BaseDirectory.xdg_config_home):
- values = line.split('=')
- if values[0] == 'XDG_DESKTOP_DIR':
- try:
- possible_desktop_folder = values[1][1:-2].replace('$HOME', os.path.expanduser('~'))
- if os.path.isdir(possible_desktop_folder):
- return possible_desktop_folder
- else:
- possible_desktop_folder = None
- break
- except IndexError:
- continue
- except IOError:
- pass
- return os.path.expanduser('~/Desktop')
-
-def register_new_app(launcher_location, apps_list, log_file):
- ''' append a new app with full desktop path if valid, take care of dups '''
-
- # default distribution launcher don't go into that function (as don't have an aboslute path)
- entry = ""
- if os.path.exists(launcher_location):
- log(" == %s: exists" % launcher_location, log_file)
- # try to strip the full path we had in unity mutter if it's part of a xdg path:
- # or try to get that for other desktop file based on name.
- candidate_desktop_filename = launcher_location.split("/")[-1]
- # some desktop file with modified exec key (like in cairo-dock contains 01desktopfilename.desktop, strip that)
- try:
- candidate_cairodock_desktop_filename = candidate_desktop_filename.split("01")[1]
- except IndexError:
- candidate_cairodock_desktop_filename = ""
- for xdg_dir in BaseDirectory.xdg_data_dirs:
- xdg_app_dir = os.path.join(xdg_dir, "applications", "")
- if launcher_location.startswith(xdg_app_dir):
- candidate_desktop_file = launcher_location.split(xdg_app_dir)[1]
- # if really the xdg path is the path to the launcher
- if not '/' in candidate_desktop_file:
- entry = candidate_desktop_file
- log(" Direct match found for system desktop file", log_file)
- break
- # second chance: try to see if the desktop filename is in xdg path and so, assume it's a match
- if not entry and os.path.exists("%s/%s" % (xdg_app_dir, candidate_desktop_filename)):
- entry = candidate_desktop_filename
- log(" Similar desktop file name with system desktop file", log_file)
- break
- # third chance: try to see if a tweaked cairo-dock like deskto file name is in xdg path
- if not entry and os.path.exists("%s/%s" % (xdg_app_dir, candidate_cairodock_desktop_filename)):
- entry = candidate_cairodock_desktop_filename
- log(" Similar Cairo-Dock -like desktop file name with system desktop file", log_file)
- break
- # fourth and last chance: try to find a corresponding Exec key.
- # Wait! scanning /usr/share/applications is heavy !!!
- # Don't panic, we have the bamf.index for that :)
- if not entry:
- exec_arg = ""
- try:
- for line in open(launcher_location):
- if "Exec=" in line:
- exec_arg = line.split("Exec=")[1]
- break
- except IOError:
- log(" Can't open %s for reading Exec" % launcher_location, log_file)
- if exec_arg:
- try:
- for line in open("/usr/share/applications/bamf.index"):
- if exec_arg in line:
- entry = line.split()[0]
- log(" Coherent exec key found with system desktop file", log_file)
- break
- except IOError:
- log(" No bamf.index file found on the system!", log_file)
-
- if not entry:
- entry = launcher_location
- log(" %s: real entry is %s" % (launcher_location, entry), log_file)
- if entry not in apps_list:
- log(" --- adding %s as not in app_list" % entry, log_file)
- apps_list.append(entry)
- else:
- log(" --- NOT adding %s as already in app_list" % entry, log_file)
- else:
- log(" == %s: doesn't exist" % launcher_location, log_file)
-
- return apps_list
-
-def save_gsettings_favorites(apps_list, log_file):
- ''' save the app list favorites to gsettings '''
-
- #print apps_list
- return_code = subprocess.call(["gsettings", "set", "com.canonical.Unity.Launcher", "favorites", str(apps_list)])
-
- if return_code != 0:
- print "Settings fail to transition to new unity compiz favorites"
- log("Settings fail to transition to new unity compiz favorites\n\n", log_file)
- if log_file:
- log_file.close()
- sys.exit(1)
-
-try:
- migration_level = subprocess.Popen(["gsettings", "get", "com.canonical.Unity.Launcher", "favorite-migration"], stdout=subprocess.PIPE).communicate()[0].strip()[1:-1]
-except OSError, e:
- print "Gsettings not executable or not installed, postponing migration. The error was: %s" % e
- sys.exit(1)
-
-if migration_level >= LAST_MIGRATION:
- print "Migration already done"
- sys.exit(0)
-
-client = gconf.client_get_default()
-
-# get current gsettings defaults into a list
-defaults_call = subprocess.Popen(["gsettings", "get", "com.canonical.Unity.Launcher", "favorites"], stdout=subprocess.PIPE)
-apps_list = [elem.strip()[1:-1] for elem in defaults_call.communicate()[0].strip()[1:-1].split(',')]
-
-log_file = get_log_file()
-log("Migration script called on %s\n" % str(datetime.datetime.now()), log_file)
-
-# first migration to unity compiz
-if migration_level < '3.2.0':
- log("======= Migration to 3.2.0 =======\n", log_file)
-
- unity_mutter_favorites_list = client.get_list('/desktop/unity/launcher/favorites/favorites_list', gconf.VALUE_STRING)
- unity_mutter_launcher_ordered = {}
- migrating_chapter_log("unity mutter", apps_list, unity_mutter_favorites_list, log_file)
- for candidate in unity_mutter_favorites_list:
- candidate_path = '/desktop/unity/launcher/favorites/%s' % candidate
- try:
- if (candidate and client.get_string('%s/type' % candidate_path) == 'application'):
- launcher_location = client.get_string('%s/desktop_file' % candidate_path)
- position = client.get_string('%s/desktop_file' % candidate_path)
- if launcher_location:
- # try to preserve the order, will be done in a second loop
- unity_mutter_launcher_ordered[position] = launcher_location
- except GError, e:
- log("Dont migrate %s: %s" % (candidate_path, e), log_file)
- continue
- for launcher_location in unity_mutter_launcher_ordered:
- apps_list = register_new_app(launcher_location, apps_list, log_file)
-
-
- # import netbook-launcher favorites and convert them
- lucid_favorites_list = client.get_list('/apps/netbook-launcher/favorites/favorites_list', gconf.VALUE_STRING)
- migrating_chapter_log("netbook-launcher favorites", apps_list, lucid_favorites_list, log_file)
- for candidate in lucid_favorites_list:
- candidate_path = '/apps/netbook-launcher/favorites/%s' % candidate
- try:
- if (candidate and client.get_string('%s/type' % candidate_path) == 'application'):
- try:
- launcher_location = client.get_string('%s/desktop_file' % candidate_path)
- except GError, e:
- log("Dont migrate %s: %s" % (candidate_path, e), log_file)
- continue
- if launcher_location:
- apps_list = register_new_app(launcher_location, apps_list, log_file)
- except GError, e:
- log("Dont migrate %s: %s" % (candidate_path, e), log_file)
- continue
-
- # get GNOME panel favorites and convert them
- panel_list = client.get_list('/apps/panel/general/toplevel_id_list', gconf.VALUE_STRING)
- candidate_objects = client.get_list('/apps/panel/general/object_id_list', gconf.VALUE_STRING)
- migrating_chapter_log("gnome-panel items", apps_list, candidate_objects, log_file)
- for candidate in candidate_objects:
- candidate_path = '/apps/panel/objects/%s' % candidate
- try:
- if (candidate and client.get_string('%s/object_type' % candidate_path) == 'launcher-object'
- and client.get_string('%s/toplevel_id' % candidate_path) in panel_list):
- launcher_location = client.get_string('%s/launcher_location' % candidate_path)
- if launcher_location:
- if not launcher_location.startswith('/'):
- launcher_location = os.path.expanduser('~/.gnome2/panel2.d/default/launchers/%s' % launcher_location)
- apps_list = register_new_app(launcher_location, apps_list, log_file)
- except GError, e:
- log("Dont migrate %s: %s" % (candidate_path, e), log_file)
- continue
-
- # get GNOME desktop launchers
- desktop_dir = get_desktop_dir()
- desktop_items = glob.glob('%s/*.desktop' % desktop_dir)
- migrating_chapter_log("desktop items in %s" % desktop_dir, apps_list, desktop_items, log_file)
- for launcher_location in glob.glob('%s/*.desktop' % desktop_dir):
- # blacklist ubiquity as will have two ubiquity in the netbook live session then
- if not "ubiquity" in launcher_location:
- apps_list = register_new_app(launcher_location, apps_list, log_file)
-
- # Now write to gsettings!
- save_gsettings_favorites(apps_list, log_file)
-
- # some autumn cleanage (gconf binding for recursive_unset seems broken)
- subprocess.call(["gconftool-2", "--recursive-unset", "/apps/netbook-launcher"])
- subprocess.call(["gconftool-2", "--recursive-unset", "/desktop/unity"])
-
-# second migration: transition popular docks entry as well
-if migration_level < '3.2.10':
- log("======= Migration to 3.2.10 =======\n", log_file)
-
- # import awn favorites
- awn_favorites_list = client.get_list('/apps/awn-applet-taskmanager/launcher_paths', gconf.VALUE_STRING)
- migrating_chapter_log("awn favorites", apps_list, awn_favorites_list, log_file)
- for launcher_location in awn_favorites_list:
- apps_list = register_new_app(launcher_location, apps_list, log_file)
-
- # import Docky favorites
- dock_list = client.get_list('/apps/docky-2/Docky/DockController/ActiveDocks', gconf.VALUE_STRING)
- for dock in dock_list:
- docky_favorites_list = client.get_list('/apps/docky-2/Docky/Interface/DockPreferences/%s/Launchers' % dock, gconf.VALUE_STRING)
- migrating_chapter_log("Docky favorites for %s" % dock, apps_list, docky_favorites_list, log_file)
- for launcher_location in docky_favorites_list:
- try:
- launcher_location = launcher_location.split("file://")[1]
- except IndexError:
- pass
- apps_list = register_new_app(launcher_location, apps_list, log_file)
-
- # import Cairo-Dock favorites
- try:
- cairodock_path = "%s/cairo-dock/current_theme/launchers" % BaseDirectory.xdg_config_home
- cairodock_favorites_list = os.listdir(cairodock_path)
- migrating_chapter_log("Cairo-Dock favorites (in %s)" % cairodock_path, apps_list, cairodock_favorites_list, log_file)
- for launcher in cairodock_favorites_list:
- launcher_location = "%s/%s" % (cairodock_path, launcher)
- apps_list = register_new_app(launcher_location, apps_list, log_file)
- except OSError:
- log(" + Can't migrate Cairo-Dock as %s doesn't exist" % cairodock_path, log_file)
-
- # Now write to gsettings!
- save_gsettings_favorites(apps_list, log_file)
-
-log("Migration script ended successfully\n\n", log_file)
-if log_file:
- log_file.close()
-
-# stamp that all went well
-subprocess.call(["gsettings", "set", "com.canonical.Unity.Launcher", "favorite-migration", "\'%s\'" % LAST_MIGRATION])
-sys.exit(0)
-
diff --git a/tools/unity.cmake b/tools/unity.cmake
index f4897a55f..af7871855 100755
--- a/tools/unity.cmake
+++ b/tools/unity.cmake
@@ -19,6 +19,7 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import gconf
+import glib
import glob
from optparse import OptionParser
import os
@@ -78,7 +79,7 @@ def reset_unity_compiz_profile ():
# as compiz set a new schema instead of a value..
try:
current_profile_schema = client.get_schema("/apps/compizconfig-1/current_profile")
- except (GError, AttributeError), e:
+ except (glib.GError, AttributeError), e:
print "WARNING: environment is incorrect: %s\nDid you just try to reset in a tty?" % e
return
diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt
index 2261d9e7b..f2108892b 100644
--- a/unity-shared/CMakeLists.txt
+++ b/unity-shared/CMakeLists.txt
@@ -41,6 +41,7 @@ set (UNITY_SHARED_SOURCES
BackgroundEffectHelper.cpp
DashStyle.cpp
FontSettings.cpp
+ KeyboardUtil.cpp
IMTextEntry.cpp
IconLoader.cpp
IconRenderer.cpp
diff --git a/unity-shared/CairoTexture.h b/unity-shared/CairoTexture.h
index dd08b3c0f..e546a9b32 100644
--- a/unity-shared/CairoTexture.h
+++ b/unity-shared/CairoTexture.h
@@ -24,7 +24,7 @@
#define UNITY_CAIROTEXTURE_H
#include <Nux/Nux.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <NuxGraphics/NuxGraphics.h>
#include <NuxGraphics/GLTextureResourceManager.h>
diff --git a/unity-shared/DashStyle.cpp b/unity-shared/DashStyle.cpp
index 36fd926e8..4fbb32ff2 100644
--- a/unity-shared/DashStyle.cpp
+++ b/unity-shared/DashStyle.cpp
@@ -32,7 +32,9 @@
#include <NuxCore/Color.h>
#include <NuxCore/Logger.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/ImageSurface.h>
+#include <NuxGraphics/CairoGraphics.h>
+
#include <Nux/PaintLayer.h>
#include <UnityCore/GLibSignal.h>
diff --git a/unity-shared/IMTextEntry.cpp b/unity-shared/IMTextEntry.cpp
index 2db7db813..db7c86c29 100644
--- a/unity-shared/IMTextEntry.cpp
+++ b/unity-shared/IMTextEntry.cpp
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: ni; tab-width: 2 -*-
/*
- * Copyright (C) 2011 Canonical Ltd
+ * Copyright (C) 2011-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Pubic License version 3 as
@@ -15,107 +15,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
-#include "config.h"
-
#include "IMTextEntry.h"
-
-#include <NuxCore/Logger.h>
-#include <UnityCore/GLibWrapper.h>
+#include <gtk/gtk.h>
namespace unity
{
-
-namespace
-{
-nux::logging::Logger logger("unity.imtextentry");
-}
-
NUX_IMPLEMENT_OBJECT_TYPE(IMTextEntry);
IMTextEntry::IMTextEntry()
: TextEntry("", NUX_TRACKER_LOCATION)
-{
- mouse_up.connect(sigc::mem_fun(this, &IMTextEntry::OnMouseButtonUp));
-}
-
-bool IMTextEntry::InspectKeyEvent(unsigned int event_type,
- unsigned int keysym,
- const char* character)
-{
- nux::Event const& event = nux::GetGraphicsDisplay()->GetCurrentEvent();
- bool need_to_filter_event = TryHandleSpecial(event);
+{}
- if (need_to_filter_event)
- need_to_filter_event = TextEntry::InspectKeyEvent(event_type, keysym, character);
-
- return need_to_filter_event;
-}
-
-bool IMTextEntry::TryHandleSpecial(nux::Event const& event)
+void IMTextEntry::CopyClipboard()
{
- /* If there is preedit, handle the event else where, but we
- want to be able to copy/paste while ibus is active */
- if (!preedit_.empty())
- return true;
-
- if (event.type != NUX_KEYDOWN)
- return false;
-
- unsigned int keyval = event.GetKeySym();
- bool shift = event.GetKeyModifierState(KEY_MODIFIER_SHIFT);
- bool ctrl = event.GetKeyModifierState(KEY_MODIFIER_CTRL);
- bool super = event.GetKeyModifierState(KEY_MODIFIER_SUPER);
- bool alt = event.GetKeyModifierState(KEY_MODIFIER_ALT);
+ int start, end;
- if ((ctrl && !shift && keyval == NUX_VK_x) || // Ctrl + X
- (shift && !ctrl && keyval == NUX_VK_DELETE)) // Shift + Del
- {
- Cut();
- }
- else if (ctrl && !shift && (keyval == NUX_VK_c || keyval == NUX_VK_INSERT)) // Ctrl + C / Ins
- {
- Copy();
- }
- else if ((ctrl && !shift && keyval == NUX_VK_v) || // Ctrl + V
- (shift && !ctrl && keyval == NUX_VK_INSERT)) // Shift + Ins
- {
- Paste();
- }
- else if (ctrl)
- {
- if (keyval == NUX_VK_LEFT || keyval == NUX_VK_RIGHT || // Ctrl + Move keys
- keyval == NUX_VK_HOME || keyval == NUX_VK_END || // Ctrl + Home / End
- keyval == NUX_VK_BACKSPACE || keyval == NUX_VK_DELETE || // Ctrl + Backspace / Delete
- keyval == NUX_VK_a) // Ctrl + A
- {
- return true;
- }
- }
- else if (!alt && !super)
+ if (GetSelectionBounds(&start, &end))
{
- return true;
+ GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text(clip, text_.c_str() + start, end - start);
}
-
- return false;
}
-void IMTextEntry::Cut()
+void IMTextEntry::PasteClipboard()
{
- Copy();
- DeleteSelection();
- QueueRefresh (true, true);
+ Paste();
}
-void IMTextEntry::Copy()
+void IMTextEntry::PastePrimaryClipboard()
{
- int start=0, end=0;
- if (GetSelectionBounds(&start, &end))
- {
- GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text(clip, text_.c_str() + start, end - start);
- }
+ Paste(true);
}
void IMTextEntry::Paste(bool primary)
@@ -145,18 +77,7 @@ void IMTextEntry::InsertText(std::string const& text)
int cursor = cursor_;
SetText(new_text.c_str());
SetCursor(cursor + text.length());
- QueueRefresh (true, true);
- }
-}
-
-void IMTextEntry::OnMouseButtonUp(int x, int y, unsigned long bflags, unsigned long kflags)
-{
- int button = nux::GetEventButton(bflags);
-
- if (button == 2)
- {
- SetCursor(XYToTextIndex(x,y));
- Paste(true);
+ QueueRefresh(true, true);
}
}
diff --git a/unity-shared/IMTextEntry.h b/unity-shared/IMTextEntry.h
index 983ae66ed..b39b37b85 100644
--- a/unity-shared/IMTextEntry.h
+++ b/unity-shared/IMTextEntry.h
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2011 Canonical Ltd
+ * Copyright (C) 2011-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
@@ -15,25 +15,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
#ifndef IM_TEXT_ENTRY_H
#define IM_TEXT_ENTRY_H
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-
#include <Nux/Nux.h>
#include <Nux/TextEntry.h>
-#include <UnityCore/GLibSignal.h>
-#include <UnityCore/GLibWrapper.h>
namespace unity
{
-using namespace unity::glib;
-using namespace nux;
-
class IMTextEntry : public nux::TextEntry
{
NUX_DECLARE_OBJECT_TYPE(IMTextEntry, nux::TextEntry);
@@ -41,16 +34,13 @@ public:
IMTextEntry();
bool im_preedit();
-private:
- bool InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character);
- void OnMouseButtonUp(int x, int y, unsigned long bflags, unsigned long kflags);
-
protected:
- bool TryHandleSpecial(nux::Event const& event);
virtual void InsertText(std::string const& text);
- virtual void Cut();
- virtual void Copy();
- virtual void Paste(bool primary = false);
+ virtual void CopyClipboard();
+ virtual void PasteClipboard();
+ virtual void PastePrimaryClipboard();
+
+ void Paste(bool primary = false);
};
}
diff --git a/unity-shared/IconRenderer.cpp b/unity-shared/IconRenderer.cpp
index bba7dbf43..7e87f9425 100644
--- a/unity-shared/IconRenderer.cpp
+++ b/unity-shared/IconRenderer.cpp
@@ -25,7 +25,7 @@
#include <NuxGraphics/GpuDevice.h>
#include <NuxGraphics/GLTextureResourceManager.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <gtk/gtk.h>
diff --git a/unity-shared/IconTexture.h b/unity-shared/IconTexture.h
index caf045da4..88428733c 100644
--- a/unity-shared/IconTexture.h
+++ b/unity-shared/IconTexture.h
@@ -25,7 +25,7 @@
#include <Nux/View.h>
// FIXME: Nux/TextureArea.h needs View included first.
#include <Nux/TextureArea.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <NuxGraphics/GraphicsEngine.h>
#include <UnityCore/GLibWrapper.h>
diff --git a/unity-shared/Introspectable.cpp b/unity-shared/Introspectable.cpp
index 59050a212..4ecd0fc18 100644
--- a/unity-shared/Introspectable.cpp
+++ b/unity-shared/Introspectable.cpp
@@ -38,7 +38,7 @@ Introspectable::~Introspectable()
child->_parents.remove(this);
}
-Introspectable::IntrospectableList const& Introspectable::GetIntrospectableChildren()
+Introspectable::IntrospectableList Introspectable::GetIntrospectableChildren()
{
return _children;
}
@@ -55,14 +55,14 @@ Introspectable::Introspect()
AddProperties(&builder);
- g_variant_builder_init(&child_builder, G_VARIANT_TYPE("a(sv)"));
+ g_variant_builder_init(&child_builder, G_VARIANT_TYPE("as"));
auto children = GetIntrospectableChildren();
for (auto it = children.begin(); it != children.end(); it++)
{
if ((*it)->GetName() != "")
{
- g_variant_builder_add(&child_builder, "(sv)", (*it)->GetName().c_str(), (*it)->Introspect());
+ g_variant_builder_add(&child_builder, "s", (*it)->GetName().c_str());
n_children++;
}
}
diff --git a/unity-shared/Introspectable.h b/unity-shared/Introspectable.h
index e6b299648..7814ca281 100644
--- a/unity-shared/Introspectable.h
+++ b/unity-shared/Introspectable.h
@@ -32,7 +32,7 @@ class Introspectable
{
public:
typedef std::list<Introspectable*> IntrospectableList;
-
+
Introspectable();
virtual ~Introspectable();
GVariant* Introspect();
@@ -40,7 +40,7 @@ public:
void AddChild(Introspectable* child);
void RemoveChild(Introspectable* child);
virtual void AddProperties(GVariantBuilder* builder) = 0;
- virtual IntrospectableList const& GetIntrospectableChildren();
+ virtual IntrospectableList GetIntrospectableChildren();
guint64 GetIntrospectionId() const;
protected:
diff --git a/plugins/unityshell/src/KeyboardUtil.cpp b/unity-shared/KeyboardUtil.cpp
index 50dc200a7..b65fbc15a 100644
--- a/plugins/unityshell/src/KeyboardUtil.cpp
+++ b/unity-shared/KeyboardUtil.cpp
@@ -17,9 +17,8 @@
* Authored by: Jason Smith <jason.smith@canonical.com>
*/
+#include <gdk/gdk.h>
#include <string.h>
-
-#include <stdio.h>
#include <cmath>
#include "KeyboardUtil.h"
@@ -31,7 +30,7 @@ KeyboardUtil::KeyboardUtil(Display *display)
: display_(display)
{
unsigned int fetch_mask = XkbGBN_KeyNamesMask | XkbGBN_ClientSymbolsMask | XkbGBN_GeometryMask;
- keyboard_ = XkbGetKeyboard (display, fetch_mask, XkbUseCoreKbd);
+ keyboard_ = XkbGetKeyboard (display, fetch_mask, XkbUseCoreKbd);
}
KeyboardUtil::~KeyboardUtil()
@@ -39,7 +38,7 @@ KeyboardUtil::~KeyboardUtil()
XkbFreeKeyboard (keyboard_, 0, True);
}
-bool KeyboardUtil::FindKeyInGeometry(XkbGeometryPtr geo, char *key_name, int& res_section, XkbBoundsRec& res_bounds)
+bool KeyboardUtil::FindKeyInGeometry(XkbGeometryPtr geo, char *key_name, int& res_section, XkbBoundsRec& res_bounds) const
{
// seems that Xkb does not give null terminated strings... was painful
int name_length = XkbKeyNameLength;
@@ -73,7 +72,7 @@ bool KeyboardUtil::FindKeyInGeometry(XkbGeometryPtr geo, char *key_name, int& re
return false;
}
-bool KeyboardUtil::CompareOffsets (int current_x, int current_y, int best_x, int best_y)
+bool KeyboardUtil::CompareOffsets(int current_x, int current_y, int best_x, int best_y) const
{
// never EVER prefer something higher on the keyboard than what we have
if (current_y > best_y)
@@ -85,7 +84,7 @@ bool KeyboardUtil::CompareOffsets (int current_x, int current_y, int best_x, int
return false;
}
-guint KeyboardUtil::ConvertKeyToKeycode (XkbKeyPtr key)
+guint KeyboardUtil::ConvertKeyToKeycode(XkbKeyPtr key) const
{
int min_code = keyboard_->min_key_code;
int max_code = keyboard_->max_key_code;
@@ -98,7 +97,7 @@ guint KeyboardUtil::ConvertKeyToKeycode (XkbKeyPtr key)
return 0;
}
-XkbBoundsRec KeyboardUtil::GetAbsoluteKeyBounds (XkbKeyPtr key, XkbRowPtr row, XkbSectionPtr section, XkbGeometryPtr geo)
+XkbBoundsRec KeyboardUtil::GetAbsoluteKeyBounds(XkbKeyPtr key, XkbRowPtr row, XkbSectionPtr section, XkbGeometryPtr geo) const
{
XkbShapePtr shape = XkbKeyShape(geo, key);
@@ -117,7 +116,7 @@ XkbBoundsRec KeyboardUtil::GetAbsoluteKeyBounds (XkbKeyPtr key, XkbRowPtr row, X
y_offset += local_shape->bounds.y2 - local_shape->bounds.y1;
else
x_offset += local_shape->bounds.x2 - local_shape->bounds.x1;
-
+
i++;
}
@@ -129,7 +128,7 @@ XkbBoundsRec KeyboardUtil::GetAbsoluteKeyBounds (XkbKeyPtr key, XkbRowPtr row, X
return result;
}
-bool KeyboardUtil::FindKeyInSectionAboveBounds (XkbGeometryPtr geo, int section_index, XkbBoundsRec const& target_bounds, guint &keycode)
+bool KeyboardUtil::FindKeyInSectionAboveBounds(XkbGeometryPtr geo, int section_index, XkbBoundsRec const& target_bounds, guint &keycode) const
{
XkbKeyPtr best = NULL;
int best_x_offset = G_MAXINT;
@@ -155,7 +154,7 @@ bool KeyboardUtil::FindKeyInSectionAboveBounds (XkbGeometryPtr geo, int section_
int center = (bounds.x1 + bounds.x2) / 2;
if (center < target_bounds.x1 || center > target_bounds.x2)
continue;
-
+
// make sure the key is actually above our target.
int current_y_offset = target_bounds.y1 - bounds.y2;
if (current_y_offset < 0)
@@ -181,7 +180,7 @@ bool KeyboardUtil::FindKeyInSectionAboveBounds (XkbGeometryPtr geo, int section_
return false;
}
-guint KeyboardUtil::GetKeycodeAboveKeySymbol(KeySym key_symbol)
+guint KeyboardUtil::GetKeycodeAboveKeySymbol(KeySym key_symbol) const
{
guint result = 0;
@@ -208,9 +207,38 @@ guint KeyboardUtil::GetKeycodeAboveKeySymbol(KeySym key_symbol)
if (found_key)
result = maybe;
}
-
+
return result;
}
+bool KeyboardUtil::IsPrintableKeySymbol(KeySym sym)
+{
+ bool printable_key = false;
+
+ if (sym == XK_Delete || sym == XK_BackSpace || sym == XK_Return)
+ {
+ printable_key = true;
+ }
+ else
+ {
+ unsigned int unicode = gdk_keyval_to_unicode(sym);
+ printable_key = g_unichar_isprint(unicode);
+ }
+
+ return printable_key;
+}
+
+bool KeyboardUtil::IsMoveKeySymbol(KeySym sym)
+{
+ bool move_key = false;
+
+ if (sym >= XK_Home && sym <= XK_Begin)
+ {
+ move_key = true;
+ }
+
+ return move_key;
+}
+
}
} \ No newline at end of file
diff --git a/plugins/unityshell/src/KeyboardUtil.h b/unity-shared/KeyboardUtil.h
index f88c066f8..0df116299 100644
--- a/plugins/unityshell/src/KeyboardUtil.h
+++ b/unity-shared/KeyboardUtil.h
@@ -33,22 +33,23 @@ namespace ui
class KeyboardUtil
{
-
public:
-
KeyboardUtil(Display *display);
- virtual ~KeyboardUtil();
+ ~KeyboardUtil();
+
+ guint GetKeycodeAboveKeySymbol(KeySym key_symbol) const;
- guint GetKeycodeAboveKeySymbol(KeySym key_symbol);
+ static bool IsPrintableKeySymbol(KeySym key_symbol);
+ static bool IsMoveKeySymbol(KeySym sym);
private:
- bool CompareOffsets (int current_x, int current_y, int best_x, int best_y);
- guint ConvertKeyToKeycode (XkbKeyPtr key);
+ bool CompareOffsets (int current_x, int current_y, int best_x, int best_y) const;
+ guint ConvertKeyToKeycode (XkbKeyPtr key) const;
- bool FindKeyInGeometry(XkbGeometryPtr geo, char *key_name, int& res_section, XkbBoundsRec& res_bounds);
- bool FindKeyInSectionAboveBounds (XkbGeometryPtr geo, int section, XkbBoundsRec const& target_bounds, guint &keycode);
+ bool FindKeyInGeometry(XkbGeometryPtr geo, char *key_name, int& res_section, XkbBoundsRec& res_bounds) const;
+ bool FindKeyInSectionAboveBounds (XkbGeometryPtr geo, int section, XkbBoundsRec const& target_bounds, guint &keycode) const;
- XkbBoundsRec GetAbsoluteKeyBounds (XkbKeyPtr key, XkbRowPtr row, XkbSectionPtr section, XkbGeometryPtr geo);
+ XkbBoundsRec GetAbsoluteKeyBounds (XkbKeyPtr key, XkbRowPtr row, XkbSectionPtr section, XkbGeometryPtr geo) const;
XkbDescPtr keyboard_;
Display *display_;
diff --git a/unity-shared/PanelStyle.cpp b/unity-shared/PanelStyle.cpp
index 6ceb965e3..2fce4eacf 100644
--- a/unity-shared/PanelStyle.cpp
+++ b/unity-shared/PanelStyle.cpp
@@ -27,7 +27,7 @@
#include <Nux/Nux.h>
#include <NuxGraphics/GraphicsEngine.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <NuxCore/Logger.h>
#include "CairoTexture.h"
diff --git a/unity-shared/PluginAdapterCompiz.cpp b/unity-shared/PluginAdapterCompiz.cpp
index ee84c0026..567d37f49 100644
--- a/unity-shared/PluginAdapterCompiz.cpp
+++ b/unity-shared/PluginAdapterCompiz.cpp
@@ -533,9 +533,7 @@ bool
PluginAdapter::IsWindowOnTop(guint32 xid)
{
Window win = xid;
- CompWindow* window;
-
- window = m_Screen->findWindow(win);
+ CompWindow* window = m_Screen->findWindow(win);
if (window)
{
@@ -543,6 +541,7 @@ PluginAdapter::IsWindowOnTop(guint32 xid)
return false;
CompPoint window_vp = window->defaultViewport();
+ nux::Geometry const& window_vp_geo = GetWorkAreaGeometry(window->id());
std::vector<Window> const& our_xids = nux::XInputWindow::NativeHandleList();
for (CompWindow* sibling = window->next; sibling; sibling = sibling->next)
@@ -550,6 +549,13 @@ PluginAdapter::IsWindowOnTop(guint32 xid)
if (sibling->defaultViewport() == window_vp && !sibling->minimized() &&
sibling->isMapped() && sibling->isViewable() && !sibling->inShowDesktopMode() &&
!(sibling->state() & CompWindowStateAboveMask) &&
+ !(sibling->type() & CompWindowTypeSplashMask) &&
+ !(sibling->type() & CompWindowTypeDockMask) &&
+ /* FIXME: This should be included by the above defaultViewport() check,
+ * but it doesn't seem to work correctly when there's only one workspace
+ * enabled, so please drop the line above when bug #996604 is fixed in
+ * Compiz. */
+ !window_vp_geo.Intersect(GetWindowGeometry(sibling->id())).IsNull() &&
std::find(our_xids.begin(), our_xids.end(), sibling->id()) == our_xids.end())
{
return false;
diff --git a/unity-shared/SearchBar.cpp b/unity-shared/SearchBar.cpp
index e47c0cb63..31f69f100 100644
--- a/unity-shared/SearchBar.cpp
+++ b/unity-shared/SearchBar.cpp
@@ -23,6 +23,7 @@
#include <Nux/HLayout.h>
#include <Nux/VLayout.h>
#include <NuxCore/Logger.h>
+
#include <UnityCore/Variant.h>
#include <glib/gi18n-lib.h>
@@ -250,7 +251,7 @@ void SearchBar::Init()
expand_icon_->mouse_click.connect(mouse_expand);
}
- sig_manager_.Add(new Signal<void, GtkSettings*, GParamSpec*>
+ sig_manager_.Add(new glib::Signal<void, GtkSettings*, GParamSpec*>
(gtk_settings_get_default(),
"notify::gtk-font-name",
sigc::mem_fun(this, &SearchBar::OnFontChanged)));
diff --git a/unity-shared/SearchBar.h b/unity-shared/SearchBar.h
index cc88e817f..130ffe7da 100644
--- a/unity-shared/SearchBar.h
+++ b/unity-shared/SearchBar.h
@@ -20,7 +20,7 @@
#ifndef SEARCH_BAR_H
#define SEARCH_BAR_H
-
+#include <gtk/gtk.h>
#include <NuxCore/Property.h>
#include <Nux/LayeredLayout.h>
#include <Nux/VLayout.h>
diff --git a/unity-shared/StaticCairoText.cpp b/unity-shared/StaticCairoText.cpp
index c01a46d25..7d9a3e2e9 100644
--- a/unity-shared/StaticCairoText.cpp
+++ b/unity-shared/StaticCairoText.cpp
@@ -27,7 +27,7 @@
#include <NuxCore/Size.h>
#include <Nux/TextureArea.h>
-#include <NuxImage/CairoGraphics.h>
+#include <NuxGraphics/CairoGraphics.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
diff --git a/unity-shared/UBusMessages.h b/unity-shared/UBusMessages.h
index 66b7faef5..603baa19f 100644
--- a/unity-shared/UBusMessages.h
+++ b/unity-shared/UBusMessages.h
@@ -35,7 +35,7 @@
#define UBUS_DASH_ABOUT_TO_SHOW "DASH_ABOUT_TO_SHOW"
// Signal sent when an overlay interface is shown, includes a gvariant
-// gvariant format is (sb), (interface-name, can_maximize?)
+// gvariant format is (sb), (interface-name, can_maximize?)
#define UBUS_OVERLAY_FORMAT_STRING "(sbi)"
#define UBUS_OVERLAY_HIDDEN "OVERLAY_HIDDEN"
#define UBUS_OVERLAY_SHOWN "OVERLAY_SHOWN"
@@ -88,6 +88,8 @@
// Signals sent when the switcher is shown, hidden or changes selection
#define UBUS_SWITCHER_SHOWN "SWITCHER_SHOWN"
+#define UBUS_SWITCHER_START "SWITCHER_SHOWN_START"
+#define UBUS_SWITCHER_END "SWITCHER_SHOWN_END"
#define UBUS_SWITCHER_SELECTION_CHANGED "SWITCHER_SELECTION_CHANGED"
#endif // UBUS_MESSAGES_H