diff options
| author | Gord Allott <gord.allott@canonical.com> | 2012-08-09 13:07:13 +0100 |
|---|---|---|
| committer | Gord Allott <gord.allott@canonical.com> | 2012-08-09 13:07:13 +0100 |
| commit | 70698c551979bdbd637a699b2b1413ece570c7ff (patch) | |
| tree | bf4d47bb803b67c48f3f324f48eafac886adcca0 | |
| parent | a766a584a9cc018e71402d09119a12b0f2fff347 (diff) | |
| parent | 7dafded1aa4111bb417021d0bbd14ed7d99f5baf (diff) | |
merge latest unity
(bzr r2419.6.16)
81 files changed, 1812 insertions, 1824 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ac6990d02..2aefa298f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,11 +133,14 @@ endif (DISABLE_MAINTAINER_CFLAGS) # # Compiz Plugins # -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;unity-protocol-private>=5.93.1") + +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;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;xfixes;unity-protocol-private>=5.93.1") # FIXME: unity-protocol-private shouldn't be there, but building of unityshell is just broken +set (UNITY_PROTOCOL_PRIVATE_DEPS "unity-protocol-private>=5.93.1") find_package (PkgConfig) pkg_check_modules (CACHED_UNITY_DEPS REQUIRED ${UNITY_PLUGIN_DEPS}) +pkg_check_modules (CACHED_UNITY_PRIVATE_DEPS REQUIRED ${UNITY_PROTOCOL_PRIVATE_DEPS}) add_subdirectory(unity-shared) add_subdirectory(panel) add_subdirectory(dash) @@ -7,7 +7,6 @@ If you want to hack on unity you need the following packages - gthread-2.0 - indicator - atk - - libutouch-geis Or if you are on ubuntu run the command, apt-get build-dep unity diff --git a/UnityCore/CMakeLists.txt b/UnityCore/CMakeLists.txt index ad33692b5..0ae006c41 100644 --- a/UnityCore/CMakeLists.txt +++ b/UnityCore/CMakeLists.txt @@ -1,5 +1,6 @@ find_package (PkgConfig) -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 unity-protocol-private) +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-protocol-private) +pkg_check_modules (PRIVATE_CORE_DEPS REQUIRED unity-protocol-private) execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} unity --variable lensesdir OUTPUT_VARIABLE _lensesdir OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -124,7 +125,8 @@ set (CORE_LIB_NAME "unity-core-${UNITY_API_VERSION}") add_library (${CORE_LIB_NAME} SHARED ${CORE_SOURCES}) set_target_properties(${CORE_LIB_NAME} PROPERTIES VERSION ${CORE_LIB_LT_CURRENT}.${CORE_LIB_LT_REV}.${CORE_LIB_LT_AGE} - SOVERSION ${CORE_LIB_LT_CURRENT}) + SOVERSION ${CORE_LIB_LT_CURRENT} + INSTALL_RPATH "${PRIVATE_CORE_DEPS_LIBRARY_DIRS}") install (TARGETS ${CORE_LIB_NAME} RUNTIME DESTINATION bin diff --git a/UnityCore/HomeLens.cpp b/UnityCore/HomeLens.cpp index 54cb14746..ee73a2775 100644 --- a/UnityCore/HomeLens.cpp +++ b/UnityCore/HomeLens.cpp @@ -105,7 +105,7 @@ public: /* Any existing categories with offsets >= target_cat_offset must be * pushed up. Update both maps by id and display name */ std::map<std::string,unsigned int>::iterator end = reg_by_id_.end(); - for (i = reg_by_id_.begin(); i != end; i++) + for (i = reg_by_id_.begin(); i != end; ++i) { if (i->second >= target_cat_offset) { @@ -114,7 +114,7 @@ public: } } - for (i = reg_by_display_name_.begin(), end = reg_by_display_name_.end(); i != end; i++) + for (i = reg_by_display_name_.begin(), end = reg_by_display_name_.end(); i != end; ++i) { if (i->second >= target_cat_offset) { @@ -637,7 +637,7 @@ void HomeLens::ResultsMerger::CheckCategoryRegistryDirty() * the category offset in the corresponding rows in the target model */ for (i = source_to_target_tags_.begin(), end = source_to_target_tags_.end(); - i != end; i++) + i != end; ++i) { source = i->first; target_tag = i->second; diff --git a/dash/ResultView.cpp b/dash/ResultView.cpp index 3b5f82907..463fbb3c5 100644 --- a/dash/ResultView.cpp +++ b/dash/ResultView.cpp @@ -97,7 +97,7 @@ void ResultView::RemoveResult(Result& result) ResultList::iterator it; std::string uri = result.uri; - for (it = results_.begin(); it != results_.end(); it++) + for (it = results_.begin(); it != results_.end(); ++it) { if (result.uri == (*it).uri) { diff --git a/dash/ResultViewGrid.cpp b/dash/ResultViewGrid.cpp index fc82a35f8..443e3aad2 100644 --- a/dash/ResultViewGrid.cpp +++ b/dash/ResultViewGrid.cpp @@ -409,7 +409,7 @@ void ResultViewGrid::OnKeyDown (unsigned long event_type, unsigned long event_ke total_rows = (expanded) ? total_rows : 1; // restrict to one row if not expanded // find the currently focused item - for (it = results_.begin(); it != results_.end(); it++) + for (it = results_.begin(); it != results_.end(); ++it) { std::string result_uri = (*it).uri; if (result_uri == focused_uri_) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index ceefbdb0e..3ac9e8db8 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -45,7 +45,6 @@ set (LAUNCHER_SOURCES FavoriteStore.cpp FavoriteStoreGSettings.cpp FavoriteStorePrivate.cpp - GeisAdapter.cpp HudLauncherIcon.cpp Launcher.cpp LauncherController.cpp diff --git a/launcher/FavoriteStoreGSettings.cpp b/launcher/FavoriteStoreGSettings.cpp index fe900099b..30ba42287 100644 --- a/launcher/FavoriteStoreGSettings.cpp +++ b/launcher/FavoriteStoreGSettings.cpp @@ -42,8 +42,8 @@ namespace { nux::logging::Logger logger("unity.favorites"); - -const char* SETTINGS_NAME = "com.canonical.Unity.Launcher"; +const std::string SETTINGS_NAME = "com.canonical.Unity.Launcher"; +const std::string SETTINGS_KEY = "favorites"; void on_settings_updated(GSettings* settings, const gchar* key, @@ -52,26 +52,17 @@ void on_settings_updated(GSettings* settings, } FavoriteStoreGSettings::FavoriteStoreGSettings() - : settings_(g_settings_new(SETTINGS_NAME)) - , ignore_signals_(false) + : ignore_signals_(false) + , settings_(g_settings_new(SETTINGS_NAME.c_str())) { - Init(); -} - -FavoriteStoreGSettings::FavoriteStoreGSettings(GSettingsBackend* backend) - : settings_(g_settings_new_with_backend(SETTINGS_NAME, backend)) - , ignore_signals_(false) -{ - Init(); -} + favorites_changed_.Connect(settings_, "changed::"+SETTINGS_KEY, [&] (GSettings*, gchar*) + { + Changed(); + }); -void FavoriteStoreGSettings::Init() -{ - g_signal_connect(settings_, "changed", G_CALLBACK(on_settings_updated), this); Refresh(); } - void FavoriteStoreGSettings::Refresh() { FillList(favorites_); @@ -81,7 +72,7 @@ void FavoriteStoreGSettings::FillList(FavoriteList& list) { list.clear(); - gchar** favs = g_settings_get_strv(settings_, "favorites"); + gchar** favs = g_settings_get_strv(settings_, SETTINGS_KEY.c_str()); for (int i = 0; favs[i] != NULL; ++i) { @@ -222,16 +213,16 @@ void FavoriteStoreGSettings::SaveFavorites(FavoriteList const& favorites, bool i } ignore_signals_ = ignore; - if (!g_settings_set_strv(settings_, "favorites", favs)) + if (!g_settings_set_strv(settings_, SETTINGS_KEY.c_str(), favs)) { LOG_WARNING(logger) << "Saving favorites failed."; } ignore_signals_ = false; } -void FavoriteStoreGSettings::Changed(std::string const& key) +void FavoriteStoreGSettings::Changed() { - if (ignore_signals_ or key != "favorites") + if (ignore_signals_) return; FavoriteList old(favorites_); @@ -261,20 +252,5 @@ void FavoriteStoreGSettings::Changed(std::string const& key) } -namespace -{ - -void on_settings_updated(GSettings* settings, - const gchar* key, - FavoriteStoreGSettings* self) -{ - if (settings and key) - { - self->Changed(key); - } -} - -} // anonymous namespace - } // namespace internal } // namespace unity diff --git a/launcher/FavoriteStoreGSettings.h b/launcher/FavoriteStoreGSettings.h index 600b6162c..5fd084b90 100644 --- a/launcher/FavoriteStoreGSettings.h +++ b/launcher/FavoriteStoreGSettings.h @@ -24,6 +24,7 @@ #include "FavoriteStore.h" #include <UnityCore/GLibWrapper.h> +#include <UnityCore/GLibSignal.h> // An abstract object that facilitates getting and modifying the list of favorites // Use GetDefault () to get the correct store for the session @@ -36,7 +37,6 @@ class FavoriteStoreGSettings : public FavoriteStore { public: FavoriteStoreGSettings(); - FavoriteStoreGSettings(GSettingsBackend* backend); virtual FavoriteList const& GetFavorites(); virtual void AddFavorite(std::string const& desktop_path, int position); @@ -45,17 +45,15 @@ public: void SaveFavorites(FavoriteList const& favorites, bool ignore = true); virtual void SetFavorites(FavoriteList const& desktop_paths); - //Methods - void Changed(std::string const& key); - private: - void Init(); void Refresh(); + void Changed(); void FillList(FavoriteList& list); FavoriteList favorites_; - glib::Object<GSettings> settings_; bool ignore_signals_; + glib::Object<GSettings> settings_; + glib::Signal<void, GSettings*, gchar*> favorites_changed_; }; } diff --git a/launcher/GeisAdapter.cpp b/launcher/GeisAdapter.cpp deleted file mode 100644 index d9fe220af..000000000 --- a/launcher/GeisAdapter.cpp +++ /dev/null @@ -1,521 +0,0 @@ -// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- -/* - * Copyright (C) 2010 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * Authored by: Jason Smith <jason.smith@canonical.com> - */ - -#include <glib.h> -#include <gdk/gdkx.h> -#include <NuxCore/Logger.h> -#include "GeisAdapter.h" - -namespace -{ - GeisAdapter* adaptor_instance = nullptr; - nux::logging::Logger logger("unity.geisadapter"); -} - -/* static */ -GeisAdapter& GeisAdapter::Instance() -{ - if (!adaptor_instance) - { - LOG_ERROR(logger) << "No GeisAdapter created yet."; - } - - return *adaptor_instance; -} - -GeisAdapter::GeisAdapter() : _root_instance(nullptr) -{ - if (adaptor_instance) - { - LOG_ERROR(logger) << "More than one GeisAdapter created."; - } - else - { - adaptor_instance = this; - } - RegisterRootInstance(); -} - -GeisAdapter::~GeisAdapter() -{ - if (_root_instance != nullptr) - geis_finish(_root_instance); - if (adaptor_instance == this) - { - adaptor_instance = nullptr; - } -} - -void -GeisAdapter::Run() -{ - int fd = -1; - GeisStatus status = GEIS_STATUS_NOT_SUPPORTED; - - if (_root_instance != nullptr) - status = geis_configuration_get_value(_root_instance, GEIS_CONFIG_UNIX_FD, &fd); - - if (status != GEIS_STATUS_SUCCESS) - return; - - _watch_id = g_io_add_watch(g_io_channel_unix_new(fd), - G_IO_IN, - &GeisAdapter::OnWatchIn, - this); -} - -gboolean -GeisAdapter::OnWatchIn(GIOChannel* source, GIOCondition condition, gpointer data) -{ - GeisAdapter* self = static_cast<GeisAdapter*>(data); - geis_event_dispatch(self->_root_instance); - return true; -} - -void -GeisAdapter::InputDeviceAdded(void* cookie, GeisInputDeviceId device_id, void* attrs) -{ -} - - -void -GeisAdapter::InputDeviceChanged(void* cookie, GeisInputDeviceId device_id, void* attrs) -{ -} - - -void -GeisAdapter::InputDeviceRemoved(void* cookie, GeisInputDeviceId device_id, void* attrs) -{ -} - -void -GeisAdapter::GestureAdded(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize count, GeisGestureAttr* attrs) -{ -} - -void -GeisAdapter::GestureRemoved(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize count, GeisGestureAttr* attrs) -{ -} - -void -GeisAdapter::GestureStart(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize count, GeisGestureAttr* attrs) -{ - GeisAdapter* self = static_cast<GeisAdapter*>(cookie); - - if (gesture_type == GEIS_GESTURE_PRIMITIVE_DRAG) - { - GeisDragData* data = self->ProcessDragGesture(count, attrs); - data->id = gesture_id; - self->drag_start.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_ROTATE) - { - GeisRotateData* data = self->ProcessRotateGesture(count, attrs); - data->id = gesture_id; - self->rotate_start.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_PINCH) - { - GeisPinchData* data = self->ProcessPinchGesture(count, attrs); - data->id = gesture_id; - self->pinch_start.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_TAP) - { - GeisTapData* data = self->ProcessTapGesture(count, attrs); - data->id = gesture_id; - self->tap.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_TOUCH) - { - GeisTouchData* data = self->ProcessTouchGesture(count, attrs); - data->id = gesture_id; - self->touch_start.emit(data); - g_free(data); - } -} - -void -GeisAdapter::GestureUpdate(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize count, GeisGestureAttr* attrs) -{ - GeisAdapter* self = static_cast<GeisAdapter*>(cookie); - - if (gesture_type == GEIS_GESTURE_PRIMITIVE_DRAG) - { - GeisDragData* data = self->ProcessDragGesture(count, attrs); - data->id = gesture_id; - self->drag_update.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_ROTATE) - { - GeisRotateData* data = self->ProcessRotateGesture(count, attrs); - data->id = gesture_id; - self->rotate_update.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_PINCH) - { - GeisPinchData* data = self->ProcessPinchGesture(count, attrs); - data->id = gesture_id; - self->pinch_update.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_TAP) - { - GeisTapData* data = self->ProcessTapGesture(count, attrs); - data->id = gesture_id; - self->tap.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_TOUCH) - { - GeisTouchData* data = self->ProcessTouchGesture(count, attrs); - data->id = gesture_id; - self->touch_update.emit(data); - g_free(data); - } -} - -void -GeisAdapter::GestureFinish(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize count, GeisGestureAttr* attrs) -{ - GeisAdapter* self = static_cast<GeisAdapter*>(cookie); - - if (gesture_type == GEIS_GESTURE_PRIMITIVE_DRAG) - { - GeisDragData* data = self->ProcessDragGesture(count, attrs); - data->id = gesture_id; - self->drag_finish.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_ROTATE) - { - GeisRotateData* data = self->ProcessRotateGesture(count, attrs); - data->id = gesture_id; - self->rotate_finish.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_PINCH) - { - GeisPinchData* data = self->ProcessPinchGesture(count, attrs); - data->id = gesture_id; - self->pinch_finish.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_TAP) - { - GeisTapData* data = self->ProcessTapGesture(count, attrs); - data->id = gesture_id; - self->tap.emit(data); - g_free(data); - } - else if (gesture_type == GEIS_GESTURE_PRIMITIVE_TOUCH) - { - GeisTouchData* data = self->ProcessTouchGesture(count, attrs); - data->id = gesture_id; - self->touch_finish.emit(data); - g_free(data); - } -} - -GeisAdapter::GeisTapData* GeisAdapter::ProcessTapGesture(GeisSize count, GeisGestureAttr* attrs) -{ - GeisTapData* result = (GeisTapData*) g_malloc0(sizeof(GeisTapData)); - - int i; - for (i = 0; i < (int) count; i++) - { - GeisGestureAttr attr = attrs[i]; - if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID)) - result->device_id = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID)) - result->window = (Window) attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP)) - result->timestamp = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X)) - result->focus_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y)) - result->focus_y = attr.float_val; - else if (g_str_equal (attr.name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) - result->touches = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_GESTURE_NAME)) - { - if (!g_strcmp0(attr.string_val, GEIS_GESTURE_TYPE_TAP1)) - result->touches = 1; - else if (!g_strcmp0(attr.string_val, GEIS_GESTURE_TYPE_TAP2)) - result->touches = 2; - else if (!g_strcmp0(attr.string_val, GEIS_GESTURE_TYPE_TAP3)) - result->touches = 3; - else if (!g_strcmp0(attr.string_val, GEIS_GESTURE_TYPE_TAP4)) - result->touches = 4; - else if (!g_strcmp0(attr.string_val, GEIS_GESTURE_TYPE_TAP5)) - result->touches = 5; - } - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TAP_TIME)) - result->tap_length_ms = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_POSITION_X)) - result->position_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y)) - result->position_y = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1)) - result->bound_x1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1)) - result->bound_y1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2)) - result->bound_x2 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2)) - result->bound_y2 = attr.float_val; - } - - return result; -} - -GeisAdapter::GeisTouchData* GeisAdapter::ProcessTouchGesture(GeisSize count, GeisGestureAttr* attrs) -{ - GeisTouchData* result = (GeisTouchData*) g_malloc0(sizeof(GeisTouchData)); - - int i; - for (i = 0; i < (int) count; i++) - { - GeisGestureAttr attr = attrs[i]; - if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID)) - result->device_id = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID)) - result->window = (Window) attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP)) - result->timestamp = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X)) - result->focus_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y)) - result->focus_y = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) - result->touches = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1)) - result->bound_x1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1)) - result->bound_y1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2)) - result->bound_x2 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2)) - result->bound_y2 = attr.float_val; - } - - return result; -} - -GeisAdapter::GeisDragData* GeisAdapter::ProcessDragGesture(GeisSize count, GeisGestureAttr* attrs) -{ - GeisDragData* result = (GeisDragData*) g_malloc0(sizeof(GeisDragData)); - - int i; - for (i = 0; i < (int) count; i++) - { - GeisGestureAttr attr = attrs[i]; - if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID)) - result->device_id = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID)) - result->window = (Window) attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP)) - result->timestamp = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X)) - result->focus_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y)) - result->focus_y = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) - result->touches = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_POSITION_X)) - result->position_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_POSITION_Y)) - result->position_y = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X)) - result->velocity_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y)) - result->velocity_y = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_DELTA_X)) - result->delta_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_DELTA_Y)) - result->delta_y = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1)) - result->bound_x1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1)) - result->bound_y1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2)) - result->bound_x2 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2)) - result->bound_y2 = attr.float_val; - } - - return result; -} - -GeisAdapter::GeisPinchData* GeisAdapter::ProcessPinchGesture(GeisSize count, GeisGestureAttr* attrs) -{ - GeisPinchData* result = (GeisPinchData*) g_malloc0(sizeof(GeisPinchData)); - - int i; - for (i = 0; i < (int) count; i++) - { - GeisGestureAttr attr = attrs[i]; - if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID)) - result->device_id = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID)) - result->window = (Window) attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP)) - result->timestamp = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X)) - result->focus_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y)) - result->focus_y = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) - result->touches = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_RADIUS)) - result->radius = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_RADIUS_DELTA)) - result->radius_delta = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_RADIAL_VELOCITY)) - result->radius_velocity = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1)) - result->bound_x1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1)) - result->bound_y1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2)) - result->bound_x2 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2)) - result->bound_y2 = attr.float_val; - } - - return result; -} - -GeisAdapter::GeisRotateData* GeisAdapter::ProcessRotateGesture(GeisSize count, GeisGestureAttr* attrs) -{ - GeisRotateData* result = (GeisRotateData*) g_malloc0(sizeof(GeisRotateData)); - - int i; - for (i = 0; i < (int) count; i++) - { - GeisGestureAttr attr = attrs[i]; - if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_DEVICE_ID)) - result->device_id = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_CHILD_WINDOW_ID)) - result->window = (Window) attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TIMESTAMP)) - result->timestamp = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_X)) - result->focus_x = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_FOCUS_Y)) - result->focus_y = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_TOUCHES)) - result->touches = attr.integer_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_ANGLE)) - result->angle = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_ANGLE_DELTA)) - result->angle_delta = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_ANGULAR_VELOCITY)) - result->angle_velocity = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X1)) - result->bound_x1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y1)) - result->bound_y1 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_X2)) - result->bound_x2 = attr.float_val; - else if (g_str_equal(attr.name, GEIS_GESTURE_ATTRIBUTE_BOUNDINGBOX_Y2)) - result->bound_y2 = attr.float_val; - } - - return result; -} - -static const char* s_gestures[] = -{ - GEIS_GESTURE_TYPE_DRAG3, GEIS_GESTURE_TYPE_TAP3, GEIS_GESTURE_TYPE_ROTATE3, GEIS_GESTURE_TYPE_PINCH3, GEIS_GESTURE_TYPE_TOUCH3, - GEIS_GESTURE_TYPE_DRAG4, GEIS_GESTURE_TYPE_TAP4, GEIS_GESTURE_TYPE_ROTATE4, GEIS_GESTURE_TYPE_PINCH4, GEIS_GESTURE_TYPE_TOUCH4, - GEIS_GESTURE_TYPE_SYSTEM, - NULL -}; - -void -GeisAdapter::RegisterRootInstance() -{ - static GeisInputFuncs input_funcs = - { - &GeisAdapter::InputDeviceAdded, - &GeisAdapter::InputDeviceChanged, - &GeisAdapter::InputDeviceRemoved - }; - - static GeisGestureFuncs gesture_funcs = - { - &GeisAdapter::GestureAdded, - &GeisAdapter::GestureRemoved, - &GeisAdapter::GestureStart, - &GeisAdapter::GestureUpdate, - &GeisAdapter::GestureFinish - }; - - GeisStatus status = GEIS_UNKNOWN_ERROR; - - GeisXcbWinInfo xcb_win_info; - xcb_win_info.display_name = NULL, - xcb_win_info.screenp = NULL, - xcb_win_info.window_id = gdk_x11_get_default_root_xwindow(); - - GeisWinInfo win_info = - { - GEIS_XCB_FULL_WINDOW, - &xcb_win_info - }; - GeisInstance instance; - - status = geis_init(&win_info, &instance); - if (status != GEIS_STATUS_SUCCESS) - { - fprintf(stderr, "error in geis_init\n"); - return; - } - - status = geis_input_devices(instance, &input_funcs, this); - if (status != GEIS_STATUS_SUCCESS) - { - fprintf(stderr, "error subscribing to input devices\n"); - geis_finish(instance); - return; - } - - status = geis_subscribe(instance, - GEIS_ALL_INPUT_DEVICES, - s_gestures, - &gesture_funcs, - this); - if (status != GEIS_STATUS_SUCCESS) - { - fprintf(stderr, "error subscribing to gestures\n"); - geis_finish(instance); - return; - } - - _root_instance = instance; -} diff --git a/launcher/GeisAdapter.h b/launcher/GeisAdapter.h deleted file mode 100644 index f68923bed..000000000 --- a/launcher/GeisAdapter.h +++ /dev/null @@ -1,172 +0,0 @@ -// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- -/* - * Copyright (C) 2010 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * aint with this program. If not, see <http://www.gnu.org/licenses/>. - * - * Authored by: Jason Smith <jason.smith@canonical.com> - */ - -#ifndef GEISADAPTER_H -#define GEISADAPTER_H - -/* Compiz */ -#include <sigc++/sigc++.h> -#include <geis/geis.h> -#include <Nux/Nux.h> - -class GeisAdapter : public sigc::trackable -{ -public: - static GeisAdapter& Instance(); - - GeisAdapter(); - ~GeisAdapter(); - - void Run(); - - typedef struct _GeisTapData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - int tap_length_ms; - float position_x; - float position_y; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisTapData; - - typedef struct _GeisDragData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - float delta_x; - float delta_y; - float velocity_x; - float velocity_y; - float position_x; - float position_y; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisDragData; - - typedef struct _GeisRotateData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - float angle; - float angle_delta; - float angle_velocity; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisRotateData; - - typedef struct _GeisPinchData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - float radius; - float radius_delta; - float radius_velocity; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisPinchData; - - typedef struct _GeisTouchData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisTouchData; - - sigc::signal<void, GeisTapData*> tap; - - sigc::signal<void, GeisDragData*> drag_start; - sigc::signal<void, GeisDragData*> drag_update; - sigc::signal<void, GeisDragData*> drag_finish; - - sigc::signal<void, GeisRotateData*> rotate_start; - sigc::signal<void, GeisRotateData*> rotate_update; - sigc::signal<void, GeisRotateData*> rotate_finish; - - sigc::signal<void, GeisPinchData*> pinch_start; - sigc::signal<void, GeisPinchData*> pinch_update; - sigc::signal<void, GeisPinchData*> pinch_finish; - - sigc::signal<void, GeisTouchData*> touch_start; - sigc::signal<void, GeisTouchData*> touch_update; - sigc::signal<void, GeisTouchData*> touch_finish; -protected: - static gboolean OnWatchIn(GIOChannel* source, GIOCondition condition, gpointer data); - - static void InputDeviceAdded(void* cookie, GeisInputDeviceId device_id, void* attrs); - static void InputDeviceChanged(void* cookie, GeisInputDeviceId device_id, void* attrs); - static void InputDeviceRemoved(void* cookie, GeisInputDeviceId device_id, void* attrs); - - static void GestureAdded(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr* attrs); - static void GestureRemoved(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr* attrs); - - static void GestureStart(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr* attrs); - static void GestureUpdate(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr* attrs); - static void GestureFinish(void* cookie, GeisGestureType gesture_type, GeisGestureId gesture_id, GeisSize attr_count, GeisGestureAttr* attrs); - - GeisTapData* ProcessTapGesture(GeisSize attr_count, GeisGestureAttr* attrs); - GeisDragData* ProcessDragGesture(GeisSize attr_count, GeisGestureAttr* attrs); - GeisPinchData* ProcessPinchGesture(GeisSize attr_count, GeisGestureAttr* attrs); - GeisRotateData* ProcessRotateGesture(GeisSize attr_count, GeisGestureAttr* attrs); - GeisTouchData* ProcessTouchGesture(GeisSize attr_count, GeisGestureAttr* attrs); - -private: - void RegisterRootInstance(); - - GeisInstance _root_instance; - guint _watch_id; -}; - -#endif diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp index bd6ebb3c5..5d4eff150 100644 --- a/launcher/Launcher.cpp +++ b/launcher/Launcher.cpp @@ -29,6 +29,7 @@ #include <NuxCore/Logger.h> #include <NuxGraphics/NuxGraphics.h> +#include <NuxGraphics/GestureEvent.h> #include <NuxGraphics/GpuDevice.h> #include <NuxGraphics/GLTextureResourceManager.h> @@ -91,6 +92,7 @@ const int MOUSE_DEADZONE = 15; const float DRAG_OUT_PIXELS = 300.0f; const std::string DND_CHECK_TIMEOUT = "dnd-check-timeout"; +const std::string STRUT_HACK_TIMEOUT = "strut-hack-timeout"; const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout"; const std::string SCROLL_TIMEOUT = "scroll-timeout"; const std::string ANIMATION_IDLE = "animation-idle"; @@ -136,8 +138,8 @@ Launcher::Launcher(nux::BaseWindow* parent, , _launcher_drag_delta_min(0) , _enter_y(0) , _last_button_press(0) - , _drag_out_id(0) , _drag_out_delta_x(0.0f) + , _drag_gesture_ongoing(false) , _last_reveal_progress(0.0f) , _collection_window(collection_window) , _selection_atom(0) @@ -185,11 +187,6 @@ Launcher::Launcher(nux::BaseWindow* parent, plugin_adapter.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); plugin_adapter.compiz_screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::EnsureAnimation)); - GeisAdapter& adapter = GeisAdapter::Instance(); - adapter.drag_start.connect(sigc::mem_fun(this, &Launcher::OnDragStart)); - adapter.drag_update.connect(sigc::mem_fun(this, &Launcher::OnDragUpdate)); - adapter.drag_finish.connect(sigc::mem_fun(this, &Launcher::OnDragFinish)); - display.changed.connect(sigc::mem_fun(this, &Launcher::OnDisplayChanged)); // 0 out timers to avoid wonky startups @@ -233,45 +230,39 @@ void Launcher::OnDisplayChanged(Display* display) _collection_window->display = display; } -void Launcher::OnDragStart(GeisAdapter::GeisDragData* data) +void +Launcher::OnDragStart(const nux::GestureEvent &event) { - if (_drag_out_id && _drag_out_id == data->id) - return; - - if (data->touches == 4) + _drag_gesture_ongoing = true; + if (_hidden) { - _drag_out_id = data->id; - if (_hidden) - { - _drag_out_delta_x = 0.0f; - } - else - { - _drag_out_delta_x = DRAG_OUT_PIXELS; - _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false); - } + _drag_out_delta_x = 0.0f; + } + else + { + _drag_out_delta_x = DRAG_OUT_PIXELS; + _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, false); } } -void Launcher::OnDragUpdate(GeisAdapter::GeisDragData* data) +void +Launcher::OnDragUpdate(const nux::GestureEvent &event) { - if (data->id == _drag_out_id) - { - _drag_out_delta_x = CLAMP(_drag_out_delta_x + data->delta_x, 0.0f, DRAG_OUT_PIXELS); - EnsureAnimation(); - } + _drag_out_delta_x = + CLAMP(_drag_out_delta_x + event.GetDelta().x, 0.0f, DRAG_OUT_PIXELS); + EnsureAnimation(); } -void Launcher::OnDragFinish(GeisAdapter::GeisDragData* data) +void +Launcher::OnDragFinish(const nux::GestureEvent &event) { - if (data->id == _drag_out_id) - { - if (_drag_out_delta_x >= DRAG_OUT_PIXELS - 90.0f) - _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, true); - TimeUtil::SetTimeStruct(&_times[TIME_DRAG_OUT], &_times[TIME_DRAG_OUT], ANIM_DURATION_SHORT); - _drag_out_id = 0; - EnsureAnimation(); - } + if (_drag_out_delta_x >= DRAG_OUT_PIXELS - 90.0f) + _hide_machine.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, true); + TimeUtil::SetTimeStruct(&_times[TIME_DRAG_OUT], + &_times[TIME_DRAG_OUT], + ANIM_DURATION_SHORT); + EnsureAnimation(); + _drag_gesture_ongoing = false; } void Launcher::AddProperties(GVariantBuilder* builder) @@ -341,9 +332,11 @@ float Launcher::DragOutProgress(struct timespec const& current) const float timeout = CLAMP((float)(unity::TimeUtil::TimeDelta(¤t, &_times[TIME_DRAG_OUT])) / (float) ANIM_DURATION_SHORT, 0.0f, 1.0f); float progress = CLAMP(_drag_out_delta_x / DRAG_OUT_PIXELS, 0.0f, 1.0f); - if (_drag_out_id || _hide_machine.GetQuirk(LauncherHideMachine::MT_DRAG_OUT)) + if (_drag_gesture_ongoing + || _hide_machine.GetQuirk(LauncherHideMachine::MT_DRAG_OUT)) return progress; - return progress * (1.0f - timeout); + else + return progress * (1.0f - timeout); } float Launcher::AutohideProgress(struct timespec const& current) const @@ -473,7 +466,7 @@ bool Launcher::AnimationInProgress() const // animations happening on specific icons LauncherModel::iterator it; - for (it = _model->begin(); it != _model->end(); it++) + for (it = _model->begin(); it != _model->end(); ++it) if (IconNeedsAnimation(*it, current)) return true; @@ -997,7 +990,7 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, // compute required height of launcher AND folding threshold float sum = 0.0f + center.y; float folding_threshold = launcher_height - _icon_size / 2.5f; - for (it = _model->begin(); it != _model->end(); it++) + for (it = _model->begin(); it != _model->end(); ++it) { float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current); sum += height; @@ -1106,7 +1099,7 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, // wont start jumping around). As a general rule ANY if () statements that modify center.y should be seen // as bugs. int index = 1; - for (it = _model->main_begin(); it != _model->main_end(); it++) + for (it = _model->main_begin(); it != _model->main_end(); ++it) { RenderArg arg; AbstractLauncherIcon::Ptr icon = *it; @@ -1120,7 +1113,7 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, // compute maximum height of shelf float shelf_sum = 0.0f; - for (it = _model->shelf_begin(); it != _model->shelf_end(); it++) + for (it = _model->shelf_begin(); it != _model->shelf_end(); ++it) { float height = (_icon_size + _space_between_icons) * IconVisibleProgress(*it, current); shelf_sum += height; @@ -1134,7 +1127,7 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args, folding_threshold += shelf_delta; center.y += shelf_delta; - for (it = _model->shelf_begin(); it != _model->shelf_end(); it++) + for (it = _model->shelf_begin(); it != _model->shelf_end(); ++it) { RenderArg arg; AbstractLauncherIcon::Ptr icon = *it; @@ -1429,6 +1422,17 @@ LauncherHideMode Launcher::GetHideMode() const /* End Launcher Show/Hide logic */ +// Hacks around compiz failing to see the struts because the window was just mapped. +bool Launcher::StrutHack() +{ + _parent->InputWindowEnableStruts(false); + + if (options()->hide_mode == LAUNCHER_HIDE_NEVER) + _parent->InputWindowEnableStruts(true); + + return false; +} + void Launcher::OnOptionsChanged(Options::Ptr options) { UpdateOptions(options); @@ -1470,6 +1474,12 @@ void Launcher::SetHideMode(LauncherHideMode hidemode) else { _parent->EnableInputWindow(true, launcher::window_title, false, false); + + if (!sources_.GetSource(STRUT_HACK_TIMEOUT)) + { + sources_.AddTimeout(1000, sigc::mem_fun(this, &Launcher::StrutHack), STRUT_HACK_TIMEOUT); + } + _parent->InputWindowEnableStruts(true); } @@ -1908,7 +1918,7 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) EventLogic(); /* draw launcher */ - for (rev_it = args.rbegin(); rev_it != args.rend(); rev_it++) + for (rev_it = args.rbegin(); rev_it != args.rend(); ++rev_it) { if ((*rev_it).stick_thingy) gPainter.Paint2DQuadColor(GfxContext, @@ -2114,7 +2124,7 @@ void Launcher::UpdateDragWindowPosition(int x, int y) AbstractLauncherIcon::Ptr iconBeforeHover; LauncherModel::iterator it; LauncherModel::iterator prevIt = _model->end(); - for (it = _model->begin(); it != _model->end(); it++) + for (it = _model->begin(); it != _model->end(); ++it) { if (!(*it)->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE) || !(*it)->IsVisibleOnMonitor(monitor)) continue; @@ -2236,9 +2246,7 @@ void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags) { - SetMousePosition(x, y); SetStateMouseOverLauncher(false); - //AbstractLauncherIcon::SetSkipTooltipDelay(false); EventLogic(); EnsureAnimation(); @@ -2460,7 +2468,7 @@ AbstractLauncherIcon::Ptr Launcher::MouseIconIntersection(int x, int y) nux::Point2 mouse_position(x, y); int inside = 0; - for (it = _model->begin(); it != _model->end(); it++) + for (it = _model->begin(); it != _model->end(); ++it) { if (!(*it)->GetQuirk(AbstractLauncherIcon::QUIRK_VISIBLE) || !(*it)->IsVisibleOnMonitor(monitor)) continue; @@ -2505,7 +2513,26 @@ void Launcher::RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLaun RestoreSystemRenderTarget(); } -void Launcher::SetOffscreenRenderTarget(nux::ObjectPtr<nux::IOpenGLBaseTexture> texture) +nux::GestureDeliveryRequest Launcher::GestureEvent(const nux::GestureEvent &event) +{ + switch(event.type) + { + case nux::EVENT_GESTURE_BEGIN: + OnDragStart(event); + break; + case nux::EVENT_GESTURE_UPDATE: + OnDragUpdate(event); + break; + default: // EVENT_GESTURE_END + OnDragFinish(event); + break; + } + + return nux::GestureDeliveryRequest::NONE; +} + +void +Launcher::SetOffscreenRenderTarget(nux::ObjectPtr<nux::IOpenGLBaseTexture> texture) { int width = texture->GetWidth(); int height = texture->GetHeight(); diff --git a/launcher/Launcher.h b/launcher/Launcher.h index 3c1c010d4..a44671a3d 100644 --- a/launcher/Launcher.h +++ b/launcher/Launcher.h @@ -32,7 +32,6 @@ #include "DNDCollectionWindow.h" #include "DndData.h" #include "EdgeBarrierController.h" -#include "GeisAdapter.h" #include "unity-shared/Introspectable.h" #include "LauncherModel.h" #include "LauncherOptions.h" @@ -136,6 +135,7 @@ public: void RenderIconToTexture(nux::GraphicsEngine& GfxContext, AbstractLauncherIcon::Ptr icon, nux::ObjectPtr<nux::IOpenGLBaseTexture> texture); + virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event); protected: // Introspectable methods std::string GetName() const; @@ -183,9 +183,9 @@ private: void OnWindowMapped(guint32 xid); void OnWindowUnmapped(guint32 xid); - void OnDragStart(GeisAdapter::GeisDragData* data); - void OnDragUpdate(GeisAdapter::GeisDragData* data); - void OnDragFinish(GeisAdapter::GeisDragData* data); + void OnDragStart(const nux::GestureEvent &event); + void OnDragUpdate(const nux::GestureEvent &event); + void OnDragFinish(const nux::GestureEvent &event); bool HandleBarrierEvent(ui::PointerBarrierWrapper* owner, ui::BarrierEvent::Ptr event); @@ -193,6 +193,7 @@ private: void OnSelectionChanged(AbstractLauncherIcon::Ptr selection); + bool StrutHack(); bool StartIconDragTimeout(); bool OnScrollTimeout(); bool OnUpdateDragManagerTimeout(); @@ -362,8 +363,8 @@ private: int _launcher_drag_delta_min; int _enter_y; int _last_button_press; - int _drag_out_id; float _drag_out_delta_x; + bool _drag_gesture_ongoing; float _last_reveal_progress; nux::Point2 _mouse_position; diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp index 49109c394..9b627daad 100644 --- a/launcher/LauncherController.cpp +++ b/launcher/LauncherController.cpp @@ -776,11 +776,12 @@ std::vector<char> Controller::GetAllShortcuts() const return shortcuts; } -std::vector<AbstractLauncherIcon::Ptr> Controller::GetAltTabIcons(bool current) const +std::vector<AbstractLauncherIcon::Ptr> Controller::GetAltTabIcons(bool current, bool show_desktop_disabled) const { std::vector<AbstractLauncherIcon::Ptr> results; - results.push_back(pimpl->desktop_icon_); + if (!show_desktop_disabled) + results.push_back(pimpl->desktop_icon_); for (auto icon : *(pimpl->model_)) { @@ -940,7 +941,7 @@ bool Controller::HandleLauncherKeyEvent(Display *display, unsigned int key_sym, LauncherModel::iterator it; // Shortcut to start launcher icons. Only relies on Keycode, ignore modifier - for (it = pimpl->model_->begin(); it != pimpl->model_->end(); it++) + for (it = pimpl->model_->begin(); it != pimpl->model_->end(); ++it) { if ((XKeysymToKeycode(display, (*it)->GetShortcut()) == key_code) || ((gchar)((*it)->GetShortcut()) == key_string[0])) diff --git a/launcher/LauncherController.h b/launcher/LauncherController.h index d636dc082..3e5dec6b0 100644 --- a/launcher/LauncherController.h +++ b/launcher/LauncherController.h @@ -56,7 +56,7 @@ public: void UpdateNumWorkspaces(int workspaces); std::vector<char> GetAllShortcuts() const; - std::vector<AbstractLauncherIcon::Ptr> GetAltTabIcons(bool current) const; + std::vector<AbstractLauncherIcon::Ptr> GetAltTabIcons(bool current, bool show_deskop_disabled) const; void PushToFront(); diff --git a/launcher/LauncherModel.cpp b/launcher/LauncherModel.cpp index fa7bab510..878942488 100644 --- a/launcher/LauncherModel.cpp +++ b/launcher/LauncherModel.cpp @@ -79,14 +79,14 @@ LauncherModel::Populate() iterator it, it2; int i = 0; - for (it = main_begin(); it != main_end(); it++) + for (it = main_begin(); it != main_end(); ++it) { _inner.push_back(*it); (*it)->SetSortPriority(i); ++i; } - for (it = shelf_begin(); it != shelf_end(); it++) + for (it = shelf_begin(); it != shelf_end(); ++it) { _inner.push_back(*it); (*it)->SetSortPriority(i); @@ -409,7 +409,7 @@ LauncherModel::at(int index) int i; // start currently selected icon - for (it = _inner.begin(), i = 0; it != _inner.end(); it++, i++) + for (it = _inner.begin(), i = 0; it != _inner.end(); ++it, i++) { if (i == index) return it; diff --git a/launcher/QuicklistView.cpp b/launcher/QuicklistView.cpp index 1c2884f43..efdd7a2dd 100644 --- a/launcher/QuicklistView.cpp +++ b/launcher/QuicklistView.cpp @@ -602,14 +602,14 @@ void QuicklistView::CancelItemsPrelightStatus() void QuicklistView::RecvItemMouseDrag(QuicklistMenuItem* item, int x, int y) { nux::Geometry geo; - for (auto item : _item_list) + for (auto it : _item_list) { - int item_index = GetItemIndex(item); + int item_index = GetItemIndex(it); if (!IsMenuItemSelectable(item_index)) continue; - geo = item->GetGeometry(); + geo = it->GetGeometry(); geo.width = _item_layout->GetBaseWidth(); if (geo.IsPointInside(x + item->GetBaseX(), y + item->GetBaseY())) diff --git a/launcher/StandaloneLauncher.cpp b/launcher/StandaloneLauncher.cpp index a3e7a7752..8dba0e4f7 100644 --- a/launcher/StandaloneLauncher.cpp +++ b/launcher/StandaloneLauncher.cpp @@ -59,7 +59,6 @@ int main(int argc, char** argv) nux::NuxInitialize(0); - GeisAdapter geis_adapter; unity::Settings settings; panel::Style panel_style; internal::FavoriteStoreGSettings favorite_store; diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp index 3c8d0ede2..0f1911d5e 100644 --- a/launcher/SwitcherController.cpp +++ b/launcher/SwitcherController.cpp @@ -52,6 +52,7 @@ Controller::Controller(unsigned int load_timeout) , main_layout_(nullptr) , monitor_(0) , visible_(false) + , show_desktop_disabled_(false) , bg_color_(0, 0, 0, 0.5) { ubus_manager_.RegisterInterest(UBUS_BACKGROUND_COLOR_CHANGED, sigc::mem_fun(this, &Controller::OnBackgroundUpdate)); @@ -72,6 +73,9 @@ void Controller::OnBackgroundUpdate(GVariant* data) void Controller::Show(ShowMode show, SortMode sort, bool reverse, std::vector<AbstractLauncherIcon::Ptr> results) { + if (results.empty()) + return; + if (sort == SortMode::FOCUS_ORDER) { std::sort(results.begin(), results.end(), CompareSwitcherItemsPriority); @@ -389,6 +393,21 @@ guint Controller::GetSwitcherInputWindowId() const return view_window_->GetInputWindowId(); } +bool Controller::IsShowDesktopDisabled() const +{ + return show_desktop_disabled_; +} + +void Controller::SetShowDesktopDisabled(bool disabled) +{ + show_desktop_disabled_ = disabled; +} + +int Controller::StartIndex() const +{ + return (show_desktop_disabled_ ? 0 : 1); +} + bool Controller::CompareSwitcherItemsPriority(AbstractLauncherIcon::Ptr first, AbstractLauncherIcon::Ptr second) { @@ -409,8 +428,11 @@ void Controller::SelectFirstItem() if (!model_) return; - AbstractLauncherIcon::Ptr first = model_->at(1); - AbstractLauncherIcon::Ptr second = model_->at(2); + int first_icon_index = StartIndex(); + int second_icon_index = first_icon_index + 1; + + AbstractLauncherIcon::Ptr first = model_->at(first_icon_index); + AbstractLauncherIcon::Ptr second = model_->at(second_icon_index); if (!first) { @@ -464,13 +486,14 @@ void Controller::AddProperties(GVariantBuilder* builder) { unity::variant::BuilderWrapper(builder) - .add("timeout-length", timeout_length()) - .add("detail-on-timeout", detail_on_timeout()) - .add("initial-detail-timeout-length", initial_detail_timeout_length()) - .add("detail-timeout-length", detail_timeout_length()) + .add("timeout_length", timeout_length()) + .add("detail_on_timeout", detail_on_timeout()) + .add("initial_detail_timeout_length", initial_detail_timeout_length()) + .add("detail_timeout_length", detail_timeout_length()) .add("visible", visible_) .add("monitor", monitor_) - .add("detail-mode", detail_mode_); + .add("show_desktop_disabled", show_desktop_disabled_) + .add("detail_mode", detail_mode_); } } // switcher namespace diff --git a/launcher/SwitcherController.h b/launcher/SwitcherController.h index 5f8015c36..9083adb49 100644 --- a/launcher/SwitcherController.h +++ b/launcher/SwitcherController.h @@ -92,6 +92,10 @@ public: guint GetSwitcherInputWindowId() const; + bool IsShowDesktopDisabled() const; + void SetShowDesktopDisabled(bool disabled); + int StartIndex() const; + protected: // Introspectable methods std::string GetName() const; @@ -126,6 +130,7 @@ private: int monitor_; bool visible_; + bool show_desktop_disabled_; nux::Color bg_color_; DetailMode detail_mode_; diff --git a/manual-tests/Launcher.txt b/manual-tests/Launcher.txt index 082a7a24f..4f1ba8f82 100644 --- a/manual-tests/Launcher.txt +++ b/manual-tests/Launcher.txt @@ -665,14 +665,17 @@ Expected Result: * The launcher should autoscroll so you can reach the trash icon. -No flickering when resizing the launcher ----------------------------------------- -Actions: - * Open gedit. - * Maximize it. Make sure it remains maximized during the test. - * Open Appearance panel in System Settings. - * Change Launcher Icon Size. +No flashing tooltips when peforming the accordion effect. +---------------------------------------------------- +Setup: + * Make sure the launcher setting is to never hide. + * Add icons to the launcher so that some of them in the bottom are folded. -Expected Results: - * The gedit window must not flicker behind the launcher. +Actions: + * Quickly move the mouse pointer to the bottom-left corner. + * Quickly move the mouse pointer outside the launcher area. + +Expected Result: + * No icon flickers near the top panel. + * See https://bugs.launchpad.net/unity/+bug/980942/+attachment/3059914/+files/launcher-accordion-effect-tooltip-bug.ogv. diff --git a/panel/PanelIndicatorEntryView.cpp b/panel/PanelIndicatorEntryView.cpp index d61d8282d..7354d6083 100644 --- a/panel/PanelIndicatorEntryView.cpp +++ b/panel/PanelIndicatorEntryView.cpp @@ -429,7 +429,6 @@ void PanelIndicatorEntryView::Refresh() unsigned int width = 0; unsigned int icon_width = 0; unsigned int height = panel::Style::Instance().panel_height; - unsigned int text_width = 0; // First lets figure out our size if (pixbuf && IsIconVisible()) @@ -484,7 +483,7 @@ void PanelIndicatorEntryView::Refresh() pango_layout_context_changed(layout); pango_layout_get_extents(layout, nullptr, &log_rect); - text_width = log_rect.width / PANGO_SCALE; + unsigned int text_width = log_rect.width / PANGO_SCALE; if (icon_width) width += spacing_; diff --git a/panel/PanelMenuView.cpp b/panel/PanelMenuView.cpp index 0b90f67c7..3d75c0afc 100644 --- a/panel/PanelMenuView.cpp +++ b/panel/PanelMenuView.cpp @@ -700,7 +700,6 @@ void PanelMenuView::DrawTitle(cairo_t *cr_real, nux::Geometry const& geo, std::s using namespace panel; cairo_t* cr; cairo_pattern_t* linpat; - const int fading_pixels = 35; int x = MAIN_LEFT_PADDING + TITLE_PADDING + geo.x; int y = geo.y; @@ -762,6 +761,7 @@ void PanelMenuView::DrawTitle(cairo_t *cr_real, nux::Geometry const& geo, std::s if (text_width > text_space) { int out_pixels = text_width - text_space; + const int fading_pixels = 35; int fading_width = out_pixels < fading_pixels ? out_pixels : fading_pixels; cairo_push_group(cr); diff --git a/panel/PanelView.cpp b/panel/PanelView.cpp index 85d8250ad..27bbfc3a5 100644 --- a/panel/PanelView.cpp +++ b/panel/PanelView.cpp @@ -219,14 +219,14 @@ void PanelView::AddProperties(GVariantBuilder* builder) void PanelView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) { - nux::Geometry geo = GetGeometry(); - nux::Geometry geo_absolute = GetAbsoluteGeometry(); + nux::Geometry const& geo = GetGeometry(); UpdateBackground(); - GfxContext.PushClippingRectangle(GetGeometry()); + GfxContext.PushClippingRectangle(geo); if ((_overlay_is_open || (_opacity != 1.0f && _opacity != 0.0f))) { + nux::Geometry const& geo_absolute = GetAbsoluteGeometry(); nux::Geometry blur_geo(geo_absolute.x, geo_absolute.y, geo.width, geo.height); if (BackgroundEffectHelper::blur_type != BLUR_NONE) @@ -251,8 +251,7 @@ PanelView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) rop.SrcBlend = GL_ONE; rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA; - nux::Geometry bg_clip = geo; - GfxContext.PushClippingRectangle(bg_clip); + GfxContext.PushClippingRectangle(geo); #ifndef NUX_OPENGLES_20 if (GfxContext.UsingGLSLCodePath()) @@ -285,12 +284,12 @@ PanelView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw) if (_overlay_is_open) { - nux::GetPainter().RenderSinglePaintLayer(GfxContext, GetGeometry(), _bg_darken_layer.get()); + nux::GetPainter().RenderSinglePaintLayer(GfxContext, geo, _bg_darken_layer.get()); } } if (!_overlay_is_open || GfxContext.UsingGLSLCodePath() == false) - nux::GetPainter().RenderSinglePaintLayer(GfxContext, GetGeometry(), _bg_layer.get()); + nux::GetPainter().RenderSinglePaintLayer(GfxContext, geo, _bg_layer.get()); GfxContext.PopClippingRectangle(); @@ -307,7 +306,7 @@ PanelView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) nux::Geometry const& geo = GetGeometry(); int bgs = 1; - GfxContext.PushClippingRectangle(GetGeometry()); + GfxContext.PushClippingRectangle(geo); GfxContext.GetRenderStates().SetBlend(true); GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER); @@ -315,7 +314,7 @@ PanelView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) if (_bg_blur_texture.IsValid() && (_overlay_is_open || (_opacity != 1.0f && _opacity != 0.0f))) { - nux::Geometry geo_absolute = GetAbsoluteGeometry (); + nux::Geometry const& geo_absolute = GetAbsoluteGeometry(); nux::TexCoordXForm texxform_blur_bg; texxform_blur_bg.flip_v_coord = true; texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD); @@ -359,13 +358,13 @@ PanelView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) if (_overlay_is_open) { - nux::GetPainter().PushLayer(GfxContext, GetGeometry(), _bg_darken_layer.get()); + nux::GetPainter().PushLayer(GfxContext, geo, _bg_darken_layer.get()); bgs++; } } if (!_overlay_is_open || GfxContext.UsingGLSLCodePath() == false) - gPainter.PushLayer(GfxContext, GetGeometry(), _bg_layer.get()); + gPainter.PushLayer(GfxContext, geo, _bg_layer.get()); if (_overlay_is_open) { @@ -378,7 +377,7 @@ PanelView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) rop.Blend = true; rop.SrcBlend = GL_DST_COLOR; rop.DstBlend = GL_ONE; - nux::GetPainter().PushTextureLayer(GfxContext, GetGeometry(), + nux::GetPainter().PushTextureLayer(GfxContext, geo, _panel_sheen->GetDeviceTexture(), texxform, nux::color::White, diff --git a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp index 74bd70d7c..ad840204c 100644 --- a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp +++ b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp @@ -292,7 +292,7 @@ UnityMTGrabHandlesScreen::handleEvent(XEvent* event) CompWindowVector::const_iterator cit = clientListStacking.begin(); CompWindowVector::const_iterator oit = mLastClientListStacking.begin(); - for (; cit != clientListStacking.end(); cit++, oit++) + for (; cit != clientListStacking.end(); ++cit, oit++) { /* All clients from this point onwards in cit are invalidated * so splice the list to the end of the new client list diff --git a/plugins/unitydialog/src/unitydialog.cpp b/plugins/unitydialog/src/unitydialog.cpp index 05b51ddc6..91f7f235e 100644 --- a/plugins/unitydialog/src/unitydialog.cpp +++ b/plugins/unitydialog/src/unitydialog.cpp @@ -367,7 +367,7 @@ UnityDialogScreen::donePaint() continue; } - it++; + ++it; } } @@ -1383,7 +1383,6 @@ UnityDialogWindow::place(CompPoint& pos) CompWindow::Geometry transientGeometry; CompRegion transientPos, outputRegion, outsideArea, outsideRegion; pos = getChildCenteredPositionForRect(mParent->serverBorderRect()); - int hdirection, vdirection; transientGeometry = CompWindow::Geometry(pos.x(), pos.y(), @@ -1406,8 +1405,8 @@ UnityDialogWindow::place(CompPoint& pos) int width; int height; - hdirection = outsideArea.boundingRect().x() < 0 ? 1 : -1; - vdirection = outsideArea.boundingRect().y() < 0 ? 1 : -1; + int hdirection = outsideArea.boundingRect().x() < 0 ? 1 : -1; + int vdirection = outsideArea.boundingRect().y() < 0 ? 1 : -1; width = outsideArea.boundingRect().width() >= window->serverBorderRect().width() ? 0 : diff --git a/plugins/unityshell/CMakeLists.txt b/plugins/unityshell/CMakeLists.txt index 2e11fb453..eaf2047a3 100644 --- a/plugins/unityshell/CMakeLists.txt +++ b/plugins/unityshell/CMakeLists.txt @@ -12,6 +12,9 @@ compiz_plugin (unityshell ) add_dependencies(unityshell unity-core-${UNITY_API_VERSION} dash-lib launcher-lib switcher-lib hud-lib panel-lib shortcuts-lib unity-shared unity-shared-compiz) target_link_libraries(unityshell unity-core-${UNITY_API_VERSION} launcher-lib dash-lib switcher-lib hud-lib panel-lib shortcuts-lib unity-shared unity-shared-compiz) +set_target_properties(unityshell + PROPERTIES INSTALL_RPATH "${CACHED_UNITY_PRIVATE_DEPS_LIBRARY_DIRS}" + INSTALL_RPATH_USE_LINK_PATH TRUE) # # Data diff --git a/plugins/unityshell/src/GestureEngine.cpp b/plugins/unityshell/src/GestureEngine.cpp deleted file mode 100644 index 9bf825b3a..000000000 --- a/plugins/unityshell/src/GestureEngine.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * GestureEngine.cpp - * This file is part of Unity - * - * Copyright (C) 2011 - Canonical Ltd. - * - * Unity is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Unity 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 Unity; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#include <X11/cursorfont.h> - -#include "ubus-server.h" -#include "UBusMessages.h" -#include "GestureEngine.h" -#include "PluginAdapter.h" - -GestureEngine::GestureEngine(CompScreen* screen) -{ - _screen = screen; - - _drag_id = 0; - _drag_window = 0; - _pinch_id = 0; - _touch_id = 0; - _drag_grab = 0; - _pinch_grab = 0; - _fleur_cursor = XCreateFontCursor (screen->dpy (), XC_fleur); - - GeisAdapter& adapter = GeisAdapter::Instance(); - - adapter.tap.connect(sigc::mem_fun(this, &GestureEngine::OnTap)); - - adapter.drag_start.connect(sigc::mem_fun(this, &GestureEngine::OnDragStart)); - adapter.drag_update.connect(sigc::mem_fun(this, &GestureEngine::OnDragUpdate)); - adapter.drag_finish.connect(sigc::mem_fun(this, &GestureEngine::OnDragFinish)); - - adapter.rotate_start.connect(sigc::mem_fun(this, &GestureEngine::OnRotateStart)); - adapter.rotate_update.connect(sigc::mem_fun(this, &GestureEngine::OnRotateUpdate)); - adapter.rotate_finish.connect(sigc::mem_fun(this, &GestureEngine::OnRotateFinish)); - - adapter.pinch_start.connect(sigc::mem_fun(this, &GestureEngine::OnPinchStart)); - adapter.pinch_update.connect(sigc::mem_fun(this, &GestureEngine::OnPinchUpdate)); - adapter.pinch_finish.connect(sigc::mem_fun(this, &GestureEngine::OnPinchFinish)); - - adapter.touch_start.connect(sigc::mem_fun(this, &GestureEngine::OnTouchStart)); - adapter.touch_update.connect(sigc::mem_fun(this, &GestureEngine::OnTouchUpdate)); - adapter.touch_finish.connect(sigc::mem_fun(this, &GestureEngine::OnTouchFinish)); -} - -GestureEngine::~GestureEngine() -{ - if (_fleur_cursor) - XFreeCursor (screen->dpy (), _fleur_cursor); -} - -void -GestureEngine::OnTap(GeisAdapter::GeisTapData* data) -{ - if (data->touches == 4) - { - UBusServer* ubus = ubus_server_get_default(); - ubus_server_send_message(ubus, UBUS_DASH_EXTERNAL_ACTIVATION, NULL); - } -} - -CompWindow* GestureEngine::FindCompWindowAtPos(float fpos_x, float fpos_y) -{ - const CompWindowVector& client_list_stacking = _screen->clientList(true); - - int pos_x = fpos_x; - int pos_y = fpos_y; - - for (auto iter = client_list_stacking.rbegin(), - end = client_list_stacking.rend(); - iter != end; ++iter) - { - CompWindow* window = *iter; - - if (pos_x >= window->x() && pos_x <= (window->width() + window->x()) - && - pos_y >= window->y() && pos_y <= (window->height() + window->y())) - return window; - } - - return nullptr; -} - -void -GestureEngine::OnDragStart(GeisAdapter::GeisDragData* data) -{ - if (data->touches == 3) - { - _drag_window = FindCompWindowAtPos(data->focus_x, data->focus_y); - - - if (!_drag_window) - return; - - if (!(_drag_window->actions() & CompWindowActionMoveMask)) - { - _drag_window = 0; - return; - } - - /* Don't allow windows to be dragged if completely maximized */ - if ((_drag_window->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE) - { - _drag_window = 0; - return; - } - - if (_drag_grab) - _screen->removeGrab(_drag_grab, NULL); - _drag_id = data->id; - _drag_grab = _screen->pushGrab(_fleur_cursor, "unity"); - _drag_window->grabNotify (_drag_window->serverGeometry ().x (), - _drag_window->serverGeometry ().y (), - 0, CompWindowGrabMoveMask | CompWindowGrabButtonMask); - } -} - -/* FIXME: CompScreen::warpPointer filters out motion events which - * other plugins may need to process, but for most cases in core - * they should be filtered out. */ -void -GestureEngine::OnDragUpdate(GeisAdapter::GeisDragData* data) -{ - if (_drag_id == data->id && _drag_window) - { - unsigned int px = std::max (std::min (pointerX + static_cast <int> (data->delta_x), screen->width ()), 0); - unsigned int py = std::max (std::min (pointerY + static_cast <int> (data->delta_y), screen->height ()), 0); - - if (_drag_window->state () & CompWindowStateMaximizedVertMask) - py = pointerY; - if (_drag_window->state () & CompWindowStateMaximizedHorzMask) - px = pointerX; - - XWarpPointer(screen->dpy (), - None, screen->root (), - 0, 0, 0, 0, - px, py); - - XSync(screen->dpy (), false); - _drag_window->move(px - pointerX, py - pointerY, false); - - pointerX = px; - pointerY = py; - } -} - -void -GestureEngine::OnDragFinish(GeisAdapter::GeisDragData* data) -{ - if (_drag_id == data->id && _drag_window) - { - _drag_window->ungrabNotify (); - _drag_window->syncPosition(); - EndDrag(); - } -} - -void -GestureEngine::EndDrag() -{ - if (_drag_window) - { - _screen->removeGrab(_drag_grab, NULL); - _drag_grab = 0; - _drag_window = 0; - _drag_id = 0; - } -} - -void -GestureEngine::OnRotateStart(GeisAdapter::GeisRotateData* data) -{ - -} -void -GestureEngine::OnRotateUpdate(GeisAdapter::GeisRotateData* data) -{ - -} -void -GestureEngine::OnRotateFinish(GeisAdapter::GeisRotateData* data) -{ - -} - -void -GestureEngine::OnTouchStart(GeisAdapter::GeisTouchData* data) -{ - if (data->touches == 3 && data->window != 0) - { - CompWindow* result = FindCompWindowAtPos(data->focus_x, data->focus_y); - - if (result) - { - PluginAdapter::Default()->ShowGrabHandles(result, false); - _touch_id = data->id; - _touch_window = result; - } - } -} - -void -GestureEngine::OnTouchUpdate(GeisAdapter::GeisTouchData* data) -{ - -} - -void -GestureEngine::OnTouchFinish(GeisAdapter::GeisTouchData* data) -{ - if (_touch_id == data->id) - { - if (_touch_window) - PluginAdapter::Default()->ShowGrabHandles(_touch_window, true); - _touch_id = 0; - _touch_window = 0; - } -} - -void -GestureEngine::OnPinchStart(GeisAdapter::GeisPinchData* data) -{ - if (data->touches == 3) - { - _pinch_window = FindCompWindowAtPos(data->focus_x, data->focus_y); - - if (!_pinch_window) - return; - - _pinch_id = data->id; - - if (_pinch_grab) - _screen->removeGrab(_pinch_grab, NULL); - _pinch_grab = _screen->pushGrab(_screen->invisibleCursor(), "unity"); - } -} -void -GestureEngine::OnPinchUpdate(GeisAdapter::GeisPinchData* data) -{ - if (data->id != _pinch_id) - return; - - if (data->radius > 1.25) - { - _pinch_window->maximize(MAXIMIZE_STATE); - EndDrag(); - } - else if (data->radius < 0.8) - { - _pinch_window->maximize(0); - EndDrag(); - } -} -void -GestureEngine::OnPinchFinish(GeisAdapter::GeisPinchData* data) -{ - if (_pinch_id == data->id && _pinch_window) - { - _screen->removeGrab(_pinch_grab, NULL); - _pinch_grab = 0; - _pinch_id = 0; - } -} diff --git a/plugins/unityshell/src/GestureEngine.h b/plugins/unityshell/src/GestureEngine.h deleted file mode 100644 index bce81628d..000000000 --- a/plugins/unityshell/src/GestureEngine.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * GestureEngine.h - * This file is part of Unity - * - * Copyright (C) 2011 - Canonical Ltd. - * - * Unity is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Unity 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 Unity; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#include <core/core.h> - -#include <sigc++/sigc++.h> -#include "GeisAdapter.h" - -class GestureEngine : public sigc::trackable -{ -public: - GestureEngine(CompScreen* screen); - virtual ~GestureEngine(); - - void OnTap(GeisAdapter::GeisTapData* data); - - void OnDragStart(GeisAdapter::GeisDragData* data); - void OnDragUpdate(GeisAdapter::GeisDragData* data); - void OnDragFinish(GeisAdapter::GeisDragData* data); - - void OnRotateStart(GeisAdapter::GeisRotateData* data); - void OnRotateUpdate(GeisAdapter::GeisRotateData* data); - void OnRotateFinish(GeisAdapter::GeisRotateData* data); - - void OnPinchStart(GeisAdapter::GeisPinchData* data); - void OnPinchUpdate(GeisAdapter::GeisPinchData* data); - void OnPinchFinish(GeisAdapter::GeisPinchData* data); - - void OnTouchStart(GeisAdapter::GeisTouchData* data); - void OnTouchUpdate(GeisAdapter::GeisTouchData* data); - void OnTouchFinish(GeisAdapter::GeisTouchData* data); - - void EndDrag(); -private: - CompWindow* FindCompWindowAtPos(float pos_x, float pos_y); - - CompScreen* _screen; - CompWindow* _drag_window; - CompWindow* _pinch_window; - CompWindow* _touch_window; - CompScreen::GrabHandle _drag_grab; - CompScreen::GrabHandle _pinch_grab; - - int _drag_id; - int _pinch_id; - int _touch_id; - - Cursor _fleur_cursor; -}; diff --git a/plugins/unityshell/src/UnityGestureBroker.cpp b/plugins/unityshell/src/UnityGestureBroker.cpp new file mode 100644 index 000000000..c05237f22 --- /dev/null +++ b/plugins/unityshell/src/UnityGestureBroker.cpp @@ -0,0 +1,129 @@ +/* + * UnityGestureBroker.cpp + * This file is part of Unity + * + * Copyright (C) 2012 - Canonical Ltd. + * + * Unity is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Unity 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 Unity; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "UnityGestureBroker.h" +#include "UnityGestureTarget.h" +#include "WindowGestureTarget.h" + +#include <X11/cursorfont.h> + +UnityGestureBroker::UnityGestureBroker() + : nux::GestureBroker() +{ + g_assert(WindowGestureTarget::fleur_cursor == 0); + WindowGestureTarget::fleur_cursor = XCreateFontCursor (screen->dpy (), XC_fleur); + + unity_target.reset(new UnityGestureTarget); +} + +UnityGestureBroker::~UnityGestureBroker() +{ + if (WindowGestureTarget::fleur_cursor) + { + XFreeCursor (screen->dpy (), WindowGestureTarget::fleur_cursor); + WindowGestureTarget::fleur_cursor = 0; + } +} + +std::vector<nux::ShPtGestureTarget> +UnityGestureBroker::FindGestureTargets(const nux::GestureEvent &event) +{ + std::vector<nux::ShPtGestureTarget> targets; + const std::vector<nux::TouchPoint> &touches = event.GetTouches(); + + if (touches.size() == 4) + { + targets.push_back(unity_target); + } + else if (touches.size() == 3) + { + CompWindow *window = FindWindowHitByGesture(event); + if (window) + { + targets.push_back(nux::ShPtGestureTarget(new WindowGestureTarget(window))); + } + } + + return targets; +} + +CompWindow *UnityGestureBroker::FindWindowHitByGesture(const nux::GestureEvent &event) +{ + if (event.IsDirectTouch()) + { + /* If a direct device is being used (e.g., a touchscreen), all touch + points must hit the same window */ + CompWindow *last_window = nullptr; + const std::vector<nux::TouchPoint> &touches = event.GetTouches(); + for (auto touch : touches) + { + CompWindow *window = FindCompWindowAtPos(touch.x, touch.y); + if (last_window) + { + if (window != last_window) + { + return nullptr; + } + } + else + { + last_window = window; + } + } + + return last_window; + } + else + { + /* If a indirect device is being used (e.g., a trackpad), the individual + touch points are not in screen coordinates and therefore it doesn't make + sense to hit-test them individually against the window tree. Instead, + we use just the focus point, which is the same as the cursor + position in this case (which is in screen coordinates). */ + return FindCompWindowAtPos(event.GetFocus().x, event.GetFocus().y); + } +} + +CompWindow* UnityGestureBroker::FindCompWindowAtPos(int pos_x, int pos_y) +{ + const CompWindowVector& client_list_stacking = screen->clientList(true); + + for (auto iter = client_list_stacking.rbegin(), + end = client_list_stacking.rend(); + iter != end; ++iter) + { + CompWindow* window = *iter; + + if (window->minimized()) + continue; + + if (window->state() & CompWindowStateHiddenMask) + continue; + + if (pos_x >= window->x() && pos_x <= (window->width() + window->x()) + && + pos_y >= window->y() && pos_y <= (window->height() + window->y())) + return window; + } + + return nullptr; +} diff --git a/plugins/unityshell/src/UnityGestureBroker.h b/plugins/unityshell/src/UnityGestureBroker.h new file mode 100644 index 000000000..d859f49a1 --- /dev/null +++ b/plugins/unityshell/src/UnityGestureBroker.h @@ -0,0 +1,45 @@ +/* + * UnityGestureBroker.h + * This file is part of Unity + * + * Copyright (C) 2011 - Canonical Ltd. + * + * Unity is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Unity 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 Unity; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include <core/core.h> + +#include <Nux/GestureBroker.h> + +class UnityGestureBroker : public nux::GestureBroker +{ +public: + UnityGestureBroker(); + virtual ~UnityGestureBroker(); + +private: + std::vector<nux::ShPtGestureTarget> + virtual FindGestureTargets(const nux::GestureEvent &event); + + CompWindow *FindWindowHitByGesture(const nux::GestureEvent &event); + + /*! + Returns the top-most CompWindow at the given position, if any. + */ + CompWindow* FindCompWindowAtPos(int pos_x, int pos_y); + + nux::ShPtGestureTarget unity_target; +}; diff --git a/plugins/unityshell/src/UnityGestureTarget.cpp b/plugins/unityshell/src/UnityGestureTarget.cpp new file mode 100644 index 000000000..3afe2ce26 --- /dev/null +++ b/plugins/unityshell/src/UnityGestureTarget.cpp @@ -0,0 +1,54 @@ +/* + * UnityGestureTarget.cpp + * This file is part of Unity + * + * Copyright (C) 2012 - Canonical Ltd. + * + * Unity is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Unity 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 Unity; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "UnityGestureTarget.h" + +#include <Nux/Nux.h> // otherwise unityshell.h inclusion will cause failures +#include "unityshell.h" + +#include "UBusMessages.h" +#include "ubus-server.h" + +using namespace nux; + +UnityGestureTarget::UnityGestureTarget() +{ + launcher = unity::UnityScreen::get(screen)->LauncherView(); +} + +GestureDeliveryRequest UnityGestureTarget::GestureEvent(const nux::GestureEvent &event) +{ + if (event.GetGestureClasses() & DRAG_GESTURE) + { + if (launcher.IsValid()) + launcher->GestureEvent(event); + } + else if (event.GetGestureClasses() == TAP_GESTURE + && event.type == EVENT_GESTURE_END) + { + ubus_server_send_message(ubus_server_get_default(), + UBUS_DASH_EXTERNAL_ACTIVATION, + NULL); + } + + return GestureDeliveryRequest::NONE; +} diff --git a/plugins/unityshell/src/UnityGestureTarget.h b/plugins/unityshell/src/UnityGestureTarget.h new file mode 100644 index 000000000..f47996e63 --- /dev/null +++ b/plugins/unityshell/src/UnityGestureTarget.h @@ -0,0 +1,44 @@ +/* + * UnityGestureTarget.h + * This file is part of Unity + * + * Copyright (C) 2012 - Canonical Ltd. + * + * Unity is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Unity 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 Unity; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef UNITY_GESTURE_TARGET_H +#define UNITY_GESTURE_TARGET_H + +#include <Nux/Gesture.h> + +/* + Target for Unity-level gestures. + I.e., for gestures that act on Unity elements, such as + the dash or launcher. + */ +class UnityGestureTarget : public nux::GestureTarget +{ + public: + UnityGestureTarget(); + + virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event); + + private: + nux::ObjectWeakPtr<nux::InputArea> launcher; +}; + +#endif // UNITY_GESTURE_TARGET_H diff --git a/plugins/unityshell/src/WindowGestureTarget.cpp b/plugins/unityshell/src/WindowGestureTarget.cpp new file mode 100644 index 000000000..37e947deb --- /dev/null +++ b/plugins/unityshell/src/WindowGestureTarget.cpp @@ -0,0 +1,215 @@ +/* + * WindowGestureTarget.cpp + * This file is part of Unity + * + * Copyright (C) 2012 - Canonical Ltd. + * + * Unity is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Unity 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 Unity; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "WindowGestureTarget.h" + +#include <Nux/Nux.h> // otherwise unityshell.h inclusion will cause failures +#include "unityshell.h" + +#include "PluginAdapter.h" + +using namespace nux; + +Cursor WindowGestureTarget::fleur_cursor = 0; + +WindowGestureTarget::WindowGestureTarget(CompWindow *window) + : window_(window), drag_grab_(0), started_window_move_(false), + window_restored_by_pinch_(false) +{ + // A workaround for the lack of weak pointers. + unity::UnityWindow *unity_window = unity::UnityWindow::get(window); + + connection_window_destruction = + unity_window->being_destroyed.connect( + sigc::mem_fun(this, &WindowGestureTarget::NullifyWindowPointer)); +} + +WindowGestureTarget::~WindowGestureTarget() +{ + connection_window_destruction.disconnect(); + if (drag_grab_) + { + if (window_) + window_->ungrabNotify(); + screen->removeGrab(drag_grab_, NULL); + } +} + +void WindowGestureTarget::NullifyWindowPointer() +{ + window_ = nullptr; +} + +GestureDeliveryRequest WindowGestureTarget::GestureEvent(const nux::GestureEvent &event) +{ + if (!window_) + return GestureDeliveryRequest::NONE; + + switch (event.type) + { + case nux::EVENT_GESTURE_BEGIN: + PluginAdapter::Default()->ShowGrabHandles(window_, false); + break; + case EVENT_GESTURE_UPDATE: + if (event.GetGestureClasses() & PINCH_GESTURE) + MaximizeOrRestoreWindowDueToPinch(event); + if (event.GetGestureClasses() & DRAG_GESTURE) + { + if (WindowCanMove()) + { + if (!started_window_move_) + { + StartWindowMove(event); + started_window_move_ = true; + } + MoveWindow(event); + } + } + break; + default: // EVENT_GESTURE_END + if (event.GetGestureClasses() & DRAG_GESTURE) + { + EndWindowMove(event); + started_window_move_ = false; + } + PluginAdapter::Default()->ShowGrabHandles(window_, true); + break; + }; + + return GestureDeliveryRequest::NONE; +} + +bool WindowGestureTarget::WindowCanMove() +{ + if (!(window_->actions() & CompWindowActionMoveMask)) + return false; + + /* Don't allow windows to be dragged if completely maximized */ + if ((window_->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE) + return false; + + /* Don't start moving a window that has just been restored. The user is likely + still performing the pinch and not expecting the window to start moving */ + if (window_restored_by_pinch_) + return false; + + return true; +} + +void WindowGestureTarget::MaximizeOrRestoreWindowDueToPinch(const nux::GestureEvent &event) +{ + if (event.GetRadius() > 1.25f) + { + window_->maximize(MAXIMIZE_STATE); + RemoveDragGrab(); + window_restored_by_pinch_ = false; + } + else if (event.GetRadius() < 0.8f) + { + if (window_->state() & MAXIMIZE_STATE) + { + window_->maximize(0); + RemoveDragGrab(); + window_restored_by_pinch_ = true; + } + } +} + +void WindowGestureTarget::StartWindowMove(const nux::GestureEvent &event) +{ + if (!event.IsDirectTouch()) + { + drag_grab_ = screen->pushGrab(fleur_cursor, "unity"); + window_->grabNotify(window_->serverGeometry().x(), + window_->serverGeometry().y(), + 0, + CompWindowGrabMoveMask | CompWindowGrabButtonMask); + } +} + +void WindowGestureTarget::MoveWindow(const nux::GestureEvent &event) +{ + const nux::Point2D<float> &delta = event.GetDelta(); + + unsigned int px = std::max(std::min(pointerX + static_cast<int>(delta.x), + screen->width()), + 0); + + unsigned int py = std::max(std::min(pointerY + static_cast<int>(delta.y), + screen->height()), + 0); + + if (window_->state() & CompWindowStateMaximizedVertMask) + py = pointerY; + if (window_->state() & CompWindowStateMaximizedHorzMask) + px = pointerX; + + if (!event.IsDirectTouch()) + { + /* FIXME: CompScreen::warpPointer filters out motion events which + other plugins may need to process, but for most cases in core + they should be filtered out. */ + XWarpPointer(screen->dpy (), + None, screen->root (), + 0, 0, 0, 0, + px, py); + } + + XSync(screen->dpy (), false); + window_->move(px - pointerX, py - pointerY, false); + + pointerX = px; + pointerY = py; +} + +void WindowGestureTarget::EndWindowMove(const nux::GestureEvent &event) +{ + window_->ungrabNotify(); + RemoveDragGrab(); + window_->syncPosition(); +} + +void WindowGestureTarget::RemoveDragGrab() +{ + if (drag_grab_) + { + screen->removeGrab(drag_grab_, NULL); + drag_grab_ = 0; + } +} + +bool WindowGestureTarget::Equals(const nux::GestureTarget& other) const +{ + const WindowGestureTarget *window_target = dynamic_cast<const WindowGestureTarget *>(&other); + + if (window_target) + { + if (window_ && window_target->window_) + return window_->id() == window_target->window_->id(); + else + return window_ == window_target->window_; + } + else + { + return false; + } +} diff --git a/plugins/unityshell/src/WindowGestureTarget.h b/plugins/unityshell/src/WindowGestureTarget.h new file mode 100644 index 000000000..e805e3948 --- /dev/null +++ b/plugins/unityshell/src/WindowGestureTarget.h @@ -0,0 +1,57 @@ +/* + * WindowGestureTarget.h + * This file is part of Unity + * + * Copyright (C) 2012 - Canonical Ltd. + * + * Unity is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Unity 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 Unity; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef WINDOW_GESTURE_TARGET_H +#define WINDOW_GESTURE_TARGET_H + +#include <Nux/Gesture.h> + +#include <core/core.h> // compiz stuff + +class WindowGestureTarget : public nux::GestureTarget +{ + public: + WindowGestureTarget(CompWindow *window); + virtual ~WindowGestureTarget(); + + virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event); + + static Cursor fleur_cursor; + + CompWindow *window() {return window_;} + private: + virtual bool Equals(const nux::GestureTarget& other) const; + void StartWindowMove(const nux::GestureEvent &event); + void MoveWindow(const nux::GestureEvent &event); + void EndWindowMove(const nux::GestureEvent &event); + void MaximizeOrRestoreWindowDueToPinch(const nux::GestureEvent &event); + bool WindowCanMove(); + void NullifyWindowPointer(); + void RemoveDragGrab(); + CompWindow *window_; + CompScreen::GrabHandle drag_grab_; + bool started_window_move_; + bool window_restored_by_pinch_; + sigc::connection connection_window_destruction; +}; + +#endif // WINDOW_GESTURE_TARGET_H diff --git a/plugins/unityshell/src/nux-layout-accessible.cpp b/plugins/unityshell/src/nux-layout-accessible.cpp index 8bec1d9e2..d692c696e 100644 --- a/plugins/unityshell/src/nux-layout-accessible.cpp +++ b/plugins/unityshell/src/nux-layout-accessible.cpp @@ -203,7 +203,7 @@ search_for_child(AtkObject* accessible, element_list = layout->GetChildren(); - for (it = element_list.begin(); it != element_list.end(); it++, result++) + for (it = element_list.begin(); it != element_list.end(); ++it, result++) { current_area = *it; if (current_area == area) diff --git a/plugins/unityshell/src/unity-launcher-accessible.cpp b/plugins/unityshell/src/unity-launcher-accessible.cpp index d20deed28..4cb4301ae 100644 --- a/plugins/unityshell/src/unity-launcher-accessible.cpp +++ b/plugins/unityshell/src/unity-launcher-accessible.cpp @@ -441,7 +441,7 @@ update_children_index(UnityLauncherAccessible* self) if (launcher_model == NULL) return; - for (it = launcher_model->begin(); it != launcher_model->end(); it++) + for (it = launcher_model->begin(); it != launcher_model->end(); ++it) { child = dynamic_cast<nux::Object*>((*it).GetPointer()); child_accessible = unity_a11y_get_accessible(child); diff --git a/plugins/unityshell/src/unity-switcher-accessible.cpp b/plugins/unityshell/src/unity-switcher-accessible.cpp index e4e2a968f..189e7d703 100644 --- a/plugins/unityshell/src/unity-switcher-accessible.cpp +++ b/plugins/unityshell/src/unity-switcher-accessible.cpp @@ -404,7 +404,7 @@ create_children(UnitySwitcherAccessible* self) if (switcher_model == NULL) return; - for (it = switcher_model->begin(); it != switcher_model->end(); it++) + for (it = switcher_model->begin(); it != switcher_model->end(); ++it) { child = *it; child_accessible = unity_launcher_icon_accessible_new(child.GetPointer()); diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp index 5bdeed855..4ea5106f2 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -29,7 +29,6 @@ #include "Launcher.h" #include "LauncherIcon.h" #include "LauncherController.h" -#include "GeisAdapter.h" #include "DevicesSettings.h" #include "PluginAdapter.h" #include "QuicklistManager.h" @@ -38,6 +37,7 @@ #include "KeyboardUtil.h" #include "unityshell.h" #include "BackgroundEffectHelper.h" +#include "UnityGestureBroker.h" #include <dbus/dbus.h> #include <dbus/dbus-glib.h> @@ -111,7 +111,6 @@ UnityScreen::UnityScreen(CompScreen* screen) , gScreen(GLScreen::get(screen)) , debugger_(this) , enable_shortcut_overlay_(true) - , gesture_engine_(screen) , needsRelayout(false) , _in_paint(false) , super_keypressed_(false) @@ -300,6 +299,7 @@ UnityScreen::UnityScreen(CompScreen* screen) optionSetAutomaximizeValueNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); optionSetAltTabTimeoutNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); optionSetAltTabBiasViewportNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); + optionSetDisableShowDesktopNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2)); optionSetAltTabForwardAllInitiate(boost::bind(&UnityScreen::altTabForwardAllInitiate, this, _1, _2, _3)); optionSetAltTabForwardInitiate(boost::bind(&UnityScreen::altTabForwardInitiate, this, _1, _2, _3)); @@ -363,7 +363,7 @@ UnityScreen::UnityScreen(CompScreen* screen) auto init_plugins_cb = sigc::mem_fun(this, &UnityScreen::initPluginActions); sources_.Add(std::make_shared<glib::Idle>(init_plugins_cb, glib::Source::Priority::DEFAULT)); - geis_adapter_.Run(); + InitGesturesSupport(); CompString name(PKGDATADIR"/panel-shadow.png"); CompString pname("unityshell"); @@ -500,6 +500,15 @@ void UnityScreen::nuxPrologue() glMatrixMode(GL_MODELVIEW); glPushMatrix(); + + /* This is needed to Fix a crash in glDrawArrays with the NVIDIA driver + * see bugs #1031554 and #982626. + * The NVIDIA driver looks to see if the legacy GL_VERTEX_ARRAY, + * GL_TEXTURE_COORDINATES_ARRAY and other such client states are enabled + * first before checking if a vertex buffer is bound and will prefer the + * client buffers over the the vertex buffer object. */ + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); #endif glGetError(); @@ -529,6 +538,11 @@ void UnityScreen::nuxEpilogue() glReadBuffer(GL_BACK); glPopAttrib(); + + /* Re-enable the client states that have been disabled in nuxPrologue, for + * NVIDIA compatibility reasons */ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); #else #ifdef USE_GLES glDepthRangef(0, 1); @@ -1211,7 +1225,7 @@ bool UnityScreen::shellCouldBeHidden(CompOutput const& output) CompWindowList const& wins = screen->windows(); for ( CompWindowList::const_reverse_iterator r = wins.rbegin() ; r != wins.rend() - ; r++ + ; ++r ) { CompWindow* w = *r; @@ -1309,10 +1323,9 @@ void UnityScreen::glPaintCompositedOutput (const CompRegion ®ion, ::GLFramebufferObject *fbo, unsigned int mask) { - bool useFbo = false; - if (doShellRepaint) { + bool useFbo = false; oldFbo = fbo->bind (); useFbo = fbo->checkStatus () && fbo->tex (); if (!useFbo) { @@ -1879,9 +1892,10 @@ bool UnityScreen::altTabInitiateCommon(CompAction* action, switcher::ShowMode sh RaiseInputWindows(); - auto results = launcher_controller_->GetAltTabIcons(show_mode == switcher::ShowMode::CURRENT_VIEWPORT); + auto results = launcher_controller_->GetAltTabIcons(show_mode == switcher::ShowMode::CURRENT_VIEWPORT, + switcher_controller_->IsShowDesktopDisabled()); - if (!(results.size() == 1 && results[0]->GetIconType() == AbstractLauncherIcon::IconType::TYPE_DESKTOP)) + if (!(results.size() == 1 && results[0]->GetIconType() == AbstractLauncherIcon::IconType::TYPE_DESKTOP) && !results.empty()) switcher_controller_->Show(show_mode, switcher::SortMode::FOCUS_ORDER, false, results); return true; @@ -1993,7 +2007,7 @@ bool UnityScreen::altTabNextWindowInitiate(CompAction* action, CompAction::State if (!switcher_controller_->Visible()) { altTabInitiateCommon(action, switcher::ShowMode::CURRENT_VIEWPORT); - switcher_controller_->Select(1); // always select the current application + switcher_controller_->Select((switcher_controller_->StartIndex())); // always select the current application } switcher_controller_->NextDetail(); @@ -2166,10 +2180,9 @@ bool UnityScreen::ShowHudInitiate(CompAction* action, { // Look to see if there is a keycode. If there is, then this isn't a // modifier only keybinding. - int key_code = 0; if (options[6].type() != CompOption::TypeUnset) { - key_code = options[6].value().i(); + int key_code = options[6].value().i(); LOG_DEBUG(logger) << "HUD initiate key code: " << key_code; // show it now, no timings or terminate needed. return ShowHud(); @@ -2596,6 +2609,9 @@ void UnityWindow::windowNotify(CompWindowNotify n) window->minimizedSetEnabled (this, false); } break; + case CompWindowNotifyBeforeDestroy: + being_destroyed.emit(); + break; default: break; } @@ -2872,6 +2888,9 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num) case UnityshellOptions::AltTabBiasViewport: PluginAdapter::Default()->bias_active_to_viewport = optionGetAltTabBiasViewport(); break; + case UnityshellOptions::DisableShowDesktop: + switcher_controller_->SetShowDesktopDisabled(optionGetDisableShowDesktop()); + break; case UnityshellOptions::ShowMinimizedWindows: compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::setFunctions (optionGetShowMinimizedWindows ()); screen->enterShowDesktopModeSetEnabled (this, optionGetShowMinimizedWindows ()); @@ -3042,6 +3061,18 @@ void UnityScreen::initLauncher() ScheduleRelayout(0); } +nux::View *UnityScreen::LauncherView() +{ + nux::View *result = nullptr; + + if (launcher_controller_) + { + result = &launcher_controller_->launcher(); + } + + return result; +} + void UnityScreen::InitHints() { // TODO move category text into a vector... @@ -3063,6 +3094,7 @@ void UnityScreen::InitHints() hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + A", _("Open the Dash App Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + F", _("Open the Dash Files Lens."), shortcut::COMPIZ_KEY_OPTION,"unityshell", "show_launcher")); hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + M", _("Open the Dash Music Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); + hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + V", _("Open the Dash Video Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher")); hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Switches between Lenses."), shortcut::HARDCODED_OPTION, _("Ctrl + Tab"))); hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Moves the focus."), shortcut::HARDCODED_OPTION, _("Cursor Keys"))); hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "", _("Open currently focused item."), shortcut::HARDCODED_OPTION, _("Enter & Return"))); @@ -3103,6 +3135,32 @@ void UnityScreen::InitHints() hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"), _("Resize window."), shortcut::COMPIZ_MOUSE_OPTION, "resize", "initiate_button")); } +void UnityScreen::InitGesturesSupport() +{ + std::unique_ptr<nux::GestureBroker> gesture_broker(new UnityGestureBroker); + wt->GetWindowCompositor().SetGestureBroker(std::move(gesture_broker)); + + gestures_sub_launcher_.reset(new nux::GesturesSubscription); + gestures_sub_launcher_->SetGestureClasses(nux::DRAG_GESTURE); + gestures_sub_launcher_->SetNumTouches(4); + gestures_sub_launcher_->SetWindowId(GDK_ROOT_WINDOW()); + gestures_sub_launcher_->Activate(); + + gestures_sub_dash_.reset(new nux::GesturesSubscription); + gestures_sub_dash_->SetGestureClasses(nux::TAP_GESTURE); + gestures_sub_dash_->SetNumTouches(4); + gestures_sub_dash_->SetWindowId(GDK_ROOT_WINDOW()); + gestures_sub_dash_->Activate(); + + gestures_sub_windows_.reset(new nux::GesturesSubscription); + gestures_sub_windows_->SetGestureClasses(nux::TOUCH_GESTURE + | nux::DRAG_GESTURE + | nux::PINCH_GESTURE); + gestures_sub_windows_->SetNumTouches(3); + gestures_sub_windows_->SetWindowId(GDK_ROOT_WINDOW()); + gestures_sub_windows_->Activate(); +} + /* Window init */ UnityWindow::UnityWindow(CompWindow* window) : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window) diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h index 34e29975e..765ad980b 100644 --- a/plugins/unityshell/src/unityshell.h +++ b/plugins/unityshell/src/unityshell.h @@ -22,6 +22,7 @@ #ifndef UNITYSHELL_H #define UNITYSHELL_H +#include <Nux/GesturesSubscription.h> #include <Nux/WindowThread.h> #include <NuxCore/Property.h> #include <sigc++/sigc++.h> @@ -46,7 +47,6 @@ #include "PanelController.h" #include "PanelStyle.h" #include "UScreen.h" -#include "GestureEngine.h" #include "DebugDBusInterface.h" #include "SwitcherController.h" #include "UBusWrapper.h" @@ -190,6 +190,8 @@ public: bool forcePaintOnTop (); + nux::View *LauncherView(); + protected: std::string GetName() const; void AddProperties(GVariantBuilder* builder); @@ -239,11 +241,12 @@ private: void OnPanelStyleChanged(); + void InitGesturesSupport(); + Settings dash_settings_; dash::Style dash_style_; panel::Style panel_style_; FontSettings font_settings_; - GeisAdapter geis_adapter_; internal::FavoriteStoreGSettings favorite_store_; /* The window thread should be the last thing removed, as c++ does it in reverse order */ @@ -261,7 +264,15 @@ private: std::list<shortcut::AbstractHint::Ptr> hints_; bool enable_shortcut_overlay_; - GestureEngine gesture_engine_; + /* Subscription for gestures that manipulate Unity launcher */ + std::unique_ptr<nux::GesturesSubscription> gestures_sub_launcher_; + + /* Subscription for gestures that manipulate Unity dash */ + std::unique_ptr<nux::GesturesSubscription> gestures_sub_dash_; + + /* Subscription for gestures that manipulate windows. */ + std::unique_ptr<nux::GesturesSubscription> gestures_sub_windows_; + bool needsRelayout; bool _in_paint; bool super_keypressed_; @@ -398,6 +409,8 @@ public: ShowdesktopHandler *mShowdesktopHandler; + //! Emited when CompWindowNotifyBeforeDestroy is received + sigc::signal<void> being_destroyed; private: void DoEnableFocus (); void DoDisableFocus (); diff --git a/plugins/unityshell/unityshell.xml.in b/plugins/unityshell/unityshell.xml.in index 2f0fbf626..5b89d6543 100644 --- a/plugins/unityshell/unityshell.xml.in +++ b/plugins/unityshell/unityshell.xml.in @@ -95,7 +95,7 @@ <_short>Key to open the first panel menu</_short> <_long>Open the first menu on the panel, allowing keyboard navigation thereafter.</_long> <default><Alt>F10</default> - </option> + </option> <option name="launcher_switcher_forward" type="key"> <_short>Key to start the launcher application switcher</_short> <_long>Switch the applications using the launcher</_long> @@ -119,6 +119,11 @@ <_long>Bias the switcher to windows which are placed on the current viewport</_long> <default>true</default> </option> + <option name="disable_show_desktop" type="bool"> + <_short>Disable Show Desktop in the switcher</_short> + <_long>Disables the Show Desktop icon in the switcher</_long> + <default>false</default> + </option> <option name="alt_tab_forward" type="key"> <_short>Key to start the switcher</_short> <_long>Start switching between windows</_long> @@ -388,7 +393,7 @@ <max>100</max> <default>75</default> </option> - + <option name="devices_option" type="int"> <_short>Show Devices</_short> <_long>Show devices in the launcher</_long> @@ -408,7 +413,7 @@ <_name>Always</_name> </desc> </option> - + <option name="shortcut_overlay" type="bool"> <_short>Enable Shortcut Hints Overlay</_short> <_long>Enable Shortcut Hints Overlay</_long> diff --git a/services/panel-main.c b/services/panel-main.c index e48f2b993..4bc5a5160 100644 --- a/services/panel-main.c +++ b/services/panel-main.c @@ -235,7 +235,7 @@ on_service_resync (PanelService *service, const gchar *indicator_id, GDBusConnec { GError *error = NULL; g_dbus_connection_emit_signal (connection, - S_NAME, + NULL, S_PATH, S_IFACE, "ReSync", @@ -256,7 +256,7 @@ on_service_entry_activated (PanelService *service, { GError *error = NULL; g_dbus_connection_emit_signal (connection, - S_NAME, + NULL, S_PATH, S_IFACE, "EntryActivated", @@ -278,7 +278,7 @@ on_service_entry_activate_request (PanelService *service, GError *error = NULL; g_warning ("%s, entry_id:%s", G_STRFUNC, entry_id); g_dbus_connection_emit_signal (connection, - S_NAME, + NULL, S_PATH, S_IFACE, "EntryActivateRequest", @@ -300,7 +300,7 @@ on_service_entry_show_now_changed (PanelService *service, { GError *error = NULL; g_dbus_connection_emit_signal (connection, - S_NAME, + NULL, S_PATH, S_IFACE, "EntryShowNowChanged", diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 01fe6993d..7eb276781 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -39,7 +39,7 @@ set (LIBS ${TEST_UNIT_DEPS_LIBRARIES} "-lunity-core-${UNITY_API_VERSION} -lcompi link_libraries (${LIBS}) set (LIB_PATHS ${TEST_UNIT_DEPS_LIBRARY_DIRS}) -link_directories (${CMAKE_BINARY_DIR}/UnityCore ${LIB_PATHS}) +link_directories (${CMAKE_BINARY_DIR}/UnityCore ${LIB_PATHS} ${COMPIZ_LIBDIR}) include_directories (. .. ../services ../UnityCore ${UNITY_SRC} ${CMAKE_BINARY_DIR}) include_directories (${CMAKE_SOURCE_DIR}/plugins/unity-mt-grab-handles/src) @@ -219,6 +219,7 @@ if (GTEST_SRC_DIR AND test_im_text_entry.cpp test_launcher_controller.cpp test_keyboard_util.cpp + test_panel_style.cpp test_resultviewgrid.cpp test_single_monitor_launcher_icon.cpp test_switcher_controller.cpp @@ -253,7 +254,6 @@ if (GTEST_SRC_DIR AND ${CMAKE_SOURCE_DIR}/launcher/FavoriteStore.cpp ${CMAKE_SOURCE_DIR}/launcher/FavoriteStoreGSettings.cpp ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp - ${CMAKE_SOURCE_DIR}/launcher/GeisAdapter.cpp ${CMAKE_SOURCE_DIR}/launcher/HudLauncherIcon.cpp ${CMAKE_SOURCE_DIR}/launcher/Launcher.cpp ${CMAKE_SOURCE_DIR}/launcher/LauncherController.cpp @@ -321,7 +321,7 @@ endif (GTEST_SRC_DIR AND GMOCK_LIB AND GMOCK_MAIN_LIB) -add_subdirectory (test-gesture-engine) +add_subdirectory (test-gestures) # # check target @@ -332,25 +332,25 @@ set (TEST_RESULT_HTML ${TEST_RESULT_DIR}/test-results.html) set (GTEST_TEST_COMMAND ./test-gtest) set (GTEST_TEST_COMMAND_XLESS ./test-gtest-xless) set (GTEST_TEST_COMMAND_DBUS dbus-test-runner --task ./test-gtest-service --task ./test-gtest-dbus) -set (GTEST_TEST_COMMAND_GESTURE_ENGINE ./test-gesture-engine/test-gesture-engine) +set (GTEST_TEST_COMMAND_GESTURES ./test-gestures/test-gestures) set (TEST_COMMAND gtester --verbose -k --g-fatal-warnings -o=${TEST_RESULT_XML} ./test-unit && ${GTEST_TEST_COMMAND} --gtest_output=xml:./ && ${GTEST_TEST_COMMAND_XLESS} --gtest_output=xml:./ - && ${GTEST_TEST_COMMAND_GESTURE_ENGINE} --gtest_output=xml:./ + && ${GTEST_TEST_COMMAND_GESTURES} --gtest_output=xml:./ && ${GTEST_TEST_COMMAND_DBUS} --gtest_output=xml:./ ) set (TEST_COMMAND_HEADLESS ${GTEST_TEST_COMMAND_XLESS} --gtest_output=xml:./ - && ${GTEST_TEST_COMMAND_GESTURE_ENGINE} --gtest_output=xml:./ + && ${GTEST_TEST_COMMAND_GESTURES} --gtest_output=xml:./ #&& ${GTEST_TEST_COMMAND_DBUS} --gtest_output=xml:./ && echo "Warning, DBus test cases are disabled!!") if (GTEST_SRC_DIR) - add_custom_target (check COMMAND ${TEST_COMMAND} DEPENDS test-unit test-gtest test-gtest-xless test-gtest-dbus test-gesture-engine) - add_custom_target (check-headless COMMAND ${TEST_COMMAND_HEADLESS} DEPENDS test-gtest-xless test-gtest-dbus test-gesture-engine) + add_custom_target (check COMMAND ${TEST_COMMAND} DEPENDS test-unit test-gtest test-gtest-xless test-gtest-dbus test-gestures) + add_custom_target (check-headless COMMAND ${TEST_COMMAND_HEADLESS} DEPENDS test-gtest-xless test-gtest-dbus test-gestures) add_custom_target (check-report COMMAND ${TEST_UNIT_COMMAND} && gtester-report ${TEST_RESULT_XML} > ${TEST_RESULT_HTML}) add_custom_target (gcheck COMMAND ${DBUS_TEST_COMMAND} DEPENDS test-gtest test-gtest-xless) else (GTEST_SRC_DIR) diff --git a/tests/autopilot/unity/tests/test_quicklist.py b/tests/autopilot/unity/tests/test_quicklist.py index b332cf82f..03d9747a2 100644 --- a/tests/autopilot/unity/tests/test_quicklist.py +++ b/tests/autopilot/unity/tests/test_quicklist.py @@ -347,3 +347,23 @@ class QuicklistKeyNavigationTests(UnityTestCase): mouse_item.mouse_move_to() self.assertThat(mouse_item.selected, Eventually(Equals(True))) self.assertThat(self.quicklist.selected_item.id, Equals(mouse_item.id)) + + def test_moving_mouse_during_grab_select_correct_menuitem(self): + """Test that moving the mouse during grabbing selects the + correct menu item. See bug #1027955. + """ + self.open_quicklist_with_mouse() + mouse_item = self.quicklist.selectable_items[0] + mouse_item.mouse_move_to() + self.assertThat(mouse_item.selected, Eventually(Equals(True))) + + # Dragging the mouse horizontally doesn't change the selection + self.mouse.press() + self.addCleanup(self.mouse.release) + self.mouse.move(mouse_item.x + mouse_item.width - 10, mouse_item.y + mouse_item.height / 2) + self.assertThat(mouse_item.selected, Eventually(Equals(True))) + + # Moving the mouse down selects the next item + mouse_item = self.quicklist.selectable_items[1] + mouse_item.mouse_move_to() + self.assertThat(mouse_item.selected, Eventually(Equals(True))) diff --git a/tests/autopilot/unity/tests/test_switcher.py b/tests/autopilot/unity/tests/test_switcher.py index 9cd23bd43..4b33b4ff4 100644 --- a/tests/autopilot/unity/tests/test_switcher.py +++ b/tests/autopilot/unity/tests/test_switcher.py @@ -9,6 +9,7 @@ from __future__ import absolute_import from autopilot.matchers import Eventually +from autopilot.testcase import multiply_scenarios import logging from testtools.matchers import Equals, Contains, Not from time import sleep @@ -19,6 +20,22 @@ from unity.tests import UnityTestCase logger = logging.getLogger(__name__) class SwitcherTestCase(UnityTestCase): + + scenarios = [ + ('show_desktop_icon_true', {'show_desktop_option': True}), + ('show_desktop_icon_false', {'show_desktop_option': False}), + ] + + def setUp(self): + super(SwitcherTestCase, self).setUp() + self.set_show_desktop(self.show_desktop_option) + + def set_show_desktop(self, state): + if type(state) is not bool: + raise TypeError("'state' must be boolean, not %r" % type(state)) + self.set_unity_option("disable_show_desktop", state) + self.assertThat(self.switcher.controller.show_desktop_disabled, Eventually(Equals(state))) + def set_timeout_setting(self, state): if type(state) is not bool: raise TypeError("'state' must be boolean, not %r" % type(state)) @@ -134,6 +151,8 @@ class SwitcherTests(SwitcherTestCase): open the switcher. """ + self.start_app("Character Map") + self.keybinding_hold("switcher/reveal_normal") self.addCleanup(self.keybinding_release, "switcher/reveal_normal") self.assertThat(self.switcher.visible, Eventually(Equals(False))) @@ -144,6 +163,8 @@ class SwitcherTests(SwitcherTestCase): def test_switcher_cancel(self): """Pressing the switcher cancel keystroke must cancel the switcher.""" + self.start_app("Character Map") + self.switcher.initiate() self.addCleanup(self.switcher.terminate) @@ -153,6 +174,8 @@ class SwitcherTests(SwitcherTestCase): def test_lazy_switcher_cancel(self): """Must be able to cancel the switcher after a 'lazy' initiation.""" + self.start_app("Character Map") + self.keybinding_hold("switcher/reveal_normal") self.addCleanup(self.keybinding_release, "switcher/reveal_normal") self.assertThat(self.switcher.visible, Eventually(Equals(False))) @@ -226,6 +249,7 @@ class SwitcherWindowsManagementTests(SwitcherTestCase): class SwitcherDetailsTests(SwitcherTestCase): """Test the details mode for the switcher.""" + def setUp(self): super(SwitcherDetailsTests, self).setUp() self.set_timeout_setting(True) @@ -271,10 +295,12 @@ class SwitcherDetailsModeTests(SwitcherTestCase): """ - scenarios = [ - ('initiate_with_grave', {'initiate_keycode': '`'}), - ('initiate_with_down', {'initiate_keycode': 'Down'}), - ] + scenarios = multiply_scenarios(SwitcherTestCase.scenarios, + [ + ('initiate_with_grave', {'initiate_keycode': '`'}), + ('initiate_with_down', {'initiate_keycode': 'Down'}), + ] + ) def test_can_start_details_mode(self): """Must be able to switch to details mode using selected scenario keycode. @@ -316,6 +342,8 @@ class SwitcherDetailsModeTests(SwitcherTestCase): self.assertVisibleWindowStack([calc_win2, calc_win1]) self.switcher.initiate() + while self.switcher.current_icon.tooltip_text != calc_win2.application.name: + self.switcher.next_icon() self.keyboard.press_and_release(self.initiate_keycode) sleep(0.5) self.switcher.select() diff --git a/tests/test-gesture-engine/CMakeLists.txt b/tests/test-gesture-engine/CMakeLists.txt deleted file mode 100644 index 49596e152..000000000 --- a/tests/test-gesture-engine/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -if (GTEST_SRC_DIR) - set(UNITY_SRC ${CMAKE_SOURCE_DIR}/plugins/unityshell/src) - - add_custom_command(OUTPUT GestureEngine.cpp GestureEngine.h UBusMessages.h - COMMAND cp ${UNITY_SRC}/GestureEngine.cpp ${UNITY_SRC}/GestureEngine.h ${CMAKE_SOURCE_DIR}/unity-shared//UBusMessages.h ${CMAKE_CURRENT_BINARY_DIR} - COMMAND sed -f ${CMAKE_CURRENT_SOURCE_DIR}/sed_script ${UNITY_SRC}/GestureEngine.cpp > ${CMAKE_CURRENT_BINARY_DIR}/GestureEngine.cpp - COMMAND sed -f ${CMAKE_CURRENT_SOURCE_DIR}/sed_script ${UNITY_SRC}/GestureEngine.h > ${CMAKE_CURRENT_BINARY_DIR}/GestureEngine.h - DEPENDS ${UNITY_SRC}/GestureEngine.cpp ${UNITY_SRC}/GestureEngine.h ${CMAKE_SOURCE_DIR}/unity-shared/UBusMessages.h - COMMENT "Copying GestureEngine source.") - - # Clean-up includes and definitions made in ../CmakeLists.txt - remove_definitions(${CFLAGS}) - set_directory_properties(PROPERTY INCLUDE_DIRECTORIES "") - # And make our own - pkg_check_modules (TEST_GESTURE_ENGINE_DEPS REQUIRED QUIET "${UNITY_PLUGIN_DEPS}") - set(TEST_GESTURE_ENGINE_CFLAGS - "-g" - "-I${CMAKE_CURRENT_SOURCE_DIR}" - "-I${CMAKE_CURRENT_BINARY_DIR}" - ${TEST_GESTURE_ENGINE_DEPS_CFLAGS} - ) - add_definitions(${TEST_GESTURE_ENGINE_CFLAGS}) - - pkg_check_modules (COMPIZ REQUIRED QUIET compiz) - link_directories (${COMPIZ_LIBDIR}) - - add_executable(test-gesture-engine - test_gesture_engine.cpp - X11_mock.cpp - GestureEngine.cpp - PluginAdapterMock.cpp - GeisAdapterMock.cpp - ubus-server-mock.cpp - ) - target_link_libraries(test-gesture-engine gtest ${TEST_GESTURE_ENGINE_DEPS_LIBRARIES} -lcompiz_core) - add_test(UnityGTestGestureEngine test-gesture-engine) - add_dependencies(test-gesture-engine gtest unity-core-${UNITY_API_VERSION}) - - add_custom_target (check-gesture-engine COMMAND ./test-gesture-engine DEPENDS test-gesture-engine) -endif (GTEST_SRC_DIR) diff --git a/tests/test-gesture-engine/GeisAdapterMock.cpp b/tests/test-gesture-engine/GeisAdapterMock.cpp deleted file mode 100644 index 2d4355a21..000000000 --- a/tests/test-gesture-engine/GeisAdapterMock.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 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 warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 3 along with this program. If not, see - * <http://www.gnu.org/licenses/> - * - * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com> - * - */ - -#include "GeisAdapterMock.h" - -GeisAdapterMock *GeisAdapterMock::_default = nullptr; - -GeisAdapterMock& GeisAdapterMock::Instance() { - if (!_default) - { - _default = new GeisAdapterMock; - } - return *_default; -} diff --git a/tests/test-gesture-engine/GeisAdapterMock.h b/tests/test-gesture-engine/GeisAdapterMock.h deleted file mode 100644 index c4237a0a8..000000000 --- a/tests/test-gesture-engine/GeisAdapterMock.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 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 warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 3 along with this program. If not, see - * <http://www.gnu.org/licenses/> - * - * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com> - * - */ - -#ifndef GEISADAPTER_MOCK_H -#define GEISADAPTER_MOCK_H - -#include <sigc++/sigc++.h> -#include <X11/Xlib.h> - -class GeisAdapterMock : public sigc::trackable -{ -public: - static GeisAdapterMock& Instance(); - - ~GeisAdapterMock() {} - - typedef struct _GeisTapData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - int tap_length_ms; - float position_x; - float position_y; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisTapData; - - typedef struct _GeisDragData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - float delta_x; - float delta_y; - float velocity_x; - float velocity_y; - float position_x; - float position_y; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisDragData; - - typedef struct _GeisRotateData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - float angle; - float angle_delta; - float angle_velocity; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisRotateData; - - typedef struct _GeisPinchData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - float radius; - float radius_delta; - float radius_velocity; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisPinchData; - - typedef struct _GeisTouchData - { - int id; - int device_id; - Window window; - int touches; - int timestamp; - float focus_x; - float focus_y; - float bound_x1; - float bound_y1; - float bound_x2; - float bound_y2; - } GeisTouchData; - - sigc::signal<void, GeisTapData*> tap; - - sigc::signal<void, GeisDragData*> drag_start; - sigc::signal<void, GeisDragData*> drag_update; - sigc::signal<void, GeisDragData*> drag_finish; - - sigc::signal<void, GeisRotateData*> rotate_start; - sigc::signal<void, GeisRotateData*> rotate_update; - sigc::signal<void, GeisRotateData*> rotate_finish; - - sigc::signal<void, GeisPinchData*> pinch_start; - sigc::signal<void, GeisPinchData*> pinch_update; - sigc::signal<void, GeisPinchData*> pinch_finish; - - sigc::signal<void, GeisTouchData*> touch_start; - sigc::signal<void, GeisTouchData*> touch_update; - sigc::signal<void, GeisTouchData*> touch_finish; - -private: - GeisAdapterMock() {} - - static GeisAdapterMock* _default; - -}; -#endif diff --git a/tests/test-gesture-engine/test_gesture_engine.cpp b/tests/test-gesture-engine/test_gesture_engine.cpp deleted file mode 100644 index 1c009bd55..000000000 --- a/tests/test-gesture-engine/test_gesture_engine.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright 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 warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 3 along with this program. If not, see - * <http://www.gnu.org/licenses/> - * - * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com> - * - */ - -#include <gtest/gtest.h> -#include <compiz_mock/core/core.h> -#include "GestureEngine.h" - -CompScreenMock concrete_screen_mock; -CompScreenMock *screen_mock = &concrete_screen_mock; -int pointerX_mock = 0; -int pointerY_mock = 0; - -class GestureEngineTest : public ::testing::Test { - protected: - virtual void SetUp() { - screen_mock->_width = 1280; - screen_mock->_height = 1024; - - GenerateWindows(); - } - - void PerformPinch(GestureEngine &gesture_engine, float peak_radius) { - CompWindowMock *middle_window = screen_mock->_client_list_stacking[1]; - - GeisAdapterMock::GeisTouchData touch_data; - touch_data.id = 1; - touch_data.touches = 3; - touch_data.window = 123; - touch_data.focus_x = 100; /* hits the middle window */ - touch_data.focus_y = 100; - gesture_engine.OnTouchStart(&touch_data); - - GeisAdapterMock::GeisPinchData pinch_data; - pinch_data.id = 1; - pinch_data.touches = 3; - pinch_data.window = 123; - pinch_data.focus_x = 100; /* hits the middle window */ - pinch_data.focus_y = 100; - pinch_data.radius = 1.0; - gesture_engine.OnPinchStart(&pinch_data); - - touch_data.focus_x += 10; - touch_data.focus_y += 20; - gesture_engine.OnTouchUpdate(&touch_data); - - pinch_data.focus_x += 10; - pinch_data.focus_y += 20; - pinch_data.radius = peak_radius; - gesture_engine.OnPinchUpdate(&pinch_data); - - gesture_engine.OnTouchFinish(&touch_data); - gesture_engine.OnPinchFinish(&pinch_data); - } - - private: - void GenerateWindows() { - /* remove windows from previous test */ - for (auto window : screen_mock->_client_list_stacking) { - delete window; - } - screen_mock->_client_list_stacking.clear(); - - /* and generate new ones */ - CompWindowMock *window; - - /* the root window */ - window = new CompWindowMock; - /* x, y, width, height, border */ - window->_geometry.set(0, 0, screen_mock->width(), screen_mock->height(), 0); - window->_serverGeometry = window->_geometry; - window->_actions = 0; - window->_state = 0; - screen_mock->_client_list_stacking.push_back(window); - - /* middle window */ - window = new CompWindowMock; - window->_geometry.set(10, 10, 400, 400, 0); - window->_serverGeometry = window->_geometry; - window->_actions = CompWindowActionMoveMask; - window->_state = 0; - screen_mock->_client_list_stacking.push_back(window); - - /* top-level window */ - window = new CompWindowMock; - window->_geometry.set(500, 500, 410, 410, 0); - window->_serverGeometry = window->_geometry; - window->_actions = CompWindowActionMoveMask; - window->_state = 0; - screen_mock->_client_list_stacking.push_back(window); - - screen_mock->_client_list = screen_mock->_client_list_stacking; - std::reverse(screen_mock->_client_list.begin(), - screen_mock->_client_list.end()); - } -}; - -TEST_F(GestureEngineTest, ThreeFingersDragMovesWindow) -{ - GestureEngine gestureEngine(screen_mock); - CompWindowMock *middle_window = screen_mock->_client_list_stacking[1]; - - GeisAdapterMock::GeisTouchData touch_data; - touch_data.id = 1; - touch_data.touches = 3; - touch_data.window = 123; - touch_data.focus_x = 100; /* hits the middle window */ - touch_data.focus_y = 100; - gestureEngine.OnTouchStart(&touch_data); - - GeisAdapterMock::GeisDragData drag_data; - drag_data.id = 1; - drag_data.touches = 3; - drag_data.window = 123; - drag_data.focus_x = 100; /* hits the middle window */ - drag_data.focus_y = 100; - gestureEngine.OnDragStart(&drag_data); - - ASSERT_FALSE(middle_window->_moved); - - touch_data.focus_x += 10; - touch_data.focus_y += 20; - gestureEngine.OnTouchUpdate(&touch_data); - - drag_data.delta_x = 10; - drag_data.delta_y = 20; - drag_data.focus_x += drag_data.delta_x; - drag_data.focus_y += drag_data.delta_x; - gestureEngine.OnDragUpdate(&drag_data); - - ASSERT_TRUE(middle_window->_moved); - ASSERT_EQ(drag_data.delta_x, middle_window->_movement_x); - ASSERT_EQ(drag_data.delta_y, middle_window->_movement_y); -} - -TEST_F(GestureEngineTest, ThreeFingersDragDoesntMoveStaticWindow) -{ - GestureEngine gestureEngine(screen_mock); - CompWindowMock *middle_window = screen_mock->_client_list_stacking[1]; - - /* can't be moved */ - middle_window->_actions = 0; - - GeisAdapterMock::GeisTouchData touch_data; - touch_data.id = 1; - touch_data.touches = 3; - touch_data.window = 123; - touch_data.focus_x = 100; /* hits the middle window */ - touch_data.focus_y = 100; - gestureEngine.OnTouchStart(&touch_data); - - GeisAdapterMock::GeisDragData drag_data; - drag_data.id = 1; - drag_data.touches = 3; - drag_data.window = 123; - drag_data.focus_x = 100; /* hits the middle window */ - drag_data.focus_y = 100; - gestureEngine.OnDragStart(&drag_data); - - ASSERT_FALSE(middle_window->_moved); - - touch_data.focus_x += 10; - touch_data.focus_y += 20; - gestureEngine.OnTouchUpdate(&touch_data); - - drag_data.delta_x = 10; - drag_data.delta_y = 20; - drag_data.focus_x += drag_data.delta_x; - drag_data.focus_y += drag_data.delta_x; - gestureEngine.OnDragUpdate(&drag_data); - - ASSERT_FALSE(middle_window->_moved); -} - -TEST_F(GestureEngineTest, ThreeFingersPinchMaximizesWindow) -{ - GestureEngine gesture_engine(screen_mock); - CompWindowMock *middle_window = screen_mock->_client_list_stacking[1]; - - PerformPinch(gesture_engine, 2.0); - - ASSERT_EQ(1, middle_window->_maximize_count); - ASSERT_EQ(MAXIMIZE_STATE, middle_window->_maximize_state); -} - -TEST_F(GestureEngineTest, ThreeFingersPinchRestoresWindow) -{ - GestureEngine gesture_engine(screen_mock); - CompWindowMock *middle_window = screen_mock->_client_list_stacking[1]; - - PerformPinch(gesture_engine, 0.3); - - ASSERT_EQ(1, middle_window->_maximize_count); - ASSERT_EQ(0, middle_window->_maximize_state); -} - -TEST_F(GestureEngineTest, MinimalThreeFingersPinchDoesNothing) -{ - GestureEngine gesture_engine(screen_mock); - CompWindowMock *middle_window = screen_mock->_client_list_stacking[1]; - - PerformPinch(gesture_engine, 1.1); - - ASSERT_EQ(0, middle_window->_maximize_count); -} - -/* Regression test for lp:979418, where the grab is not removed if the gesture - * id is 0. */ -TEST_F(GestureEngineTest, DragGrabCheck) -{ - screen_mock->_grab_count = 0; - - GestureEngine gesture_engine(screen_mock); - - GeisAdapterMock::GeisDragData drag_data; - drag_data.id = 0; - drag_data.touches = 3; - drag_data.window = 123; - drag_data.focus_x = 100; /* hits the middle window */ - drag_data.focus_y = 100; - gesture_engine.OnDragStart(&drag_data); - - gesture_engine.OnDragFinish(&drag_data); - - ASSERT_EQ(0, screen_mock->_grab_count); -} - -int main(int argc, char** argv) -{ - ::testing::InitGoogleTest(&argc, argv); - - int ret = RUN_ALL_TESTS(); - - return ret; -} diff --git a/tests/test-gestures/CMakeLists.txt b/tests/test-gestures/CMakeLists.txt new file mode 100644 index 000000000..8d85541f7 --- /dev/null +++ b/tests/test-gestures/CMakeLists.txt @@ -0,0 +1,71 @@ +if (GTEST_SRC_DIR) + set(UNITY_SRC ${CMAKE_SOURCE_DIR}/plugins/unityshell/src) + + add_custom_command(OUTPUT UnityGestureBroker.cpp + UnityGestureBroker.h + UBusMessages.h + WindowGestureTarget.h + WindowGestureTarget.cpp + + COMMAND cp ${UNITY_SRC}/UnityGestureBroker.cpp + ${UNITY_SRC}/UnityGestureBroker.h + ${CMAKE_SOURCE_DIR}/unity-shared//UBusMessages.h + ${UNITY_SRC}/WindowGestureTarget.h + ${UNITY_SRC}/WindowGestureTarget.cpp + ${CMAKE_CURRENT_BINARY_DIR} + + COMMAND sed -f ${CMAKE_CURRENT_SOURCE_DIR}/sed_script_broker + ${UNITY_SRC}/UnityGestureBroker.cpp > ${CMAKE_CURRENT_BINARY_DIR}/UnityGestureBroker.cpp + + COMMAND sed -f ${CMAKE_CURRENT_SOURCE_DIR}/sed_script_broker + ${UNITY_SRC}/UnityGestureBroker.h > ${CMAKE_CURRENT_BINARY_DIR}/UnityGestureBroker.h + + COMMAND sed -f ${CMAKE_CURRENT_SOURCE_DIR}/sed_script_gesture + ${UNITY_SRC}/WindowGestureTarget.h > ${CMAKE_CURRENT_BINARY_DIR}/WindowGestureTarget.h + + COMMAND sed -f ${CMAKE_CURRENT_SOURCE_DIR}/sed_script_gesture + ${UNITY_SRC}/WindowGestureTarget.cpp > ${CMAKE_CURRENT_BINARY_DIR}/WindowGestureTarget.cpp + + DEPENDS ${UNITY_SRC}/UnityGestureBroker.cpp + ${UNITY_SRC}/UnityGestureBroker.h + ${CMAKE_SOURCE_DIR}/unity-shared/UBusMessages.h + ${UNITY_SRC}/WindowGestureTarget.h + ${UNITY_SRC}/WindowGestureTarget.cpp + sed_script_broker + sed_script_gesture + + COMMENT "Copying and modifying sources under test.") + + # Clean-up includes and definitions made in ../CmakeLists.txt + remove_definitions(${CFLAGS}) + set_directory_properties(PROPERTY INCLUDE_DIRECTORIES "") + # And make our own + pkg_check_modules (TEST_GESTURES_DEPS REQUIRED QUIET "${UNITY_PLUGIN_DEPS}") + set(TEST_GESTURES_CFLAGS + "-g" + "-I${CMAKE_CURRENT_SOURCE_DIR}" + "-I${CMAKE_CURRENT_BINARY_DIR}" + ${TEST_GESTURES_DEPS_CFLAGS} + ) + add_definitions(${TEST_GESTURES_CFLAGS}) + + pkg_check_modules (COMPIZ REQUIRED QUIET compiz) + link_directories (${COMPIZ_LIBDIR}) + + add_executable(test-gestures + test_gestures_main.cpp + test_gesture_broker.cpp + test_window_gesture_target.cpp + X11_mock.cpp + UnityGestureBroker.cpp + WindowGestureTarget.cpp + PluginAdapterMock.cpp + ubus-server-mock.cpp + UnityGestureTargetMock.h + ) + target_link_libraries(test-gestures gtest ${TEST_GESTURES_DEPS_LIBRARIES} -lcompiz_core) + add_test(UnityGTestGestures test-gestures) + add_dependencies(test-gestures gtest unity-core-${UNITY_API_VERSION}) + + add_custom_target (check-gestures COMMAND ./test-gestures DEPENDS test-gestures) +endif (GTEST_SRC_DIR) diff --git a/tests/test-gestures/FakeGestureEvent.h b/tests/test-gestures/FakeGestureEvent.h new file mode 100644 index 000000000..9cc13aa76 --- /dev/null +++ b/tests/test-gestures/FakeGestureEvent.h @@ -0,0 +1,63 @@ +#ifndef FAKE_GESTURE_EVENT_H +#define FAKE_GESTURE_EVENT_H + +#include <NuxGraphics/GestureEvent.h> +#include <map> + +namespace nux { +class FakeGestureEvent +{ + public: + nux::EventType type; + + int gesture_id; + int gesture_classes; + bool is_direct_touch; + int timestamp; + nux::Point2D<float> focus; + nux::Point2D<float> delta; + float angle; + float angle_delta; + float angular_velocity; + int tap_duration; + nux::Point2D<float> velocity; + float radius; + float radius_delta; + float radial_velocity; + std::vector<nux::TouchPoint> touches; + bool is_construction_finished; + + nux::GestureEvent &ToGestureEvent() + { + event_.type = type; + + event_.gesture_id_ = gesture_id; + event_.gesture_classes_ = gesture_classes; + event_.is_direct_touch_ = is_direct_touch; + event_.timestamp_ = timestamp; + event_.focus_ = focus; + event_.delta_ = delta; + event_.angle_ = angle; + event_.angle_delta_ = angle_delta; + event_.angular_velocity_ = angular_velocity; + event_.tap_duration_ = tap_duration; + event_.velocity_ = velocity; + event_.radius_ = radius; + event_.radius_delta_ = radius_delta; + event_.radial_velocity_ = radial_velocity; + event_.touches_ = touches; + event_.is_construction_finished_ = is_construction_finished; + + return event_; + } + + private: + nux::GestureEvent event_; +}; +} // namespace nux + +// maps a gesture id to its acceptance +extern std::map<int, int> g_gesture_event_accept_count; +extern std::map<int, int> g_gesture_event_reject_count; + +#endif // FAKE_GESTURE_EVENT_H diff --git a/tests/test-gestures/NuxMock.h b/tests/test-gestures/NuxMock.h new file mode 100644 index 000000000..28dfe7bf8 --- /dev/null +++ b/tests/test-gestures/NuxMock.h @@ -0,0 +1,19 @@ +#ifndef NUX_MOCK_H +#define NUX_MOCK_H + +#include <Nux/Nux.h> + +namespace nux +{ + +class InputAreaMock : public Object +{ + public: + void GestureEvent(const GestureEvent &event) + { + } +}; + +} // namespace nux + +#endif // NUX_MOCK_H diff --git a/tests/test-gesture-engine/PluginAdapterMock.cpp b/tests/test-gestures/PluginAdapterMock.cpp index a71af2421..a71af2421 100644 --- a/tests/test-gesture-engine/PluginAdapterMock.cpp +++ b/tests/test-gestures/PluginAdapterMock.cpp diff --git a/tests/test-gesture-engine/PluginAdapterMock.h b/tests/test-gestures/PluginAdapterMock.h index 2b111a68b..2b111a68b 100644 --- a/tests/test-gesture-engine/PluginAdapterMock.h +++ b/tests/test-gestures/PluginAdapterMock.h diff --git a/tests/test-gestures/UnityGestureTargetMock.h b/tests/test-gestures/UnityGestureTargetMock.h new file mode 100644 index 000000000..9fd621fb8 --- /dev/null +++ b/tests/test-gestures/UnityGestureTargetMock.h @@ -0,0 +1,15 @@ +#ifndef UNITY_GESTURE_TARGET_MOCK_H +#define UNITY_GESTURE_TARGET_MOCK_H + +#include <Nux/Gesture.h> + +class UnityGestureTargetMock : public nux::GestureTarget +{ + public: + virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event) + { + return nux::GestureDeliveryRequest::NONE; + } +}; + +#endif // UNITY_GESTURE_TARGET_MOCK_H diff --git a/tests/test-gestures/WindowGestureTargetMock.h b/tests/test-gestures/WindowGestureTargetMock.h new file mode 100644 index 000000000..e43bad80c --- /dev/null +++ b/tests/test-gestures/WindowGestureTargetMock.h @@ -0,0 +1,55 @@ +#ifndef WINDOW_GESTURE_TARGET_MOCK_H +#define WINDOW_GESTURE_TARGET_MOCK_H + +#include <Nux/Gesture.h> + +#include <set> + +class CompWindowMock; +class WindowGestureTargetMock; + +extern std::set<WindowGestureTargetMock*> g_window_target_mocks; + +class WindowGestureTargetMock : public nux::GestureTarget +{ + public: + WindowGestureTargetMock(CompWindowMock *window) : window(window) + { + g_window_target_mocks.insert(this); + } + + virtual ~WindowGestureTargetMock() + { + g_window_target_mocks.erase(this); + } + + virtual nux::GestureDeliveryRequest GestureEvent(const nux::GestureEvent &event) + { + events_received.push_back(event); + return nux::GestureDeliveryRequest::NONE; + } + + CompWindowMock *window; + std::list<nux::GestureEvent> events_received; + + static Cursor fleur_cursor; + private: + virtual bool Equals(const nux::GestureTarget& other) const + { + const WindowGestureTargetMock *window_target = dynamic_cast<const WindowGestureTargetMock *>(&other); + + if (window_target) + { + if (window && window_target->window) + return window->id() == window_target->window->id(); + else + return window == window_target->window; + } + else + { + return false; + } + } +}; + +#endif // WINDOW_GESTURE_TARGET_MOCK_H diff --git a/tests/test-gesture-engine/X11_mock.cpp b/tests/test-gestures/X11_mock.cpp index 5560aa9ac..5560aa9ac 100644 --- a/tests/test-gesture-engine/X11_mock.cpp +++ b/tests/test-gestures/X11_mock.cpp diff --git a/tests/test-gesture-engine/X11_mock.h b/tests/test-gestures/X11_mock.h index f98e028be..f98e028be 100644 --- a/tests/test-gesture-engine/X11_mock.h +++ b/tests/test-gestures/X11_mock.h diff --git a/tests/test-gesture-engine/compiz_mock/core/core.h b/tests/test-gestures/compiz_mock/core/core.h index f1c358fbf..f1c358fbf 100644 --- a/tests/test-gesture-engine/compiz_mock/core/core.h +++ b/tests/test-gestures/compiz_mock/core/core.h diff --git a/tests/test-gesture-engine/compiz_mock/core/screen.h b/tests/test-gestures/compiz_mock/core/screen.h index 38795db15..225d41c65 100644 --- a/tests/test-gesture-engine/compiz_mock/core/screen.h +++ b/tests/test-gestures/compiz_mock/core/screen.h @@ -31,41 +31,42 @@ typedef std::vector<CompWindowMock*> CompWindowMockVector; class CompScreenMock { public: - CompScreenMock() : _grab_count(0) {} + CompScreenMock() : grab_count_(0), next_grab_handle_(1) {} typedef int GrabHandle; - int width() const {return _width;} - int height() const {return _height;} + int width() const {return width_;} + int height() const {return height_;} - Display *dpy() {return _dpy;} + Display *dpy() {return dpy_;} const CompWindowMockVector & clientList(bool stackingOrder = true) { if (stackingOrder) - return _client_list_stacking; + return client_list_stacking_; else - return _client_list; + return client_list_; } - Window root() {return _root;} + Window root() {return root_;} GrabHandle pushGrab(Cursor cursor, const char *name) { - _grab_count++; - return 0; + grab_count_++; + return next_grab_handle_++; } void removeGrab(GrabHandle handle, CompPoint *restorePointer) { - _grab_count--; + grab_count_--; } Cursor invisibleCursor() {return 1;} - int _width; - int _height; - Display *_dpy; - CompWindowMockVector _client_list; - CompWindowMockVector _client_list_stacking; - Window _root; - int _grab_count; + int width_; + int height_; + Display *dpy_; + CompWindowMockVector client_list_; + CompWindowMockVector client_list_stacking_; + Window root_; + int grab_count_; + int next_grab_handle_; }; extern CompScreenMock *screen_mock; diff --git a/tests/test-gesture-engine/compiz_mock/core/window.h b/tests/test-gestures/compiz_mock/core/window.h index d65524b7d..f5e930107 100644 --- a/tests/test-gesture-engine/compiz_mock/core/window.h +++ b/tests/test-gestures/compiz_mock/core/window.h @@ -24,46 +24,56 @@ /* The real CompWindow */ #include <core/window.h> -class CompWindowMock { +class CompWindowMock +{ public: - CompWindowMock() : _moved(false), _maximize_count(0), _maximize_state(0) {} + CompWindowMock() : moved_(false), maximize_count_(0), maximize_state_(0), + minimized_(false) {} - int x() const {return _geometry.x();} - int y() const {return _geometry.y();} - int width() const {return _geometry.width() + (_geometry.border()*2);} - int height() const {return _geometry.height() + (_geometry.border()*2);} + int x() const {return geometry_.x();} + int y() const {return geometry_.y();} + int width() const {return geometry_.width() + (geometry_.border()*2);} + int height() const {return geometry_.height() + (geometry_.border()*2);} + int id() { return id_; } - void move(int dx, int dy, bool immediate = true) { - _moved = true; - _movement_x = dx; - _movement_y = dy; + void move(int dx, int dy, bool immediate = true) + { + moved_ = true; + movement_x_ = dx; + movement_y_ = dy; } - unsigned int actions () {return _actions;} + unsigned int actions () {return actions_;} - void maximize(int state) {++_maximize_count; _maximize_state = state;} + bool minimized() { return minimized_; } + + void maximize(int state) {++maximize_count_; maximize_state_ = state;} /* OBS: I wonder why it returns a reference */ - unsigned int &state() {return _state;} + unsigned int &state() {return state_;} void grabNotify(int x, int y, unsigned int state, unsigned int mask) {} void ungrabNotify() {} void syncPosition() {} - compiz::window::Geometry &serverGeometry() {return _serverGeometry;} + compiz::window::Geometry &serverGeometry() {return server_geometry_;} + + unsigned int actions_; + unsigned int state_; + compiz::window::Geometry server_geometry_; + compiz::window::Geometry geometry_; + + bool moved_; + int movement_x_; + int movement_y_; - unsigned int _actions; - unsigned int _state; - compiz::window::Geometry _serverGeometry; - compiz::window::Geometry _geometry; + int maximize_count_; + int maximize_state_; - bool _moved; - int _movement_x; - int _movement_y; + int id_; - int _maximize_count; - int _maximize_state; + bool minimized_; }; #endif diff --git a/tests/test-gestures/sed_script_broker b/tests/test-gestures/sed_script_broker new file mode 100644 index 000000000..3f256b0f6 --- /dev/null +++ b/tests/test-gestures/sed_script_broker @@ -0,0 +1,11 @@ +s|<core/core.h>|<compiz_mock/core/core.h>| +s|\<CompScreen\>|CompScreenMock|g +s|\<CompWindow\>|CompWindowMock|g +s|\<CompWindowVector\>|CompWindowMockVector|g +s|\<screen\>|screen_mock|g +s|\<pointerX\>|pointerX_mock|g +s|\<pointerY\>|pointerY_mock|g +s|\<XFreeCursor\>|XFreeCursorMock|g +s|\<XCreateFontCursor\>|XCreateFontCursorMock|g +s|\<WindowGestureTarget\>|WindowGestureTargetMock|g +s|\<UnityGestureTarget\>|UnityGestureTargetMock|g diff --git a/tests/test-gesture-engine/sed_script b/tests/test-gestures/sed_script_gesture index 94fb691f6..c2e3ffa48 100644 --- a/tests/test-gesture-engine/sed_script +++ b/tests/test-gestures/sed_script_gesture @@ -9,6 +9,10 @@ s|\<XSync\>|XSyncMock|g s|\<XWarpPointer\>|XWarpPointerMock|g s|\<XFreeCursor\>|XFreeCursorMock|g s|\<XCreateFontCursor\>|XCreateFontCursorMock|g -s|\<GeisAdapter\>|GeisAdapterMock|g -s|\<PluginAdapter\>|PluginAdapterMock|g s|\<ubus-server.h\>|ubus-server-mock.h|g +s|\<unityshell.h\>|unityshell_mock.h|g +s|\<PluginAdapter\>|PluginAdapterMock|g +s|\<UnityWindow\>|UnityWindowMock|g +s|\<UnityScreen\>|UnityScreenMock|g +s|\<InputArea\>|InputAreaMock|g +s|\<Nux/Nux\.h\>|NuxMock.h|g diff --git a/tests/test-gestures/test_gesture_broker.cpp b/tests/test-gestures/test_gesture_broker.cpp new file mode 100644 index 000000000..b7f30ec04 --- /dev/null +++ b/tests/test-gestures/test_gesture_broker.cpp @@ -0,0 +1,137 @@ +/* + * Copyright 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 warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com> + * + */ + +#include <gtest/gtest.h> +#include <compiz_mock/core/core.h> +#include "UnityGestureBroker.h" +#include "FakeGestureEvent.h" +#include "unityshell_mock.h" +#include "WindowGestureTargetMock.h" + +class GestureBrokerTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + screen_mock->width_ = 1280; + screen_mock->height_ = 1024; + + GenerateWindows(); + } + + private: + void GenerateWindows() + { + /* remove windows from previous test */ + for (auto window : screen_mock->client_list_stacking_) { + delete window; + } + screen_mock->client_list_stacking_.clear(); + + /* and generate new ones */ + CompWindowMock *window; + + /* the root window */ + window = new unity::UnityWindowMock; + window->id_ = 0; + /* x, y, width, height, border */ + window->geometry_.set(0, 0, screen_mock->width(), screen_mock->height(), 0); + window->server_geometry_ = window->geometry_; + window->actions_ = 0; + window->state_ = 0; + screen_mock->client_list_stacking_.push_back(window); + + /* middle window */ + window = new unity::UnityWindowMock; + window->id_ = 1; + window->geometry_.set(10, 10, 400, 400, 0); + window->server_geometry_ = window->geometry_; + window->actions_ = CompWindowActionMoveMask; + window->state_ = 0; + screen_mock->client_list_stacking_.push_back(window); + + /* top-level window */ + window = new unity::UnityWindowMock; + window->id_ = 2; + window->geometry_.set(500, 500, 410, 410, 0); + window->server_geometry_ = window->geometry_; + window->actions_ = CompWindowActionMoveMask; + window->state_ = 0; + screen_mock->client_list_stacking_.push_back(window); + + screen_mock->client_list_ = screen_mock->client_list_stacking_; + std::reverse(screen_mock->client_list_.begin(), + screen_mock->client_list_.end()); + } +}; + +/* + Tests that events from a three-fingers' Touch gesture goes to the + correct window. I.e., to the window that lies where the gesture starts. + */ +TEST_F(GestureBrokerTest, ThreeFingersTouchHitsCorrectWindow) +{ + UnityGestureBroker gesture_broker; + CompWindowMock *middle_window = screen_mock->client_list_stacking_[1]; + nux::FakeGestureEvent fake_event; + + // init counters + g_gesture_event_accept_count[0] = 0; + g_gesture_event_reject_count[0] = 0; + + /* prepare and send the fake event */ + fake_event.type = nux::EVENT_GESTURE_BEGIN; + fake_event.gesture_id = 0; + fake_event.is_direct_touch = false; + fake_event.focus.x = 100.0f; // hits the middle window + fake_event.focus.y = 100.0f; + // in touch device's coordinate system (because it's not a direct device). + // Thus not used by WindowCompositor + fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); + fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); + fake_event.touches.push_back(nux::TouchPoint(2, 22.0f, 22.0f)); + fake_event.is_construction_finished = false; + gesture_broker.ProcessGestureBegin(fake_event.ToGestureEvent()); + + // Gesture shouldn't be accepted as constructions hasn't finished + ASSERT_EQ(0, g_gesture_event_accept_count[0]); + ASSERT_EQ(0, g_gesture_event_reject_count[0]); + ASSERT_EQ(1, g_window_target_mocks.size()); + WindowGestureTargetMock *target_mock = *g_window_target_mocks.begin(); + ASSERT_TRUE(target_mock->window == middle_window); + // No events yet as the broker didn't accept the gesture yet + ASSERT_EQ(0, target_mock->events_received.size()); + + fake_event.type = nux::EVENT_GESTURE_UPDATE; + fake_event.delta.x += 10.0f; + fake_event.delta.y += 20.0f; + fake_event.focus.x += fake_event.delta.x; + fake_event.focus.y += fake_event.delta.y; + fake_event.is_construction_finished = true; + gesture_broker.ProcessGestureUpdate(fake_event.ToGestureEvent()); + + // Gesture should have been accepted now since the construction has finished. + ASSERT_EQ(1, g_gesture_event_accept_count[0]); + ASSERT_EQ(0, g_gesture_event_reject_count[0]); + // Check that this gesture target is still valid + ASSERT_EQ(1, g_window_target_mocks.count(target_mock)); + // Gesture events should have been sent to the target by now + ASSERT_EQ(2, target_mock->events_received.size()); +} diff --git a/tests/test-gestures/test_gestures_main.cpp b/tests/test-gestures/test_gestures_main.cpp new file mode 100644 index 000000000..d362b5746 --- /dev/null +++ b/tests/test-gestures/test_gestures_main.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 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 warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com> + * + */ + +#include <gtest/gtest.h> +#include <compiz_mock/core/core.h> +#include <NuxGraphics/GestureEvent.h> +#include "WindowGestureTargetMock.h" +#include "unityshell_mock.h" + +unity::UnityScreenMock concrete_screen_mock; +CompScreenMock *screen_mock = &concrete_screen_mock; +int pointerX_mock = 0; +int pointerY_mock = 0; + +std::map<int, int> g_gesture_event_accept_count; +void nux::GestureEvent::Accept() +{ + g_gesture_event_accept_count[gesture_id_] = + g_gesture_event_accept_count[gesture_id_] + 1; +} + +std::map<int, int> g_gesture_event_reject_count; +void nux::GestureEvent::Reject() +{ + g_gesture_event_reject_count[gesture_id_] = + g_gesture_event_reject_count[gesture_id_] + 1; +} + +Cursor WindowGestureTargetMock::fleur_cursor = 0; +std::set<WindowGestureTargetMock*> g_window_target_mocks; + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + + int ret = RUN_ALL_TESTS(); + + return ret; +} diff --git a/tests/test-gestures/test_window_gesture_target.cpp b/tests/test-gestures/test_window_gesture_target.cpp new file mode 100644 index 000000000..4491a9ca3 --- /dev/null +++ b/tests/test-gestures/test_window_gesture_target.cpp @@ -0,0 +1,235 @@ +/* + * Copyright 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 warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com> + * + */ + +#include <gtest/gtest.h> +#include <compiz_mock/core/core.h> +#include "FakeGestureEvent.h" +#include "unityshell_mock.h" +#include <WindowGestureTarget.h> + +class WindowGestureTargetTest : public ::testing::Test +{ + protected: + virtual void SetUp() + { + screen_mock->width_ = 1280; + screen_mock->height_ = 1024; + } + + void PerformPinch(WindowGestureTarget &gesture_target, float peak_radius) + { + nux::FakeGestureEvent fake_event; + + fake_event.type = nux::EVENT_GESTURE_BEGIN; + fake_event.gesture_id = 0; + fake_event.gesture_classes = nux::PINCH_GESTURE; + fake_event.is_direct_touch = false; + // in touch device's coordinate system (because it's not a direct device). + // Thus not used by WindowCompositor + fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); + fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); + fake_event.touches.push_back(nux::TouchPoint(2, 22.0f, 22.0f)); + fake_event.focus.x = gesture_target.window()->geometry_.centerX(); + fake_event.focus.y = gesture_target.window()->geometry_.centerY();; + fake_event.radius = 1.0; + fake_event.is_construction_finished = false; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + + fake_event.type = nux::EVENT_GESTURE_UPDATE; + fake_event.radius = peak_radius; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + + fake_event.type = nux::EVENT_GESTURE_END; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + } +}; + +TEST_F(WindowGestureTargetTest, ThreeFingersDragMovesWindow) +{ + unity::UnityWindowMock window; + window.geometry_.set(10, 10, 400, 400, 0); + window.server_geometry_ = window.geometry_; + window.actions_ = CompWindowActionMoveMask; + window.state_ = 0; + window.id_ = 1; + + WindowGestureTarget gesture_target(&window); + + nux::FakeGestureEvent fake_event; + + /* prepare and send the fake event */ + fake_event.type = nux::EVENT_GESTURE_BEGIN; + fake_event.gesture_id = 0; + fake_event.gesture_classes = nux::TOUCH_GESTURE; + fake_event.is_direct_touch = false; + fake_event.focus.x = 100.0f; // hits the middle window + fake_event.focus.y = 100.0f; + // in touch device's coordinate system (because it's not a direct device). + // Thus not used by WindowCompositor + fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); + fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); + fake_event.touches.push_back(nux::TouchPoint(2, 22.0f, 22.0f)); + fake_event.is_construction_finished = false; + fake_event.radius = 1.0f; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + + ASSERT_FALSE(window.moved_); + + fake_event.type = nux::EVENT_GESTURE_UPDATE; + fake_event.gesture_classes = nux::TOUCH_GESTURE | nux::DRAG_GESTURE; + fake_event.delta.x = 10.0f; + fake_event.delta.y = 20.0f; + fake_event.focus.x += fake_event.delta.x; + fake_event.focus.y += fake_event.delta.y; + fake_event.is_construction_finished = true; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + + ASSERT_TRUE(window.moved_); + ASSERT_EQ(fake_event.delta.x, window.movement_x_); + ASSERT_EQ(fake_event.delta.y, window.movement_y_); +} + +TEST_F(WindowGestureTargetTest, ThreeFingersDragDoesntMoveStaticWindow) +{ + + unity::UnityWindowMock window; + window.geometry_.set(10, 10, 400, 400, 0); + window.server_geometry_ = window.geometry_; + window.actions_ = 0; /* can't be moved */ + window.state_ = 0; + window.id_ = 1; + + WindowGestureTarget gesture_target(&window); + + nux::FakeGestureEvent fake_event; + + /* prepare and send the fake event */ + fake_event.type = nux::EVENT_GESTURE_BEGIN; + fake_event.gesture_id = 0; + fake_event.is_direct_touch = false; + fake_event.focus.x = 100.0f; // hits the middle window + fake_event.focus.y = 100.0f; + // in touch device's coordinate system (because it's not a direct device). + // Thus not used by WindowCompositor + fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); + fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); + fake_event.touches.push_back(nux::TouchPoint(2, 22.0f, 22.0f)); + fake_event.is_construction_finished = false; + fake_event.radius = 1.0f; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + + ASSERT_FALSE(window.moved_); + + fake_event.type = nux::EVENT_GESTURE_UPDATE; + fake_event.delta.x += 10.0f; + fake_event.delta.y += 20.0f; + fake_event.focus.x += fake_event.delta.x; + fake_event.focus.y += fake_event.delta.y; + fake_event.is_construction_finished = true; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + + ASSERT_FALSE(window.moved_); +} + +TEST_F(WindowGestureTargetTest, ThreeFingersPinchMaximizesWindow) +{ + unity::UnityWindowMock window; + window.geometry_.set(10, 10, 400, 400, 0); + window.server_geometry_ = window.geometry_; + window.actions_ = CompWindowActionMoveMask; + window.state_ = 0; + window.id_ = 1; + + WindowGestureTarget gesture_target(&window); + + PerformPinch(gesture_target, 2.0); + + ASSERT_EQ(1, window.maximize_count_); + ASSERT_EQ(MAXIMIZE_STATE, window.maximize_state_); +} + +TEST_F(WindowGestureTargetTest, ThreeFingersPinchRestoresWindow) +{ + unity::UnityWindowMock window; + window.geometry_.set(10, 10, 400, 400, 0); + window.server_geometry_ = window.geometry_; + window.actions_ = CompWindowActionMoveMask; + window.state_ = MAXIMIZE_STATE; + window.id_ = 1; + + WindowGestureTarget gesture_target(&window); + + PerformPinch(gesture_target, 0.3); + + ASSERT_EQ(1, window.maximize_count_); + ASSERT_EQ(0, window.maximize_state_); +} + +TEST_F(WindowGestureTargetTest, MinimalThreeFingersPinchDoesNothing) +{ + unity::UnityWindowMock window; + window.geometry_.set(10, 10, 400, 400, 0); + window.server_geometry_ = window.geometry_; + window.actions_ = CompWindowActionMoveMask; + window.state_ = 0; + window.id_ = 1; + + WindowGestureTarget gesture_target(&window); + + PerformPinch(gesture_target, 1.1); + + ASSERT_EQ(0, window.maximize_count_); +} + +/* Regression test for lp:979418, where the grab is not removed if the gesture + * id is 0. */ +TEST_F(WindowGestureTargetTest, DragGrabCheck) +{ + screen_mock->grab_count_ = 0; + + unity::UnityWindowMock window; + window.geometry_.set(10, 10, 400, 400, 0); + window.server_geometry_ = window.geometry_; + window.actions_ = CompWindowActionMoveMask; + window.state_ = 0; + window.id_ = 1; + + WindowGestureTarget gesture_target(&window); + + /* prepare and send the fake event */ + nux::FakeGestureEvent fake_event; + fake_event.type = nux::EVENT_GESTURE_BEGIN; + fake_event.gesture_id = 0; + fake_event.is_direct_touch = false; + fake_event.focus.x = 100.0f; // hits the middle window + fake_event.focus.y = 100.0f; + // in touch device's coordinate system (because it's not a direct device). + // Thus not used by WindowCompositor + fake_event.touches.push_back(nux::TouchPoint(0, 10.0f, 10.0f)); + fake_event.touches.push_back(nux::TouchPoint(1, 20.0f, 20.0f)); + fake_event.touches.push_back(nux::TouchPoint(2, 22.0f, 22.0f)); + fake_event.is_construction_finished = false; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + + fake_event.type = nux::EVENT_GESTURE_END; + gesture_target.GestureEvent(fake_event.ToGestureEvent()); + + ASSERT_EQ(0, screen_mock->grab_count_); +} diff --git a/tests/test-gesture-engine/ubus-server-mock.cpp b/tests/test-gestures/ubus-server-mock.cpp index 8305aedff..8305aedff 100644 --- a/tests/test-gesture-engine/ubus-server-mock.cpp +++ b/tests/test-gestures/ubus-server-mock.cpp diff --git a/tests/test-gesture-engine/ubus-server-mock.h b/tests/test-gestures/ubus-server-mock.h index 21a642253..21a642253 100644 --- a/tests/test-gesture-engine/ubus-server-mock.h +++ b/tests/test-gestures/ubus-server-mock.h diff --git a/tests/test-gestures/unityshell_mock.h b/tests/test-gestures/unityshell_mock.h new file mode 100644 index 000000000..dd054abf4 --- /dev/null +++ b/tests/test-gestures/unityshell_mock.h @@ -0,0 +1,52 @@ +#ifndef UNITYSHELL_MOCK_H +#define UNITYSHELL_MOCK_H + +#include <compiz_mock/core/core.h> +#include <sigc++/sigc++.h> +#include <NuxMock.h> + +namespace unity +{ + +class UnityWindowMock : public CompWindowMock +{ + public: + static UnityWindowMock *get(CompWindowMock *window) + { + return static_cast<UnityWindowMock*>(window); + + } + + sigc::signal<void> being_destroyed; +}; + +class UnityScreenMock : public CompScreenMock +{ + public: + UnityScreenMock() + : launcher_(new nux::InputAreaMock) + { + } + + virtual ~UnityScreenMock() + { + launcher_->Dispose(); + } + + static UnityScreenMock *get(CompScreenMock *screen) + { + return static_cast<UnityScreenMock*>(screen); + + } + + nux::InputAreaMock *LauncherView() + { + return launcher_; + } + + nux::InputAreaMock *launcher_; +}; + +} // namespace unity + +#endif // UNITYSHELL_MOCK_H diff --git a/tests/test_favorite_store_gsettings.cpp b/tests/test_favorite_store_gsettings.cpp index 9604dc712..c491efce3 100644 --- a/tests/test_favorite_store_gsettings.cpp +++ b/tests/test_favorite_store_gsettings.cpp @@ -41,10 +41,9 @@ using testing::Eq; namespace { // Constant +const gchar* SETTINGS_NAME = "com.canonical.Unity.Launcher"; +const gchar* SETTINGS_KEY = "favorites"; const gchar* SCHEMA_DIRECTORY = BUILDDIR"/settings"; -const gchar* BASE_STORE_FILE = BUILDDIR"/settings/test-favorite-store-gsettings.store"; -const gchar* BASE_STORE_CONTENTS = "[com/canonical/unity/launcher]\n" \ - "favorites=['%s', '%s', '%s']"; const char* base_store_favs[] = { BUILDDIR"/tests/data/ubuntuone-installer.desktop", BUILDDIR"/tests/data/ubuntu-software-center.desktop", @@ -76,41 +75,34 @@ bool ends_with(std::string const& value, std::string const& suffix) class TestFavoriteStoreGSettings : public testing::Test { public: - glib::Object<GSettingsBackend> backend; - std::unique_ptr<internal::FavoriteStoreGSettings> setting_singleton_instance; + std::unique_ptr<internal::FavoriteStoreGSettings> favorite_store; + glib::Object<GSettings> gsettings_client; virtual void SetUp() { // set the data directory so gsettings can find the schema - g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIRECTORY, false); + g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIRECTORY, true); + g_setenv("GSETTINGS_BACKEND", "memory", true); - glib::Error error; - glib::String contents(g_strdup_printf(BASE_STORE_CONTENTS, - base_store_favs[0], - base_store_favs[1], - base_store_favs[2] - )); + favorite_store.reset(new internal::FavoriteStoreGSettings()); - g_file_set_contents(BASE_STORE_FILE, - contents.Value(), - -1, - error.AsOutParam()); - - ASSERT_FALSE(error); - - backend = g_keyfile_settings_backend_new(BASE_STORE_FILE, "/", "root"); - setting_singleton_instance.reset(new internal::FavoriteStoreGSettings(backend.RawPtr())); + // Setting the test values + gsettings_client = g_settings_new(SETTINGS_NAME); + g_settings_set_strv(gsettings_client, SETTINGS_KEY, NULL); + g_settings_set_strv(gsettings_client, SETTINGS_KEY, base_store_favs); } virtual void TearDown() { + g_setenv("GSETTINGS_SCHEMA_DIR", "", true); + g_setenv("GSETTINGS_BACKEND", "", true); } - }; TEST_F(TestFavoriteStoreGSettings, TestAllocation) { - EXPECT_TRUE(G_IS_SETTINGS_BACKEND(backend.RawPtr())); + FavoriteStore &settings = FavoriteStore::Instance(); + EXPECT_EQ(&settings, favorite_store.get()); } TEST_F(TestFavoriteStoreGSettings, TestGetFavorites) @@ -245,9 +237,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteAddedSignalFirst) favs.push_back(base_store_favs[0]); favs.push_back(base_store_favs[1]); favs.push_back(base_store_favs[2]); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); ASSERT_TRUE(signal_received); EXPECT_EQ(position, base_store_favs[0]); @@ -273,9 +263,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteAddedSignalMiddle) favs.push_back(base_store_favs[1]); favs.push_back(other_desktop); favs.push_back(base_store_favs[2]); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); ASSERT_TRUE(signal_received); EXPECT_EQ(position, base_store_favs[1]); @@ -301,9 +289,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteAddedSignalEnd) favs.push_back(base_store_favs[1]); favs.push_back(base_store_favs[2]); favs.push_back(other_desktop); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); ASSERT_TRUE(signal_received); EXPECT_EQ(position, base_store_favs[2]); @@ -326,9 +312,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteAddedSignalEmpty) FavoriteList favs; favs.push_back(other_desktop); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); ASSERT_TRUE(signal_received); EXPECT_EQ(position, ""); @@ -350,9 +334,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteRemoved) FavoriteList favs; favs.push_back(base_store_favs[0]); favs.push_back(base_store_favs[2]); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); ASSERT_TRUE(signal_received); EXPECT_EQ(path_removed, base_store_favs[1]); @@ -372,9 +354,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteReordered) favs.push_back(base_store_favs[0]); favs.push_back(base_store_favs[2]); favs.push_back(base_store_favs[1]); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); ASSERT_TRUE(signal_received); @@ -382,9 +362,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteReordered) favs.push_back(base_store_favs[0]); favs.push_back(base_store_favs[2]); favs.push_back(base_store_favs[1]); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); ASSERT_FALSE(signal_received); } @@ -415,9 +393,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteSignalsMixed1) favs.push_back(base_store_favs[0]); favs.push_back(base_store_favs[1]); favs.push_back(other_desktop); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); EXPECT_TRUE(added_received); EXPECT_TRUE(removed_received); @@ -450,9 +426,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteSignalsMixed2) favs.push_back(base_store_favs[1]); favs.push_back(other_desktop); favs.push_back(base_store_favs[0]); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); EXPECT_TRUE(added_received); EXPECT_TRUE(removed_received); @@ -484,9 +458,7 @@ TEST_F(TestFavoriteStoreGSettings, TestFavoriteSignalsMixed3) FavoriteList favs; favs.push_back(base_store_favs[1]); favs.push_back(base_store_favs[0]); - setting_singleton_instance->SaveFavorites(favs, false); - - sleep(1); + favorite_store->SaveFavorites(favs, false); EXPECT_FALSE(added_received); EXPECT_TRUE(removed_received); diff --git a/tests/test_launcher_controller.cpp b/tests/test_launcher_controller.cpp index bbc461de2..d3908b789 100644 --- a/tests/test_launcher_controller.cpp +++ b/tests/test_launcher_controller.cpp @@ -74,7 +74,6 @@ protected: Settings settings; panel::Style panel_style; MockFavoriteStore favorite_store; - GeisAdapter geis_adapter; Controller lc; }; } diff --git a/tests/test_main.cpp b/tests/test_main.cpp index e2c6a9116..a92978dab 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -4,7 +4,6 @@ #include <NuxCore/Logger.h> #include <Nux/Nux.h> -#include "GestureEngine.h" #include "unity-shared/PluginAdapter.h" #include "unity-shared/WindowManager.h" @@ -27,7 +26,6 @@ int main(int argc, char** argv) // Setting the PluginAdapter to null, using the Standalone version at link time. PluginAdapter::Initialize(NULL); WindowManager::SetDefault(PluginAdapter::Default()); - GeisAdapter geis_adapter; int ret = RUN_ALL_TESTS(); diff --git a/tests/test_panel_style.cpp b/tests/test_panel_style.cpp new file mode 100644 index 000000000..3e795c3d4 --- /dev/null +++ b/tests/test_panel_style.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 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 warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 3 along with this program. If not, see + * <http://www.gnu.org/licenses/> + * + * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> + * + */ + +#include <config.h> + +#include <gio/gio.h> +#include <gtest/gtest.h> + +#include "unity-shared/PanelStyle.h" +#include "unity-shared/UnitySettings.h" + +using namespace unity; +using namespace testing; + +namespace +{ + +const std::string TITLEBAR_FONT = "Ubuntu Bold 11"; + +class TestPanelStyle : public Test +{ +public: + glib::Object<GSettings> gsettings; + Settings unity_settings; + std::unique_ptr<panel::Style> panel_style_instance; + + /* override */ void SetUp() + { + g_setenv("GSETTINGS_BACKEND", "memory", TRUE); + + gsettings = g_settings_new("org.gnome.desktop.wm.preferences"); + g_settings_set_string(gsettings, "titlebar-font", TITLEBAR_FONT.c_str()); + + panel_style_instance.reset(new panel::Style()); + } + + /* override */ void TearDown() + { + g_setenv("GSETTINGS_BACKEND", "", TRUE); + } +}; + +TEST_F(TestPanelStyle, TestGetFontDescription) +{ + ASSERT_EQ(panel_style_instance->GetFontDescription(panel::PanelItem::TITLE), TITLEBAR_FONT); +} + +TEST_F(TestPanelStyle, TestChangedSignal) +{ + bool signal_received = false; + + panel_style_instance->changed.connect([&](){ + signal_received = true; + }); + + g_settings_set_string(gsettings, "titlebar-font", "Ubuntu Italic 11"); + + sleep(1); + + ASSERT_TRUE(signal_received); + ASSERT_EQ(panel_style_instance->GetFontDescription(panel::PanelItem::TITLE), "Ubuntu Italic 11"); +} + +} diff --git a/tests/test_switcher_controller.cpp b/tests/test_switcher_controller.cpp
|
