summaryrefslogtreecommitdiff
diff options
-rw-r--r--CMakeLists.txt15
-rw-r--r--HACKING1
-rw-r--r--UnityCore/CMakeLists.txt3
-rw-r--r--UnityCore/GLibSource.cpp27
-rw-r--r--UnityCore/GLibSource.h19
-rw-r--r--UnityCore/HomeLens.cpp412
-rw-r--r--UnityCore/HomeLens.h1
-rw-r--r--UnityCore/Lens.cpp209
-rw-r--r--UnityCore/Lens.h16
-rw-r--r--UnityCore/Preview.cpp4
-rw-r--r--UnityCore/Preview.h4
-rw-r--r--UnityCore/Variant.cpp9
-rw-r--r--UnityCore/Variant.h2
-rw-r--r--com.canonical.Unity.gschema.xml26
-rw-r--r--dash/DashView.cpp6
-rwxr-xr-xdash/LensView.cpp101
-rw-r--r--dash/LensView.h3
-rw-r--r--dash/previews/ApplicationPreview.cpp2
-rw-r--r--dash/previews/CMakeLists.txt6
-rw-r--r--dash/previews/PreviewContainer.cpp44
-rw-r--r--dash/previews/PreviewContainer.h2
-rw-r--r--dash/previews/PreviewInfoHintWidget.cpp1
-rw-r--r--dash/previews/Track.cpp1
-rw-r--r--hud/HudButton.cpp18
-rw-r--r--hud/HudView.cpp63
-rw-r--r--hud/HudView.h6
-rw-r--r--launcher/AbstractVolumeMonitorWrapper.h7
-rw-r--r--launcher/CMakeLists.txt9
-rw-r--r--launcher/DeviceLauncherIcon.cpp425
-rw-r--r--launcher/DeviceLauncherIcon.h78
-rw-r--r--launcher/DeviceLauncherSection.cpp46
-rw-r--r--launcher/DeviceLauncherSection.h24
-rw-r--r--launcher/DeviceNotificationDisplay.h45
-rw-r--r--launcher/DeviceNotificationDisplayImp.cpp82
-rw-r--r--launcher/DeviceNotificationDisplayImp.h46
-rw-r--r--launcher/DevicesSettings.cpp143
-rw-r--r--launcher/DevicesSettings.h64
-rw-r--r--launcher/DevicesSettingsImp.cpp151
-rw-r--r--launcher/DevicesSettingsImp.h50
-rw-r--r--launcher/EdgeBarrierController.cpp12
-rw-r--r--launcher/FileManagerOpener.h45
-rw-r--r--launcher/FileManagerOpenerImp.cpp35
-rw-r--r--launcher/FileManagerOpenerImp.h39
-rw-r--r--launcher/Launcher.cpp257
-rw-r--r--launcher/Launcher.h12
-rw-r--r--launcher/LauncherController.cpp19
-rw-r--r--launcher/LauncherController.h1
-rw-r--r--launcher/LauncherControllerPrivate.h2
-rw-r--r--launcher/LauncherDragWindow.cpp41
-rw-r--r--launcher/LauncherDragWindow.h11
-rw-r--r--launcher/LauncherModel.cpp294
-rw-r--r--launcher/LauncherModel.h37
-rw-r--r--launcher/MockLauncherIcon.h28
-rw-r--r--launcher/SwitcherController.cpp2
-rw-r--r--launcher/Volume.h62
-rw-r--r--launcher/VolumeImp.cpp294
-rw-r--r--launcher/VolumeImp.h68
-rw-r--r--launcher/VolumeLauncherIcon.cpp305
-rw-r--r--launcher/VolumeLauncherIcon.h62
-rw-r--r--manual-tests/Hud.txt4
-rw-r--r--manual-tests/Launcher.txt37
-rw-r--r--plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.cpp43
-rw-r--r--plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h4
-rw-r--r--plugins/unitydialog/src/unitydialog.cpp131
-rw-r--r--plugins/unitydialog/src/unitydialog.h20
-rw-r--r--plugins/unityshell/CMakeLists.txt2
-rw-r--r--plugins/unityshell/src/ScreenEffectFramebufferObject.cpp243
-rw-r--r--plugins/unityshell/src/ScreenEffectFramebufferObject.h89
-rw-r--r--plugins/unityshell/src/WindowMinimizeSpeedController.cpp108
-rw-r--r--plugins/unityshell/src/WindowMinimizeSpeedController.h57
-rw-r--r--plugins/unityshell/src/unitya11y.cpp129
-rw-r--r--plugins/unityshell/src/unityshell.cpp1081
-rw-r--r--plugins/unityshell/src/unityshell.h75
-rw-r--r--plugins/unityshell/unityshell.xml.in20
-rw-r--r--po/POTFILES.in3
-rw-r--r--services/CMakeLists.txt3
-rw-r--r--services/panel-a11y.c118
-rw-r--r--shortcuts/StandaloneShortcuts.cpp7
-rw-r--r--tests/CMakeLists.txt13
-rw-r--r--tests/autopilot/unity/emulators/workspace.py1
-rw-r--r--tests/autopilot/unity/tests/test_hud.py75
-rw-r--r--tests/autopilot/unity/tests/xim/__init__.py0
-rw-r--r--tests/autopilot/unity/tests/xim/test_gcin.py72
-rw-r--r--tests/gmockmount.c167
-rw-r--r--tests/gmockmount.h55
-rw-r--r--tests/gmockvolume.c131
-rw-r--r--tests/gmockvolume.h16
-rw-r--r--tests/test_device_launcher_section.cpp12
-rw-r--r--tests/test_edge_barrier_controller.cpp8
-rw-r--r--tests/test_glib_source.cpp34
-rw-r--r--tests/test_home_lens.cpp265
-rw-r--r--tests/test_launcher.cpp126
-rw-r--r--tests/test_launcher_controller.cpp65
-rw-r--r--tests/test_launcher_drag_window.cpp91
-rw-r--r--tests/test_launcher_minimize_speed.cpp123
-rw-r--r--tests/test_launcher_model.cpp365
-rw-r--r--tests/test_lens.cpp41
-rw-r--r--tests/test_volume_imp.cpp163
-rw-r--r--tests/test_volume_launcher_icon.cpp498
-rw-r--r--tools/convert-files/compiz-profile-active-unity.convert15
-rw-r--r--tools/convert-files/compiz-profile-unity.convert15
-rwxr-xr-xtools/unity.cmake47
-rw-r--r--unity-shared/BGHash.cpp12
-rw-r--r--unity-shared/CMakeLists.txt6
-rw-r--r--unity-shared/CoverArt.cpp1
-rw-r--r--unity-shared/PanelStyle.cpp62
-rw-r--r--unity-shared/PanelStyle.h1
-rw-r--r--unity-shared/PluginAdapter.h4
-rw-r--r--unity-shared/PluginAdapterCompiz.cpp67
-rw-r--r--unity-shared/PluginAdapterStandalone.cpp6
-rw-r--r--unity-shared/PreviewStyle.cpp14
-rw-r--r--unity-shared/PreviewStyle.h3
-rw-r--r--unity-shared/WindowManager.cpp5
-rw-r--r--unity-shared/WindowManager.h2
114 files changed, 5746 insertions, 2806 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6dc34c6b3..5332d8f48 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,16 +17,13 @@ set (CMAKE_CXX_FLAGS "-DGNOME_DESKTOP_USE_UNSTABLE_API -std=c++0x -fno-permissiv
set (CMAKE_CXX_FLAGS_DEBUG "-g3")
set (CMAKE_CXX_FLAGS_RELEASE "")
-if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l")
- set (UNITY_STANDALONE_LADD "-lunity-core-${UNITY_API_VERSION} -lm")
+if (BUILD_GLES)
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNUX_OPENGLES_20 -DUSE_GLES")
+ set (UNITY_STANDALONE_LADD "-lunity-core-${UNITY_API_VERSION} -lm -lpthread -ldl")
else ()
- set (UNITY_STANDALONE_LADD "-lunity-core-${UNITY_API_VERSION} -lm -lGL -lGLU")
+ set (UNITY_STANDALONE_LADD "-lunity-core-${UNITY_API_VERSION} -lm -lpthread -ldl -lGL -lGLU")
endif ()
-if (BUILD_GLES)
- SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNUX_OPENGLES_20 -DUSE_GLES")
-endif (BUILD_GLES)
-
#
# Niceties
#
@@ -130,9 +127,7 @@ 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;dbus-glib-1;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;xfixes;unity-protocol-private>=5.95.1;libgeis")
-# FIXME: unity-protocol-private shouldn't be there, but building of unityshell is just broken
+set (UNITY_PLUGIN_DEPS "compiz>=0.9.8.0;nux-3.0>=3.0.0;libbamf3;dee-1.0;gio-2.0;gio-unix-2.0;gmodule-2.0;dbusmenu-glib-0.4;x11;libstartup-notification-1.0;gthread-2.0;indicator3-0.4>=0.4.90;atk;atk-bridge-2.0;unity-misc>=0.4.0;dbus-glib-1;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;xfixes;unity-protocol-private>=5.95.1;libgeis;xrender>=0.9")
set (UNITY_PROTOCOL_PRIVATE_DEPS "unity-protocol-private>=5.95.1")
find_package (PkgConfig)
diff --git a/HACKING b/HACKING
index a2ac75320..997a53989 100644
--- a/HACKING
+++ b/HACKING
@@ -7,6 +7,7 @@ If you want to hack on unity you need the following packages
- gthread-2.0
- indicator
- atk
+ - libatk-adaptor
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 bfc526410..f3091a940 100644
--- a/UnityCore/CMakeLists.txt
+++ b/UnityCore/CMakeLists.txt
@@ -103,7 +103,6 @@ set (CFLAGS
add_definitions (${CFLAGS})
set (LIBS ${CORE_DEPS_LIBRARIES})
-link_libraries (${LIBS})
set (LIB_PATHS ${CORE_DEPS_LIBRARY_DIRS})
link_directories(${LIB_PATHS})
@@ -124,7 +123,9 @@ set (CORE_LIB_LT_AGE 0)
set (CORE_LIB_LT_VERSION "${CORE_LIB_LT_CURRENT}:${CORE_LIB_LT_REV}:${CORE_LIB_LT_AGE}")
set (CORE_LIB_NAME "unity-core-${UNITY_API_VERSION}")
+
add_library (${CORE_LIB_NAME} SHARED ${CORE_SOURCES})
+target_link_libraries (${CORE_LIB_NAME} ${LIBS})
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}
diff --git a/UnityCore/GLibSource.cpp b/UnityCore/GLibSource.cpp
index dbce7cf5b..29de4ed63 100644
--- a/UnityCore/GLibSource.cpp
+++ b/UnityCore/GLibSource.cpp
@@ -69,13 +69,12 @@ Source::Priority Source::GetPriority() const
return static_cast<Priority>(prio);
}
-bool Source::Run(Callback callback)
+bool Source::Run(Callback const& callback)
{
if (!source_ || source_id_ || IsRunning())
return false;
- callback_ = callback;
- callback_data_ = new CallBackData(this);
+ callback_data_ = new CallBackData(this, callback);
g_source_set_callback(source_, SourceCallback, callback_data_, DestroyCallback);
source_id_ = g_source_attach(source_, nullptr);
@@ -101,16 +100,14 @@ gboolean Source::SourceCallback(gpointer data)
if (!data)
return G_SOURCE_REMOVE;
- auto self = static_cast<CallBackData*>(data)->self;
+ auto cb_data = static_cast<CallBackData*>(data);
- if (self && self->callback_ && self->callback_())
+ if (cb_data && cb_data->callback_fn_ && cb_data->callback_fn_())
{
return G_SOURCE_CONTINUE;
}
- else
- {
- return G_SOURCE_REMOVE;
- }
+
+ return G_SOURCE_REMOVE;
}
void Source::DestroyCallback(gpointer data)
@@ -133,7 +130,7 @@ void Source::DestroyCallback(gpointer data)
}
-Timeout::Timeout(unsigned int milliseconds, Callback cb, Priority prio)
+Timeout::Timeout(unsigned int milliseconds, Callback const& cb, Priority prio)
{
Init(milliseconds, prio);
Run(cb);
@@ -151,7 +148,7 @@ void Timeout::Init(unsigned int milliseconds, Priority prio)
}
-TimeoutSeconds::TimeoutSeconds(unsigned int seconds, Callback cb, Priority prio)
+TimeoutSeconds::TimeoutSeconds(unsigned int seconds, Callback const& cb, Priority prio)
{
Init(seconds, prio);
Run(cb);
@@ -169,7 +166,7 @@ void TimeoutSeconds::Init(unsigned int seconds, Priority prio)
}
-Idle::Idle(Callback cb, Priority prio)
+Idle::Idle(Callback const& cb, Priority prio)
{
Init(prio);
Run(cb);
@@ -255,7 +252,7 @@ Source::Ptr SourceManager::AddTimeout(unsigned int milliseconds, std::string con
return nullptr;
}
-Source::Ptr SourceManager::AddTimeout(unsigned int milliseconds, Source::Callback cb, std::string const& nick)
+Source::Ptr SourceManager::AddTimeout(unsigned int milliseconds, Source::Callback const& cb, std::string const& nick)
{
auto timeout = std::make_shared<Timeout>(milliseconds);
@@ -280,7 +277,7 @@ Source::Ptr SourceManager::AddTimeoutSeconds(unsigned int seconds, std::string c
return nullptr;
}
-Source::Ptr SourceManager::AddTimeoutSeconds(unsigned int seconds, Source::Callback cb, std::string const& nick)
+Source::Ptr SourceManager::AddTimeoutSeconds(unsigned int seconds, Source::Callback const& cb, std::string const& nick)
{
auto timeout = std::make_shared<TimeoutSeconds>(seconds);
@@ -305,7 +302,7 @@ Source::Ptr SourceManager::AddIdle(std::string const& nick)
return nullptr;
}
-Source::Ptr SourceManager::AddIdle(Source::Callback cb, std::string const& nick)
+Source::Ptr SourceManager::AddIdle(Source::Callback const& cb, std::string const& nick)
{
auto idle = std::make_shared<Idle>();
diff --git a/UnityCore/GLibSource.h b/UnityCore/GLibSource.h
index 468e6b8af..3a09c088c 100644
--- a/UnityCore/GLibSource.h
+++ b/UnityCore/GLibSource.h
@@ -77,7 +77,7 @@ public:
* This Run a source using the @callback function as Source's callback.
* The method will return false if the source is already running, true otherwise.
*/
- bool Run(Callback callback);
+ bool Run(Callback const& callback);
bool IsRunning() const;
/**
@@ -104,11 +104,13 @@ protected:
private:
struct CallBackData
{
- CallBackData(Source* src)
+ CallBackData(Source* src, Callback const& callback)
: self(src)
+ , callback_fn_(callback)
{}
Source* self;
+ Callback callback_fn_;
};
static gboolean SourceCallback(gpointer data);
@@ -116,7 +118,6 @@ private:
unsigned int source_id_;
CallBackData* callback_data_;
- Callback callback_;
};
@@ -133,7 +134,7 @@ class Timeout : public Source
{
public:
Timeout(unsigned int milliseconds, Priority prio = Priority::DEFAULT);
- Timeout(unsigned int milliseconds, Callback cb, Priority prio = Priority::DEFAULT);
+ Timeout(unsigned int milliseconds, Callback const& cb, Priority prio = Priority::DEFAULT);
private:
void Init(unsigned int milliseconds, Priority prio);
@@ -153,7 +154,7 @@ class TimeoutSeconds : public Source
{
public:
TimeoutSeconds(unsigned int seconds, Priority prio = Priority::DEFAULT);
- TimeoutSeconds(unsigned int seconds, Callback cb, Priority prio = Priority::DEFAULT);
+ TimeoutSeconds(unsigned int seconds, Callback const& cb, Priority prio = Priority::DEFAULT);
private:
void Init(unsigned int seconds, Priority prio);
@@ -173,7 +174,7 @@ class Idle : public Source
{
public:
Idle(Priority prio = Priority::DEFAULT_IDLE);
- Idle(Callback cb, Priority prio = Priority::DEFAULT_IDLE);
+ Idle(Callback const& cb, Priority prio = Priority::DEFAULT_IDLE);
private:
void Init(Priority prio);
@@ -206,13 +207,13 @@ public:
bool Add(Source::Ptr const& source, std::string const& nick = "");
Source::Ptr AddTimeout(unsigned int milliseconds, std::string const& nick = "");
- Source::Ptr AddTimeout(unsigned int milliseconds, Source::Callback cb, std::string const& nick = "");
+ Source::Ptr AddTimeout(unsigned int milliseconds, Source::Callback const& cb, std::string const& nick = "");
Source::Ptr AddTimeoutSeconds(unsigned int seconds, std::string const& nick = "");
- Source::Ptr AddTimeoutSeconds(unsigned int seconds, Source::Callback cb, std::string const& nick = "");
+ Source::Ptr AddTimeoutSeconds(unsigned int seconds, Source::Callback const& cb, std::string const& nick = "");
Source::Ptr AddIdle(std::string const& nick = "");
- Source::Ptr AddIdle(Source::Callback cb, std::string const& nick = "");
+ Source::Ptr AddIdle(Source::Callback const& cb, std::string const& nick = "");
bool Remove(std::string const& nick);
bool Remove(unsigned int id);
diff --git a/UnityCore/HomeLens.cpp b/UnityCore/HomeLens.cpp
index be1f82b0f..da995637f 100644
--- a/UnityCore/HomeLens.cpp
+++ b/UnityCore/HomeLens.cpp
@@ -15,14 +15,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
+ * Michal Hruby <michal.hruby@canonical.com>
*/
#include <glib.h>
+#include <dee-icu.h>
#include <string>
#include <stdexcept>
#include <map>
#include <set>
#include <utility>
+#include <algorithm>
#include "GLibSignal.h"
#include "HomeLens.h"
@@ -44,6 +47,8 @@ nux::logging::Logger logger("unity.dash.homelens");
const gchar* const HOMELENS_PRIORITY = "unity-homelens-priority";
const gchar* const HOMELENS_RESULTS_MODEL = "unity-homelens-results-model";
+const unsigned RESULTS_NAME_COLUMN = 4;
+const unsigned RESULTS_COMMENT_COLUMN = 5;
}
/*
@@ -136,6 +141,21 @@ public:
return target_cat_index;
}
+ void UnregisterAllForModel(DeeModel* model)
+ {
+ auto it = reg_category_map_.begin();
+
+ // References and iterators to the erased elements are invalidated.
+ // Other references and iterators are not affected.
+ while (it != reg_category_map_.end())
+ {
+ if (it->first.first == model)
+ reg_category_map_.erase(it++);
+ else
+ ++it;
+ }
+ }
+
void NotifyOrderChanged ()
{
owner_->categories_reordered();
@@ -157,17 +177,18 @@ public:
ModelMerger(glib::Object<DeeModel> target);
virtual ~ModelMerger();
- void AddSource(Lens::Ptr& owner_lens, glib::Object<DeeModel> source);
+ virtual void AddSource(Lens::Ptr& owner_lens, glib::Object<DeeModel> source);
+ virtual void RemoveSource(glib::Object<DeeModel> const& old_source);
protected:
- virtual void OnSourceRowAdded(DeeModel *model, DeeModelIter *iter);
+ virtual void OnSourceRowAdded(DeeModel* model, DeeModelIter* iter);
virtual void OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter);
virtual void OnSourceRowChanged(DeeModel* model, DeeModelIter* iter);
- void EnsureRowBuf(DeeModel *source);
+ void EnsureRowBuf(DeeModel* source);
/* The merge tag lives on the source models, pointing to the mapped
* row in the target model */
- DeeModelTag* FindSourceToTargetTag(DeeModel *model);
+ DeeModelTag* FindSourceToTargetTag(DeeModel* model);
protected:
std::map<Lens::Ptr, glib::Object<DeeModel> > sources_by_owner_;
@@ -197,9 +218,9 @@ public:
HomeLens::CategoryRegistry* cat_registry);
protected:
- void OnSourceRowAdded(DeeModel *model, DeeModelIter *iter);
- void OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter);
- void OnSourceRowChanged(DeeModel *model, DeeModelIter *iter);
+ void OnSourceRowAdded(DeeModel* model, DeeModelIter* iter);
+ void OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter);
+ void OnSourceRowChanged(DeeModel* model, DeeModelIter* iter);
private:
HomeLens::CategoryRegistry* cat_registry_;
@@ -221,15 +242,22 @@ public:
HomeLens::CategoryRegistry* cat_registry,
MergeMode merge_mode);
- void OnSourceRowAdded(DeeModel *model, DeeModelIter *iter);
- void OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter);
+ void OnSourceRowAdded(DeeModel* model, DeeModelIter* iter);
+ void OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter);
- std::vector<unsigned> GetOrder();
+ std::vector<unsigned> GetDefaultOrder();
+ std::string GetLensIdForCategory(unsigned) const;
+ std::map<unsigned, Lens::Ptr> const& GetCategoryToLensMap() const;
+ MergeMode GetMergeMode() const { return merge_mode_; }
+
+protected:
+ void RemoveSource(glib::Object<DeeModel> const& old_source);
private:
HomeLens::CategoryRegistry* cat_registry_;
MergeMode merge_mode_;
std::multimap<unsigned, unsigned, std::greater<unsigned> > category_ordering_;
+ std::map<unsigned, Lens::Ptr> category_to_owner_;
};
/*
@@ -241,9 +269,9 @@ class HomeLens::FiltersMerger : public ModelMerger
public:
FiltersMerger(glib::Object<DeeModel> target);
- void OnSourceRowAdded(DeeModel *model, DeeModelIter *iter);
- void OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter);
- void OnSourceRowChanged(DeeModel *model, DeeModelIter *iter);
+ void OnSourceRowAdded(DeeModel* model, DeeModelIter* iter);
+ void OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter);
+ void OnSourceRowChanged(DeeModel* model, DeeModelIter* iter);
};
/*
@@ -255,11 +283,53 @@ public:
Impl(HomeLens* owner, MergeMode merge_mode);
~Impl();
+ struct CategorySorter
+ {
+ CategorySorter(std::map<unsigned, unsigned>& results_per_category,
+ std::map<unsigned, Lens::Ptr> const& category_owner_map)
+ : results_per_category_(results_per_category)
+ , category_to_owner_(category_owner_map)
+ {}
+
+ bool operator() (unsigned cat_a, unsigned cat_b)
+ {
+ bool a_has_personal_content = false;
+ bool b_has_personal_content = false;
+
+ auto it = category_to_owner_.find(cat_a);
+ if (it != category_to_owner_.end() && it->second)
+ {
+ a_has_personal_content = it->second->provides_personal_content();
+ }
+ it = category_to_owner_.find(cat_b);
+ if (it != category_to_owner_.end() && it->second)
+ {
+ b_has_personal_content = it->second->provides_personal_content();
+ }
+
+ // prioritize categories that have private content
+ if (a_has_personal_content != b_has_personal_content)
+ {
+ return a_has_personal_content ? true : false;
+ }
+
+ return results_per_category_[cat_a] > results_per_category_[cat_b];
+ }
+
+ private:
+ std::map<unsigned, unsigned>& results_per_category_;
+ std::map<unsigned, Lens::Ptr> const& category_to_owner_;
+ };
+
void OnLensAdded(Lens::Ptr& lens);
gsize FindLensPriority (Lens::Ptr& lens);
void EnsureCategoryAnnotation(Lens::Ptr& lens, DeeModel* results, DeeModel* categories);
Lens::Ptr FindLensForUri(std::string const& uri);
std::vector<unsigned> GetCategoriesOrder();
+ void LensSearchFinished(Lens::Ptr const& lens);
+ bool ResultsContainVisibleMatch(unsigned category);
+
+ std::string const& last_search_string() const { return last_search_string_; }
HomeLens* owner_;
Lenses::LensList lenses_;
@@ -268,7 +338,11 @@ public:
HomeLens::CategoryMerger categories_merger_;
HomeLens::FiltersMerger filters_merger_;
int running_searches_;
+ bool apps_lens_contains_visible_match;
+ std::string last_search_string_;
glib::Object<GSettings> settings_;
+ std::vector<unsigned> cached_categories_order_;
+ std::map<unsigned, glib::Object<DeeModel> > category_filter_models_;
};
/*
@@ -324,7 +398,7 @@ void HomeLens::ModelMerger::AddSource(Lens::Ptr& owner_lens,
{
if (it->second == source)
return; // this model was already added
- sig_manager_.Disconnect(it->second);
+ RemoveSource(it->second);
}
sources_by_owner_[owner_lens] = source;
@@ -344,12 +418,23 @@ void HomeLens::ModelMerger::AddSource(Lens::Ptr& owner_lens,
sigc::mem_fun(this, &HomeLens::ModelMerger::OnSourceRowChanged)));
}
-void HomeLens::ModelMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *iter)
+void HomeLens::ModelMerger::RemoveSource(glib::Object<DeeModel> const& source)
+{
+ if (!source)
+ {
+ LOG_ERROR(logger) << "Trying to remove NULL source from ModelMerger";
+ return;
+ }
+
+ sig_manager_.Disconnect(source);
+}
+
+void HomeLens::ModelMerger::OnSourceRowAdded(DeeModel* model, DeeModelIter* iter)
{
// Default impl. does nothing.
}
-void HomeLens::ResultsMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *iter)
+void HomeLens::ResultsMerger::OnSourceRowAdded(DeeModel* model, DeeModelIter* iter)
{
DeeModelIter* target_iter;
int target_cat_offset, source_cat_offset;
@@ -390,7 +475,7 @@ void HomeLens::ResultsMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *it
for (unsigned int i = 0; i < n_cols_; i++) g_variant_unref(row_buf_[i]);
}
-void HomeLens::CategoryMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *iter)
+void HomeLens::CategoryMerger::OnSourceRowAdded(DeeModel* model, DeeModelIter* iter)
{
DeeModel* results_model;
DeeModelIter* target_iter;
@@ -413,15 +498,19 @@ void HomeLens::CategoryMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *i
target_tag = FindSourceToTargetTag(model);
unsigned source_cat_offset = dee_model_get_position(model, iter);
- if (merge_mode_ == MergeMode::OWNER_LENS)
+ Lens::Ptr owner_lens;
+ for (auto it = sources_by_owner_.begin(); it != sources_by_owner_.end(); ++it)
{
- for (auto it = sources_by_owner_.begin(); it != sources_by_owner_.end(); ++it)
+ if (it->second == model)
{
- if (it->second == model)
- {
- lens_name = it->first->name();
- }
+ owner_lens = it->first;
+ break;
}
+ }
+
+ if (merge_mode_ == MergeMode::OWNER_LENS)
+ {
+ if (owner_lens) lens_name = owner_lens->name();
display_name = lens_name.c_str();
}
else
@@ -458,6 +547,9 @@ void HomeLens::CategoryMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *i
cat_registry_->RegisterCategoryOffset(results_model, source_cat_offset,
display_name);
+ if (owner_lens) category_to_owner_[target_cat_index] = owner_lens;
+
+ // ensure priorities are taken into account, so default order works
gsize lens_priority = GPOINTER_TO_SIZE(g_object_get_data(
G_OBJECT(model), HOMELENS_PRIORITY));
unsigned lens_prio = static_cast<unsigned>(lens_priority);
@@ -470,14 +562,14 @@ void HomeLens::CategoryMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *i
for (unsigned int i = 0; i < n_cols_; i++) g_variant_unref(row_buf_[i]);
}
-void HomeLens::FiltersMerger::OnSourceRowAdded(DeeModel *model, DeeModelIter *iter)
+void HomeLens::FiltersMerger::OnSourceRowAdded(DeeModel* model, DeeModelIter* iter)
{
/* Supporting filters on the home screen is possible, but *quite* tricky.
* So... Discard ALL the rows!
*/
}
-void HomeLens::CategoryMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter)
+void HomeLens::CategoryMerger::OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter)
{
/* We don't support removals of categories.
* You can check out any time you like, but you can never leave
@@ -488,7 +580,7 @@ void HomeLens::CategoryMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter
LOG_DEBUG(logger) << "Removal of categories not supported.";
}
-void HomeLens::ModelMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter)
+void HomeLens::ModelMerger::OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter)
{
DeeModelIter* target_iter;
DeeModelTag* target_tag;
@@ -506,17 +598,17 @@ void HomeLens::ModelMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *it
dee_model_remove(target_, target_iter);
}
-void HomeLens::ResultsMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter)
+void HomeLens::ResultsMerger::OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter)
{
ModelMerger::OnSourceRowRemoved(model, iter);
}
-void HomeLens::FiltersMerger::OnSourceRowRemoved(DeeModel *model, DeeModelIter *iter)
+void HomeLens::FiltersMerger::OnSourceRowRemoved(DeeModel* model, DeeModelIter* iter)
{
/* We aren't adding any rows to the merged model, so nothing to do here */
}
-void HomeLens::ModelMerger::OnSourceRowChanged(DeeModel *model, DeeModelIter *iter)
+void HomeLens::ModelMerger::OnSourceRowChanged(DeeModel* model, DeeModelIter* iter)
{
DeeModelIter* target_iter;
DeeModelTag* target_tag;
@@ -534,18 +626,18 @@ void HomeLens::ModelMerger::OnSourceRowChanged(DeeModel *model, DeeModelIter *it
for (unsigned int i = 0; i < n_cols_; i++) g_variant_unref(row_buf_[i]);
}
-void HomeLens::ResultsMerger::OnSourceRowChanged(DeeModel *model, DeeModelIter *iter)
+void HomeLens::ResultsMerger::OnSourceRowChanged(DeeModel* model, DeeModelIter* iter)
{
// FIXME: We can support this, but we need to re-calculate the category offset
LOG_WARN(logger) << "In-line changing of results not supported in the home lens. Sorry.";
}
-void HomeLens::FiltersMerger::OnSourceRowChanged(DeeModel *model, DeeModelIter *iter)
+void HomeLens::FiltersMerger::OnSourceRowChanged(DeeModel* model, DeeModelIter* iter)
{
/* We aren't adding any rows to the merged model, so nothing to do here */
}
-void HomeLens::ModelMerger::EnsureRowBuf(DeeModel *model)
+void HomeLens::ModelMerger::EnsureRowBuf(DeeModel* model)
{
if (G_UNLIKELY (n_cols_ == 0))
{
@@ -606,12 +698,20 @@ void HomeLens::ModelMerger::EnsureRowBuf(DeeModel *model)
}
}
-DeeModelTag* HomeLens::ModelMerger::FindSourceToTargetTag(DeeModel *model)
+DeeModelTag* HomeLens::ModelMerger::FindSourceToTargetTag(DeeModel* model)
{
return source_to_target_tags_[model];
}
-std::vector<unsigned> HomeLens::CategoryMerger::GetOrder()
+void HomeLens::CategoryMerger::RemoveSource(glib::Object<DeeModel> const& source)
+{
+ // call base()
+ HomeLens::ModelMerger::RemoveSource(source);
+
+ cat_registry_->UnregisterAllForModel(source);
+}
+
+std::vector<unsigned> HomeLens::CategoryMerger::GetDefaultOrder()
{
std::vector<unsigned> result;
for (auto it = category_ordering_.begin(); it != category_ordering_.end(); ++it)
@@ -622,6 +722,23 @@ std::vector<unsigned> HomeLens::CategoryMerger::GetOrder()
return result;
}
+std::string HomeLens::CategoryMerger::GetLensIdForCategory(unsigned cat) const
+{
+ auto lens_it = category_to_owner_.find(cat);
+ if (lens_it != category_to_owner_.end())
+ {
+ if (lens_it->second) return lens_it->second->id();
+ }
+
+ return "";
+}
+
+std::map<unsigned, Lens::Ptr> const&
+HomeLens::CategoryMerger::GetCategoryToLensMap() const
+{
+ return category_to_owner_;
+}
+
HomeLens::Impl::Impl(HomeLens *owner, MergeMode merge_mode)
: owner_(owner)
, cat_registry_(owner)
@@ -629,6 +746,7 @@ HomeLens::Impl::Impl(HomeLens *owner, MergeMode merge_mode)
, categories_merger_(owner->categories()->model(), &cat_registry_, merge_mode)
, filters_merger_(owner->filters()->model())
, running_searches_(0)
+ , apps_lens_contains_visible_match(false)
, settings_(g_settings_new("com.canonical.Unity.Dash"))
{
DeeModel* results = owner->results()->model();
@@ -743,9 +861,10 @@ void HomeLens::Impl::OnLensAdded (Lens::Ptr& lens)
/* When we dispatch a search we inc the search count and when we finish
* one we decrease it. When we reach 0 we'll emit search_finished. */
- lens->global_search_finished.connect([&] (Hints const& hints) {
+ lens->global_search_finished.connect([this, lens] (Hints const& hints) {
running_searches_--;
+ LensSearchFinished(lens);
if (running_searches_ <= 0)
{
owner_->search_finished.emit(Hints());
@@ -784,41 +903,15 @@ void HomeLens::Impl::OnLensAdded (Lens::Ptr& lens)
filters_merger_.AddSource(lens, filters_prop());
}
- /*
- * We'll assume that the models' swarm names do not change during life cycle
- * of a lens.
- * Otherwise we might run into a race where we would associate category
- * model to a results model that is about to be replaced by a new one.
- */
- lens->connected.changed.connect([&] (bool is_connected)
- {
- if (is_connected)
- {
- EnsureCategoryAnnotation(lens, lens->categories()->model(),
- lens->global_results()->model());
- categories_merger_.AddSource(lens, lens->categories()->model());
- results_merger_.AddSource(lens, lens->global_results()->model());
- filters_merger_.AddSource(lens, lens->filters()->model());
- }
- });
- /*
- results_prop.changed.connect([&] (glib::Object<DeeModel> model)
- {
- EnsureCategoryAnnotation(lens, lens->categories()->model(), model);
- results_merger_.AddSource(model);
- });
-
- categories_prop.changed.connect([&] (glib::Object<DeeModel> model)
- {
- EnsureCategoryAnnotation(lens, model, lens->global_results()->model());
- categories_merger_.AddSource(model);
- });
-
- filters_prop.changed.connect([&] (glib::Object<DeeModel> model)
+ /* Make sure the models are properly annotated when they change */
+ lens->models_changed.connect([&] ()
{
- filters_merger_.AddSource(model);
+ EnsureCategoryAnnotation(lens, lens->categories()->model(),
+ lens->global_results()->model());
+ categories_merger_.AddSource(lens, lens->categories()->model());
+ results_merger_.AddSource(lens, lens->global_results()->model());
+ filters_merger_.AddSource(lens, lens->filters()->model());
});
- */
/*
* Register pre-existing categories up front
@@ -838,9 +931,175 @@ void HomeLens::Impl::OnLensAdded (Lens::Ptr& lens)
}
}
+void HomeLens::Impl::LensSearchFinished(Lens::Ptr const& lens)
+{
+ auto order_vector = categories_merger_.GetDefaultOrder();
+
+ // get number of results per category
+ std::map<unsigned, unsigned> results_per_cat;
+ for (unsigned i = 0; i < order_vector.size(); i++)
+ {
+ unsigned category = order_vector.at(i);
+ auto model = owner_->GetFilterModelForCategory(category);
+ results_per_cat[category] = model ? dee_model_get_n_rows(model) : 0;
+ }
+
+ CategorySorter sorter(results_per_cat,
+ categories_merger_.GetCategoryToLensMap());
+ // stable sort based on number of results in each cat
+ std::stable_sort(order_vector.begin(), order_vector.end(), sorter);
+
+ // ensure shopping is second, need map[cat] = lens
+ int shopping_index = -1;
+ int apps_index = -1;
+ for (unsigned i = 0; i < order_vector.size(); i++)
+ {
+ // get lens that owns this category
+ std::string const& lens_id(categories_merger_.GetLensIdForCategory(order_vector.at(i)));
+ if (lens_id == "shopping.lens")
+ shopping_index = i;
+ else if (lens_id == "applications.lens")
+ apps_index = i;
+ }
+
+ if (lens->id() == "applications.lens")
+ {
+ // checking the results isn't extermely fast, so cache the result
+ apps_lens_contains_visible_match = ResultsContainVisibleMatch(order_vector[apps_index]);
+ }
+
+ // if there are no results in the apps category, we can't reorder,
+ // otherwise shopping won't end up being 2nd
+ if (apps_lens_contains_visible_match && apps_index > 0 &&
+ results_per_cat[order_vector[apps_index]] > 0)
+ {
+ // we want apps first
+ unsigned apps_cat_num = order_vector.at(apps_index);
+ order_vector.erase(order_vector.begin() + apps_index);
+ order_vector.insert(order_vector.begin(), apps_cat_num);
+
+ // we might shift the shopping index
+ if (shopping_index >= 0 && shopping_index < apps_index) shopping_index++;
+ }
+
+ if (shopping_index >= 0 && shopping_index != 2)
+ {
+ unsigned shopping_cat_num = order_vector.at(shopping_index);
+ order_vector.erase(order_vector.begin() + shopping_index);
+ order_vector.insert(order_vector.begin() + 2, shopping_cat_num);
+ }
+
+ if (cached_categories_order_ != order_vector)
+ {
+ cached_categories_order_ = order_vector;
+ owner_->categories_reordered();
+ }
+}
+
+bool HomeLens::Impl::ResultsContainVisibleMatch(unsigned category)
+{
+ // this method searches for match of the search string in the display name
+ // or comment fields
+ auto filter_model = owner_->GetFilterModelForCategory(category);
+ if (!filter_model) return false;
+ if (last_search_string_.empty()) return true;
+
+ int checked_results = 5;
+
+ glib::Object<DeeModel> model(dee_sequence_model_new());
+ dee_model_set_schema(model, "s", "s", NULL);
+
+ DeeModelIter* iter = dee_model_get_first_iter(filter_model);
+ DeeModelIter* end_iter = dee_model_get_last_iter(filter_model);
+
+ // add first few results to the temporary model
+ while (iter != end_iter)
+ {
+ glib::Variant name(dee_model_get_value(filter_model, iter, RESULTS_NAME_COLUMN),
+ glib::StealRef());
+ glib::Variant comment(dee_model_get_value(filter_model, iter, RESULTS_COMMENT_COLUMN),
+ glib::StealRef());
+ GVariant* members[2] = { name, comment };
+ dee_model_append_row(model, members);
+
+ iter = dee_model_next(filter_model, iter);
+ if (--checked_results <= 0) break;
+ }
+
+ if (dee_model_get_n_rows(model) == 0) return false;
+
+ // setup model reader, analyzer and instantiate an index
+ DeeModelReader reader;
+ dee_model_reader_new([] (DeeModel* m, DeeModelIter* iter, gpointer data) -> gchar*
+ {
+ return g_strdup_printf("%s\n%s",
+ dee_model_get_string(m, iter, 0),
+ dee_model_get_string(m, iter, 1));
+ }, NULL, NULL, &reader);
+ glib::Object<DeeAnalyzer> analyzer(DEE_ANALYZER(dee_text_analyzer_new()));
+ dee_analyzer_add_term_filter(analyzer,
+ [] (DeeTermList* terms_in, DeeTermList* terms_out, gpointer data) -> void
+ {
+ auto filter = static_cast<DeeICUTermFilter*>(data);
+ for (unsigned i = 0; i < dee_term_list_num_terms(terms_in); i++)
+ {
+ dee_term_list_add_term(terms_out, dee_icu_term_filter_apply(filter, dee_term_list_get_term(terms_in, i)));
+ }
+ },
+ dee_icu_term_filter_new_ascii_folder(),
+ (GDestroyNotify)dee_icu_term_filter_destroy);
+ // ready to instantiate the index
+ glib::Object<DeeIndex> index(DEE_INDEX(dee_tree_index_new(model, analyzer, &reader)));
+
+ // tokenize the search string, so this will work with multiple words
+ glib::Object<DeeTermList> search_terms(DEE_TERM_LIST(g_object_new(DEE_TYPE_TERM_LIST, NULL)));
+ dee_analyzer_tokenize(analyzer, last_search_string_.c_str(), search_terms);
+
+ std::set<DeeModelIter*> iters;
+ for (unsigned i = 0; i < dee_term_list_num_terms(search_terms); i++)
+ {
+ glib::Object<DeeResultSet> results(dee_index_lookup(index, dee_term_list_get_term(search_terms, i), DEE_TERM_MATCH_PREFIX));
+ if (i == 0)
+ {
+ while (dee_result_set_has_next(results))
+ {
+ iters.insert(dee_result_set_next(results));
+ }
+ }
+ else
+ {
+ std::set<DeeModelIter*> iters2;
+ while (dee_result_set_has_next(results))
+ {
+ iters2.insert(dee_result_set_next(results));
+ }
+ // intersect the sets, set iterators are stable, so we can do this
+ auto it = iters.begin();
+ while (it != iters.end())
+ {
+ if (iters2.find(*it) == iters2.end())
+ iters.erase(it++);
+ else
+ ++it;
+ }
+ // no need to check more terms if the base set is already empty
+ if (iters.empty()) break;
+ }
+ }
+
+ // there is a match if the iterator is isn't empty
+ return !iters.empty();
+}
+
std::vector<unsigned> HomeLens::Impl::GetCategoriesOrder()
{
- return categories_merger_.GetOrder();
+ auto default_order = categories_merger_.GetDefaultOrder();
+ if (!last_search_string_.empty() &&
+ cached_categories_order_.size() == default_order.size())
+ {
+ return cached_categories_order_;
+ }
+ return default_order;
}
HomeLens::HomeLens(std::string const& name,
@@ -853,6 +1112,9 @@ HomeLens::HomeLens(std::string const& name,
, pimpl(new Impl(this, merge_mode))
{
count.SetGetterFunction(sigc::mem_fun(&pimpl->lenses_, &Lenses::LensList::size));
+ last_search_string.SetGetterFunction(sigc::mem_fun(pimpl, &HomeLens::Impl::last_search_string));
+ last_global_search_string.SetGetterFunction(sigc::mem_fun(pimpl, &HomeLens::Impl::last_search_string));
+
search_in_global = false;
}
@@ -915,6 +1177,8 @@ void HomeLens::Search(std::string const& search_string)
/* Reset running search counter */
pimpl->running_searches_ = 0;
+ pimpl->last_search_string_ = search_string;
+ pimpl->apps_lens_contains_visible_match = false;
for (auto lens: pimpl->lenses_)
{
@@ -967,5 +1231,15 @@ std::vector<unsigned> HomeLens::GetCategoriesOrder()
return pimpl->GetCategoriesOrder();
}
+glib::Object<DeeModel> HomeLens::GetFilterModelForCategory(unsigned category)
+{
+ auto it = pimpl->category_filter_models_.find(category);
+ if (it != pimpl->category_filter_models_.end()) return it->second;
+
+ auto model = Lens::GetFilterModelForCategory(category);
+ pimpl->category_filter_models_[category] = model;
+ return model;
+}
+
}
}
diff --git a/UnityCore/HomeLens.h b/UnityCore/HomeLens.h
index f92ee70a6..0facd0fa1 100644
--- a/UnityCore/HomeLens.h
+++ b/UnityCore/HomeLens.h
@@ -75,6 +75,7 @@ public:
void Preview(std::string const& uri);
std::vector<unsigned> GetCategoriesOrder();
+ glib::Object<DeeModel> GetFilterModelForCategory(unsigned category);
private:
class Impl;
diff --git a/UnityCore/Lens.cpp b/UnityCore/Lens.cpp
index d0c3a0e53..a4e0c5b0d 100644
--- a/UnityCore/Lens.cpp
+++ b/UnityCore/Lens.cpp
@@ -36,6 +36,8 @@ namespace dash
namespace
{
nux::logging::Logger logger("unity.dash.lens");
+
+const unsigned CATEGORY_COLUMN = 2;
}
using std::string;
@@ -77,7 +79,8 @@ public:
string const& results_model_name,
string const& global_results_model_name,
string const& categories_model_name,
- string const& filters_model_name);
+ string const& filters_model_name,
+ GVariantIter* hints_iter);
void OnViewTypeChanged(ViewType view_type);
void GlobalSearch(std::string const& search_string);
@@ -86,11 +89,14 @@ public:
void ActivationReply(GVariant* parameters);
void Preview(std::string const& uri);
void ActivatePreviewAction(std::string const& action_id,
- std::string const& uri);
+ std::string const& uri,
+ Hints const& hints);
void SignalPreview(std::string const& preview_uri,
glib::Variant const& preview_update,
glib::DBusProxy::ReplyCallback reply_cb);
std::vector<unsigned> GetCategoriesOrder();
+ glib::Object<DeeModel> GetFilterModelForCategory(unsigned category);
+ void GetFilterForCategoryIndex(unsigned category, DeeFilter* filter);
string const& id() const;
string const& dbus_name() const;
@@ -108,6 +114,10 @@ public:
Categories::Ptr const& categories() const;
Filters::Ptr const& filters() const;
bool connected() const;
+ bool provides_personal_content() const;
+
+ string const& last_search_string() const { return last_search_string_; }
+ string const& last_global_search_string() const { return last_global_search_string_; }
Lens* owner_;
@@ -126,16 +136,19 @@ public:
Categories::Ptr categories_;
Filters::Ptr filters_;
bool connected_;
+ bool provides_personal_content_;
string private_connection_name_;
+ string last_search_string_;
+ string last_global_search_string_;
glib::DBusProxy* proxy_;
glib::Object<GCancellable> search_cancellable_;
glib::Object<GCancellable> global_search_cancellable_;
glib::Object<GCancellable> preview_cancellable_;
- GVariant *results_variant_;
- GVariant *global_results_variant_;
+ glib::Variant results_variant_;
+ glib::Variant global_results_variant_;
};
Lens::Impl::Impl(Lens* owner,
@@ -165,9 +178,8 @@ Lens::Impl::Impl(Lens* owner,
, categories_(new Categories(model_type))
, filters_(new Filters(model_type))
, connected_(false)
+ , provides_personal_content_(false)
, proxy_(NULL)
- , results_variant_(NULL)
- , global_results_variant_(NULL)
{
if (model_type == ModelType::REMOTE)
{
@@ -199,6 +211,9 @@ Lens::Impl::Impl(Lens* owner,
owner_->categories.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::categories));
owner_->filters.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::filters));
owner_->connected.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::connected));
+ owner_->provides_personal_content.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::provides_personal_content));
+ owner_->last_search_string.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::last_search_string));
+ owner_->last_global_search_string.SetGetterFunction(sigc::mem_fun(this, &Lens::Impl::last_global_search_string));
owner_->view_type.changed.connect(sigc::mem_fun(this, &Lens::Impl::OnViewTypeChanged));
}
@@ -236,13 +251,11 @@ void Lens::Impl::OnProxyDisconnected()
void Lens::Impl::ResultsModelUpdated(unsigned long long begin_seqnum,
unsigned long long end_seqnum)
{
- if (results_variant_ != NULL &&
- end_seqnum >= ExtractModelSeqnum (results_variant_))
+ if (results_variant_ && end_seqnum >= ExtractModelSeqnum (results_variant_))
{
- glib::Variant dict(results_variant_, glib::StealRef());
Hints hints;
- dict.ASVToHints(hints);
+ results_variant_.ASVToHints(hints);
owner_->search_finished.emit(hints);
@@ -253,13 +266,12 @@ void Lens::Impl::ResultsModelUpdated(unsigned long long begin_seqnum,
void Lens::Impl::GlobalResultsModelUpdated(unsigned long long begin_seqnum,
unsigned long long end_seqnum)
{
- if (global_results_variant_ != NULL &&
+ if (global_results_variant_ &&
end_seqnum >= ExtractModelSeqnum (global_results_variant_))
{
- glib::Variant dict(global_results_variant_, glib::StealRef());
Hints hints;
- dict.ASVToHints(hints);
+ global_results_variant_.ASVToHints(hints);
owner_->global_search_finished.emit(hints);
@@ -296,8 +308,7 @@ void Lens::Impl::OnSearchFinished(GVariant* parameters)
if (results_->seqnum < reply_seqnum)
{
// wait for the end-transaction signal
- if (results_variant_) g_variant_unref (results_variant_);
- results_variant_ = g_variant_ref (parameters);
+ results_variant_ = parameters;
// ResultsModelUpdated will emit OnSearchFinished
return;
@@ -318,8 +329,7 @@ void Lens::Impl::OnGlobalSearchFinished(GVariant* parameters)
if (global_results_->seqnum < reply_seqnum)
{
// wait for the end-transaction signal
- if (global_results_variant_) g_variant_unref (global_results_variant_);
- global_results_variant_ = g_variant_ref (parameters);
+ global_results_variant_ = parameters;
// GlobalResultsModelUpdated will emit OnGlobalSearchFinished
return;
@@ -367,15 +377,28 @@ void Lens::Impl::OnChanged(GVariant* parameters)
<< " Filters: " << filters_model_name << "\n";
if (dbus_path.Str() == dbus_path_)
{
+ std::string categories_model_swarm_name(categories_model_name.Str());
+ std::string filters_model_swarm_name(filters_model_name.Str());
+ std::string results_model_swarm_name(results_model_name.Str());
+ std::string global_results_model_swarm_name(global_results_model_name.Str());
+ bool models_changed =
+ categories_model_swarm_name != categories_->swarm_name ||
+ filters_model_swarm_name != filters_->swarm_name ||
+ results_model_swarm_name != results_->swarm_name ||
+ global_results_model_swarm_name != global_results_->swarm_name;
+
/* FIXME: We ignore hints for now */
UpdateProperties(search_in_global,
visible,
search_hint.Str(),
private_connection_name.Str(),
- results_model_name.Str(),
- global_results_model_name.Str(),
- categories_model_name.Str(),
- filters_model_name.Str());
+ results_model_swarm_name,
+ global_results_model_swarm_name,
+ categories_model_swarm_name,
+ filters_model_swarm_name,
+ hints_iter);
+
+ if (models_changed) owner_->models_changed.emit();
}
else
{
@@ -398,7 +421,8 @@ void Lens::Impl::UpdateProperties(bool search_in_global,
string const& results_model_name,
string const& global_results_model_name,
string const& categories_model_name,
- string const& filters_model_name)
+ string const& filters_model_name,
+ GVariantIter* hints_iter)
{
// Diff the properties received from those we have
if (search_hint_ != search_hint)
@@ -419,6 +443,26 @@ void Lens::Impl::UpdateProperties(bool search_in_global,
owner_->visible.EmitChanged(visible_);
}
+ bool provides_personal_content = false;
+ gchar* key;
+ GVariant* value;
+
+ // g_variant_iter_loop manages the memory automatically, as long
+ // as the iteration is not stopped in the middle
+ while (g_variant_iter_loop(hints_iter, "{sv}", &key, &value))
+ {
+ if (g_strcmp0(key, "provides-personal-content") == 0)
+ {
+ provides_personal_content = g_variant_get_boolean(value) != FALSE;
+ }
+ }
+
+ if (provides_personal_content_ != provides_personal_content)
+ {
+ provides_personal_content_ = provides_personal_content;
+ owner_->provides_personal_content.EmitChanged(provides_personal_content_);
+ }
+
if (private_connection_name_ != private_connection_name)
{
// FIXME: Update all the models as they are no longer valid when we use this
@@ -447,11 +491,8 @@ void Lens::Impl::GlobalSearch(std::string const& search_string)
g_cancellable_cancel (global_search_cancellable_);
global_search_cancellable_ = g_cancellable_new ();
- if (global_results_variant_)
- {
- g_variant_unref (global_results_variant_);
- global_results_variant_ = NULL;
- }
+ global_results_variant_ = NULL;
+ last_global_search_string_ = search_string;
proxy_->Call("GlobalSearch",
g_variant_new("(sa{sv})",
@@ -459,6 +500,7 @@ void Lens::Impl::GlobalSearch(std::string const& search_string)
&b),
sigc::mem_fun(this, &Lens::Impl::OnGlobalSearchFinished),
global_search_cancellable_);
+
g_variant_builder_clear(&b);
}
@@ -478,11 +520,8 @@ void Lens::Impl::Search(std::string const& search_string)
if (search_cancellable_) g_cancellable_cancel (search_cancellable_);
search_cancellable_ = g_cancellable_new ();
- if (results_variant_)
- {
- g_variant_unref (results_variant_);
- results_variant_ = NULL;
- }
+ results_variant_ = NULL;
+ last_search_string_ = search_string;
proxy_->Call("Search",
g_variant_new("(sa{sv})",
@@ -571,7 +610,8 @@ void Lens::Impl::Preview(std::string const& uri)
}
void Lens::Impl::ActivatePreviewAction(std::string const& action_id,
- std::string const& uri)
+ std::string const& uri,
+ Hints const& hints)
{
LOG_DEBUG(logger) << "Activating action '" << action_id << "' on '" << id_ << "'";
@@ -585,10 +625,35 @@ void Lens::Impl::ActivatePreviewAction(std::string const& action_id,
activation_uri += ":";
activation_uri += uri;
- proxy_->Call("Activate",
- g_variant_new("(su)", activation_uri.c_str(),
- UNITY_PROTOCOL_ACTION_TYPE_PREVIEW_ACTION),
- sigc::mem_fun(this, &Lens::Impl::ActivationReply));
+ if (hints.empty())
+ {
+ // FIXME: we should really be using the (sua{sv}) method all the time,
+ // but we're past freezes and having to logout and back in is
+ // too big of a deal after beta freeze
+ proxy_->Call("Activate",
+ g_variant_new("(su)", activation_uri.c_str(),
+ UNITY_PROTOCOL_ACTION_TYPE_PREVIEW_ACTION),
+ sigc::mem_fun(this, &Lens::Impl::ActivationReply));
+ }
+ else
+ {
+ GVariantBuilder b;
+ g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}"));
+
+ for (auto it = hints.begin(); it != hints.end(); ++it)
+ {
+ GVariant* variant = it->second;
+ g_variant_builder_add(&b, "{sv}", it->first.c_str(), variant);
+ }
+
+ proxy_->Call("ActivateWithHints",
+ g_variant_new("(sua{sv})", activation_uri.c_str(),
+ UNITY_PROTOCOL_ACTION_TYPE_PREVIEW_ACTION,
+ &b),
+ sigc::mem_fun(this, &Lens::Impl::ActivationReply));
+
+ g_variant_builder_clear(&b);
+ }
}
void Lens::Impl::SignalPreview(std::string const& preview_uri,
@@ -621,6 +686,61 @@ std::vector<unsigned> Lens::Impl::GetCategoriesOrder()
return result;
}
+glib::Object<DeeModel> Lens::Impl::GetFilterModelForCategory(unsigned category)
+{
+ DeeFilter filter;
+ GetFilterForCategoryIndex(category, &filter);
+ glib::Object<DeeModel> filter_model(dee_filter_model_new(results_->model(), &filter));
+
+ return filter_model;
+}
+
+static void category_filter_map_func (DeeModel* orig_model,
+ DeeFilterModel* filter_model,
+ gpointer user_data)
+{
+ DeeModelIter* iter;
+ DeeModelIter* end;
+ unsigned index = GPOINTER_TO_UINT(user_data);
+
+ iter = dee_model_get_first_iter(orig_model);
+ end = dee_model_get_last_iter(orig_model);
+ while (iter != end)
+ {
+ unsigned category_index = dee_model_get_uint32(orig_model, iter,
+ CATEGORY_COLUMN);
+ if (index == category_index)
+ {
+ dee_filter_model_append_iter(filter_model, iter);
+ }
+ iter = dee_model_next(orig_model, iter);
+ }
+}
+
+static gboolean category_filter_notify_func (DeeModel* orig_model,
+ DeeModelIter* orig_iter,
+ DeeFilterModel* filter_model,
+ gpointer user_data)
+{
+ unsigned index = GPOINTER_TO_UINT(user_data);
+ unsigned category_index = dee_model_get_uint32(orig_model, orig_iter,
+ CATEGORY_COLUMN);
+
+ if (index != category_index)
+ return FALSE;
+
+ dee_filter_model_insert_iter_with_original_order(filter_model, orig_iter);
+ return TRUE;
+}
+
+void Lens::Impl::GetFilterForCategoryIndex(unsigned category, DeeFilter* filter)
+{
+ filter->map_func = category_filter_map_func;
+ filter->map_notify = category_filter_notify_func;
+ filter->destroy = nullptr;
+ filter->userdata = GUINT_TO_POINTER(category);
+}
+
string const& Lens::Impl::id() const
{
return id_;
@@ -707,6 +827,11 @@ bool Lens::Impl::connected() const
return connected_;
}
+bool Lens::Impl::provides_personal_content() const
+{
+ return provides_personal_content_;
+}
+
Lens::Lens(string const& id_,
string const& dbus_name_,
string const& dbus_path_,
@@ -780,9 +905,10 @@ void Lens::Preview(std::string const& uri)
}
void Lens::ActivatePreviewAction(std::string const& action_id,
- std::string const& uri)
+ std::string const& uri,
+ Hints const& hints)
{
- pimpl->ActivatePreviewAction(action_id, uri);
+ pimpl->ActivatePreviewAction(action_id, uri, hints);
}
void Lens::SignalPreview(std::string const& uri,
@@ -797,6 +923,11 @@ std::vector<unsigned> Lens::GetCategoriesOrder()
return pimpl->GetCategoriesOrder();
}
+glib::Object<DeeModel> Lens::GetFilterModelForCategory(unsigned category)
+{
+ return pimpl->GetFilterModelForCategory(category);
+}
+
}
}
diff --git a/UnityCore/Lens.h b/UnityCore/Lens.h
index 71a5bd0e7..08a448107 100644
--- a/UnityCore/Lens.h
+++ b/UnityCore/Lens.h
@@ -86,10 +86,18 @@ public:
virtual void Activate(std::string const& uri);
virtual void Preview(std::string const& uri);
virtual void ActivatePreviewAction(std::string const& action_id,
- std::string const& uri);
+ std::string const& uri,
+ Hints const& hints);
virtual void SignalPreview(std::string const& uri,
glib::Variant const& preview_update,
glib::DBusProxy::ReplyCallback reply_cb = nullptr);
+
+ /**
+ * Note that this model is only valid for as long as the results model
+ * doesn't change.
+ * (you should call this again after models_changed is emitted)
+ */
+ virtual glib::Object<DeeModel> GetFilterModelForCategory(unsigned category);
virtual std::vector<unsigned> GetCategoriesOrder();
nux::RWProperty<std::string> id;
@@ -107,10 +115,16 @@ public:
nux::RWProperty<Categories::Ptr> categories;
nux::RWProperty<Filters::Ptr> filters;
nux::RWProperty<bool> connected;
+ nux::RWProperty<bool> provides_personal_content;
+ nux::ROProperty<std::string> last_search_string;
+ nux::ROProperty<std::string> last_global_search_string;
nux::Property<ViewType> view_type;
sigc::signal<void> categories_reordered;
+ /* Emitted when any of the models' swarm name changes, but collates the name
+ * changes into a single signal emission (when all are changed) */
+ sigc::signal<void> models_changed;
sigc::signal<void, Hints const&> search_finished;
sigc::signal<void, Hints const&> global_search_finished;
sigc::signal<void, std::string const&, HandledType, Hints const&> activated;
diff --git a/UnityCore/Preview.cpp b/UnityCore/Preview.cpp
index 5d9b37d99..6f8b6bfff 100644
--- a/UnityCore/Preview.cpp
+++ b/UnityCore/Preview.cpp
@@ -262,11 +262,11 @@ void Preview::Update(glib::Variant const& properties,
}
}
-void Preview::PerformAction(std::string const& id) const
+void Preview::PerformAction(std::string const& id, Lens::Hints const& hints) const
{
if (pimpl->parent_lens_)
{
- pimpl->parent_lens_->ActivatePreviewAction(id, preview_uri);
+ pimpl->parent_lens_->ActivatePreviewAction(id, preview_uri, hints);
}
else
{
diff --git a/UnityCore/Preview.h b/UnityCore/Preview.h
index 1bb1bbc32..1b43b1033 100644
--- a/UnityCore/Preview.h
+++ b/UnityCore/Preview.h
@@ -112,7 +112,9 @@ public:
ActionPtrList GetActions() const;
InfoHintPtrList GetInfoHints() const;
- void PerformAction(std::string const& id) const;
+ void PerformAction(std::string const& id,
+ std::map<std::string, glib::Variant> const& hints =
+ std::map<std::string, glib::Variant>()) const;
void EmitClosed() const;
protected:
diff --git a/UnityCore/Variant.cpp b/UnityCore/Variant.cpp
index f1aff32b2..21507d001 100644
--- a/UnityCore/Variant.cpp
+++ b/UnityCore/Variant.cpp
@@ -97,8 +97,8 @@ bool Variant::ASVToHints(HintsMap& hints) const
Variant& Variant::operator=(GVariant* val)
{
- if (variant_) g_variant_unref (variant_);
- variant_ = g_variant_ref_sink (val);
+ if (variant_) g_variant_unref(variant_);
+ variant_ = val ? g_variant_ref_sink(val) : val;
return *this;
}
@@ -108,6 +108,11 @@ Variant::operator GVariant* () const
return variant_;
}
+Variant::operator bool() const
+{
+ return bool(variant_);
+}
+
} // namespace glib
namespace variant
diff --git a/UnityCore/Variant.h b/UnityCore/Variant.h
index b9ee024dc..a851a060d 100644
--- a/UnityCore/Variant.h
+++ b/UnityCore/Variant.h
@@ -55,6 +55,8 @@ public:
Variant& operator=(GVariant*);
operator GVariant*() const;
+ operator bool() const;
+
private:
GVariant* variant_;
};
diff --git a/com.canonical.Unity.gschema.xml b/com.canonical.Unity.gschema.xml
index 501cbebd5..7656110a5 100644
--- a/com.canonical.Unity.gschema.xml
+++ b/com.canonical.Unity.gschema.xml
@@ -21,6 +21,26 @@
<summary>Whether the home screen should be expanded.</summary>
<description>Whether the home screen should be expanded.</description>
</key>
+ <key type="i" name="minimize-count">
+ <default>0</default>
+ <summary>Number of times a normal window has been minimized.</summary>
+ <description>This is used to adjust the animation speed by making it progressively faster the more it is used.</description>
+ </key>
+ <key type="i" name="minimize-fast-duration">
+ <default>300</default>
+ <summary>The duration for the minimize animation when it is at its fastest setting.</summary>
+ <description>This is the duration that the minimize animation will have when it has been used more than an number of times equal minimize-speed-threshold.</description>
+ </key>
+ <key type="i" name="minimize-slow-duration">
+ <default>800</default>
+ <summary>The duration for the minimize animation when it is at its slowest setting.</summary>
+ <description>This is the duration that the minimize animation will have when it has never been used.</description>
+ </key>
+ <key type="i" name="minimize-speed-threshold">
+ <default>100</default>
+ <summary>The number of minimizations required to reach maximum speed.</summary>
+ <description>The speed of the minimize animation will progressively get faster as minimize-count approaches this value.</description>
+ </key>
</schema>
<schema path="/com/canonical/unity/launcher/" id="com.canonical.Unity.Launcher" gettext-domain="unity">
<key type="as" name="favorites">
@@ -42,10 +62,10 @@
</key>
</schema>
<schema path="/com/canonical/unity/devices/" id="com.canonical.Unity.Devices" gettext-domain="unity">
- <key type="as" name="favorites">
+ <key type="as" name="blacklist">
<default>[]</default>
- <summary>List of device uuid for favorites on the launcher.</summary>
- <description>These devices are shown in the Launcher by default.</description>
+ <summary>List of device uuid blacklist from the launcher.</summary>
+ <description>These devices are not shown in the launcher by default.</description>
</key>
</schema>
<schema path="/com/canonical/unity/dash/" id="com.canonical.Unity.Dash" gettext-domain="unity">
diff --git a/dash/DashView.cpp b/dash/DashView.cpp
index fb6bde6dd..65bd73e50 100644
--- a/dash/DashView.cpp
+++ b/dash/DashView.cpp
@@ -247,6 +247,12 @@ void DashView::AboutToHide()
home_lens_->view_type = ViewType::HIDDEN;
LOG_DEBUG(logger) << "Setting ViewType " << ViewType::HIDDEN
<< " on '" << home_lens_->id() << "'";
+
+ // if a preview is open, close it
+ if (preview_displaying_)
+ {
+ ClosePreview();
+ }
}
void DashView::SetupViews()
diff --git a/dash/LensView.cpp b/dash/LensView.cpp
index 16128abc1..2e8ab0903 100755
--- a/dash/LensView.cpp
+++ b/dash/LensView.cpp
@@ -45,8 +45,6 @@ nux::logging::Logger logger("unity.dash.lensview");
const int CARD_VIEW_GAP_VERT = 24; // pixels
const int CARD_VIEW_GAP_HORIZ = 25; // pixels
-
-const unsigned CATEGORY_COLUMN = 2;
}
// This is so we can access some protected members in scrollview.
@@ -248,11 +246,8 @@ void LensView::SetupResults()
{
for (unsigned int i = 0; i < categories_.size(); ++i)
{
- PlacesGroup* group = categories_[i];
- ResultViewGrid* grid = static_cast<ResultViewGrid*>(group->GetChildView());
- DeeFilter filter;
- GetFilterForCategoryIndex(i, &filter);
- glib::Object<DeeModel> filter_model(dee_filter_model_new(model, &filter));
+ ResultViewGrid* grid = GetGridForCategory(i);
+ glib::Object<DeeModel> filter_model(lens_->GetFilterModelForCategory(i));
Results::Ptr results_model = lens_->results;
grid->SetModel(filter_model, results_model->GetTag());
}
@@ -310,7 +305,7 @@ void LensView::OnCategoryAdded(Category const& category)
counts_[group] = 0;
ResultView* grid;
-
+
if (renderer_name == "tile-horizontal")
{
grid = new ResultViewGrid(NUX_TRACKER_LOCATION);
@@ -318,12 +313,12 @@ void LensView::OnCategoryAdded(Category const& category)
static_cast<ResultViewGrid*> (grid)->horizontal_spacing = CARD_VIEW_GAP_HORIZ;
static_cast<ResultViewGrid*> (grid)->vertical_spacing = CARD_VIEW_GAP_VERT;
}
- else if (renderer_name == "flow")
+ else if (renderer_name == "flow" && nux::GetWindowThread()->GetGraphicsEngine().UsingGLSLCodePath())
{
grid = new CoverflowResultView(NUX_TRACKER_LOCATION);
grid->SetModelRenderer(new ResultRendererTile(NUX_TRACKER_LOCATION));
group->SetHeaderCountVisible(false);
- }
+ }
else
{
grid = new ResultViewGrid(NUX_TRACKER_LOCATION);
@@ -360,9 +355,7 @@ void LensView::OnCategoryAdded(Category const& category)
Results::Ptr results_model = lens_->results;
if (results_model->model())
{
- DeeFilter filter;
- GetFilterForCategoryIndex(index, &filter);
- glib::Object<DeeModel> filter_model(dee_filter_model_new(results_model->model(), &filter));
+ glib::Object<DeeModel> filter_model(lens_->GetFilterModelForCategory(index));
grid->SetModel(filter_model, results_model->GetTag());
}
@@ -422,62 +415,13 @@ void LensView::OnCategoryOrderChanged()
}
}
-static void category_filter_map_func (DeeModel* orig_model,
- DeeFilterModel* filter_model,
- gpointer user_data)
-{
- DeeModelIter* iter;
- DeeModelIter* end;
- unsigned index = GPOINTER_TO_UINT(user_data);
-
- iter = dee_model_get_first_iter(orig_model);
- end = dee_model_get_last_iter(orig_model);
- while (iter != end)
- {
- unsigned category_index = dee_model_get_uint32(orig_model, iter,
- CATEGORY_COLUMN);
- if (index == category_index)
- {
- dee_filter_model_append_iter(filter_model, iter);
- }
- iter = dee_model_next(orig_model, iter);
- }
-}
-
-static gboolean category_filter_notify_func (DeeModel* orig_model,
- DeeModelIter* orig_iter,
- DeeFilterModel* filter_model,
- gpointer user_data)
-{
- unsigned index = GPOINTER_TO_UINT(user_data);
- unsigned category_index = dee_model_get_uint32(orig_model, orig_iter,
- CATEGORY_COLUMN);
-
- if (index != category_index)
- return FALSE;
-
- dee_filter_model_insert_iter_with_original_order(filter_model, orig_iter);
- return TRUE;
-}
-
-void LensView::GetFilterForCategoryIndex(unsigned index, DeeFilter* filter)
-{
- filter->map_func = category_filter_map_func;
- filter->map_notify = category_filter_notify_func;
- filter->destroy = nullptr;
- filter->userdata = GUINT_TO_POINTER(index);
-}
-
bool LensView::ReinitializeFilterModels()
{
Results::Ptr results_model = lens_->results;
for (unsigned i = last_good_filter_model_ + 1; i < categories_.size(); ++i)
{
- PlacesGroup* group = categories_[i];
- ResultViewGrid* grid = static_cast<ResultViewGrid*>(group->GetChildView());
- DeeFilter filter;
- GetFilterForCategoryIndex(i, &filter);
- glib::Object<DeeModel> filter_model(dee_filter_model_new(results_model->model(), &filter));
+ ResultViewGrid* grid = GetGridForCategory(i);
+ glib::Object<DeeModel> filter_model(lens_->GetFilterModelForCategory(i));
grid->SetModel(filter_model, results_model->GetTag());
}
@@ -486,6 +430,13 @@ bool LensView::ReinitializeFilterModels()
return false;
}
+ResultViewGrid* LensView::GetGridForCategory(unsigned category_index)
+{
+ if (category_index >= categories_.size()) return nullptr;
+ PlacesGroup* group = categories_.at(category_index);
+ return static_cast<ResultViewGrid*>(group->GetChildView());
+}
+
void LensView::OnResultAdded(Result const& result)
{
try {
@@ -755,18 +706,20 @@ void LensView::ActivateFirst()
Results::Ptr results = lens_->results;
if (results->count())
{
- // FIXME: Linear search in the result model, use category grid's model!
- for (unsigned int c = 0; c < scroll_layout_->GetChildren().size(); ++c)
+ // the first displayed category might not be categories_[0]
+ auto category_order = lens_->GetCategoriesOrder();
+ for (unsigned int i = 0; i < category_order.size(); i++)
{
- for (unsigned int i = 0; i < results->count(); ++i)
+ unsigned cat_index = category_order.at(i);
+ ResultViewGrid* grid = GetGridForCategory(cat_index);
+ if (grid == nullptr) continue;
+ auto it = grid->GetIteratorAtRow(0);
+ if (!it.IsLast())
{
- Result result = results->RowAtIndex(i);
- if (result.category_index == c && result.uri != "")
- {
- uri_activated(result.uri);
- lens_->Activate(result.uri);
- return;
- }
+ Result result(*it);
+ uri_activated(result.uri);
+ lens_->Activate(result.uri);
+ return;
}
}
// Fallback
diff --git a/dash/LensView.h b/dash/LensView.h
index b9867c21a..7dbe940d4 100644
--- a/dash/LensView.h
+++ b/dash/LensView.h
@@ -95,8 +95,7 @@ private:
void QueueFixRenderering();
bool FixRenderering();
bool ReinitializeFilterModels();
-
- static void GetFilterForCategoryIndex(unsigned index, DeeFilter* filter);
+ ResultViewGrid* GetGridForCategory(unsigned category_index);
void BuildPreview(std::string const& uri, Preview::Ptr model);
diff --git a/dash/previews/ApplicationPreview.cpp b/dash/previews/ApplicationPreview.cpp
index b32c5421d..79841fe15 100644
--- a/dash/previews/ApplicationPreview.cpp
+++ b/dash/previews/ApplicationPreview.cpp
@@ -309,7 +309,7 @@ void ApplicationPreview::PreLayoutManagement()
image_->SetMinMaxSize(geo_art.width, geo_art.height);
int details_width = MAX(0, geo.width - geo_art.width - style.GetPanelSplitWidth() - style.GetDetailsLeftMargin() - style.GetDetailsRightMargin());
- int top_app_info_max_width = details_width - style.GetAppIconAreaWidth() - style.GetSpaceBetweenIconAndDetails();
+ int top_app_info_max_width = MAX(0, details_width - style.GetAppIconAreaWidth() - style.GetSpaceBetweenIconAndDetails());
if (title_) { title_->SetMaximumWidth(top_app_info_max_width); }
if (subtitle_) { subtitle_->SetMaximumWidth(top_app_info_max_width); }
diff --git a/dash/previews/CMakeLists.txt b/dash/previews/CMakeLists.txt
index 2ccb845dd..15d47bfe8 100644
--- a/dash/previews/CMakeLists.txt
+++ b/dash/previews/CMakeLists.txt
@@ -10,13 +10,13 @@ set (CFLAGS
"-I${CMAKE_CURRENT_BINARY_DIR}"
)
-if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l")
set (CFLAGS ${CFLAGS} "-fPIC")
-endif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+endif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7l")
add_definitions (${CFLAGS})
-set (LIBS ${CACHED_UNITY_DEPS_LIBRARIES} "-lunity-core-${UNITY_API_VERSION} -lm -lGL -lGLU")
+set (LIBS ${CACHED_UNITY_DEPS_LIBRARIES} ${UNITY_STANDALONE_LADD})
link_libraries (${LIBS})
set (LIB_PATHS ${CACHED_UNITY_DEPS_LIBRARY_DIRS})
diff --git a/dash/previews/PreviewContainer.cpp b/dash/previews/PreviewContainer.cpp
index f07c80d2b..54cc3bf99 100644
--- a/dash/previews/PreviewContainer.cpp
+++ b/dash/previews/PreviewContainer.cpp
@@ -149,9 +149,9 @@ public:
nux::Geometry swipeOut = geometry;
if (swipe_.direction == Navigation::RIGHT)
- swipeOut.OffsetPosition(-(curve_progress * (geometry.GetWidth() + parent_->nav_left_->GetGeometry().GetWidth())), 0);
+ swipeOut.OffsetPosition(-(curve_progress * (parent_->GetGeometry().width - geometry.x)), 0);
else if (swipe_.direction == Navigation::LEFT)
- swipeOut.OffsetPosition(curve_progress* (geometry.GetWidth() + parent_->nav_right_->GetGeometry().GetWidth()), 0);
+ swipeOut.OffsetPosition(curve_progress* (parent_->GetGeometry().width - geometry.x), 0);
current_preview_->SetGeometry(swipeOut);
}
@@ -162,9 +162,9 @@ public:
nux::Geometry swipeIn = geometry;
if (swipe_.direction == Navigation::RIGHT)
- swipeIn.OffsetPosition(float(geometry.GetWidth() + parent_->nav_right_->GetGeometry().GetWidth()) - (curve_progress * (geometry.GetWidth() + parent_->nav_right_->GetGeometry().GetWidth())), 0);
+ swipeIn.OffsetPosition(float(parent_->GetGeometry().width - geometry.x) - (curve_progress * (parent_->GetGeometry().width - geometry.x)), 0);
else if (swipe_.direction == Navigation::LEFT)
- swipeIn.OffsetPosition(-((1.0-curve_progress)*(geometry.GetWidth() + parent_->nav_left_->GetGeometry().GetWidth())), 0);
+ swipeIn.OffsetPosition(-((1.0-curve_progress)*(parent_->GetGeometry().width - geometry.x)), 0);
swipe_.preview->SetGeometry(swipeIn);
}
}
@@ -355,7 +355,6 @@ PreviewContainer::PreviewContainer(NUX_FILE_LINE_DECL)
: View(NUX_FILE_LINE_PARAM)
, content_layout_(nullptr)
, nav_disabled_(Navigation::NONE)
- , last_calc_height_(0)
, navigation_progress_speed_(0.0)
, navigation_count_(0)
{
@@ -411,7 +410,7 @@ void PreviewContainer::SetupViews()
layout_ = new nux::HLayout();
SetLayout(layout_);
- layout_->AddSpace(0, 0);
+ layout_->AddSpace(0, 1);
nav_left_ = new PreviewNavigator(Orientation::LEFT, NUX_TRACKER_LOCATION);
AddChild(nav_left_);
@@ -421,8 +420,9 @@ void PreviewContainer::SetupViews()
layout_->AddView(nav_left_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
content_layout_ = new PreviewContent(this);
+ content_layout_->SetMinMaxSize(style.GetPreviewWidth(), style.GetPreviewHeight());
AddChild(content_layout_);
- layout_->AddLayout(content_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
+ layout_->AddLayout(content_layout_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
nav_right_ = new PreviewNavigator(Orientation::RIGHT, NUX_TRACKER_LOCATION);
AddChild(nav_right_);
@@ -431,7 +431,7 @@ void PreviewContainer::SetupViews()
nav_right_->activated.connect([&]() { navigate_right.emit(); });
layout_->AddView(nav_right_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
- layout_->AddSpace(0, 0);
+ layout_->AddSpace(0, 1);
content_layout_->start_navigation.connect([&]()
{
@@ -497,32 +497,6 @@ void PreviewContainer::DrawContent(nux::GraphicsEngine& gfx_engine, bool force_d
gfx_engine.PopClippingRectangle();
}
-void PreviewContainer::PreLayoutManagement()
-{
- previews::Style& style = previews::Style::Instance();
- nux::Geometry const& geo = GetGeometry();
-
- int available_preview_width = MAX(1, geo.width - nav_left_->GetGeometry().width - nav_right_->GetGeometry().width);
- int aspect_altered_height = available_preview_width / style.GetPreviewAspectRatio();
-
- aspect_altered_height = CLAMP(aspect_altered_height, 1, geo.height);
- if (last_calc_height_ != aspect_altered_height)
- {
- last_calc_height_ = aspect_altered_height;
-
- content_layout_->SetMinimumHeight(aspect_altered_height);
- content_layout_->SetMaximumHeight(aspect_altered_height);
-
- nav_left_->SetMinimumHeight(aspect_altered_height);
- nav_left_->SetMaximumHeight(aspect_altered_height);
-
- nav_right_->SetMinimumHeight(aspect_altered_height);
- nav_right_->SetMaximumHeight(aspect_altered_height);
- }
-
- View::PreLayoutManagement();
-}
-
bool PreviewContainer::AnimationInProgress()
{
// short circuit to avoid unneeded calculations
@@ -569,7 +543,7 @@ bool PreviewContainer::QueueAnimation()
last_progress_time_ = current;
QueueDraw();
- return true;
+ return false;
}
bool PreviewContainer::AcceptKeyNavFocus()
diff --git a/dash/previews/PreviewContainer.h b/dash/previews/PreviewContainer.h
index 6e790295f..78b19750e 100644
--- a/dash/previews/PreviewContainer.h
+++ b/dash/previews/PreviewContainer.h
@@ -81,7 +81,6 @@ public:
protected:
void Draw(nux::GraphicsEngine& gfx_engine, bool force_draw);
void DrawContent(nux::GraphicsEngine& gfx_engine, bool force_draw);
- void PreLayoutManagement();
bool InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character);
void OnKeyDown(unsigned long event_type, unsigned long event_keysym, unsigned long event_state, const TCHAR* character, unsigned short key_repeat_count);
@@ -101,7 +100,6 @@ private:
PreviewNavigator* nav_right_;
PreviewContent* content_layout_;
Navigation nav_disabled_;
- int last_calc_height_;
// Animation
struct timespec last_progress_time_;
diff --git a/dash/previews/PreviewInfoHintWidget.cpp b/dash/previews/PreviewInfoHintWidget.cpp
index 1e90b4964..793b55e26 100644
--- a/dash/previews/PreviewInfoHintWidget.cpp
+++ b/dash/previews/PreviewInfoHintWidget.cpp
@@ -210,6 +210,7 @@ void PreviewInfoHintWidget::PreLayoutManagement()
int info_value_width = geo.width;
info_value_width -= layout_spacing;
info_value_width -= info_hint_width;
+ info_value_width = MAX(0, info_value_width);
for (InfoHint const& info_hint : info_hints_)
{
diff --git a/dash/previews/Track.cpp b/dash/previews/Track.cpp
index cfd7bf1f7..ca02a59d9 100644
--- a/dash/previews/Track.cpp
+++ b/dash/previews/Track.cpp
@@ -265,7 +265,6 @@ void Track::SetupViews()
duration_layout_->AddSpace(0, 1);
duration_layout_->AddView(duration_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
- layout->SetSpaceBetweenChildren(6);
layout->AddLayout(track_status_layout_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
layout->AddLayout(title_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
layout->AddLayout(duration_layout_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
diff --git a/hud/HudButton.cpp b/hud/HudButton.cpp
index 13159eba7..3ab6ff043 100644
--- a/hud/HudButton.cpp
+++ b/hud/HudButton.cpp
@@ -75,6 +75,22 @@ HudButton::HudButton(NUX_FILE_LINE_DECL)
{
QueueDraw();
});
+
+ mouse_move.connect([&](int x, int y, int dx, int dy, unsigned int button, unsigned int key)
+ {
+ if (!fake_focused)
+ fake_focused = true;
+ });
+
+ mouse_enter.connect([&](int x, int y, unsigned int button, unsigned int key)
+ {
+ fake_focused = true;
+ });
+
+ mouse_leave.connect([&](int x, int y, unsigned int button, unsigned int key)
+ {
+ fake_focused = false;
+ });
}
void HudButton::InitTheme()
@@ -113,7 +129,6 @@ bool HudButton::AcceptKeyNavFocus()
return false;
}
-
long HudButton::ComputeContentSize()
{
long ret = nux::Button::ComputeContentSize();
@@ -207,6 +222,7 @@ void HudButton::SetQuery(Query::Ptr query)
nux::StaticCairoText* text = new nux::StaticCairoText(item.first);
text->SetTextColor(nux::Color(1.0f, 1.0f, 1.0f, item.second ? 1.0f : 0.5f));
text->SetFont(button_font);
+ text->SetInputEventSensitivity(false);
hlayout_->AddView(text, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
}
}
diff --git a/hud/HudView.cpp b/hud/HudView.cpp
index 567392983..7c779b632 100644
--- a/hud/HudView.cpp
+++ b/hud/HudView.cpp
@@ -66,6 +66,7 @@ View::View()
, timeline_need_more_draw_(false)
, selected_button_(0)
, show_embedded_icon_(true)
+ , keyboard_stole_focus_(false)
{
renderer_.SetOwner(this);
renderer_.need_redraw.connect([this] () {
@@ -251,6 +252,22 @@ void View::SetQueries(Hud::Queries queries)
query_activated.emit(dynamic_cast<HudButton*>(view)->GetQuery());
});
+ button->mouse_move.connect([&](int x, int y, int dx, int dy, unsigned long mouse_button, unsigned long special_key) {
+ if (keyboard_stole_focus_)
+ {
+ MouseStealsHudButtonFocus();
+ keyboard_stole_focus_ = false;
+ }
+ });
+
+ button->mouse_enter.connect([&](int x, int y, unsigned long mouse_button, unsigned long special_key) {
+ MouseStealsHudButtonFocus();
+ });
+
+ button->mouse_leave.connect([&](int x, int y, unsigned long mouse_button, unsigned long special_key) {
+ SelectLastFocusedButton();
+ });
+
button->key_nav_focus_activate.connect([&](nux::Area* area) {
query_activated.emit(dynamic_cast<HudButton*>(area)->GetQuery());
});
@@ -484,6 +501,49 @@ void View::DrawContent(nux::GraphicsEngine& gfx_context, bool force_draw)
}
}
+void View::MouseStealsHudButtonFocus()
+{
+ LoseSelectedButtonFocus();
+ FindNewSelectedButton();
+}
+
+void View::LoseSelectedButtonFocus()
+{
+ int button_index = 1;
+ for (auto it = buttons_.rbegin(); it != buttons_.rend(); ++it)
+ {
+ if (selected_button_ == button_index)
+ (*it)->fake_focused = false;
+ ++button_index;
+ }
+}
+
+void View::FindNewSelectedButton()
+{
+ int button_index = 1;
+ for (auto it = buttons_.rbegin(); it != buttons_.rend(); ++it)
+ {
+ if ((*it)->fake_focused)
+ {
+ query_selected.emit((*it)->GetQuery());
+ selected_button_ = button_index;
+ return;
+ }
+ ++button_index;
+ }
+}
+
+void View::SelectLastFocusedButton()
+{
+ int button_index = 1;
+ for (auto it = buttons_.rbegin(); it != buttons_.rend(); ++it)
+ {
+ if (button_index == selected_button_)
+ (*it)->fake_focused = true;
+ ++button_index;
+ }
+}
+
// Keyboard navigation
bool View::AcceptKeyNavFocus()
{
@@ -656,12 +716,12 @@ nux::Area* View::FindKeyFocusArea(unsigned int event_type,
(*next)->fake_focused = true;
query_selected.emit((*next)->GetQuery());
--selected_button_;
+ keyboard_stole_focus_ = true;
}
break;
}
}
}
-
if (event_type == nux::NUX_KEYDOWN && direction == nux::KEY_NAV_DOWN)
{
std::list<HudButton::Ptr>::reverse_iterator rit;
@@ -679,6 +739,7 @@ nux::Area* View::FindKeyFocusArea(unsigned int event_type,
(*next)->fake_focused = true;
query_selected.emit((*next)->GetQuery());
++selected_button_;
+ keyboard_stole_focus_ = true;
}
break;
}
diff --git a/hud/HudView.h b/hud/HudView.h
index 8e654b49f..982bafe24 100644
--- a/hud/HudView.h
+++ b/hud/HudView.h
@@ -85,6 +85,11 @@ private:
void ProcessGrowShrink();
+ void MouseStealsHudButtonFocus();
+ void LoseSelectedButtonFocus();
+ void FindNewSelectedButton();
+ void SelectLastFocusedButton();
+
std::string GetName() const;
void AddProperties(GVariantBuilder* builder);
IntrospectableList GetIntrospectableChildren();
@@ -116,6 +121,7 @@ private:
int selected_button_;
bool show_embedded_icon_;
bool activated_signal_sent_;
+ bool keyboard_stole_focus_;
};
diff --git a/launcher/AbstractVolumeMonitorWrapper.h b/launcher/AbstractVolumeMonitorWrapper.h
index 155c0a8c7..a9ca1facc 100644
--- a/launcher/AbstractVolumeMonitorWrapper.h
+++ b/launcher/AbstractVolumeMonitorWrapper.h
@@ -27,7 +27,6 @@
#include <sigc++/trackable.h>
#include <UnityCore/GLibWrapper.h>
-#include <UnityCore/GLibSignal.h>
namespace unity
{
@@ -54,8 +53,8 @@ public:
sigc::signal<void, glib::Object<GVolume> const&> volume_removed;
};
-} // namespace launcher
-} // namespace unity
+}
+}
-#endif // UNITYSHELL_ABSTRACT_VOLUME_MONITOR_WRAPPER_H
+#endif
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 3ac9e8db8..28bb87dde 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -37,14 +37,15 @@ set (LAUNCHER_SOURCES
DNDCollectionWindow.cpp
Decaymulator.cpp
DesktopLauncherIcon.cpp
- DeviceLauncherIcon.cpp
DeviceLauncherSection.cpp
- DevicesSettings.cpp
+ DeviceNotificationDisplayImp.cpp
+ DevicesSettingsImp.cpp
DndData.cpp
EdgeBarrierController.cpp
FavoriteStore.cpp
FavoriteStoreGSettings.cpp
FavoriteStorePrivate.cpp
+ FileManagerOpenerImp.cpp
HudLauncherIcon.cpp
Launcher.cpp
LauncherController.cpp
@@ -71,6 +72,8 @@ set (LAUNCHER_SOURCES
SpacerLauncherIcon.cpp
Tooltip.cpp
TrashLauncherIcon.cpp
+ VolumeImp.cpp
+ VolumeLauncherIcon.cpp
VolumeMonitorWrapper.cpp
)
@@ -87,7 +90,7 @@ set (SWITCHER_SOURCES
add_library (switcher-lib STATIC ${SWITCHER_SOURCES})
add_dependencies (switcher-lib unity-core-${UNITY_API_VERSION} unity-shared)
-#
+#
# Standalone variant
#
add_executable (launcher StandaloneLauncher.cpp)
diff --git a/launcher/DeviceLauncherIcon.cpp b/launcher/DeviceLauncherIcon.cpp
deleted file mode 100644
index af56343f0..000000000
--- a/launcher/DeviceLauncherIcon.cpp
+++ /dev/null
@@ -1,425 +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: Neil Jagdish Patel <neil.patel@canonical.com>
- */
-
-#include "DeviceLauncherIcon.h"
-
-#include <algorithm>
-#include <list>
-
-#include <glib/gi18n-lib.h>
-#include <libnotify/notify.h>
-#include <NuxCore/Logger.h>
-
-#include "DevicesSettings.h"
-#include "unity-shared/IconLoader.h"
-#include "unity-shared/ubus-server.h"
-#include "unity-shared/UBusMessages.h"
-
-namespace unity
-{
-namespace launcher
-{
-namespace
-{
-
-nux::logging::Logger logger("unity.launcher");
-
-const unsigned int volume_changed_timeout = 500;
-
-}
-
-DeviceLauncherIcon::DeviceLauncherIcon(glib::Object<GVolume> const& volume)
- : SimpleLauncherIcon(IconType::DEVICE)
- , volume_(volume)
-{
- gsignals_.Add<void, GVolume*>(volume, "changed", sigc::mem_fun(this, &DeviceLauncherIcon::OnVolumeChanged));
- DevicesSettings::GetDefault().changed.connect(sigc::mem_fun(this, &DeviceLauncherIcon::OnSettingsChanged));
-
- // Checks if in favorites!
- glib::String uuid(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UUID));
- DeviceList favorites = DevicesSettings::GetDefault().GetFavorites();
- DeviceList::iterator pos = std::find(favorites.begin(), favorites.end(), uuid.Str());
-
- keep_in_launcher_ = pos != favorites.end();
-
- UpdateDeviceIcon();
- UpdateVisibility();
-}
-
-void DeviceLauncherIcon::OnVolumeChanged(GVolume* volume)
-{
- if (!G_IS_VOLUME(volume))
- return;
-
- changed_timeout_.reset(new glib::Timeout(volume_changed_timeout, [this]() {
- UpdateDeviceIcon();
- UpdateVisibility();
- return false;
- }));
-}
-
-void DeviceLauncherIcon::UpdateVisibility()
-{
- switch (DevicesSettings::GetDefault().GetDevicesOption())
- {
- case DevicesSettings::NEVER:
- SetQuirk(Quirk::VISIBLE, false);
- break;
- case DevicesSettings::ONLY_MOUNTED:
- if (keep_in_launcher_)
- {
- SetQuirk(Quirk::VISIBLE, true);
- }
- else
- {
- glib::Object<GMount> mount(g_volume_get_mount(volume_));
- SetQuirk(Quirk::VISIBLE, mount);
- }
- break;
- case DevicesSettings::ALWAYS:
- SetQuirk(Quirk::VISIBLE, true);
- break;
- }
-}
-
-void DeviceLauncherIcon::UpdateDeviceIcon()
-{
- name_ = glib::String(g_volume_get_name(volume_)).Str();
-
- glib::Object<GIcon> icon(g_volume_get_icon(volume_));
- glib::String icon_string(g_icon_to_string(icon));
-
- tooltip_text = name_;
- icon_name = icon_string.Str();
-
- SetQuirk(Quirk::RUNNING, false);
-}
-
-bool
-DeviceLauncherIcon::CanEject()
-{
- return g_volume_can_eject(volume_);
-}
-
-bool
-DeviceLauncherIcon::CanStop()
-{
- return g_drive_can_stop(g_volume_get_drive(volume_));
-}
-
-AbstractLauncherIcon::MenuItemsVector DeviceLauncherIcon::GetMenus()
-{
- MenuItemsVector result;
- glib::Object<DbusmenuMenuitem> menu_item;
- glib::Object<GDrive> drive(g_volume_get_drive(volume_));
- typedef glib::Signal<void, DbusmenuMenuitem*, int> ItemSignal;
-
- // "Lock to Launcher"/"Unlock from Launcher" item
- if (DevicesSettings::GetDefault().GetDevicesOption() == DevicesSettings::ONLY_MOUNTED
- && drive && !g_drive_is_media_removable (drive))
- {
- menu_item = dbusmenu_menuitem_new();
-
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, !keep_in_launcher_ ? _("Lock to Launcher") : _("Unlock from Launcher"));
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
-
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- sigc::mem_fun(this, &DeviceLauncherIcon::OnTogglePin)));
- result.push_back(menu_item);
- }
-
- // "Open" item
- menu_item = dbusmenu_menuitem_new();
-
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Open"));
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
-
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
- ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0));
- }));
-
- result.push_back(menu_item);
-
- // "Eject" item
- if (drive && g_drive_can_eject(drive))
- {
- menu_item = dbusmenu_menuitem_new();
-
- GList *list = g_drive_get_volumes(drive);
- if (list)
- {
- if (!list->next) // If the list has only one item
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Eject"));
- else
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Eject parent drive"));
-
- g_list_free_full(list, g_object_unref);
- }
-
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
-
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
- Eject();
- }));
-
- result.push_back(menu_item);
- }
-
- // "Safely remove" item
- if (drive && g_drive_can_stop(drive))
- {
- menu_item = dbusmenu_menuitem_new();
-
- GList *list = g_drive_get_volumes(drive);
- if (list)
- {
- if (!list->next) // If the list has only one item
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Safely remove"));
- else
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Safely remove parent drive"));
-
- g_list_free_full(list, g_object_unref);
- }
-
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
-
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
- StopDrive();
- }));
-
- result.push_back(menu_item);
- }
-
- // "Unmount" item
- if (!g_volume_can_eject(volume_)) // Don't need Unmount if can Eject
- {
- glib::Object<GMount> mount(g_volume_get_mount(volume_));
-
- if (mount && g_mount_can_unmount(mount))
- {
- menu_item = dbusmenu_menuitem_new();
-
- dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Unmount"));
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
- dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
-
- gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
- Unmount();
- }));
-
- result.push_back(menu_item);
- }
- }
-
- return result;
-}
-
-void DeviceLauncherIcon::ShowMount(GMount* mount)
-{
- if (G_IS_MOUNT(mount))
- {
- glib::Object<GFile> root(g_mount_get_root(mount));
-
- if (G_IS_FILE(root.RawPtr()))
- {
- glib::String uri(g_file_get_uri(root));
- glib::Error error;
-
- g_app_info_launch_default_for_uri(uri.Value(), NULL, &error);
-
- if (error)
- {
- LOG_WARNING(logger) << "Cannot open volume '" << name_
- << "': Unable to show " << uri
- << ": " << error;
- }
- }
- else
- {
- LOG_WARNING(logger) << "Cannot open volume '" << name_
- << "': Mount has no root";
- }
- }
- else
- {
- LOG_WARNING(logger) << "Cannot open volume '" << name_
- << "': Mount-point is invalid";
- }
-}
-
-void DeviceLauncherIcon::ActivateLauncherIcon(ActionArg arg)
-{
- SimpleLauncherIcon::ActivateLauncherIcon(arg);
- SetQuirk(Quirk::STARTING, true);
-
- glib::Object<GMount> mount(g_volume_get_mount(volume_));
-
- if (G_IS_MOUNT(mount.RawPtr()))
- ShowMount(mount);
- else
- g_volume_mount(volume_,
- (GMountMountFlags)0,
- NULL,
- NULL,
- (GAsyncReadyCallback)&DeviceLauncherIcon::OnMountReady,
- this);
-}
-
-void DeviceLauncherIcon::OnMountReady(GObject* object,
- GAsyncResult* result,
- DeviceLauncherIcon* self)
-{
- glib::Error error;
-
- if (g_volume_mount_finish(self->volume_, result, &error))
- {
- glib::Object<GMount> mount(g_volume_get_mount(self->volume_));
- self->ShowMount(mount);
- }
- else
- {
- LOG_WARNING(logger) << "Cannot open volume '" << self->name_ << "' : " <<
- (error ? error.Message() : "Mount operation failed");
- }
-}
-
-void DeviceLauncherIcon::OnEjectReady(GObject* object,
- GAsyncResult* result,
- DeviceLauncherIcon* self)
-{
- if (g_volume_eject_with_operation_finish(self->volume_, result, NULL))
- {
- IconLoader::GetDefault().LoadFromGIconString(self->icon_name(), 48,
- sigc::bind(sigc::mem_fun(self, &DeviceLauncherIcon::ShowNotification), self->name_));
- }
-}
-
-void DeviceLauncherIcon::ShowNotification(std::string const& icon_name,
- unsigned size,
- glib::Object<GdkPixbuf> const& pixbuf,
- std::string const& name)
-{
- glib::Object<NotifyNotification> notification(notify_notification_new(name.c_str(),
- _("The drive has been successfully ejected"),
- NULL));
-
- notify_notification_set_hint(notification,
- "x-canonical-private-synchronous",
- g_variant_new_boolean(TRUE));
-
- if (GDK_IS_PIXBUF(pixbuf.RawPtr()))
- notify_notification_set_image_from_pixbuf(notification, pixbuf);
-
- notify_notification_show(notification, NULL);
-}
-
-void DeviceLauncherIcon::Eject()
-{
- glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(NULL));
-
- g_volume_eject_with_operation(volume_,
- (GMountUnmountFlags)0,
- mount_op,
- NULL,
- (GAsyncReadyCallback)OnEjectReady,
- this);
-}
-
-void DeviceLauncherIcon::OnTogglePin(DbusmenuMenuitem* item, int time)
-{
- glib::String uuid(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UUID));
-
- keep_in_launcher_ = !keep_in_launcher_;
-
- if (!keep_in_launcher_)
- {
- // If the volume is not mounted hide the icon
- glib::Object<GMount> mount(g_volume_get_mount(volume_));
-
- if (!mount)
- SetQuirk(Quirk::VISIBLE, false);
-
- // Remove from favorites
- if (!uuid.Str().empty())
- DevicesSettings::GetDefault().RemoveFavorite(uuid.Str());
- }
- else
- {
- if (!uuid.Str().empty())
- DevicesSettings::GetDefault().AddFavorite(uuid.Str());
- }
-}
-
-void DeviceLauncherIcon::OnUnmountReady(GObject* object,
- GAsyncResult* result,
- DeviceLauncherIcon* self)
-{
- if (G_IS_MOUNT(object))
- g_mount_unmount_with_operation_finish(G_MOUNT(object), result, NULL);
-}
-
-void DeviceLauncherIcon::Unmount()
-{
- glib::Object<GMount> mount(g_volume_get_mount(volume_));
-
- if (mount)
- {
- glib::Object<GMountOperation> op(gtk_mount_operation_new(NULL));
-
- g_mount_unmount_with_operation(mount, (GMountUnmountFlags)0, op, NULL,
- (GAsyncReadyCallback)OnUnmountReady, this);
- }
-}
-
-void DeviceLauncherIcon::OnRemoved()
-{
- Remove();
-}
-
-void DeviceLauncherIcon::StopDrive()
-{
- glib::Object<GDrive> drive(g_volume_get_drive(volume_));
- glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(NULL));
-
- g_drive_stop(drive, (GMountUnmountFlags)0, mount_op, NULL, NULL, NULL);
-}
-
-void DeviceLauncherIcon::OnSettingsChanged()
-{
- // Checks if in favourites!
- glib::String uuid(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UUID));
- DeviceList favorites = DevicesSettings::GetDefault().GetFavorites();
- DeviceList::iterator pos = std::find(favorites.begin(), favorites.end(), uuid.Str());
-
- keep_in_launcher_ = pos != favorites.end();
-
- UpdateVisibility();
-}
-
-std::string DeviceLauncherIcon::GetName() const
-{
- return "DeviceLauncherIcon";
-}
-
-} // namespace launcher
-} // namespace unity
diff --git a/launcher/DeviceLauncherIcon.h b/launcher/DeviceLauncherIcon.h
deleted file mode 100644
index c0c3ca9eb..000000000
--- a/launcher/DeviceLauncherIcon.h
+++ /dev/null
@@ -1,78 +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: Neil Jagdish Patel <neil.patel@canonical.com>
- */
-
-#ifndef _DEVICE_LAUNCHER_ICON_H__H
-#define _DEVICE_LAUNCHER_ICON_H__H
-
-#include <gio/gio.h>
-#include <UnityCore/GLibWrapper.h>
-#include <UnityCore/GLibSignal.h>
-
-#include "SimpleLauncherIcon.h"
-
-namespace unity
-{
-namespace launcher
-{
-
-class DeviceLauncherIcon : public SimpleLauncherIcon
-{
-public:
- typedef nux::ObjectPtr<DeviceLauncherIcon> Ptr;
-
- DeviceLauncherIcon(glib::Object<GVolume> const& volume);
-
- void OnRemoved();
- bool CanEject();
- bool CanStop();
- void Eject();
- void StopDrive();
-
-protected:
- MenuItemsVector GetMenus();
- std::string GetName() const;
-
-private:
- void UpdateVisibility();
- void UpdateDeviceIcon();
- void ActivateLauncherIcon(ActionArg arg);
- void ShowMount(GMount* mount);
- void Unmount();
- void OnTogglePin(DbusmenuMenuitem* item, int time);
- void OnSettingsChanged();
- void ShowNotification(std::string const&, unsigned, glib::Object<GdkPixbuf> const&, std::string const&);
- void OnVolumeChanged(GVolume* volume);
- static void OnChanged(GVolume* volume, DeviceLauncherIcon* self);
- static void OnMountReady(GObject* object, GAsyncResult* result, DeviceLauncherIcon* self);
- static void OnEjectReady(GObject* object, GAsyncResult* result, DeviceLauncherIcon* self);
- static void OnUnmountReady(GObject* object, GAsyncResult* result, DeviceLauncherIcon* self);
-
-private:
- glib::Source::UniquePtr changed_timeout_;
- glib::Object<GVolume> volume_;
- glib::SignalManager gsignals_;
-
- std::string name_;
- bool keep_in_launcher_;
-};
-
-}
-} // namespace unity
-
-#endif // _DEVICE_LAUNCHER_ICON_H__H
diff --git a/launcher/DeviceLauncherSection.cpp b/launcher/DeviceLauncherSection.cpp
index 5fa8cbf36..b618f0cb9 100644
--- a/launcher/DeviceLauncherSection.cpp
+++ b/launcher/DeviceLauncherSection.cpp
@@ -18,19 +18,27 @@
*/
#include "DeviceLauncherSection.h"
+#include "DeviceNotificationDisplayImp.h"
+#include "DevicesSettings.h"
+#include "FileManagerOpenerImp.h"
+#include "VolumeImp.h"
namespace unity
{
namespace launcher
{
-DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor)
+DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor,
+ DevicesSettings::Ptr devices_settings)
: monitor_(volume_monitor)
+ , devices_settings_(devices_settings)
+ , file_manager_opener_(new FileManagerOpenerImp)
+ , device_notification_display_(new DeviceNotificationDisplayImp)
{
monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded));
monitor_->volume_removed.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeRemoved));
-
- device_populate_idle_.Run([&] () {
+
+ device_populate_idle_.Run([this] () {
PopulateEntries();
return false;
});
@@ -39,29 +47,21 @@ DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr v
void DeviceLauncherSection::PopulateEntries()
{
for (auto volume : monitor_->GetVolumes())
- {
- // Sanity check. Avoid duplicates.
- if (map_.find(volume) != map_.end())
- continue;
-
- DeviceLauncherIcon::Ptr icon(new DeviceLauncherIcon(volume));
-
- map_[volume] = icon;
- IconAdded.emit(icon);
- }
+ TryToCreateAndAddIcon(volume);
}
-/* Uses a std::map to track all the volume icons shown and not shown.
- * Keep in mind: when "volume-removed" is recevied we should erase
- * the pair (GVolume - DeviceLauncherIcon) from the std::map to avoid leaks
- */
void DeviceLauncherSection::OnVolumeAdded(glib::Object<GVolume> const& volume)
{
- // Sanity check. Avoid duplicates.
+ TryToCreateAndAddIcon(volume);
+}
+
+void DeviceLauncherSection::TryToCreateAndAddIcon(glib::Object<GVolume> volume)
+{
if (map_.find(volume) != map_.end())
return;
- DeviceLauncherIcon::Ptr icon(new DeviceLauncherIcon(volume));
+ VolumeLauncherIcon::Ptr icon(new VolumeLauncherIcon(std::make_shared<VolumeImp>(volume, file_manager_opener_, device_notification_display_),
+ devices_settings_));
map_[volume] = icon;
IconAdded.emit(icon);
@@ -73,12 +73,8 @@ void DeviceLauncherSection::OnVolumeRemoved(glib::Object<GVolume> const& volume)
// Sanity check
if (volume_it != map_.end())
- {
- volume_it->second->OnRemoved();
map_.erase(volume_it);
- }
}
-} // namespace launcher
-} // namespace unity
-
+}
+}
diff --git a/launcher/DeviceLauncherSection.h b/launcher/DeviceLauncherSection.h
index 249939068..551fa4a2a 100644
--- a/launcher/DeviceLauncherSection.h
+++ b/launcher/DeviceLauncherSection.h
@@ -17,15 +17,19 @@
* Andrea Azzarone <andrea.azzarone@canonical.com>
*/
-#ifndef _DEVICE_LAUNCHER_SECTION_H_
-#define _DEVICE_LAUNCHER_SECTION_H_
+#ifndef UNITYSHELL_DEVICE_LAUNCHER_SECTION_H
+#define UNITYSHELL_DEVICE_LAUNCHER_SECTION_H
#include <map>
+#include <memory>
#include <UnityCore/GLibSource.h>
-#include "DeviceLauncherIcon.h"
#include "AbstractVolumeMonitorWrapper.h"
+#include "DevicesSettings.h"
+#include "DeviceNotificationDisplay.h"
+#include "FileManagerOpener.h"
+#include "VolumeLauncherIcon.h"
namespace unity
{
@@ -35,7 +39,8 @@ namespace launcher
class DeviceLauncherSection : public sigc::trackable
{
public:
- DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor);
+ DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor,
+ DevicesSettings::Ptr devices_settings);
sigc::signal<void, AbstractLauncherIcon::Ptr> IconAdded;
@@ -43,13 +48,18 @@ private:
void PopulateEntries();
void OnVolumeAdded(glib::Object<GVolume> const& volume);
void OnVolumeRemoved(glib::Object<GVolume> const& volume);
+ void TryToCreateAndAddIcon(glib::Object<GVolume> volume);
- std::map<GVolume*, DeviceLauncherIcon::Ptr> map_;
+ std::map<GVolume*, VolumeLauncherIcon::Ptr> map_;
AbstractVolumeMonitorWrapper::Ptr monitor_;
+ DevicesSettings::Ptr devices_settings_;
+ FileManagerOpener::Ptr file_manager_opener_;
+ DeviceNotificationDisplay::Ptr device_notification_display_;
+
glib::Idle device_populate_idle_;
};
}
-} // namespace unity
+}
-#endif // _DEVICE_LAUNCHER_SECTION_H_
+#endif
diff --git a/launcher/DeviceNotificationDisplay.h b/launcher/DeviceNotificationDisplay.h
new file mode 100644
index 000000000..2c12a899a
--- /dev/null
+++ b/launcher/DeviceNotificationDisplay.h
@@ -0,0 +1,45 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_H
+#define UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_H
+
+#include <boost/noncopyable.hpp>
+#include <memory>
+#include <string>
+
+namespace unity
+{
+namespace launcher
+{
+
+class DeviceNotificationDisplay : private boost::noncopyable
+{
+public:
+ typedef std::shared_ptr<DeviceNotificationDisplay> Ptr;
+
+ virtual ~DeviceNotificationDisplay() {}
+
+ virtual void Display(std::string const& icon_name, std::string const& volume_name) = 0;
+};
+
+}
+}
+
+#endif
diff --git a/launcher/DeviceNotificationDisplayImp.cpp b/launcher/DeviceNotificationDisplayImp.cpp
new file mode 100644
index 000000000..cbb04c77d
--- /dev/null
+++ b/launcher/DeviceNotificationDisplayImp.cpp
@@ -0,0 +1,82 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#include <gdk/gdk.h>
+#include <glib/gi18n-lib.h>
+#include <libnotify/notify.h>
+#include <sigc++/sigc++.h>
+#include <UnityCore/GLibWrapper.h>
+
+#include "DeviceNotificationDisplayImp.h"
+#include "unity-shared/IconLoader.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+//
+// Start private implementation
+//
+class DeviceNotificationDisplayImp::Impl
+{
+public:
+ void Show(std::string const& icon_name, std::string const& volume_name)
+ {
+ int icon_size = 48;
+ IconLoader::GetDefault().LoadFromGIconString(icon_name, icon_size,
+ sigc::bind(sigc::mem_fun(this, &Impl::ShowNotificationWhenIconIsReady), volume_name));
+ }
+
+ void ShowNotificationWhenIconIsReady(std::string const& icon_name,
+ unsigned size,
+ glib::Object<GdkPixbuf> const& pixbuf,
+ std::string const& volume_name)
+ {
+ glib::Object<NotifyNotification> notification(notify_notification_new(volume_name.c_str(),
+ _("The drive has been successfully ejected"),
+ nullptr));
+
+ notify_notification_set_hint(notification, "x-canonical-private-synchronous", g_variant_new_boolean(TRUE));
+
+ if (GDK_IS_PIXBUF(pixbuf.RawPtr()))
+ notify_notification_set_image_from_pixbuf(notification, pixbuf);
+
+ notify_notification_show(notification, nullptr);
+ }
+};
+
+//
+// End private implementation
+//
+
+DeviceNotificationDisplayImp::DeviceNotificationDisplayImp()
+ : pimpl(new Impl)
+{}
+
+DeviceNotificationDisplayImp::~DeviceNotificationDisplayImp()
+{}
+
+void DeviceNotificationDisplayImp::Display(std::string const& icon_name, std::string const& volume_name)
+{
+ pimpl->Show(icon_name, volume_name);
+}
+
+}
+}
diff --git a/launcher/DeviceNotificationDisplayImp.h b/launcher/DeviceNotificationDisplayImp.h
new file mode 100644
index 000000000..910951b15
--- /dev/null
+++ b/launcher/DeviceNotificationDisplayImp.h
@@ -0,0 +1,46 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_IMP_H
+#define UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_IMP_H
+
+#include "DeviceNotificationDisplay.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class DeviceNotificationDisplayImp : public DeviceNotificationDisplay
+{
+public:
+ DeviceNotificationDisplayImp();
+ virtual ~DeviceNotificationDisplayImp();
+
+ virtual void Display(std::string const& icon_name, std::string const& volume_name);
+
+private:
+ class Impl;
+ std::unique_ptr<Impl> pimpl;
+};
+
+}
+}
+
+#endif
diff --git a/launcher/DevicesSettings.cpp b/launcher/DevicesSettings.cpp
deleted file mode 100644
index 7b09bf070..000000000
--- a/launcher/DevicesSettings.cpp
+++ /dev/null
@@ -1,143 +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: Andrea Azzarone <aazzarone@hotmail.it>
- */
-
-#include "DevicesSettings.h"
-
-#include <algorithm>
-
-namespace unity {
-
-namespace {
-
-const char* SETTINGS_NAME = "com.canonical.Unity.Devices";
-
-void on_settings_updated(GSettings* settings,
- const gchar* key,
- DevicesSettings* self);
-
-} // anonymous namespace
-
-DevicesSettings& DevicesSettings::GetDefault()
-{
- static DevicesSettings instance;
- return instance;
-}
-
-DevicesSettings::DevicesSettings()
- : settings_(g_settings_new(SETTINGS_NAME))
- , ignore_signals_(false)
- , devices_option_(ONLY_MOUNTED)
-{
-
- g_signal_connect(settings_, "changed", G_CALLBACK(on_settings_updated), this);
-
- Refresh();
-}
-
-void DevicesSettings::Refresh()
-{
- gchar** favs = g_settings_get_strv(settings_, "favorites");
-
- favorites_.clear();
-
- for (int i = 0; favs[i] != NULL; i++)
- favorites_.push_back(favs[i]);
-
- g_strfreev(favs);
-}
-
-void DevicesSettings::AddFavorite(std::string const& uuid)
-{
- if (uuid.empty())
- return;
-
- favorites_.push_back(uuid);
-
- SaveFavorites(favorites_);
- Refresh();
-}
-
-void DevicesSettings::RemoveFavorite(std::string const& uuid)
-{
- if (uuid.empty())
- return;
-
- DeviceList::iterator pos = std::find(favorites_.begin(), favorites_.end(), uuid);
- if (pos == favorites_.end())
- return;
-
- favorites_.erase(pos);
- SaveFavorites(favorites_);
- Refresh();
-}
-
-void DevicesSettings::SaveFavorites(DeviceList const& favorites)
-{
- const int size = favorites.size();
- const char* favs[size + 1];
- favs[size] = NULL;
-
- int index = 0;
- for (DeviceList::const_iterator i = favorites.begin(), end = favorites.end();
- i != end; ++i, ++index)
- {
- favs[index] = i->c_str();
- }
-
- ignore_signals_ = true;
- if (!g_settings_set_strv(settings_, "favorites", favs))
- g_warning("Saving favorites failed.");
- ignore_signals_ = false;
-}
-
-
-void DevicesSettings::Changed(std::string const& key)
-{
- if (ignore_signals_)
- return;
-
- Refresh();
-
- changed.emit();
-}
-
-void DevicesSettings::SetDevicesOption(DevicesOption devices_option)
-{
- if (devices_option == devices_option_)
- return;
-
- devices_option_ = devices_option;
-
- changed.emit();
-}
-
-namespace {
-
-void on_settings_updated(GSettings* settings,
- const gchar* key,
- DevicesSettings* self)
-{
- if (settings and key) {
- self->Changed(key);
- }
-}
-
-} // anonymous namespace
-
-} // namespace unity
diff --git a/launcher/DevicesSettings.h b/launcher/DevicesSettings.h
index ad2a24de8..8dda12fc8 100644
--- a/launcher/DevicesSettings.h
+++ b/launcher/DevicesSettings.h
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2010 Canonical Ltd
+ * Copyright (C) 2010-12 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
@@ -14,61 +14,39 @@
* 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: Andrea Azzarone <aazzarone@hotmail.it>
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
*/
-#ifndef DEVICES_SETTINGS_H
-#define DEVICES_SETTINGS_H
+#ifndef UNITYSHELL_DEVICES_SETTINGS_H
+#define UNITYSHELL_DEVICES_SETTINGS_H
-#include <list>
+#include <boost/noncopyable.hpp>
+#include <memory>
#include <string>
-#include <gio/gio.h>
-#include <boost/utility.hpp>
-#include <sigc++/sigc++.h>
-#include <UnityCore/GLibWrapper.h>
+#include <sigc++/signal.h>
+#include <sigc++/trackable.h>
-namespace unity {
-
-typedef std::list<std::string> DeviceList;
+namespace unity
+{
+namespace launcher
+{
-class DevicesSettings : boost::noncopyable
+class DevicesSettings : boost::noncopyable, public sigc::trackable
{
public:
- typedef enum
- {
- NEVER = 0,
- ONLY_MOUNTED,
- ALWAYS
+ typedef std::shared_ptr<DevicesSettings> Ptr;
- } DevicesOption;
+ virtual ~DevicesSettings() {};
- DevicesSettings();
-
- static DevicesSettings& GetDefault();
+ virtual bool IsABlacklistedDevice(std::string const& uuid) const = 0;
+ virtual void TryToBlacklist(std::string const& uuid) = 0;
+ virtual void TryToUnblacklist(std::string const& uuid) = 0;
- void SetDevicesOption(DevicesOption devices_option);
- DevicesOption GetDevicesOption() { return devices_option_; };
-
- DeviceList const& GetFavorites() { return favorites_; };
- void AddFavorite(std::string const& uuid);
- void RemoveFavorite(std::string const& uuid);
-
- void Changed(std::string const& key);
-
- // Signals
sigc::signal<void> changed;
-
-private:
- void Refresh();
- void SaveFavorites(DeviceList const& favorites);
-
- glib::Object<GSettings> settings_;
- DeviceList favorites_;
- bool ignore_signals_;
- DevicesOption devices_option_;
};
-} // namespace unity
+}
+}
-#endif // DEVICES_SETTINGS_H
+#endif
diff --git a/launcher/DevicesSettingsImp.cpp b/launcher/DevicesSettingsImp.cpp
new file mode 100644
index 000000000..7933cd524
--- /dev/null
+++ b/launcher/DevicesSettingsImp.cpp
@@ -0,0 +1,151 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2010-12 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: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#include <list>
+
+#include <gio/gio.h>
+#include <NuxCore/Logger.h>
+
+#include "DevicesSettingsImp.h"
+#include <UnityCore/GLibSignal.h>
+#include <UnityCore/GLibWrapper.h>
+
+namespace unity
+{
+namespace launcher
+{
+namespace
+{
+
+nux::logging::Logger logger("unity.device.settings");
+
+const std::string SETTINGS_NAME = "com.canonical.Unity.Devices";
+const std::string KEY_NAME = "blacklist";
+
+}
+
+//
+// Start private implementation
+//
+class DevicesSettingsImp::Impl
+{
+public:
+ Impl(DevicesSettingsImp* parent)
+ : parent_(parent)
+ , settings_(g_settings_new(SETTINGS_NAME.c_str()))
+ {
+ DownloadBlacklist();
+ ConnectSignals();
+ }
+
+ void ConnectSignals()
+ {
+ settings_changed_signal_.Connect(settings_, "changed::" + KEY_NAME, [this] (GSettings*, gchar*) {
+ DownloadBlacklist();
+ parent_->changed.emit();
+ });
+ }
+
+ void DownloadBlacklist()
+ {
+ std::shared_ptr<gchar*> downloaded_blacklist(g_settings_get_strv(settings_, KEY_NAME.c_str()), g_strfreev);
+
+ blacklist_.clear();
+
+ auto downloaded_blacklist_raw = downloaded_blacklist.get();
+ for (int i = 0; downloaded_blacklist_raw[i]; ++i)
+ blacklist_.push_back(downloaded_blacklist_raw[i]);
+ }
+
+ void UploadBlacklist()
+ {
+ const int size = blacklist_.size();
+ const char* blacklist_to_be_uploaded[size+1];
+
+ int index = 0;
+ for (auto item : blacklist_)
+ blacklist_to_be_uploaded[index++] = item.c_str();
+ blacklist_to_be_uploaded[index] = nullptr;
+
+ if (!g_settings_set_strv(settings_, KEY_NAME.c_str(), blacklist_to_be_uploaded))
+ {
+ LOG_WARNING(logger) << "Saving blacklist failed.";
+ }
+ }
+
+ bool IsABlacklistedDevice(std::string const& uuid) const
+ {
+ auto begin = std::begin(blacklist_);
+ auto end = std::end(blacklist_);
+ return std::find(begin, end, uuid) != end;
+ }
+
+ void TryToBlacklist(std::string const& uuid)
+ {
+ if (uuid.empty() || IsABlacklistedDevice(uuid))
+ return;
+
+ blacklist_.push_back(uuid);
+ UploadBlacklist();
+ }
+
+ void TryToUnblacklist(std::string const& uuid)
+ {
+ if (uuid.empty() || !IsABlacklistedDevice(uuid))
+ return;
+
+ blacklist_.remove(uuid);
+ UploadBlacklist();
+ }
+
+ DevicesSettingsImp* parent_;
+ glib::Object<GSettings> settings_;
+ std::list<std::string> blacklist_;
+ glib::Signal<void, GSettings*, gchar*> settings_changed_signal_;
+
+};
+
+//
+// End private implementation
+//
+
+DevicesSettingsImp::DevicesSettingsImp()
+ : pimpl(new Impl(this))
+{}
+
+DevicesSettingsImp::~DevicesSettingsImp()
+{}
+
+bool DevicesSettingsImp::IsABlacklistedDevice(std::string const& uuid) const
+{
+ return pimpl->IsABlacklistedDevice(uuid);
+}
+
+void DevicesSettingsImp::TryToBlacklist(std::string const& uuid)
+{
+ pimpl->TryToBlacklist(uuid);
+}
+
+void DevicesSettingsImp::TryToUnblacklist(std::string const& uuid)
+{
+ pimpl->TryToUnblacklist(uuid);
+}
+
+} // namespace launcher
+} // namespace unity
diff --git a/launcher/DevicesSettingsImp.h b/launcher/DevicesSettingsImp.h
new file mode 100644
index 000000000..658ed4f71
--- /dev/null
+++ b/launcher/DevicesSettingsImp.h
@@ -0,0 +1,50 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITYSHELL_DEVICES_SETTINGS_IMP_H
+#define UNITYSHELL_DEVICES_SETTINGS_IMP_H
+
+#include "DevicesSettings.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class DevicesSettingsImp : public DevicesSettings
+{
+public:
+ typedef std::shared_ptr<DevicesSettingsImp> Ptr;
+
+ DevicesSettingsImp();
+ virtual ~DevicesSettingsImp();
+
+ virtual bool IsABlacklistedDevice(std::string const& uuid) const;
+ virtual void TryToBlacklist(std::string const& uuid);
+ virtual void TryToUnblacklist(std::string const& uuid);
+
+private:
+ class Impl;
+ std::unique_ptr<Impl> pimpl;
+};
+
+}
+}
+
+#endif
diff --git a/launcher/EdgeBarrierController.cpp b/launcher/EdgeBarrierController.cpp
index 8bfa1ebac..4f549cc3d 100644
--- a/launcher/EdgeBarrierController.cpp
+++ b/launcher/EdgeBarrierController.cpp
@@ -155,6 +155,12 @@ void EdgeBarrierController::Impl::SetupBarriers(std::vector<nux::Geometry> const
void EdgeBarrierController::Impl::OnPointerBarrierEvent(PointerBarrierWrapper* owner, BarrierEvent::Ptr event)
{
+ if (owner->released)
+ {
+ BarrierRelease(owner, event->event_id);
+ return;
+ }
+
unsigned int monitor = owner->index;
bool process = true;
@@ -166,11 +172,7 @@ void EdgeBarrierController::Impl::OnPointerBarrierEvent(PointerBarrierWrapper* o
process = false;
}
- if (process && owner->released)
- {
- BarrierRelease(owner, event->event_id);
- }
- else if (process && owner->x1 > 0)
+ if (process && owner->x1 > 0)
{
decaymulator_.value = decaymulator_.value + event->velocity;
diff --git a/launcher/FileManagerOpener.h b/launcher/FileManagerOpener.h
new file mode 100644
index 000000000..a318930bc
--- /dev/null
+++ b/launcher/FileManagerOpener.h
@@ -0,0 +1,45 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITYSHELL_FILEMANAGER_OPENER_H
+#define UNITYSHELL_FILEMANAGER_OPENER_H
+
+#include <boost/noncopyable.hpp>
+#include <memory>
+#include <string>
+
+namespace unity
+{
+namespace launcher
+{
+
+class FileManagerOpener : private boost::noncopyable
+{
+public:
+ typedef std::shared_ptr<FileManagerOpener> Ptr;
+
+ virtual ~FileManagerOpener() {}
+
+ virtual void Open(std::string const& uri) = 0;
+};
+
+}
+}
+
+#endif
diff --git a/launcher/FileManagerOpenerImp.cpp b/launcher/FileManagerOpenerImp.cpp
new file mode 100644
index 000000000..8fb2cd964
--- /dev/null
+++ b/launcher/FileManagerOpenerImp.cpp
@@ -0,0 +1,35 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#include <gio/gio.h>
+
+#include "FileManagerOpenerImp.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+void FileManagerOpenerImp::Open(std::string const& uri)
+{
+ g_app_info_launch_default_for_uri(uri. c_str(), nullptr, nullptr);
+}
+
+}
+}
diff --git a/launcher/FileManagerOpenerImp.h b/launcher/FileManagerOpenerImp.h
new file mode 100644
index 000000000..6a4d62562
--- /dev/null
+++ b/launcher/FileManagerOpenerImp.h
@@ -0,0 +1,39 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITYSHELL_FILEMANAGER_OPENER_IMP_H
+#define UNITYSHELL_FILEMANAGER_OPENER_IMP_H
+
+#include "FileManagerOpener.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class FileManagerOpenerImp : public FileManagerOpener
+{
+public:
+ virtual void Open(std::string const& uri);
+};
+
+}
+}
+
+#endif
diff --git a/launcher/Launcher.cpp b/launcher/Launcher.cpp
index 2ed206db8..7afeced30 100644
--- a/launcher/Launcher.cpp
+++ b/launcher/Launcher.cpp
@@ -92,7 +92,6 @@ 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";
@@ -178,9 +177,8 @@ Launcher::Launcher(nux::BaseWindow* parent,
ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed));
WindowManager& plugin_adapter = *(WindowManager::Default());
- plugin_adapter.window_mapped.connect(sigc::mem_fun(this, &Launcher::OnWindowMapped));
- plugin_adapter.window_unmapped.connect(sigc::mem_fun(this, &Launcher::OnWindowUnmapped));
-
+ plugin_adapter.window_mapped.connect(sigc::hide(sigc::mem_fun(this, &Launcher::DndTimeoutSetup)));
+ plugin_adapter.window_unmapped.connect(sigc::hide(sigc::mem_fun(this, &Launcher::DndTimeoutSetup)));
plugin_adapter.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
plugin_adapter.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
plugin_adapter.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
@@ -215,7 +213,7 @@ Launcher::Launcher(nux::BaseWindow* parent,
launcher_sheen_ = cache.FindTexture("dash_sheen", 0, 0, cb);
launcher_pressure_effect_ = cache.FindTexture("launcher_pressure_effect", 0, 0, cb);
- options.changed.connect(sigc::mem_fun (this, &Launcher::OnOptionsChanged));
+ options.changed.connect(sigc::mem_fun(this, &Launcher::OnOptionsChanged));
}
/* Introspection */
@@ -955,7 +953,10 @@ float Launcher::DragLimiter(float x)
nux::Color FullySaturateColor (nux::Color color)
{
float max = std::max<float>(color.red, std::max<float>(color.green, color.blue));
- color = color * (1.0f / max);
+ if (max > 0.0f)
+ {
+ color = color * (1.0f / max);
+ }
return color;
}
@@ -1103,7 +1104,6 @@ void Launcher::RenderArgs(std::list<RenderArg> &launcher_args,
{
RenderArg arg;
AbstractLauncherIcon::Ptr icon = *it;
-
FillRenderArg(icon, arg, center, parent_abs_geo, folding_threshold, folded_size, folded_spacing,
autohide_offset, folded_z_distance, animation_neg_rads, current);
arg.colorify = colorify;
@@ -1394,27 +1394,6 @@ void Launcher::DndTimeoutSetup()
sources_.AddTimeout(200, cb_func, DND_CHECK_TIMEOUT);
}
-void Launcher::OnWindowMapped(guint32 xid)
-{
- //CompWindow* window = _screen->findWindow(xid);
- //if (window && window->type() | CompWindowTypeDndMask)
- //{
- DndTimeoutSetup();
- //}
-
- if (GetActionState() != ACTION_NONE)
- ResetMouseDragState();
-}
-
-void Launcher::OnWindowUnmapped(guint32 xid)
-{
- //CompWindow* window = _screen->findWindow(xid);
- //if (window && window->type() | CompWindowTypeDndMask)
- //{
- DndTimeoutSetup();
- //}
-}
-
void Launcher::OnPluginStateChanged()
{
_hide_machine.SetQuirk (LauncherHideMachine::EXPO_ACTIVE, WindowManager::Default ()->IsExpoActive ());
@@ -1428,21 +1407,9 @@ 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);
-
options->option_changed.connect(sigc::mem_fun(this, &Launcher::OnOptionChanged));
}
@@ -1473,26 +1440,9 @@ void Launcher::ConfigureBarrier()
void Launcher::SetHideMode(LauncherHideMode hidemode)
{
- if (hidemode != LAUNCHER_HIDE_NEVER)
- {
- _parent->InputWindowEnableStruts(false);
- }
- else
- {
- static bool first_time = true;
-
- _parent->EnableInputWindow(true, launcher::window_title, false, false);
-
- if (first_time && !sources_.GetSource(STRUT_HACK_TIMEOUT))
- {
- sources_.AddTimeout(1000, sigc::mem_fun(this, &Launcher::StrutHack), STRUT_HACK_TIMEOUT);
- first_time = false;
- }
-
- _parent->InputWindowEnableStruts(true);
- }
-
- _hide_machine.SetMode((LauncherHideMachine::HideMode) hidemode);
+ bool fixed_launcher = (hidemode == LAUNCHER_HIDE_NEVER);
+ _parent->InputWindowEnableStruts(fixed_launcher);
+ _hide_machine.SetMode(static_cast<LauncherHideMachine::HideMode>(hidemode));
EnsureAnimation();
}
@@ -1719,6 +1669,11 @@ LauncherModel::Ptr Launcher::GetModel() const
return _model;
}
+void Launcher::SetDevicesSettings(DevicesSettings::Ptr devices_settings)
+{
+ devices_settings_ = devices_settings;
+}
+
void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr selection)
{
nux::Geometry const& geo = GetGeometry();
@@ -1798,9 +1753,8 @@ void Launcher::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
if (_drag_icon && _render_drag_window)
{
RenderIconToTexture(GfxContext, _drag_icon, _offscreen_drag_texture);
- _drag_window->ShowWindow(true);
-
_render_drag_window = false;
+ ShowDragWindow();
}
// clear region
@@ -1995,9 +1949,7 @@ long Launcher::PostLayoutManagement(long LayoutResult)
void Launcher::OnDragWindowAnimCompleted()
{
- if (_drag_window)
- _drag_window->ShowWindow(false);
-
+ HideDragWindow();
EnsureAnimation();
}
@@ -2029,7 +1981,8 @@ void Launcher::StartIconDragRequest(int x, int y)
// FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
// on an internal Launcher property then
- if (drag_icon && _last_button_press == 1 && _model->IconHasSister(drag_icon))
+ bool can_drag = (_model->IconHasSister(drag_icon) || drag_icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE);
+ if (drag_icon && _last_button_press == 1 && can_drag)
{
SetActionState(ACTION_DRAG_ICON);
StartIconDrag(drag_icon);
@@ -2043,12 +1996,8 @@ void Launcher::StartIconDragRequest(int x, int y)
}
else
{
- _drag_icon = NULL;
- if (_drag_window)
- {
- _drag_window->ShowWindow(false);
- _drag_window = nullptr;
- }
+ _drag_icon = nullptr;
+ HideDragWindow();
}
}
@@ -2060,11 +2009,7 @@ void Launcher::StartIconDrag(AbstractLauncherIcon::Ptr icon)
_hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true);
_drag_icon = icon;
- if (_drag_window)
- {
- _drag_window->ShowWindow(false);
- }
-
+ HideDragWindow();
_offscreen_drag_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(_icon_size, _icon_size, 1, nux::BITFMT_R8G8B8A8);
_drag_window = new LauncherDragWindow(_offscreen_drag_texture);
@@ -2077,7 +2022,10 @@ void Launcher::EndIconDrag()
{
if (_drag_window)
{
- AbstractLauncherIcon::Ptr hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
+ AbstractLauncherIcon::Ptr hovered_icon;
+
+ if (!_drag_window->Cancelled())
+ hovered_icon = MouseIconIntersection(_mouse_position.x, _mouse_position.y);
if (hovered_icon && hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
{
@@ -2085,20 +2033,21 @@ void Launcher::EndIconDrag()
launcher_removerequest.emit(_drag_icon);
- _drag_window->ShowWindow(false);
+ HideDragWindow();
EnsureAnimation();
}
else
{
- _model->Save();
-
- _drag_window->SetAnimationTarget((int)(_drag_icon->GetCenter(monitor).x),
- (int)(_drag_icon->GetCenter(monitor).y));
- _drag_window->StartAnimation();
+ if (!_drag_window->Cancelled())
+ _model->Save();
if (_drag_window->on_anim_completed.connected())
_drag_window->on_anim_completed.disconnect();
_drag_window->on_anim_completed = _drag_window->anim_completed.connect(sigc::mem_fun(this, &Launcher::OnDragWindowAnimCompleted));
+
+ auto const& icon_center = _drag_icon->GetCenter(monitor);
+ _drag_window->SetAnimationTarget(icon_center.x, icon_center.y),
+ _drag_window->StartAnimation();
}
}
@@ -2111,61 +2060,87 @@ void Launcher::EndIconDrag()
ubus_.SendMessage(UBUS_LAUNCHER_ICON_END_DND);
}
+void Launcher::ShowDragWindow()
+{
+ if (!_drag_window || _drag_window->IsVisible())
+ return;
+
+ _drag_window->GrabKeyboard();
+ _drag_window->ShowWindow(true);
+ _drag_window->PushToFront();
+
+ bool is_before;
+ AbstractLauncherIcon::Ptr const& closer = _model->GetClosestIcon(_drag_icon, is_before);
+ _drag_window->drag_cancel_request.connect([this, closer, is_before] {
+ if (is_before)
+ _model->ReorderAfter(_drag_icon, closer);
+ else
+ _model->ReorderBefore(_drag_icon, closer, true);
+
+ ResetMouseDragState();
+ });
+}
+
+void Launcher::HideDragWindow()
+{
+ if (!_drag_window)
+ return;
+
+ _drag_window->UnGrabKeyboard();
+ _drag_window->ShowWindow(false);
+ _drag_window = nullptr;
+}
+
void Launcher::UpdateDragWindowPosition(int x, int y)
{
- if (_drag_window)
- {
- nux::Geometry const& geo = _drag_window->GetGeometry();
- _drag_window->SetBaseXY(x - geo.width / 2, y - geo.height / 2);
+ if (!_drag_window)
+ return;
+
+ auto const& icon_geo = _drag_window->GetGeometry();
+ _drag_window->SetBaseXY(x - icon_geo.width / 2, y - icon_geo.height / 2);
+
+ if (!_drag_icon)
+ return;
+
+ auto const& launcher_geo = GetGeometry();
+ auto hovered_icon = MouseIconIntersection((launcher_geo.x + launcher_geo.width) / 2.0, y - GetAbsoluteY());
+ struct timespec current;
+ clock_gettime(CLOCK_MONOTONIC, &current);
+ float progress = DragThresholdProgress(current);
- AbstractLauncherIcon::Ptr hovered_icon = MouseIconIntersection((int)((GetGeometry().x + GetGeometry().width) / 2.0f), y - GetAbsoluteGeometry().y);
+ // Icons of different types can't be mixed, so let's avoid this.
+ if (hovered_icon && hovered_icon->GetIconType() != _drag_icon->GetIconType())
+ hovered_icon = nullptr;
- struct timespec current;
- clock_gettime(CLOCK_MONOTONIC, &current);
- if (_drag_icon && hovered_icon && _drag_icon != hovered_icon)
+ if (hovered_icon && _drag_icon != hovered_icon)
+ {
+ if (progress >= 1.0f)
{
- float progress = DragThresholdProgress(current);
-
- if (progress >= 1.0f)
- _model->ReorderSmart(_drag_icon, hovered_icon, true);
- else if (progress == 0.0f) {
- if (_drag_icon->GetIconType() == hovered_icon->GetIconType()) {
- _model->ReorderBefore(_drag_icon, hovered_icon, false);
- } else {
- // LauncherModel::ReorderBefore does not work on different icon types
- // so if hovered_icon is of a different type than _drag_icon
- // try to use LauncherModel::ReorderAfter with the icon that is before hovered_icon
- AbstractLauncherIcon::Ptr iconBeforeHover;
- LauncherModel::iterator it;
- LauncherModel::iterator prevIt = _model->end();
- for (it = _model->begin(); it != _model->end(); ++it)
- {
- if (!(*it)->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) || !(*it)->IsVisibleOnMonitor(monitor))
- continue;
-
- if ((*it) == hovered_icon) {
- if (prevIt != _model->end()) {
- iconBeforeHover = *prevIt;
- }
- break;
- }
-
- prevIt = it;
- }
-
- if (iconBeforeHover && _drag_icon != iconBeforeHover) {
- _model->ReorderAfter(_drag_icon, iconBeforeHover);
- }
- }
- }
+ _model->ReorderSmart(_drag_icon, hovered_icon, true);
+ }
+ else if (progress == 0.0f)
+ {
+ _model->ReorderBefore(_drag_icon, hovered_icon, false);
+ }
+ }
+ else if (!hovered_icon && progress == 0.0f)
+ {
+ // If no icon is hovered, then we can add our icon to the bottom
+ for (auto it = _model->main_rbegin(); it != _model->main_rend(); ++it)
+ {
+ auto const& icon = *it;
- if (progress >= 1.0f)
+ if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) ||
+ !icon->IsVisibleOnMonitor(monitor) ||
+ icon->GetIconType() != _drag_icon->GetIconType())
{
- _model->ReorderSmart(_drag_icon, hovered_icon, true);
+ continue;
}
- else if (progress == 0.0f)
+
+ if (y >= icon->GetCenter(monitor).y)
{
- _model->ReorderBefore(_drag_icon, hovered_icon, false);
+ _model->ReorderAfter(_drag_icon, icon);
+ break;
}
}
}
@@ -2581,7 +2556,7 @@ void Launcher::OnDNDDataCollected(const std::list<char*>& mimes)
for (auto it : _dnd_data.Uris())
{
- if (g_str_has_suffix(it.c_str(), ".desktop"))
+ if (g_str_has_suffix(it.c_str(), ".desktop") || g_str_has_prefix(it.c_str(), "device://"))
{
_steal_drag = true;
break;
@@ -2631,7 +2606,18 @@ void Launcher::DndReset()
for (auto it : *_model)
{
- it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, is_overlay_open);
+ auto icon_type = it->GetIconType();
+
+ if (icon_type == AbstractLauncherIcon::IconType::HOME ||
+ icon_type == AbstractLauncherIcon::IconType::HUD)
+ {
+ it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
+ }
+ else
+ {
+ it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, is_overlay_open && !_hovered);
+ }
+
it->SetQuirk(AbstractLauncherIcon::Quirk::PRESENTED, false);
}
@@ -2686,7 +2672,7 @@ void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes)
// see if the launcher wants this one
for (auto it : _dnd_data.Uris())
{
- if (g_str_has_suffix(it.c_str(), ".desktop"))
+ if (g_str_has_suffix(it.c_str(), ".desktop") || g_str_has_prefix(it.c_str(), "device://"))
{
_steal_drag = true;
break;
@@ -2824,6 +2810,11 @@ void Launcher::ProcessDndDrop(int x, int y)
g_free(path);
}
}
+ else if (devices_settings_ && g_str_has_prefix(it.c_str(), "device://"))
+ {
+ const gchar* uuid = it.c_str() + 9;
+ devices_settings_->TryToUnblacklist(uuid);
+ }
}
}
else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)
diff --git a/launcher/Launcher.h b/launcher/Launcher.h
index 04524bd35..b4b1dad00 100644
--- a/launcher/Launcher.h
+++ b/launcher/Launcher.h
@@ -30,6 +30,7 @@
#include "PointerBarrier.h"
#include "unity-shared/AbstractIconRenderer.h"
#include "unity-shared/BackgroundEffectHelper.h"
+#include "DevicesSettings.h"
#include "DNDCollectionWindow.h"
#include "DndData.h"
#include "EdgeBarrierController.h"
@@ -82,6 +83,8 @@ public:
void SetModel(LauncherModel::Ptr model);
LauncherModel::Ptr GetModel() const;
+ void SetDevicesSettings(DevicesSettings::Ptr devices_settings);
+
void StartKeyShowLauncher();
void EndKeyShowLauncher();
@@ -185,9 +188,6 @@ private:
void OnOptionChanged();
void UpdateOptions(Options::Ptr options);
- void OnWindowMapped(guint32 xid);
- void OnWindowUnmapped(guint32 xid);
-
void OnDragStart(const nux::GestureEvent &event);
void OnDragUpdate(const nux::GestureEvent &event);
void OnDragFinish(const nux::GestureEvent &event);
@@ -291,7 +291,7 @@ private:
void OnActionDone(GVariant* data);
- AbstractLauncherIcon::Ptr MouseIconIntersection(int x, int y);
+ virtual AbstractLauncherIcon::Ptr MouseIconIntersection(int x, int y);
void EventLogic();
void MouseDownLogic(int x, int y, unsigned long button_flags, unsigned long key_flags);
void MouseUpLogic(int x, int y, unsigned long button_flags, unsigned long key_flags);
@@ -299,7 +299,9 @@ private:
void StartIconDragRequest(int x, int y);
void StartIconDrag(AbstractLauncherIcon::Ptr icon);
void EndIconDrag();
+ void ShowDragWindow();
void UpdateDragWindowPosition(int x, int y);
+ void HideDragWindow();
void ResetMouseDragState();
@@ -393,6 +395,8 @@ private:
ui::AbstractIconRenderer::Ptr icon_renderer;
BackgroundEffectHelper bg_effect_helper_;
+ DevicesSettings::Ptr devices_settings_;
+
UBusManager ubus_;
glib::SourceManager sources_;
diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp
index 87a3ce6e4..bcc372fcb 100644
--- a/launcher/LauncherController.cpp
+++ b/launcher/LauncherController.cpp
@@ -29,7 +29,7 @@
#include "LauncherOptions.h"
#include "BamfLauncherIcon.h"
#include "DesktopLauncherIcon.h"
-#include "DeviceLauncherIcon.h"
+#include "VolumeLauncherIcon.h"
#include "FavoriteStore.h"
#include "HudLauncherIcon.h"
#include "LauncherController.h"
@@ -95,7 +95,8 @@ Controller::Impl::Impl(Display* display, Controller* parent)
, model_(new LauncherModel())
, sort_priority_(0)
, volume_monitor_(new VolumeMonitorWrapper)
- , device_section_(volume_monitor_)
+ , devices_settings_(new DevicesSettingsImp)
+ , device_section_(volume_monitor_, devices_settings_)
, show_desktop_icon_(false)
, display_(display)
, matcher_(bamf_matcher_get_default())
@@ -267,6 +268,7 @@ Launcher* Controller::Impl::CreateLauncher(int monitor)
launcher->monitor = monitor;
launcher->options = parent_->options();
launcher->SetModel(model_);
+ launcher->SetDevicesSettings(devices_settings_);
nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
layout->AddView(launcher, 1);
@@ -278,7 +280,7 @@ Launcher* Controller::Impl::CreateLauncher(int monitor)
launcher_window->SetBackgroundColor(nux::color::Transparent);
launcher_window->ShowWindow(true);
launcher_window->EnableInputWindow(true, launcher::window_title, false, false);
- launcher_window->InputWindowEnableStruts(false);
+ launcher_window->InputWindowEnableStruts(parent_->options()->hide_mode == LAUNCHER_HIDE_NEVER);
launcher_window->SetEnterFocusInputArea(launcher);
launcher->launcher_addrequest.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest));
@@ -424,10 +426,10 @@ void Controller::Impl::OnLauncherRemoveRequest(AbstractLauncherIcon::Ptr icon)
}
case AbstractLauncherIcon::IconType::DEVICE:
{
- DeviceLauncherIcon* device_icon = dynamic_cast<DeviceLauncherIcon*>(icon.GetPointer());
+ auto device_icon = dynamic_cast<VolumeLauncherIcon*>(icon.GetPointer());
if (device_icon && device_icon->CanEject())
- device_icon->Eject();
+ device_icon->EjectAndShowNotification();
else if (device_icon && device_icon->CanStop())
device_icon->StopDrive();
@@ -686,10 +688,6 @@ void Controller::Impl::SetupBamf()
GList* apps, *l;
BamfApplication* app;
- // Sufficiently large number such that we ensure proper sorting
- // (avoids case where first item gets tacked onto end rather than start)
- int priority = 100;
-
FavoriteList const& favs = FavoriteStore::Instance().GetFavorites();
for (FavoriteList::const_iterator i = favs.begin(), end = favs.end();
@@ -699,9 +697,8 @@ void Controller::Impl::SetupBamf()
if (fav)
{
- fav->SetSortPriority(priority);
+ fav->SetSortPriority(sort_priority_++);
RegisterIcon(fav);
- priority++;
}
}
diff --git a/launcher/LauncherController.h b/launcher/LauncherController.h
index 3e5dec6b0..e18f2cae2 100644
--- a/launcher/LauncherController.h
+++ b/launcher/LauncherController.h
@@ -32,6 +32,7 @@ namespace unity
{
namespace launcher
{
+
class AbstractLauncherIcon;
class Launcher;
class LauncherModel;
diff --git a/launcher/LauncherControllerPrivate.h b/launcher/LauncherControllerPrivate.h
index 2eb1a1f9a..cd730a37e 100644
--- a/launcher/LauncherControllerPrivate.h
+++ b/launcher/LauncherControllerPrivate.h
@@ -27,6 +27,7 @@
#include "AbstractLauncherIcon.h"
#include "DeviceLauncherSection.h"
+#include "DevicesSettingsImp.h"
#include "EdgeBarrierController.h"
#include "LauncherController.h"
#include "Launcher.h"
@@ -126,6 +127,7 @@ public:
nux::ObjectPtr<Launcher> keyboard_launcher_;
int sort_priority_;
AbstractVolumeMonitorWrapper::Ptr volume_monitor_;
+ DevicesSettingsImp::Ptr devices_settings_;
DeviceLauncherSection device_section_;
LauncherEntryRemoteModel remote_model_;
AbstractLauncherIcon::Ptr expo_icon_;
diff --git a/launcher/LauncherDragWindow.cpp b/launcher/LauncherDragWindow.cpp
index b78e84132..53334ab89 100644
--- a/launcher/LauncherDragWindow.cpp
+++ b/launcher/LauncherDragWindow.cpp
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
-* Copyright (C) 2010 Canonical Ltd
+* Copyright (C) 2010-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Jason Smith <jason.smith@canonical.com>
+* Marco Trevisan <marco.trevisan@canonical.com>
*/
#include <Nux/Nux.h>
@@ -23,6 +24,7 @@
#include <Nux/TextureArea.h>
#include "LauncherDragWindow.h"
+#include "unity-shared/WindowManager.h"
namespace unity
{
@@ -33,22 +35,45 @@ NUX_IMPLEMENT_OBJECT_TYPE(LauncherDragWindow);
LauncherDragWindow::LauncherDragWindow(nux::ObjectPtr<nux::IOpenGLBaseTexture> icon)
: nux::BaseWindow("")
+ , _cancelled(false)
, _icon(icon)
{
SetBaseSize(_icon->GetWidth(), _icon->GetHeight());
+
+ key_down.connect([this] (unsigned long, unsigned long keysym, unsigned long, const char*, unsigned short) {
+ if (keysym == NUX_VK_ESCAPE)
+ CancelDrag();
+ });
+
+ auto wm = WindowManager::Default();
+ wm->window_mapped.connect(sigc::hide(sigc::mem_fun(this, &LauncherDragWindow::CancelDrag)));
+ wm->window_unmapped.connect(sigc::hide(sigc::mem_fun(this, &LauncherDragWindow::CancelDrag)));
}
LauncherDragWindow::~LauncherDragWindow()
{
if (on_anim_completed.connected())
on_anim_completed.disconnect();
+
+ UnGrabKeyboard();
}
-bool LauncherDragWindow::Animating()
+bool LauncherDragWindow::Animating() const
{
return bool(animation_timer_);
}
+bool LauncherDragWindow::Cancelled() const
+{
+ return _cancelled;
+}
+
+void LauncherDragWindow::CancelDrag()
+{
+ _cancelled = true;
+ drag_cancel_request.emit();
+}
+
void LauncherDragWindow::SetAnimationTarget(int x, int y)
{
_animation_target = nux::Point2(x, y);
@@ -86,8 +111,8 @@ bool LauncherDragWindow::OnAnimationTimeout()
if (new_geo.x == target_x && new_geo.y == target_y)
{
- anim_completed.emit();
animation_timer_.reset();
+ anim_completed.emit();
return false;
}
@@ -118,5 +143,15 @@ LauncherDragWindow::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw
GfxContext.PopClippingRectangle();
}
+bool LauncherDragWindow::InspectKeyEvent(unsigned int event_type, unsigned int keysym, const char* character)
+{
+ return (event_type == nux::NUX_KEYDOWN);
+}
+
+bool LauncherDragWindow::AcceptKeyNavFocus()
+{
+ return true;
+}
+
} // namespace launcher
} // namespace unity
diff --git a/launcher/LauncherDragWindow.h b/launcher/LauncherDragWindow.h
index 51041d36c..cda37d342 100644
--- a/launcher/LauncherDragWindow.h
+++ b/launcher/LauncherDragWindow.h
@@ -37,7 +37,6 @@ class LauncherDragWindow : public nux::BaseWindow
NUX_DECLARE_OBJECT_TYPE(LauncherDragWindow, nux::BaseWindow);
public:
LauncherDragWindow(nux::ObjectPtr<nux::IOpenGLBaseTexture> icon);
-
~LauncherDragWindow();
void DrawContent(nux::GraphicsEngine& gfxContext, bool forceDraw);
@@ -45,14 +44,22 @@ public:
void SetAnimationTarget(int x, int y);
void StartAnimation();
- bool Animating();
+ bool Animating() const;
+ bool Cancelled() const;
sigc::signal<void> anim_completed;
+ sigc::signal<void> drag_cancel_request;
sigc::connection on_anim_completed;
+protected:
+ bool InspectKeyEvent(unsigned int event_type, unsigned int keysym, const char* character);
+ bool AcceptKeyNavFocus();
+
private:
bool OnAnimationTimeout();
+ void CancelDrag();
+ bool _cancelled;
nux::ObjectPtr<nux::IOpenGLBaseTexture> _icon;
nux::Point2 _animation_target;
glib::Source::UniquePtr animation_timer_;
diff --git a/launcher/LauncherModel.cpp b/launcher/LauncherModel.cpp
index 15583508b..8e01465dd 100644
--- a/launcher/LauncherModel.cpp
+++ b/launcher/LauncherModel.cpp
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2010 Canonical Ltd
+ * Copyright (C) 2010-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Jason Smith <jason.smith@canonical.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
#include "LauncherModel.h"
@@ -30,8 +31,7 @@ namespace launcher
LauncherModel::LauncherModel()
: selection_(0)
-{
-}
+{}
std::string LauncherModel::GetName() const
{
@@ -54,12 +54,12 @@ unity::debug::Introspectable::IntrospectableList LauncherModel::GetIntrospectabl
return introspection_results_;
}
-bool LauncherModel::IconShouldShelf(AbstractLauncherIcon::Ptr icon) const
+bool LauncherModel::IconShouldShelf(AbstractLauncherIcon::Ptr const& icon) const
{
return icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH;
}
-bool LauncherModel::CompareIcons(AbstractLauncherIcon::Ptr first, AbstractLauncherIcon::Ptr second)
+bool LauncherModel::CompareIcons(AbstractLauncherIcon::Ptr const& first, AbstractLauncherIcon::Ptr const& second)
{
if (first->GetIconType() < second->GetIconType())
return true;
@@ -69,36 +69,43 @@ bool LauncherModel::CompareIcons(AbstractLauncherIcon::Ptr first, AbstractLaunch
return first->SortPriority() < second->SortPriority();
}
-bool
-LauncherModel::Populate()
+void LauncherModel::PopulatePart(iterator begin, iterator end)
{
- Base copy = _inner;
-
- _inner.clear();
+ AbstractLauncherIcon::Ptr prev_icon;
+ for (auto it = begin; it != end; ++it)
+ {
+ auto const& icon = *it;
+ _inner.push_back(icon);
- iterator it, it2;
+ if (prev_icon)
+ {
+ // Ensuring that the current icon has higher priority than previous one
+ if (icon->SortPriority() < prev_icon->SortPriority())
+ {
+ int new_priority = prev_icon->SortPriority() + 1;
+ icon->SetSortPriority(new_priority);
+ }
+ }
- int i = 0;
- for (it = main_begin(); it != main_end(); ++it)
- {
- _inner.push_back(*it);
- (*it)->SetSortPriority(i);
- ++i;
+ prev_icon = icon;
}
+}
- for (it = shelf_begin(); it != shelf_end(); ++it)
- {
- _inner.push_back(*it);
- (*it)->SetSortPriority(i);
- ++i;
- }
+bool LauncherModel::Populate()
+{
+ Base copy = _inner;
+ _inner.clear();
+ PopulatePart(main_begin(), main_end());
+ PopulatePart(shelf_begin(), shelf_end());
return copy.size() == _inner.size() && !std::equal(begin(), end(), copy.begin());
}
-void
-LauncherModel::AddIcon(AbstractLauncherIcon::Ptr icon)
+void LauncherModel::AddIcon(AbstractLauncherIcon::Ptr const& icon)
{
+ if (!icon || std::find(begin(), end(), icon) != end())
+ return;
+
if (IconShouldShelf(icon))
_inner_shelf.push_back(icon);
else
@@ -113,8 +120,7 @@ LauncherModel::AddIcon(AbstractLauncherIcon::Ptr icon)
icon->on_icon_removed_connection = icon->remove.connect(sigc::mem_fun(this, &LauncherModel::OnIconRemove));
}
-void
-LauncherModel::RemoveIcon(AbstractLauncherIcon::Ptr icon)
+void LauncherModel::RemoveIcon(AbstractLauncherIcon::Ptr const& icon)
{
size_t size;
@@ -130,23 +136,20 @@ LauncherModel::RemoveIcon(AbstractLauncherIcon::Ptr icon)
}
}
-void
-LauncherModel::OnIconRemove(AbstractLauncherIcon::Ptr icon)
+void LauncherModel::OnIconRemove(AbstractLauncherIcon::Ptr const& icon)
{
- timeouts_.AddTimeout(1000, [&, icon] {
+ timeouts_.AddTimeout(1000, [this, icon] {
RemoveIcon(icon);
return false;
});
}
-void
-LauncherModel::Save()
+void LauncherModel::Save()
{
saved.emit();
}
-void
-LauncherModel::Sort()
+void LauncherModel::Sort()
{
std::stable_sort(_inner_shelf.begin(), _inner_shelf.end(), &LauncherModel::CompareIcons);
std::stable_sort(_inner_main.begin(), _inner_main.end(), &LauncherModel::CompareIcons);
@@ -155,15 +158,14 @@ LauncherModel::Sort()
order_changed.emit();
}
-bool
-LauncherModel::IconHasSister(AbstractLauncherIcon::Ptr icon) const
+bool LauncherModel::IconHasSister(AbstractLauncherIcon::Ptr const& icon) const
{
+ if (!icon)
+ return false;
+
const_iterator it;
const_iterator end;
- if (icon && icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
- return true;
-
if (IconShouldShelf(icon))
{
it = _inner_shelf.begin();
@@ -177,17 +179,16 @@ LauncherModel::IconHasSister(AbstractLauncherIcon::Ptr icon) const
for (; it != end; ++it)
{
- AbstractLauncherIcon::Ptr iter_icon = *it;
- if ((iter_icon != icon)
- && iter_icon->GetIconType() == icon->GetIconType())
+ AbstractLauncherIcon::Ptr const& iter_icon = *it;
+
+ if (iter_icon != icon && iter_icon->GetIconType() == icon->GetIconType())
return true;
}
return false;
}
-void
-LauncherModel::ReorderAfter(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other)
+void LauncherModel::ReorderAfter(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other)
{
if (icon == other || icon.IsNull() || other.IsNull())
return;
@@ -195,32 +196,20 @@ LauncherModel::ReorderAfter(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon
if (icon->GetIconType() != other->GetIconType())
return;
- int i = 0;
- for (LauncherModel::iterator it = begin(); it != end(); ++it)
- {
- if ((*it) == icon)
- continue;
+ icon->SetSortPriority(other->SortPriority() + 1);
- if ((*it) == other)
- {
- (*it)->SetSortPriority(i);
- ++i;
-
- icon->SetSortPriority(i);
- ++i;
- }
- else
- {
- (*it)->SetSortPriority(i);
- ++i;
- }
+ for (auto it = std::next(std::find(begin(), end(), other)); it != end(); ++it)
+ {
+ // Increasing the priority of the icons next to the other one
+ auto const& icon_it = *it;
+ int new_priority = icon_it->SortPriority() + 1;
+ icon_it->SetSortPriority(new_priority);
}
Sort();
}
-void
-LauncherModel::ReorderBefore(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other, bool save)
+void LauncherModel::ReorderBefore(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate)
{
if (icon == other || icon.IsNull() || other.IsNull())
return;
@@ -228,43 +217,45 @@ LauncherModel::ReorderBefore(AbstractLauncherIcon::Ptr icon, AbstractLauncherIco
if (icon->GetIconType() != other->GetIconType())
return;
- int i = 0;
- int j = 0;
- for (auto icon_it : _inner)
+ bool found_target = false;
+ bool center = false;
+
+ for (auto const& icon_it : _inner)
{
if (icon_it == icon)
{
- j++;
+ center = !center;
continue;
}
+ int new_priority = icon_it->SortPriority() + (found_target ? 1 : -1);
+ icon_it->SetSortPriority(new_priority);
+
if (icon_it == other)
{
- icon->SetSortPriority(i);
- if (i != j && save)
+ if (animate && center)
icon_it->SaveCenter();
- i++;
- icon_it->SetSortPriority(i);
- if (i != j && save)
+ center = !center;
+ new_priority = new_priority - 1;
+ icon->SetSortPriority(new_priority);
+
+ if (animate && center)
icon_it->SaveCenter();
- i++;
+
+ found_target = true;
}
else
{
- icon_it->SetSortPriority(i);
- if (i != j && save)
+ if (animate && center)
icon_it->SaveCenter();
- i++;
}
- j++;
}
Sort();
}
-void
-LauncherModel::ReorderSmart(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other, bool save)
+void LauncherModel::ReorderSmart(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate)
{
if (icon == other || icon.IsNull() || other.IsNull())
return;
@@ -272,49 +263,41 @@ LauncherModel::ReorderSmart(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon
if (icon->GetIconType() != other->GetIconType())
return;
- int i = 0;
- int j = 0;
- bool skipped = false;
- for (auto icon_it : _inner)
+ bool found_icon = false;
+ bool found_target = false;
+ bool center = false;
+
+ for (auto const& icon_it : _inner)
{
if (icon_it == icon)
{
- skipped = true;
- j++;
+ found_icon = true;
+ center = !center;
continue;
}
+ int new_priority = icon_it->SortPriority() + (found_target ? 1 : -1);
+ icon_it->SetSortPriority(new_priority);
+
if (icon_it == other)
{
- if (!skipped)
- {
- icon->SetSortPriority(i);
- if (i != j && save)
- icon_it->SaveCenter();
- i++;
- }
+ if (animate && center)
+ icon_it->SaveCenter();
+
+ center = !center;
+ new_priority = new_priority + (found_icon ? 1 : -1);
+ icon->SetSortPriority(new_priority);
- icon_it->SetSortPriority(i);
- if (i != j && save)
+ if (animate && center)
icon_it->SaveCenter();
- i++;
- if (skipped)
- {
- icon->SetSortPriority(i);
- if (i != j && save)
- icon_it->SaveCenter();
- i++;
- }
+ found_target = true;
}
else
{
- icon_it->SetSortPriority(i);
- if (i != j && save)
+ if (animate && center)
icon_it->SaveCenter();
- i++;
}
- j++;
}
Sort();
@@ -357,7 +340,7 @@ void LauncherModel::SelectNext()
if (temp >= Size())
temp = 0;
- if (_inner[temp]->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE))
+ if (_inner[temp]->IsVisible())
{
selection_ = temp;
selection_changed.emit(Selection());
@@ -377,7 +360,7 @@ void LauncherModel::SelectPrevious()
if (temp < 0)
temp = Size() - 1;
- if (_inner[temp]->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE))
+ if (_inner[temp]->IsVisible())
{
selection_ = temp;
selection_changed.emit(Selection());
@@ -387,23 +370,74 @@ void LauncherModel::SelectPrevious()
}
}
+AbstractLauncherIcon::Ptr LauncherModel::GetClosestIcon(AbstractLauncherIcon::Ptr const& icon, bool& is_before) const
+{
+ AbstractLauncherIcon::Ptr prev, next;
+ bool found_target = false;
+
+ for (auto const& current : _inner)
+ {
+ if (current->GetIconType() != icon->GetIconType())
+ continue;
+
+ if (!found_target)
+ {
+ if (current == icon)
+ {
+ found_target = true;
+
+ if (prev)
+ break;
+ }
+ else
+ {
+ prev = current;
+ }
+ }
+ else
+ {
+ next = current;
+ break;
+ }
+ }
+
+ is_before = next.IsNull();
+
+ return is_before ? prev : next;
+}
+
+int LauncherModel::IconIndex(AbstractLauncherIcon::Ptr const& target) const
+{
+ int pos = 0;
+ bool found = false;
+
+ for (auto const& icon : _inner)
+ {
+ if (icon == target)
+ {
+ found = true;
+ break;
+ }
+
+ ++pos;
+ }
+
+ return found ? pos : -1;
+}
/* iterators */
-LauncherModel::iterator
-LauncherModel::begin()
+LauncherModel::iterator LauncherModel::begin()
{
return _inner.begin();
}
-LauncherModel::iterator
-LauncherModel::end()
+LauncherModel::iterator LauncherModel::end()
{
return _inner.end();
}
-LauncherModel::iterator
-LauncherModel::at(int index)
+LauncherModel::iterator LauncherModel::at(int index)
{
LauncherModel::iterator it;
int i;
@@ -418,62 +452,52 @@ LauncherModel::at(int index)
return (LauncherModel::iterator)NULL;
}
-LauncherModel::reverse_iterator
-LauncherModel::rbegin()
+LauncherModel::reverse_iterator LauncherModel::rbegin()
{
return _inner.rbegin();
}
-LauncherModel::reverse_iterator
-LauncherModel::rend()
+LauncherModel::reverse_iterator LauncherModel::rend()
{
return _inner.rend();
}
-LauncherModel::iterator
-LauncherModel::main_begin()
+LauncherModel::iterator LauncherModel::main_begin()
{
return _inner_main.begin();
}
-LauncherModel::iterator
-LauncherModel::main_end()
+LauncherModel::iterator LauncherModel::main_end()
{
return _inner_main.end();
}
-LauncherModel::reverse_iterator
-LauncherModel::main_rbegin()
+LauncherModel::reverse_iterator LauncherModel::main_rbegin()
{
return _inner_main.rbegin();
}
-LauncherModel::reverse_iterator
-LauncherModel::main_rend()
+LauncherModel::reverse_iterator LauncherModel::main_rend()
{
return _inner_main.rend();
}
-LauncherModel::iterator
-LauncherModel::shelf_begin()
+LauncherModel::iterator LauncherModel::shelf_begin()
{
return _inner_shelf.begin();
}
-LauncherModel::iterator
-LauncherModel::shelf_end()
+LauncherModel::iterator LauncherModel::shelf_end()
{
return _inner_shelf.end();
}
-LauncherModel::reverse_iterator
-LauncherModel::shelf_rbegin()
+LauncherModel::reverse_iterator LauncherModel::shelf_rbegin()
{
return _inner_shelf.rbegin();
}
-LauncherModel::reverse_iterator
-LauncherModel::shelf_rend()
+LauncherModel::reverse_iterator LauncherModel::shelf_rend()
{
return _inner_shelf.rend();
}
diff --git a/launcher/LauncherModel.h b/launcher/LauncherModel.h
index e6295b6cf..19385e251 100644
--- a/launcher/LauncherModel.h
+++ b/launcher/LauncherModel.h
@@ -1,6 +1,6 @@
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
/*
- * Copyright (C) 2010 Canonical Ltd
+ * Copyright (C) 2010-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Jason Smith <jason.smith@canonical.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
#ifndef LAUNCHERMODEL_H
@@ -41,20 +42,18 @@ public:
LauncherModel();
- void AddIcon(AbstractLauncherIcon::Ptr icon);
- void RemoveIcon(AbstractLauncherIcon::Ptr icon);
+ void AddIcon(AbstractLauncherIcon::Ptr const& icon);
+ void RemoveIcon(AbstractLauncherIcon::Ptr const& icon);
void Save();
void Sort();
int Size() const;
- void OnIconRemove(AbstractLauncherIcon::Ptr icon);
+ bool IconHasSister(AbstractLauncherIcon::Ptr const& icon) const;
+ int IconIndex(AbstractLauncherIcon::Ptr const& icon) const;
- bool IconHasSister(AbstractLauncherIcon::Ptr icon) const;
-
- void ReorderAfter(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other);
- void ReorderBefore(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other, bool save);
-
- void ReorderSmart(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other, bool save);
+ void ReorderAfter(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other);
+ void ReorderBefore(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate);
+ void ReorderSmart(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate);
AbstractLauncherIcon::Ptr Selection() const;
int SelectionIndex() const;
@@ -62,6 +61,8 @@ public:
void SelectNext();
void SelectPrevious();
+ AbstractLauncherIcon::Ptr GetClosestIcon(AbstractLauncherIcon::Ptr const& icon, bool& is_before) const;
+
iterator begin();
iterator end();
iterator at(int index);
@@ -78,17 +79,17 @@ public:
reverse_iterator shelf_rbegin();
reverse_iterator shelf_rend();
- sigc::signal<void, AbstractLauncherIcon::Ptr> icon_added;
- sigc::signal<void, AbstractLauncherIcon::Ptr> icon_removed;
+ sigc::signal<void, AbstractLauncherIcon::Ptr const&> icon_added;
+ sigc::signal<void, AbstractLauncherIcon::Ptr const&> icon_removed;
+ sigc::signal<void, AbstractLauncherIcon::Ptr const&> selection_changed;
sigc::signal<void> order_changed;
sigc::signal<void> saved;
- sigc::signal<void, AbstractLauncherIcon::Ptr> selection_changed;
- IntrospectableList GetIntrospectableChildren();
protected:
// Introspectable methods
std::string GetName() const;
void AddProperties(GVariantBuilder* builder);
+ IntrospectableList GetIntrospectableChildren();
private:
Base _inner;
@@ -99,10 +100,10 @@ private:
glib::SourceManager timeouts_;
bool Populate();
-
- bool IconShouldShelf(AbstractLauncherIcon::Ptr icon) const;
-
- static bool CompareIcons(AbstractLauncherIcon::Ptr first, AbstractLauncherIcon::Ptr second);
+ void PopulatePart(iterator begin, iterator end);
+ void OnIconRemove(AbstractLauncherIcon::Ptr const& icon);
+ bool IconShouldShelf(AbstractLauncherIcon::Ptr const& icon) const;
+ static bool CompareIcons(AbstractLauncherIcon::Ptr const& first, AbstractLauncherIcon::Ptr const& second);
/* Template Methods */
public:
diff --git a/launcher/MockLauncherIcon.h b/launcher/MockLauncherIcon.h
index ba3f30ce4..b52cb272b 100644
--- a/launcher/MockLauncherIcon.h
+++ b/launcher/MockLauncherIcon.h
@@ -44,12 +44,12 @@ class MockLauncherIcon : public AbstractLauncherIcon
{
NUX_DECLARE_OBJECT_TYPE(MockLauncherIcon, AbstractLauncherIcon);
public:
- MockLauncherIcon()
- : icon_(0)
+ MockLauncherIcon(IconType type = IconType::APPLICATION)
+ : type_(type)
+ , sort_priority_(0)
+ , icon_(0)
{
tooltip_text = "Mock Icon";
- sort_priority_ = 0;
- type_ = IconType::APPLICATION;
for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i)
{
@@ -58,7 +58,7 @@ public:
}
std::string GetName() const { return "MockLauncherIcon"; }
-
+
void AddProperties(GVariantBuilder* builder) {}
void HideTooltip() {}
@@ -130,11 +130,16 @@ public:
return false;
}
- void SetCenter(nux::Point3 center, int monitor, nux::Geometry geo) {}
+ void SetCenter(nux::Point3 center, int monitor, nux::Geometry geo)
+ {
+ center.x += geo.x;
+ center.y += geo.y;
+ center_[monitor] = center;
+ }
nux::Point3 GetCenter(int monitor)
{
- return nux::Point3();
+ return center_[monitor];
}
nux::Point3 GetSavedCenter(int monitor)
@@ -288,9 +293,9 @@ public:
bool IsVisible() const { return false; }
void AboutToRemove() {}
-
+
void Stick(bool save = true) {}
-
+
void UnStick() {}
private:
@@ -341,11 +346,12 @@ private:
return result;
}
- nux::BaseTexture* icon_;
- int sort_priority_;
IconType type_;
+ int sort_priority_;
+ nux::BaseTexture* icon_;
bool quirks_[unsigned(Quirk::LAST)];
timespec quirk_times_[unsigned(Quirk::LAST)];
+ std::map<int, nux::Point3> center_;
};
}
diff --git a/launcher/SwitcherController.cpp b/launcher/SwitcherController.cpp
index a4ecaf104..910c728d1 100644
--- a/launcher/SwitcherController.cpp
+++ b/launcher/SwitcherController.cpp
@@ -46,7 +46,7 @@ namespace switcher
Controller::Controller(unsigned int load_timeout)
: timeout_length(75)
, detail_on_timeout(true)
- , detail_timeout_length(250)
+ , detail_timeout_length(500)
, initial_detail_timeout_length(1500)
, construct_timeout_(load_timeout)
, main_layout_(nullptr)
diff --git a/launcher/Volume.h b/launcher/Volume.h
new file mode 100644
index 000000000..0675a14f7
--- /dev/null
+++ b/launcher/Volume.h
@@ -0,0 +1,62 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITYSHELL_VOLUME_H
+#define UNITYSHELL_VOLUME_H
+
+#include <boost/noncopyable.hpp>
+#include <memory>
+#include <sigc++/signal.h>
+#include <sigc++/trackable.h>
+#include <string>
+
+namespace unity
+{
+namespace launcher
+{
+
+class Volume : private boost::noncopyable, public sigc::trackable
+{
+public:
+ typedef std::shared_ptr<Volume> Ptr;
+
+ virtual ~Volume() {}
+
+ virtual bool CanBeEjected() const = 0;
+ virtual bool CanBeRemoved() const = 0;
+ virtual bool CanBeStopped() const = 0;
+ virtual std::string GetName() const = 0;
+ virtual std::string GetIconName() const = 0;
+ virtual std::string GetIdentifier() const = 0;
+ virtual bool HasSiblings() const = 0;
+ virtual bool IsMounted() const = 0;
+
+ virtual void EjectAndShowNotification() = 0;
+ virtual void MountAndOpenInFileManager() = 0;
+ virtual void StopDrive() = 0;
+ virtual void Unmount() = 0;
+
+ sigc::signal<void> changed;
+ sigc::signal<void> removed;
+};
+
+}
+}
+
+#endif
diff --git a/launcher/VolumeImp.cpp b/launcher/VolumeImp.cpp
new file mode 100644
index 000000000..f3899289a
--- /dev/null
+++ b/launcher/VolumeImp.cpp
@@ -0,0 +1,294 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <UnityCore/GLibSignal.h>
+
+#include "VolumeImp.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+//
+// Start private implementation
+//
+
+class VolumeImp::Impl
+{
+public:
+ Impl(glib::Object<GVolume> const& volume,
+ FileManagerOpener::Ptr const& file_manager_opener,
+ DeviceNotificationDisplay::Ptr const& device_notification_display,
+ VolumeImp* parent)
+ : parent_(parent)
+ , cancellable_(g_cancellable_new())
+ , volume_(volume)
+ , file_manager_opener_(file_manager_opener)
+ , device_notification_display_(device_notification_display)
+ {
+ signal_volume_changed_.Connect(volume_, "changed", [this] (GVolume*) {
+ parent_->changed.emit();
+ });
+
+ signal_volume_removed_.Connect(volume_, "removed", [this] (GVolume*) {
+ parent_->removed.emit();
+ });
+ }
+
+ ~Impl()
+ {
+ g_cancellable_cancel(cancellable_);
+ }
+
+ bool CanBeEjected() const
+ {
+ return g_volume_can_eject(volume_) != FALSE;
+ }
+
+ bool CanBeRemoved() const
+ {
+ glib::Object<GDrive> drive(g_volume_get_drive(volume_));
+ return drive && g_drive_is_media_removable(drive) != FALSE;
+ }
+
+ bool CanBeStopped() const
+ {
+ glib::Object<GDrive> drive(g_volume_get_drive(volume_));
+ return drive && g_drive_can_stop(drive) != FALSE;
+ }
+
+ std::string GetName() const
+ {
+ return glib::String(g_volume_get_name(volume_)).Str();
+ }
+
+ std::string GetIconName() const
+ {
+ glib::Object<GIcon> icon(g_volume_get_icon(volume_));
+ return glib::String(g_icon_to_string(icon)).Str();
+ }
+
+ std::string GetIdentifier() const
+ {
+ return glib::String(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UUID)).Str();
+ }
+
+ bool HasSiblings() const
+ {
+ glib::Object<GDrive> drive(g_volume_get_drive(volume_));
+
+ if (!drive)
+ return false;
+
+ GList* volumes = g_drive_get_volumes(drive);
+ bool has_sibilings = volumes && volumes->next;
+
+ if (volumes)
+ g_list_free_full(volumes, g_object_unref);
+
+ return has_sibilings;
+ }
+
+ bool IsMounted() const
+ {
+ glib::Object<GMount> mount(g_volume_get_mount(volume_));
+ return static_cast<bool>(mount);
+ }
+
+ void EjectAndShowNotification()
+ {
+ if (!CanBeEjected())
+ return;
+
+ glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(nullptr));
+
+ g_volume_eject_with_operation(volume_,
+ (GMountUnmountFlags)0,
+ mount_op,
+ nullptr,
+ (GAsyncReadyCallback)OnEjectReady,
+ this);
+ }
+
+ static void OnEjectReady(GObject* object, GAsyncResult* result, Impl* self)
+ {
+ if (g_volume_eject_with_operation_finish(self->volume_, result, nullptr))
+ {
+ self->device_notification_display_->Display(self->GetIconName(), self->GetName());
+ }
+ }
+
+ void MountAndOpenInFileManager()
+ {
+ if (!IsMounted())
+ MountAndOnFinishOpenInFileManager();
+ else
+ OpenInFileManager();
+ }
+
+ void MountAndOnFinishOpenInFileManager()
+ {
+ g_volume_mount(volume_,
+ (GMountMountFlags) 0,
+ nullptr,
+ nullptr,
+ (GAsyncReadyCallback) &Impl::OnMountFinish,
+ this);
+ }
+
+ static void OnMountFinish(GObject* object,
+ GAsyncResult* result,
+ Impl* self)
+ {
+ if (g_volume_mount_finish(self->volume_, result, nullptr))
+ self->OpenInFileManager();
+ }
+
+ void OpenInFileManager()
+ {
+ file_manager_opener_->Open(GetUri());
+ }
+
+ std::string GetUri()
+ {
+ glib::Object<GMount> mount(g_volume_get_mount(volume_));
+ glib::Object<GFile> root(g_mount_get_root(mount));
+
+ if (root.IsType(G_TYPE_FILE))
+ return glib::String(g_file_get_uri(root)).Str();
+ else
+ return std::string();
+ }
+
+ void StopDrive()
+ {
+ if (!CanBeStopped())
+ return;
+
+ glib::Object<GDrive> drive(g_volume_get_drive(volume_));
+ glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(NULL));
+
+ g_drive_stop(drive,
+ (GMountUnmountFlags)0,
+ mount_op,
+ nullptr, nullptr, nullptr);
+ }
+
+ void Unmount()
+ {
+ if (!IsMounted())
+ return;
+
+ glib::Object<GMount> mount(g_volume_get_mount(volume_));
+ glib::Object<GMountOperation> op(gtk_mount_operation_new(nullptr));
+
+ g_mount_unmount_with_operation(mount,
+ (GMountUnmountFlags)0,
+ op,
+ nullptr, nullptr, nullptr);
+ }
+
+ VolumeImp* parent_;
+ glib::Object<GCancellable> cancellable_;
+ glib::Object<GVolume> volume_;
+ FileManagerOpener::Ptr file_manager_opener_;
+ DeviceNotificationDisplay::Ptr device_notification_display_;
+
+ glib::Signal<void, GVolume*> signal_volume_changed_;
+ glib::Signal<void, GVolume*> signal_volume_removed_;
+};
+
+//
+// End private implementation
+//
+
+VolumeImp::VolumeImp(glib::Object<GVolume> const& volume,
+ FileManagerOpener::Ptr const& file_manager_opener,
+ DeviceNotificationDisplay::Ptr const& device_notification_display)
+ : pimpl(new Impl(volume, file_manager_opener, device_notification_display, this))
+{}
+
+VolumeImp::~VolumeImp()
+{}
+
+bool VolumeImp::CanBeEjected() const
+{
+ return pimpl->CanBeEjected();
+}
+
+bool VolumeImp::CanBeRemoved() const
+{
+ return pimpl->CanBeRemoved();
+}
+
+bool VolumeImp::CanBeStopped() const
+{
+ return pimpl->CanBeStopped();
+}
+
+std::string VolumeImp::GetName() const
+{
+ return pimpl->GetName();
+}
+
+std::string VolumeImp::GetIconName() const
+{
+ return pimpl->GetIconName();
+}
+
+std::string VolumeImp::GetIdentifier() const
+{
+ return pimpl->GetIdentifier();
+}
+
+bool VolumeImp::HasSiblings() const
+{
+ return pimpl->HasSiblings();
+}
+
+bool VolumeImp::IsMounted() const
+{
+ return pimpl->IsMounted();
+}
+
+void VolumeImp::MountAndOpenInFileManager()
+{
+ pimpl->MountAndOpenInFileManager();
+}
+
+void VolumeImp::EjectAndShowNotification()
+{
+ pimpl->EjectAndShowNotification();
+}
+
+void VolumeImp::StopDrive()
+{
+ pimpl->StopDrive();
+}
+
+void VolumeImp::Unmount()
+{
+ pimpl->Unmount();
+}
+
+} // namespace launcher
+} // namespace unity
diff --git a/launcher/VolumeImp.h b/launcher/VolumeImp.h
new file mode 100644
index 000000000..0d8cc2112
--- /dev/null
+++ b/launcher/VolumeImp.h
@@ -0,0 +1,68 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITYSHELL_VOLUME_IMP_H
+#define UNITYSHELL_VOLUME_IMP_H
+
+#include <memory>
+
+#include <UnityCore/GLibWrapper.h>
+
+#include "DeviceNotificationDisplay.h"
+#include "FileManagerOpener.h"
+#include "Volume.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class VolumeImp : public Volume
+{
+public:
+ typedef std::shared_ptr<VolumeImp> Ptr;
+
+ VolumeImp(glib::Object<GVolume> const& volume,
+ FileManagerOpener::Ptr const& file_manager_opener,
+ DeviceNotificationDisplay::Ptr const& device_notification_display);
+ virtual ~VolumeImp();
+
+ virtual bool CanBeEjected() const;
+ virtual bool CanBeRemoved() const;
+ virtual bool CanBeStopped() const;
+ virtual std::string GetName() const;
+ virtual std::string GetIconName() const;
+ virtual std::string GetIdentifier() const;
+ virtual bool HasSiblings() const;
+ virtual bool IsMounted() const;
+
+ virtual void EjectAndShowNotification();
+ virtual void MountAndOpenInFileManager();
+ virtual void StopDrive();
+ virtual void Unmount();
+
+private:
+ class Impl;
+ std::unique_ptr<Impl> pimpl;
+};
+
+}
+}
+
+#endif
diff --git a/launcher/VolumeLauncherIcon.cpp b/launcher/VolumeLauncherIcon.cpp
new file mode 100644
index 000000000..bba622e9b
--- /dev/null
+++ b/launcher/VolumeLauncherIcon.cpp
@@ -0,0 +1,305 @@
+// -*- 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: Neil Jagdish Patel <neil.patel@canonical.com>
+ * Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+
+#include <glib/gi18n-lib.h>
+#include <NuxCore/Logger.h>
+#include <UnityCore/GLibSignal.h>
+
+#include "DevicesSettings.h"
+#include "Volume.h"
+#include "VolumeLauncherIcon.h"
+
+namespace unity
+{
+namespace launcher
+{
+namespace
+{
+
+nux::logging::Logger logger("unity.launcher");
+
+const unsigned int volume_changed_timeout = 500;
+
+}
+
+//
+// Start private implementation
+//
+class VolumeLauncherIcon::Impl
+{
+public:
+ typedef glib::Signal<void, DbusmenuMenuitem*, int> ItemSignal;
+
+ Impl(Volume::Ptr const& volume,
+ DevicesSettings::Ptr const& devices_settings,
+ VolumeLauncherIcon* parent)
+ : parent_(parent)
+ , volume_(volume)
+ , devices_settings_(devices_settings)
+ {
+ UpdateIcon();
+ UpdateVisibility();
+ ConnectSignals();
+ }
+
+ ~Impl()
+ {
+ volume_changed_conn_.disconnect();
+ volume_removed_conn_.disconnect();
+ settings_changed_conn_.disconnect();
+ }
+
+ void UpdateIcon()
+ {
+ parent_->tooltip_text = volume_->GetName();
+ parent_->icon_name = volume_->GetIconName();
+
+ parent_->SetQuirk(Quirk::RUNNING, false);
+ }
+
+ void UpdateVisibility()
+ {
+ UpdateKeepInLauncher();
+ parent_->SetQuirk(Quirk::VISIBLE, keep_in_launcher_);
+ }
+
+ void UpdateKeepInLauncher()
+ {
+ auto identifier = volume_->GetIdentifier();
+ keep_in_launcher_ = !devices_settings_->IsABlacklistedDevice(identifier);
+ }
+
+ void ConnectSignals()
+ {
+ volume_changed_conn_ = volume_->changed.connect(sigc::mem_fun(this, &Impl::OnVolumeChanged));
+ volume_removed_conn_ = volume_->removed.connect(sigc::mem_fun(this, &Impl::OnVolumeRemoved));
+ settings_changed_conn_ = devices_settings_->changed.connect(sigc::mem_fun(this, &Impl::OnSettingsChanged));
+ }
+
+ void OnVolumeChanged()
+ {
+ UpdateIcon();
+ }
+
+ void OnVolumeRemoved()
+ {
+ if (devices_settings_->IsABlacklistedDevice(volume_->GetIdentifier()))
+ devices_settings_->TryToUnblacklist(volume_->GetIdentifier());
+
+ parent_->Remove();
+ }
+
+ void OnSettingsChanged()
+ {
+ UpdateVisibility();
+ }
+
+ bool CanEject() const
+ {
+ return volume_->CanBeEjected();
+ }
+
+ void EjectAndShowNotification()
+ {
+ return volume_->EjectAndShowNotification();
+ }
+
+ bool CanStop() const
+ {
+ return volume_->CanBeStopped();
+ }
+
+ void StopDrive()
+ {
+ volume_->StopDrive();
+ }
+
+ void ActivateLauncherIcon(ActionArg arg)
+ {
+ parent_->SimpleLauncherIcon::ActivateLauncherIcon(arg);
+ volume_->MountAndOpenInFileManager();
+ }
+
+ MenuItemsVector GetMenus()
+ {
+ MenuItemsVector result;
+
+ AppendUnlockFromLauncherItem(result);
+ AppendOpenItem(result);
+ AppendEjectItem(result);
+ AppendSafelyRemoveItem(result);
+ AppendUnmountItem(result);
+
+ return result;
+ }
+
+ void AppendUnlockFromLauncherItem(MenuItemsVector& menu)
+ {
+ if (volume_->GetIdentifier().empty())
+ return;
+
+ glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
+
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Unlock from Launcher"));
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
+
+ gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ auto identifier = volume_->GetIdentifier();
+ devices_settings_->TryToBlacklist(identifier);
+ }));
+
+ menu.push_back(menu_item);
+ }
+
+ void AppendOpenItem(MenuItemsVector& menu)
+ {
+ glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
+
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Open"));
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
+
+ gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ volume_->MountAndOpenInFileManager();
+ }));
+
+ menu.push_back(menu_item);
+ }
+
+ void AppendEjectItem(MenuItemsVector& menu)
+ {
+ if (!volume_->CanBeEjected())
+ return;
+
+ glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
+
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, volume_->HasSiblings() ? _("Eject parent drive") : _("Eject"));
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
+
+ gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ volume_->EjectAndShowNotification();
+ }));
+
+ menu.push_back(menu_item);
+ }
+
+ void AppendSafelyRemoveItem(MenuItemsVector& menu)
+ {
+ if (!volume_->CanBeStopped())
+ return;
+
+ glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
+
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, volume_->HasSiblings() ? _("Safely remove parent drive") : _("Safely remove"));
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
+
+ gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ volume_->StopDrive();
+ }));
+
+ menu.push_back(menu_item);
+ }
+
+ void AppendUnmountItem(MenuItemsVector& menu)
+ {
+ if (!volume_->IsMounted() || volume_->CanBeEjected() || volume_->CanBeStopped())
+ return;
+
+ glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
+
+ dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Unmount"));
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
+ dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
+
+ gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
+ volume_->Unmount();
+ }));
+
+ menu.push_back(menu_item);
+ }
+
+ VolumeLauncherIcon* parent_;
+ bool keep_in_launcher_;
+ Volume::Ptr volume_;
+ DevicesSettings::Ptr devices_settings_;
+
+ glib::SignalManager gsignals_;
+ sigc::connection settings_changed_conn_;
+ sigc::connection volume_changed_conn_;
+ sigc::connection volume_removed_conn_;
+};
+
+//
+// End private implementation
+//
+
+VolumeLauncherIcon::VolumeLauncherIcon(Volume::Ptr const& volume,
+ DevicesSettings::Ptr const& devices_settings)
+ : SimpleLauncherIcon(IconType::DEVICE)
+ , pimpl_(new Impl(volume, devices_settings, this))
+{}
+
+VolumeLauncherIcon::~VolumeLauncherIcon()
+{}
+
+bool VolumeLauncherIcon::CanEject() const
+{
+ return pimpl_->CanEject();
+}
+
+void VolumeLauncherIcon::EjectAndShowNotification()
+{
+ pimpl_->EjectAndShowNotification();
+}
+
+bool VolumeLauncherIcon::CanStop() const
+{
+ return pimpl_->CanStop();
+}
+
+void VolumeLauncherIcon::StopDrive()
+{
+ return pimpl_->StopDrive();
+}
+
+void VolumeLauncherIcon::ActivateLauncherIcon(ActionArg arg)
+{
+ pimpl_->ActivateLauncherIcon(arg);
+}
+
+AbstractLauncherIcon::MenuItemsVector VolumeLauncherIcon::GetMenus()
+{
+ return pimpl_->GetMenus();
+}
+
+//
+// Introspection
+//
+std::string VolumeLauncherIcon::GetName() const
+{
+ return "VolumeLauncherIcon";
+}
+
+} // namespace launcher
+} // namespace unity
diff --git a/launcher/VolumeLauncherIcon.h b/launcher/VolumeLauncherIcon.h
new file mode 100644
index 000000000..48e3e975f
--- /dev/null
+++ b/launcher/VolumeLauncherIcon.h
@@ -0,0 +1,62 @@
+// -*- 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: Neil Jagdish Patel <neil.patel@canonical.com>
+ * Andrea Azzarone <andrea.azzarone@canonical.com>
+ */
+
+#ifndef UNITYSHELL_VOLUME_LAUNCHER_ICON_H
+#define UNITYSHELL_VOLUME_LAUNCHER_ICON_H
+
+#include "Volume.h"
+#include "DevicesSettings.h"
+#include "SimpleLauncherIcon.h"
+
+namespace unity
+{
+namespace launcher
+{
+
+class VolumeLauncherIcon : public SimpleLauncherIcon
+{
+public:
+ typedef nux::ObjectPtr<VolumeLauncherIcon> Ptr;
+
+ VolumeLauncherIcon(Volume::Ptr const& volume,
+ DevicesSettings::Ptr const& devices_settings);
+ virtual ~VolumeLauncherIcon();
+
+ bool CanEject() const; // TODO: rename to public virtual bool IsTrashable();
+ void EjectAndShowNotification(); // TODO: rename to private virtual void DoDropToTrash();
+ bool CanStop() const;
+ void StopDrive();
+ MenuItemsVector GetMenus();
+
+protected:
+ virtual void ActivateLauncherIcon(ActionArg arg);
+
+ // Introspection
+ virtual std::string GetName() const;
+
+private:
+ class Impl;
+ std::shared_ptr<Impl> pimpl_;
+};
+
+}
+}
+
+#endif
diff --git a/manual-tests/Hud.txt b/manual-tests/Hud.txt
index d3d4ac445..1bf527b5d 100644
--- a/manual-tests/Hud.txt
+++ b/manual-tests/Hud.txt
@@ -1,6 +1,6 @@
Alt+Enter Crash
---------------
-Tests that Alt+Enter does not cause unity to crash (LP: #960957)
+Test that Alt+Enter does not cause Compiz/Unity to crash (LP: #960957)
Setup:
@@ -11,4 +11,4 @@ Expected Result:
Nothing happens
Wrong Result:
- Unity/compiz crashes
+ Unity/Compiz crashes
diff --git a/manual-tests/Launcher.txt b/manual-tests/Launcher.txt
index adad15ece..0b1206518 100644
--- a/manual-tests/Launcher.txt
+++ b/manual-tests/Launcher.txt
@@ -92,6 +92,7 @@ This test verifies that dragging icons to the trash removes them from the
launcher, and that the animation is smooth.
Setup:
+#. Ensure that you have multiple applications running or pinned to the launcher
Actions:
#. Move mouse pointer over an application or device icon (not BFB, Workspace switcher or trash)
@@ -110,6 +111,7 @@ Dragging icons to reorder - initial position
This test is all position of the dragged image in relation to the mouse pointer.
Setup:
+#. Ensure that you have multiple applications running or pinned to the launcher
Actions:
#. Move the mouse so it is over a launcher icon for an application
@@ -128,6 +130,7 @@ This test is all about the smoothness of the animation around the reordering
of icons in the launcher.
Setup:
+#. Ensure that you have multiple applications running or pinned to the launcher
Actions:
#. Move the mouse so it is over a launcher icon for an application
@@ -135,13 +138,15 @@ Actions:
#. Drag the icon up and down over the icons in the launcher
Expected Result:
- * As the centre of the dragged icon passes the mid-point of the next item
- above or below it, the icon being dragged over moves and is replaced by the
- blank "space".
+ * As the center of the dragged icon passes the mid-point of the next item
+ above or below it, the icon being dragged over moves and is replaced by the
+ blank "space".
* The animation should be smooth
* If the dragged icon is moved rapidly, multiple icons can be moving either
- upwards or downwards as the space is moved into place under the dragged icon
- * The BFB and the switcher icons do not move
+ upwards or downwards as the space is moved into place under the dragged icon
+ * Dragging the second application icon (the third icon of the launcher) below
+ the BFB or above the workspace switcher should be possible.
+ * The BFB and the workspace switcher icons do not move
Dragging icons to reorder - away from launcher
@@ -149,6 +154,7 @@ Dragging icons to reorder - away from launcher
This test is about reordering the icons without the animation showing.
Setup:
+#. Ensure that you have multiple applications running or pinned to the launcher
Actions:
#. Move the mouse so it is over a launcher icon for an application
@@ -161,7 +167,7 @@ Expected Result:
* As the icon is dragged away from the launcher, the "space" is closed up
and replaced with a grey line.
* As the icon is dragged up and down, the line moves between other launcher
- icons.
+ icons of the same type.
* When released, the icon "flies" back into the launcher, a spaces opens for
it, and the any pips for running apps show again.
@@ -171,6 +177,7 @@ Dragged launcher icons out of the launcher are properly drawn
This test ensures that the launcher icons out of the launcher are properly drawn
Setup:
+#. Ensure that you have multiple applications running or pinned to the launcher
Actions:
#. Move the mouse so it is over a launcher icon for an application
@@ -677,3 +684,21 @@ Actions:
Expected Results:
* The gedit window must not flicker behind the launcher.
+
+
+Custom background color works
+-----------------------------
+This test ensures that the custom background color (set via ccsm) works correctly.
+
+Setup:
+#. Ensure that ccsm is installed (package compizconfig-settings-manager)
+
+Actions:
+#. Open ccsm
+#. Click on Ubuntu Unity Plugin
+#. Choose Experimental tab, click on Background Color, set Color name to #000000 and Opacity to 180
+
+Expected Result:
+ The background color of the Launcher is black, and the icons are still visible.
+ The Launcher must stay black when Dash or HUD are opened, and the color must
+ be persistent between sessions (logout/login).
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 ad840204c..e16cb89c3 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
@@ -223,9 +223,9 @@ UnityMTGrabHandlesScreen::raiseHandle (const boost::shared_ptr <const unity::MT:
void
UnityMTGrabHandlesScreen::handleEvent(XEvent* event)
{
- CompWindow* w, *oldPrev, *oldNext;
+ CompWindow* w;
- w = oldPrev = oldNext = NULL;
+ w = NULL;
switch (event->type)
{
@@ -438,29 +438,19 @@ UnityMTGrabHandlesWindow::getOutputExtents(CompWindowExtents& output)
bool
UnityMTGrabHandlesWindow::glDraw(const GLMatrix& transform,
-#ifdef USE_MODERN_COMPIZ_GL
const GLWindowPaintAttrib& attrib,
-#else
- GLFragment::Attrib& fragment,
-#endif
const CompRegion& region,
unsigned int mask)
{
/* Draw the window on the bottom, we will be drawing the
* handles on top */
-#ifdef USE_MODERN_COMPIZ_GL
bool status = gWindow->glDraw(transform, attrib, region, mask);
-#else
- bool status = gWindow->glDraw(transform, fragment, region, mask);
-#endif
if (mHandles && mHandles->visible())
{
unsigned int allowedHandles = unity::MT::getLayoutForMask (window->state (), window->actions ());
unsigned int handle = 0;
- UMTGH_SCREEN (screen);
-
for(unity::MT::TextureLayout layout : mHandles->layout (allowedHandles))
{
/* We want to set the geometry of the handle to the window
@@ -472,17 +462,11 @@ UnityMTGrabHandlesWindow::glDraw(const GLMatrix& transform,
GLTexture::MatrixList matl;
GLTexture::Matrix mat = tex->matrix();
CompRegion paintRegion(region);
-#ifdef USE_MODERN_COMPIZ_GL
GLWindowPaintAttrib wAttrib(attrib);
-#endif
/* We can reset the window geometry since it will be
* re-added later */
-#ifdef USE_MODERN_COMPIZ_GL
gWindow->vertexBuffer()->begin();
-#else
- gWindow->geometry().reset();
-#endif
/* Not sure what this does, but it is necessary
* (adjusts for scale?) */
@@ -498,35 +482,22 @@ UnityMTGrabHandlesWindow::glDraw(const GLMatrix& transform,
* dim (so we get a nice render for things like
* wobbly etc etc */
gWindow->glAddGeometry(matl, reg, paintRegion);
-#ifdef USE_MODERN_COMPIZ_GL
- gWindow->vertexBuffer()->end();
- wAttrib.opacity = mHandles->opacity();
-#else
- /* Did it succeed? */
- if (gWindow->geometry().vertices)
- {
- fragment.setOpacity(mHandles->opacity());
- /* Texture rendering set-up */
- us->gScreen->setTexEnvMode(GL_MODULATE);
-#endif
+
+ if (gWindow->vertexBuffer()->end())
+ {
+ wAttrib.opacity = mHandles->opacity();
+
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* Draw the dim texture with all of it's modified
* geometry glory */
gWindow->glDrawTexture(tex,
-#ifdef USE_MODERN_COMPIZ_GL
transform, wAttrib,
-#else
- fragment,
-#endif
mask | PAINT_WINDOW_BLEND_MASK
| PAINT_WINDOW_TRANSLUCENT_MASK |
PAINT_WINDOW_TRANSFORMED_MASK);
/* Texture rendering tear-down */
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-#ifndef USE_MODERN_COMPIZ_GL
- us->gScreen->setTexEnvMode(GL_REPLACE);
}
-#endif
}
handle++;
diff --git a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h
index 9cd99b9d1..f0d3776e5 100644
--- a/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h
+++ b/plugins/unity-mt-grab-handles/src/unity-mt-grab-handles.h
@@ -229,11 +229,7 @@ public:
void moveNotify(int dx, int dy, bool immediate);
bool glDraw(const GLMatrix&,
-#ifdef USE_MODERN_COMPIZ_GL
const GLWindowPaintAttrib&,
-#else
- GLFragment::Attrib&,
-#endif
const CompRegion&,
unsigned int);
diff --git a/plugins/unitydialog/src/unitydialog.cpp b/plugins/unitydialog/src/unitydialog.cpp
index 91f7f235e..3951b65f7 100644
--- a/plugins/unitydialog/src/unitydialog.cpp
+++ b/plugins/unitydialog/src/unitydialog.cpp
@@ -420,12 +420,8 @@ UnityDialogWindow::glAddGeometry(const GLTexture::MatrixList& matrices,
/* Collect textures */
void
UnityDialogWindow::glDrawTexture(GLTexture* texture,
-#ifdef USE_MODERN_COMPIZ_GL
const GLMatrix &transform,
const GLWindowPaintAttrib &attrib,
-#else
- GLFragment::Attrib& fa,
-#endif
unsigned int mask)
{
unity::PaintInfoCollector::Active ()->processTexture (texture);
@@ -448,16 +444,12 @@ unity::GeometryCollection::status ()
collectedMinVertices.size () == collectedMatrixLists.size ());
}
-void
+bool
unity::GeometryCollection::addGeometryForWindow (CompWindow *w, const CompRegion &paintRegion)
{
/* We can reset the window geometry since it will be
* re-added later */
-#ifdef USE_MODERN_COMPIZ_GL
GLWindow::get (w)->vertexBuffer()->begin();
-#else
- GLWindow::get (w)->geometry().reset();
-#endif
for (unsigned int i = 0; i < collectedMatrixLists.size (); i++)
{
@@ -472,9 +464,7 @@ unity::GeometryCollection::addGeometryForWindow (CompWindow *w, const CompRegion
GLWindow::get (w)->glAddGeometry(matl, reg, paintRegion, min, max);
}
-#ifdef USE_MODERN_COMPIZ_GL
- GLWindow::get (w)->vertexBuffer()->end();
-#endif
+ return GLWindow::get (w)->vertexBuffer()->end();
}
void
@@ -511,9 +501,7 @@ unity::TexGeometryCollection::setTexture (GLTexture *tex)
void
unity::TexGeometryCollection::addGeometriesAndDrawTextureForWindow(CompWindow *w,
-#ifdef USE_MODERN_COMPIZ_GL
const GLMatrix &transform,
-#endif
unsigned int mask)
{
if (mTexture && mGeometries.status ())
@@ -524,47 +512,25 @@ unity::TexGeometryCollection::addGeometriesAndDrawTextureForWindow(CompWindow *w
if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
paintRegion = infiniteRegion;
- mGeometries.addGeometryForWindow (w, paintRegion);
-
-#ifdef USE_MODERN_COMPIZ_GL
- UnityDialogScreen *uds = UnityDialogScreen::get (screen);
- GLWindowPaintAttrib attrib (gWindow->lastPaintAttrib());
- unsigned int glDrawTextureIndex = gWindow->glDrawTextureGetCurrentIndex();
- /* Texture rendering set-up */
-// uds->gScreen->setTexEnvMode(GL_MODULATE);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- /* Draw the dim texture with all of it's modified
- * geometry glory */
- gWindow->glDrawTextureSetCurrentIndex(MAXSHORT);
- gWindow->glDrawTexture(mTexture, transform, attrib, mask
- | PAINT_WINDOW_BLEND_MASK
- | PAINT_WINDOW_TRANSLUCENT_MASK
- | PAINT_WINDOW_TRANSFORMED_MASK);
- gWindow->glDrawTextureSetCurrentIndex(glDrawTextureIndex);
- /* Texture rendering tear-down */
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- uds->gScreen->setTexEnvMode(GL_REPLACE);
-#else
- if (gWindow->geometry().vertices)
+ if (mGeometries.addGeometryForWindow (w, paintRegion))
{
- UnityDialogScreen *uds = UnityDialogScreen::get (screen);
- GLFragment::Attrib fa (gWindow->lastPaintAttrib());
- unsigned int glDrawTextureIndex = gWindow->glDrawTextureGetCurrentIndex();
- /* Texture rendering set-up */
- uds->gScreen->setTexEnvMode(GL_MODULATE);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- /* Draw the dim texture with all of it's modified
- * geometry glory */
- gWindow->glDrawTextureSetCurrentIndex(MAXSHORT);
- gWindow->glDrawTexture(mTexture, fa, mask | PAINT_WINDOW_BLEND_MASK
- | PAINT_WINDOW_TRANSLUCENT_MASK |
- PAINT_WINDOW_TRANSFORMED_MASK);
- gWindow->glDrawTextureSetCurrentIndex(glDrawTextureIndex);
- /* Texture rendering tear-down */
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- uds->gScreen->setTexEnvMode(GL_REPLACE);
+ UnityDialogScreen *uds = UnityDialogScreen::get (screen);
+ GLWindowPaintAttrib attrib (gWindow->lastPaintAttrib());
+ unsigned int glDrawTextureIndex = gWindow->glDrawTextureGetCurrentIndex();
+ /* Texture rendering set-up */
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ /* Draw the dim texture with all of it's modified
+ * geometry glory */
+ gWindow->glDrawTextureSetCurrentIndex(MAXSHORT);
+ gWindow->glDrawTexture(mTexture, transform, attrib, mask
+ | PAINT_WINDOW_BLEND_MASK
+ | PAINT_WINDOW_TRANSLUCENT_MASK
+ | PAINT_WINDOW_TRANSFORMED_MASK);
+ gWindow->glDrawTextureSetCurrentIndex(glDrawTextureIndex);
+ /* Texture rendering tear-down */
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ uds->gScreen->setTexEnvMode(GL_REPLACE);
}
-#endif
}
}
@@ -619,17 +585,11 @@ unity::PaintInfoCollector::processTexture (GLTexture *tex)
void
unity::PaintInfoCollector::drawGeometriesForWindow(CompWindow *w,
-#ifdef USE_MODERN_COMPIZ_GL
const GLMatrix &transform,
-#endif
unsigned int pm)
{
for (unity::TexGeometryCollection &tcg : mCollection)
-#if USE_MODERN_COMPIZ_GL
tcg.addGeometriesAndDrawTextureForWindow (w, transform, pm);
-#else
- tcg.addGeometriesAndDrawTextureForWindow (w, pm);
-#endif
}
unity::PaintInfoCollector * unity::PaintInfoCollector::active_collector = NULL;
@@ -644,11 +604,7 @@ unity::PaintInfoCollector::Active ()
bool
UnityDialogWindow::glDraw(const GLMatrix& transform,
-#ifdef USE_MODERN_COMPIZ_GL
const GLWindowPaintAttrib& attrib,
-#else
- GLFragment::Attrib& fragment,
-#endif
const CompRegion& region,
unsigned int mask)
{
@@ -660,11 +616,7 @@ UnityDialogWindow::glDraw(const GLMatrix& transform,
/* Draw the window on the bottom, we will be drawing the
* dim render on top */
bool status = gWindow->glDraw(transform,
-#ifdef USE_MODERN_COMPIZ_GL
attrib,
-#else
- fragment,
-#endif
region, mask);
UNITY_DIALOG_SCREEN(screen);
@@ -673,17 +625,11 @@ UnityDialogWindow::glDraw(const GLMatrix& transform,
{
GLTexture::MatrixList matl;
GLTexture::Matrix mat = tex->matrix();
-#ifdef USE_MODERN_COMPIZ_GL
GLWindowPaintAttrib wAttrib(attrib);
-#endif
/* We can reset the window geometry since it will be
* re-added later */
-#ifdef USE_MODERN_COMPIZ_GL
gWindow->vertexBuffer()->begin();
-#else
- gWindow->geometry().reset();
-#endif
/* Scale the dim render by the ratio of dim size
* to window size */
@@ -704,48 +650,25 @@ UnityDialogWindow::glDraw(const GLMatrix& transform,
* dim (so we get a nice render for things like
* wobbly etc etc */
gWindow->glAddGeometry(matl, reg, paintRegion);
-#ifdef USE_MODERN_COMPIZ_GL
- gWindow->vertexBuffer()->end();
-#endif
-
-#ifdef USE_MODERN_COMPIZ_GL
- unsigned int glDrawTextureIndex = gWindow->glDrawTextureGetCurrentIndex();
- wAttrib.opacity = mShadeProgress;
- /* Texture rendering set-up */
-// uds->gScreen->setTexEnvMode(GL_MODULATE);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- /* Draw the dim texture with all of it's modified
- * geometry glory */
- gWindow->glDrawTextureSetCurrentIndex(MAXSHORT);
- gWindow->glDrawTexture(tex, transform, attrib, mask
- | PAINT_WINDOW_BLEND_MASK
- | PAINT_WINDOW_TRANSLUCENT_MASK
- | PAINT_WINDOW_TRANSFORMED_MASK);
- gWindow->glDrawTextureSetCurrentIndex(glDrawTextureIndex);
- /* Texture rendering tear-down */
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- uds->gScreen->setTexEnvMode(GL_REPLACE);
-#else
- /* Did it succeed? */
- if (gWindow->geometry().vertices)
+ if (gWindow->vertexBuffer()->end())
{
unsigned int glDrawTextureIndex = gWindow->glDrawTextureGetCurrentIndex();
- fragment.setOpacity(mShadeProgress);
+ wAttrib.opacity = mShadeProgress;
/* Texture rendering set-up */
- uds->gScreen->setTexEnvMode(GL_MODULATE);
+ // uds->gScreen->setTexEnvMode(GL_MODULATE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
/* Draw the dim texture with all of it's modified
* geometry glory */
gWindow->glDrawTextureSetCurrentIndex(MAXSHORT);
- gWindow->glDrawTexture(tex, fragment, mask | PAINT_WINDOW_BLEND_MASK
- | PAINT_WINDOW_TRANSLUCENT_MASK |
- PAINT_WINDOW_TRANSFORMED_MASK);
+ gWindow->glDrawTexture(tex, transform, attrib, mask
+ | PAINT_WINDOW_BLEND_MASK
+ | PAINT_WINDOW_TRANSLUCENT_MASK
+ | PAINT_WINDOW_TRANSFORMED_MASK);
gWindow->glDrawTextureSetCurrentIndex(glDrawTextureIndex);
/* Texture rendering tear-down */
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
uds->gScreen->setTexEnvMode(GL_REPLACE);
}
-#endif
}
for (CompWindow* w : mTransients)
@@ -759,9 +682,7 @@ UnityDialogWindow::glDraw(const GLMatrix& transform,
pc.collect();
pc.drawGeometriesForWindow (window,
-#ifdef USE_MODERN_COMPIZ_GL
transform,
-#endif
mask);
}
}
diff --git a/plugins/unitydialog/src/unitydialog.h b/plugins/unitydialog/src/unitydialog.h
index eee9adea7..4f3f26338 100644
--- a/plugins/unitydialog/src/unitydialog.h
+++ b/plugins/unitydialog/src/unitydialog.h
@@ -40,7 +40,7 @@ namespace unity
GeometryCollection ();
bool status ();
- void addGeometryForWindow (CompWindow *, const CompRegion &paintRegion);
+ bool addGeometryForWindow (CompWindow *, const CompRegion &paintRegion);
void addGeometry (const GLTexture::MatrixList &ml,
const CompRegion &r,
int min,
@@ -64,13 +64,9 @@ namespace unity
int max);
void setTexture (GLTexture *);
-#ifdef USE_MODERN_COMPIZ_GL
void addGeometriesAndDrawTextureForWindow (CompWindow *w,
const GLMatrix &transform,
- unsigned int mask);
-#else
- void addGeometriesAndDrawTextureForWindow (CompWindow *, unsigned int pm);
-#endif
+ unsigned int mask);
private:
GLTexture* mTexture;
@@ -84,13 +80,9 @@ namespace unity
PaintInfoCollector (CompWindow *w);
void collect ();
-#ifdef USE_MODERN_COMPIZ_GL
void drawGeometriesForWindow (CompWindow *w,
const GLMatrix &transform,
unsigned int pm);
-#else
- void drawGeometriesForWindow (CompWindow *w, unsigned int pm);
-#endif
void processGeometry (const GLTexture::MatrixList &ml,
const CompRegion &r,
@@ -255,11 +247,7 @@ public:
bool
glDraw(const GLMatrix&,
-#ifdef USE_MODERN_COMPIZ_GL
const GLWindowPaintAttrib&,
-#else
- GLFragment::Attrib&,
-#endif
const CompRegion&, unsigned int);
bool
@@ -275,12 +263,8 @@ public:
void
glDrawTexture(GLTexture* texture,
-#ifdef USE_MODERN_COMPIZ_GL
const GLMatrix& transform,
const GLWindowPaintAttrib& attrib,
-#else
- GLFragment::Attrib& attrib,
-#endif
unsigned int mask);
diff --git a/plugins/unityshell/CMakeLists.txt b/plugins/unityshell/CMakeLists.txt
index eaf2047a3..c6ad6f75d 100644
--- a/plugins/unityshell/CMakeLists.txt
+++ b/plugins/unityshell/CMakeLists.txt
@@ -6,7 +6,7 @@ set (COMPIZ_PLUGIN_INSTALL_TYPE "package")
compiz_plugin (unityshell
PKGDEPS ${UNITY_PLUGIN_DEPS}
- PLUGINDEPS composite opengl compiztoolbox
+ PLUGINDEPS composite opengl compiztoolbox scale
CFLAGSADD "-DINSTALLPREFIX='\"${CMAKE_INSTALL_PREFIX}\"' -DPKGDATADIR='\"${PKGDATADIR}\"' -I${CMAKE_BINARY_DIR} -I${CMAKE_SOURCE_DIR} ${BOOT_LOGGER_FLAG} -DGETTEXT_PACKAGE='\"unity\"' ${MAINTAINER_CFLAGS} -I${CMAKE_SOURCE_DIR}/dash/ -I${CMAKE_SOURCE_DIR}/launcher/ -I${CMAKE_SOURCE_DIR}/hud/ -I${CMAKE_SOURCE_DIR}/panel/ -I${CMAKE_SOURCE_DIR}/shortcuts/ -I${CMAKE_SOURCE_DIR}/unity-shared/"
LIBDIRS "${CMAKE_BINARY_DIR}/UnityCore"
)
diff --git a/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp b/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp
deleted file mode 100644
index de9be43f3..000000000
--- a/plugins/unityshell/src/ScreenEffectFramebufferObject.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
-/* Compiz unity plugin
- * unity.h
- *
- * Copyright (c) 2010-11 Canonical Ltd.
- *
- * This program 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 3
- * of the License, or (at your option) any later version.
- *
- * 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.
- *
- * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
- */
-
-#ifndef USE_GLES
-#include "ScreenEffectFramebufferObject.h"
-#include "BackgroundEffectHelper.h"
-#include <NuxCore/Logger.h>
-#include <dlfcn.h>
-
-namespace
-{
- nux::logging::Logger logger ("unity.screeneffectframebufferobject");
-}
-
-void unity::ScreenEffectFramebufferObject::paint (const nux::Geometry &output)
-{
- /* Draw the bit of the relevant framebuffer for each output */
-
- glPushAttrib (GL_VIEWPORT_BIT);
- glViewport (0, 0, mScreenSize.width, mScreenSize.height);
-
- if (mFBTexture)
- {
- glEnable (GL_TEXTURE_2D);
- activeTexture (GL_TEXTURE0_ARB);
- glBindTexture (GL_TEXTURE_2D, mFBTexture);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- glPushAttrib (GL_SCISSOR_BIT);
- glEnable (GL_SCISSOR_TEST);
-
- glScissor (output.x, mScreenSize.height - (output.y + output.height),
- output.width, output.height);
-
- /* FIXME: This needs to be GL_TRIANGLE_STRIP */
- glBegin (GL_QUADS);
- glTexCoord2f (0, 1);
- glVertex2i (mGeometry.x, mGeometry.y);
- glTexCoord2f (0, 0);
- glVertex2i (mGeometry.x, mGeometry.y + mGeometry.height);
- glTexCoord2f (1, 0);
- glVertex2i (mGeometry.x + mGeometry.width, mGeometry.y + mGeometry.height);
- glTexCoord2f (1, 1);
- glVertex2i (mGeometry.x + mGeometry.width, mGeometry.y);
- glEnd ();
-
- activeTexture (GL_TEXTURE0_ARB);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glBindTexture (GL_TEXTURE_2D, 0);
- glDisable (GL_TEXTURE_2D);
- glPopAttrib ();
- }
- glPopAttrib ();
-}
-
-void unity::ScreenEffectFramebufferObject::onScreenSizeChanged(const nux::Geometry& screenSize)
-{
- mScreenSize = screenSize;
-}
-
-
-void unity::ScreenEffectFramebufferObject::unbind ()
-{
- if (!mBoundCnt)
- return;
-
- mBoundCnt--;
-
- (*bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
-
- glDrawBuffer (GL_BACK);
- glReadBuffer (GL_BACK);
-
- /* Matches the viewport set we did in ::bind () */
- glPopAttrib ();
-
-}
-
-bool unity::ScreenEffectFramebufferObject::status ()
-{
- return mFboStatus;
-}
-
-void unity::ScreenEffectFramebufferObject::bind (const nux::Geometry &output)
-{
- /* Very important!
- * Don't bind unless BackgroundEffectHelper says it's necessary.
- * Because binding has a severe impact on graphics performance and we
- * can't afford to do it every frame. (LP: #861061) (LP: #987304)
- */
- if (!BackgroundEffectHelper::HasDirtyHelpers())
- return;
-
- /* Clear the error bit */
- glGetError ();
-
- if (!mFBTexture)
- {
- glGenTextures (1, &mFBTexture);
-
- glBindTexture (GL_TEXTURE_2D, mFBTexture);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, mGeometry.width, mGeometry.height, 0, GL_BGRA,
-#if IMAGE_BYTE_ORDER == MSBFirst
- GL_UNSIGNED_INT_8_8_8_8_REV,
-#else
- GL_UNSIGNED_BYTE,
-#endif
- NULL);
-
- glBindTexture (GL_TEXTURE_2D, 0);
-
- if (glGetError () != GL_NO_ERROR)
- {
- mFboHandle = 0;
- mFboStatus = false;
- return;
- }
- }
-
- (*bindFramebuffer) (GL_FRAMEBUFFER_EXT, mFboHandle);
-
- (*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D, mFBTexture, 0);
-
- (*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
- GL_TEXTURE_2D, 0, 0);
-
- /* Ensure that a framebuffer is actually available */
- if (!mFboStatus)
- {
- GLint status = (*checkFramebufferStatus) (GL_DRAW_FRAMEBUFFER);
-
- if (status != GL_FRAMEBUFFER_COMPLETE)
- {
- switch (status)
- {
- case GL_FRAMEBUFFER_UNDEFINED:
- LOG_WARN (logger) << "no window";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- LOG_WARN (logger) << "attachment incomplete";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- LOG_WARN (logger) << "no buffers attached to fbo";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- LOG_WARN (logger) << "some attachment in glDrawBuffers doesn't exist in FBO";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- LOG_WARN (logger) << "some attachment in glReadBuffers doesn't exist in FBO";
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED:
- LOG_WARN (logger) << "unsupported internal format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- LOG_WARN (logger) << "different levels of sampling for each attachment";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
- LOG_WARN (logger) << "number of layers is different";
- break;
- default:
- LOG_WARN (logger) << "unable to bind the framebuffer for an unknown reason";
- break;
- }
-
- bindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
- deleteFramebuffers (1, &mFboHandle);
-
- glDrawBuffer (GL_BACK);
- glReadBuffer (GL_BACK);
-
- mFboHandle = 0;
-
- mFboStatus = false;
- }
- else
- mFboStatus = true;
- }
-
- if (mFboStatus)
- {
- glPushAttrib (GL_VIEWPORT_BIT);
-
- glViewport (output.x,
- mScreenSize.height - (output.y + output.height),
- output.width,
- output.height);
- }
-
- mBoundCnt++;
-}
-
-
-unity::ScreenEffectFramebufferObject::ScreenEffectFramebufferObject (GLXGetProcAddressProc p, const nux::Geometry &geom)
- : getProcAddressGLX (p)
- , mFboStatus (false)
- , mFBTexture (0)
- , mGeometry (geom)
- , mBoundCnt (0)
- , mScreenSize (geom)
-{
- activeTexture = (GLActiveTextureProc) (*getProcAddressGLX) ((GLubyte *) "glActiveTexture");
- genFramebuffers = (GLGenFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glGenFramebuffersEXT");
- deleteFramebuffers = (GLDeleteFramebuffersProc) (*getProcAddressGLX) ((GLubyte *)"glDeleteFramebuffersEXT");
- bindFramebuffer = (GLBindFramebufferProc) (*getProcAddressGLX) ((GLubyte *)"glBindFramebufferEXT");
- checkFramebufferStatus = (GLCheckFramebufferStatusProc) (*getProcAddressGLX) ((GLubyte *) "glCheckFramebufferStatusEXT");
- framebufferTexture2D = (GLFramebufferTexture2DProc) (*getProcAddressGLX) ((GLubyte *) "glFramebufferTexture2DEXT");
-
- (*genFramebuffers) (1, &mFboHandle);
-}
-
-unity::ScreenEffectFramebufferObject::~ScreenEffectFramebufferObject ()
-{
- (*deleteFramebuffers) (1, &mFboHandle);
-
- if (mFBTexture)
- glDeleteTextures (1, &mFBTexture);
-}
-
-#endif // USE_GLES
-
diff --git a/plugins/unityshell/src/ScreenEffectFramebufferObject.h b/plugins/unityshell/src/ScreenEffectFramebufferObject.h
deleted file mode 100644
index 9ccfb9a92..000000000
--- a/plugins/unityshell/src/ScreenEffectFramebufferObject.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
-/* Compiz unity plugin
- * unity.h
- *
- * Copyright (c) 2010-11 Canonical Ltd.
- *
- * This program 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 3
- * of the License, or (at your option) any later version.
- *
- * 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.
- *
- * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
- */
-
-#ifndef UNITY_SCREENEFFECT_FRAMEBUFFER_H
-#define UNITY_SCREENEFFECT_FRAMEBUFFER_H
-
-#ifndef USE_MODERN_COMPIZ_GL
-#include <Nux/Nux.h>
-
-namespace unity
-{
-class ScreenEffectFramebufferObject
-{
-public:
-
- typedef boost::shared_ptr <ScreenEffectFramebufferObject> Ptr;
- typedef void (*FuncPtr) (void);
- typedef FuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
-
- ScreenEffectFramebufferObject (GLXGetProcAddressProc, const nux::Geometry &geom);
- ~ScreenEffectFramebufferObject ();
-
-public:
-
- void bind (const nux::Geometry &geom);
- void unbind ();
-
- bool status ();
- void paint (const nux::Geometry &geom);
- bool bound () { return mBoundCnt > 0; }
-
- GLuint texture () { return mFBTexture; }
-
- void onScreenSizeChanged (const nux::Geometry &screenSize);
-
-private:
-
- FuncPtr getProcAddr (const std::string &);
-
- typedef void (*GLActiveTextureProc) (GLenum texture);
- typedef void (*GLGenFramebuffersProc) (GLsizei n,
- GLuint *framebuffers);
- typedef void (*GLDeleteFramebuffersProc) (GLsizei n,
- GLuint *framebuffers);
- typedef void (*GLBindFramebufferProc) (GLenum target,
- GLuint framebuffer);
- typedef GLenum (*GLCheckFramebufferStatusProc) (GLenum target);
- typedef void (*GLFramebufferTexture2DProc) (GLenum target,
- GLenum attachment,
- GLenum textarget,
- GLuint texture,
- GLint level);
-
- GLXGetProcAddressProc getProcAddressGLX;
- GLActiveTextureProc activeTexture;
- GLGenFramebuffersProc genFramebuffers;
- GLDeleteFramebuffersProc deleteFramebuffers;
- GLBindFramebufferProc bindFramebuffer;
- GLCheckFramebufferStatusProc checkFramebufferStatus;
- GLFramebufferTexture2DProc framebufferTexture2D;
- /* compiz fbo handle that goes through to nux */
- GLuint mFboHandle; // actual handle to the framebuffer_ext
- bool mFboStatus; // did the framebuffer texture bind succeed
- GLuint mFBTexture;
- nux::Geometry mGeometry;
- unsigned int mBoundCnt;
-
- nux::Geometry mScreenSize;
-};
-} // namespace unity
-
-#endif // USE_MODERN_COMPIZ_GL
-#endif
diff --git a/plugins/unityshell/src/WindowMinimizeSpeedController.cpp b/plugins/unityshell/src/WindowMinimizeSpeedController.cpp
new file mode 100644
index 000000000..66f28d8fc
--- /dev/null
+++ b/plugins/unityshell/src/WindowMinimizeSpeedController.cpp
@@ -0,0 +1,108 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/* Compiz unity plugin
+ * unity.h
+ *
+ * Copyright (c) 2010-11 Canonical Ltd.
+ *
+ * This program 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 3
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * Your own copyright notice would go above. You are free to choose whatever
+ * licence you want, just take note that some compiz code is GPL and you will
+ * not be able to re-use it if you want to use a different licence.
+ */
+
+#include <gio/gio.h>
+#include <NuxCore/Logger.h>
+
+#include "WindowMinimizeSpeedController.h"
+
+namespace
+{
+
+nux::logging::Logger logger ("unity.WindowMinimizeSpeedController");
+
+namespace local
+{
+const std::string UNITY_SCHEMA = "com.canonical.Unity";
+}
+}
+
+WindowMinimizeSpeedController::WindowMinimizeSpeedController()
+ : _settings(g_settings_new(local::UNITY_SCHEMA.c_str()))
+ , _minimize_count(g_settings_get_int(_settings, "minimize-count"))
+ , _minimize_speed_threshold(g_settings_get_int(_settings, "minimize-speed-threshold"))
+ , _minimize_slow_duration(g_settings_get_int(_settings, "minimize-slow-duration"))
+ , _minimize_fast_duration(g_settings_get_int(_settings, "minimize-fast-duration"))
+{
+ _minimize_count_changed.Connect(_settings, "changed::minimize-count",
+ [&] (GSettings*, gchar* name) {
+ _minimize_count = g_settings_get_int(_settings, name);
+ SetDuration();
+ });
+ _minimize_speed_threshold_changed.Connect(_settings, "changed::minimize-speed-threshold",
+ [&] (GSettings*, gchar* name) {
+ _minimize_speed_threshold = g_settings_get_int(_settings, name);
+ SetDuration();
+ });
+ _minimize_fast_duration_changed.Connect(_settings, "changed::minimize-fast-duration",
+ [&] (GSettings*, gchar* name) {
+ _minimize_fast_duration = g_settings_get_int(_settings, name);
+ SetDuration();
+ });
+ _minimize_slow_duration_changed.Connect(_settings, "changed::minimize-slow-duration",
+ [&] (GSettings*, gchar* name) {
+ _minimize_slow_duration = g_settings_get_int(_settings, name);
+ SetDuration();
+ });
+}
+
+void WindowMinimizeSpeedController::UpdateCount()
+{
+ if (_minimize_count < _minimize_speed_threshold) {
+ _minimize_count += 1;
+ g_settings_set_int(_settings, "minimize-count", _minimize_count);
+ }
+}
+
+int WindowMinimizeSpeedController::getDuration()
+{
+ return mDuration;
+}
+
+void WindowMinimizeSpeedController::SetDuration()
+{
+ /* Perform some sanity checks on the configuration values */
+ if (_minimize_fast_duration > _minimize_slow_duration)
+ {
+ LOG_WARN(logger) << "Configuration mismatch: minimize-fast-duration ("
+ << _minimize_fast_duration
+ << ") is longer than minimize-slow-duration ("
+ << _minimize_slow_duration << "). Not changing speed.";
+ return;
+ }
+
+ if (_minimize_count < 0)
+ _minimize_count = 0;
+ if (_minimize_count > _minimize_speed_threshold)
+ _minimize_count = _minimize_speed_threshold;
+
+ /* Adjust the speed so that it gets linearly closer to maximum speed as we
+ approach the threshold */
+ int speed_range = _minimize_slow_duration - _minimize_fast_duration;
+ float position = (_minimize_speed_threshold <= 0) ? 1.0 :
+ static_cast<float>(_minimize_count) / _minimize_speed_threshold;
+ int duration = _minimize_slow_duration - std::ceil(position * speed_range);
+
+ if (duration != mDuration) {
+ mDuration = duration;
+ DurationChanged.emit();
+ }
+}
diff --git a/plugins/unityshell/src/WindowMinimizeSpeedController.h b/plugins/unityshell/src/WindowMinimizeSpeedController.h
new file mode 100644
index 000000000..49bcbad14
--- /dev/null
+++ b/plugins/unityshell/src/WindowMinimizeSpeedController.h
@@ -0,0 +1,57 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/* Compiz unity plugin
+ * unity.h
+ *
+ * Copyright (c) 2010-11 Canonical Ltd.
+ *
+ * This program 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 3
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * Your own copyright notice would go above. You are free to choose whatever
+ * licence you want, just take note that some compiz code is GPL and you will
+ * not be able to re-use it if you want to use a different licence.
+ */
+
+#ifndef WINDOWMINIMIZESPEEDCONTROLLER_H
+#define WINDOWMINIMIZESPEEDCONTROLLER_H
+
+#include <core/core.h>
+#include <UnityCore/GLibWrapper.h>
+#include <UnityCore/GLibSignal.h>
+#include <sigc++/sigc++.h>
+
+typedef struct _GSettings GSettings;
+
+using namespace unity;
+
+class WindowMinimizeSpeedController
+{
+public:
+ WindowMinimizeSpeedController();
+ void UpdateCount();
+ int getDuration();
+ sigc::signal<void> DurationChanged;
+
+private:
+ void SetDuration();
+
+ glib::Object<GSettings> _settings;
+ int _minimize_count;
+ int _minimize_speed_threshold;
+ int _minimize_slow_duration;
+ int _minimize_fast_duration;
+ glib::Signal<void, GSettings*, gchar* > _minimize_count_changed;
+ glib::Signal<void, GSettings*, gchar* > _minimize_speed_threshold_changed;
+ glib::Signal<void, GSettings*, gchar* > _minimize_slow_duration_changed;
+ glib::Signal<void, GSettings*, gchar* > _minimize_fast_duration_changed;
+ int mDuration;
+};
+
+#endif // WINDOWMINIMIZESPEEDCONTROLLER_H
diff --git a/plugins/unityshell/src/unitya11y.cpp b/plugins/unityshell/src/unitya11y.cpp
index 9a8c143d9..1035af609 100644
--- a/plugins/unityshell/src/unitya11y.cpp
+++ b/plugins/unityshell/src/unitya11y.cpp
@@ -20,6 +20,7 @@
#include <gio/gio.h>
#include <gmodule.h>
#include <stdio.h>
+#include <atk-bridge.h>
#include "unitya11y.h"
#include "unitya11ytests.h"
@@ -62,12 +63,6 @@ static GHashTable* accessible_table = NULL;
static gboolean a11y_initialized = FALSE;
-#define INIT_METHOD "gnome_accessibility_module_init"
-#define DESKTOP_SCHEMA "org.gnome.desktop.interface"
-#define ACCESSIBILITY_ENABLED_KEY "toolkit-accessibility"
-#define AT_SPI_SCHEMA "org.a11y.atspi"
-#define ATK_BRIDGE_LOCATION_KEY "atk-bridge-location"
-
static void
unity_a11y_restore_environment(void)
{
@@ -82,102 +77,6 @@ load_unity_atk_util(nux::WindowThread* wt)
g_type_class_unref(g_type_class_ref(UNITY_TYPE_UTIL_ACCESSIBLE));
}
-/* This method is required because g_setting_new aborts if the schema
- is not present. */
-static gboolean
-has_gsettings_schema(const gchar* schema)
-{
- const char* const* list_schemas = NULL;
- gboolean found = FALSE;
- int i = 0;
-
- list_schemas = g_settings_list_schemas();
- for (i = 0; list_schemas [i]; i++)
- {
- if (!g_strcmp0(list_schemas[i], schema))
- {
- found = TRUE;
- break;
- }
- }
-
- return found;
-}
-
-static gboolean
-should_enable_a11y(void)
-{
- GSettings* desktop_settings = NULL;
- gboolean value = FALSE;
-
- if (!has_gsettings_schema(DESKTOP_SCHEMA))
- return FALSE;
-
- desktop_settings = g_settings_new(DESKTOP_SCHEMA);
- value = g_settings_get_boolean(desktop_settings, ACCESSIBILITY_ENABLED_KEY);
-
- g_object_unref(desktop_settings);
-
- return value;
-}
-
-static gchar*
-get_atk_bridge_path(void)
-{
- GSettings* atspi_settings = NULL;
- GVariant *variant = NULL;
- char* value = NULL;
-
- if (!has_gsettings_schema(AT_SPI_SCHEMA))
- return NULL;
-
- atspi_settings = g_settings_new(AT_SPI_SCHEMA);
- variant = g_settings_get_value (atspi_settings, ATK_BRIDGE_LOCATION_KEY);
- value = g_variant_dup_bytestring (variant, NULL);
-
- g_variant_unref (variant);
- g_object_unref(atspi_settings);
-
- return value;
-}
-
-static gboolean
-a11y_invoke_module(const char* module_path)
-{
- GModule* handle;
- void (*invoke_fn)(void);
-
- if (!module_path)
- {
- g_warning("Accessibility: invalid module path (NULL)");
-
- return FALSE;
- }
-
- if (!(handle = g_module_open(module_path, (GModuleFlags)0)))
- {
- g_warning("Accessibility: failed to load module '%s': '%s'",
- module_path, g_module_error());
-
- return FALSE;
- }
-
- if (!g_module_symbol(handle, INIT_METHOD, (gpointer*)&invoke_fn))
- {
- g_warning("Accessibility: error library '%s' does not include "
- "method '%s' required for accessibility support",
- module_path, INIT_METHOD);
- g_module_close(handle);
-
- return FALSE;
- }
-
- invoke_fn();
-
- return TRUE;
-}
-
-/********************************************************************************/
/*
* In order to avoid the atk-bridge loading and the GAIL
* initialization during the gtk_init, it is required to set some
@@ -194,35 +93,19 @@ unity_a11y_preset_environment(void)
/*
* Initializes the accessibility (ATK) support on Unity
*
- * It loads the atk-bridge if required. It checks:
- * * If the proper gsettings keys are set
- * * Loads the proper AtkUtil implementation
*/
void
unity_a11y_init(nux::WindowThread* wt)
{
- gchar* bridge_path = NULL;
-
- unity_a11y_restore_environment();
-
- if (!should_enable_a11y())
+ if (a11y_initialized)
return;
+ unity_a11y_restore_environment();
load_unity_atk_util(wt);
+ atk_bridge_adaptor_init(NULL, NULL);
+ atk_get_root();
- bridge_path = get_atk_bridge_path();
-
- if (a11y_invoke_module(bridge_path))
- {
- g_debug("Unity Oneiric accessibility started, using bridge on %s",
- bridge_path);
-
- atk_get_root();
-
- a11y_initialized = TRUE;
- }
-
- g_free(bridge_path);
+ a11y_initialized = TRUE;
// NOTE: we run the unit tests manually while developing by
// uncommenting this. Take a look at the explanation in the
diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp
index 17a2bb9c2..0ec87f497 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 "DevicesSettings.h"
#include "PluginAdapter.h"
#include "QuicklistManager.h"
#include "StartupNotifyService.h"
@@ -44,6 +43,9 @@
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <libnotify/notify.h>
+#include <cairo-xlib-xrender.h>
+
+#include <text/text.h>
#include <sstream>
#include <memory>
@@ -81,6 +83,9 @@ nux::logging::Logger logger("unity.shell");
UnityScreen* uScreen = 0;
+const unsigned int SCALE_CLOSE_ICON_SIZE = 19;
+const unsigned int SCALE_ITEMS_PADDING = 5;
+
void reset_glib_logging();
void configure_logging();
void capture_g_log_calls(const gchar* log_domain,
@@ -119,9 +124,6 @@ UnityScreen::UnityScreen(CompScreen* screen)
, allowWindowPaint(false)
, _key_nav_mode_requested(false)
, _last_output(nullptr)
-#ifndef USE_MODERN_COMPIZ_GL
- , _active_fbo (0)
-#endif
, grab_index_ (0)
, painting_tray_ (false)
, last_scroll_event_(0)
@@ -129,6 +131,8 @@ UnityScreen::UnityScreen(CompScreen* screen)
, panel_texture_has_changed_(true)
, paint_panel_(false)
, scale_just_activated_(false)
+ , scale_highlighted_window_(0)
+ , minimize_speed_controller(new WindowMinimizeSpeedController())
{
Timer timer;
#ifndef USE_GLES
@@ -243,25 +247,6 @@ UnityScreen::UnityScreen(CompScreen* screen)
uScreen = this;
_in_paint = false;
-#ifndef USE_MODERN_COMPIZ_GL
- void *dlhand = dlopen ("libunityshell.so", RTLD_LAZY);
-
- if (dlhand)
- {
- dlerror ();
- glXGetProcAddressP = (ScreenEffectFramebufferObject::GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
- if (dlerror () != NULL)
- glXGetProcAddressP = NULL;
- }
-
- if (GL::fbo)
- {
- nux::Geometry geometry (0, 0, screen->width (), screen->height ());
- uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
- uScreen->_fbo->onScreenSizeChanged (geometry);
- }
-#endif
-
optionSetShowHudInitiate(boost::bind(&UnityScreen::ShowHudInitiate, this, _1, _2, _3));
optionSetShowHudTerminate(boost::bind(&UnityScreen::ShowHudTerminate, this, _1, _2, _3));
optionSetBackgroundColorNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
@@ -281,7 +266,6 @@ UnityScreen::UnityScreen(CompScreen* screen)
optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
- optionSetDevicesOptionNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetShortcutOverlayNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetShowDesktopIconNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
@@ -386,6 +370,11 @@ UnityScreen::UnityScreen(CompScreen* screen)
}
panel::Style::Instance().changed.connect(sigc::mem_fun(this, &UnityScreen::OnPanelStyleChanged));
+ WindowManager::Default()->terminate_spread.connect([this] { scale_highlighted_window_ = 0; });
+
+ minimize_speed_controller->DurationChanged.connect(
+ sigc::mem_fun(this, &UnityScreen::OnMinimizeDurationChanged)
+ );
}
UnityScreen::~UnityScreen()
@@ -495,17 +484,6 @@ void UnityScreen::nuxPrologue()
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
-
-#ifndef USE_MODERN_COMPIZ_GL
- /* 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
#endif
glGetError();
@@ -514,9 +492,6 @@ void UnityScreen::nuxPrologue()
void UnityScreen::nuxEpilogue()
{
#ifndef USE_GLES
-#ifndef USE_MODERN_COMPIZ_GL
- (*GL::bindFramebuffer)(GL_FRAMEBUFFER_EXT, _active_fbo);
-#endif
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@@ -538,19 +513,9 @@ void UnityScreen::nuxEpilogue()
glPopAttrib();
-#ifndef USE_MODERN_COMPIZ_GL
- /* Re-enable the client states that have been disabled in nuxPrologue, for
- * NVIDIA compatibility reasons */
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-#endif
+ glDepthRange(0, 1);
#else
-#ifdef USE_GLES
glDepthRangef(0, 1);
-#else
- glDepthRange(0, 1);
-#endif
- //glViewport(-1, -1, 2, 2);
gScreen->resetRasterPos();
#endif
@@ -562,86 +527,9 @@ void UnityScreen::setPanelShadowMatrix(const GLMatrix& matrix)
panel_shadow_matrix_ = matrix;
}
+/* Currently unimplemented */
void UnityScreen::paintPanelShadow(const GLMatrix& matrix)
{
-#ifndef USE_MODERN_COMPIZ_GL
- if (sources_.GetSource(local::RELAYOUT_TIMEOUT))
- return;
-
- if (PluginAdapter::Default()->IsExpoActive())
- return;
-
- CompOutput* output = _last_output;
- float vc[4];
- float h = 20.0f;
- float w = 1.0f;
- float panel_h = panel_style_.panel_height;
-
- float x1 = output->x();
- float y1 = output->y() + panel_h;
- float x2 = x1 + output->width();
- float y2 = y1 + h;
-
- glPushMatrix ();
- glLoadMatrixf (panel_shadow_matrix_.getMatrix ());
-
- vc[0] = x1;
- vc[1] = x2;
- vc[2] = y1;
- vc[3] = y2;
-
- // compiz doesn't use the same method of tracking monitors as our toolkit
- // we need to make sure we properly associate with the right monitor
- int current_monitor = -1;
- auto monitors = UScreen::GetDefault()->GetMonitors();
- int i = 0;
- for (auto monitor : monitors)
- {
- if (monitor.x == output->x() && monitor.y == output->y())
- {
- current_monitor = i;
- break;
- }
- i++;
- }
-
- if (!(launcher_controller_->IsOverlayOpen() && current_monitor == dash_monitor_)
- && panel_controller_->opacity() > 0.0f)
- {
- foreach(GLTexture * tex, _shadow_texture)
- {
- glEnable(GL_BLEND);
- glColor4f(1.0f, 1.0f, 1.0f, panel_controller_->opacity());
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- GL::activeTexture(GL_TEXTURE0_ARB);
- tex->enable(GLTexture::Fast);
-
- glTexParameteri(tex->target(), GL_TEXTURE_WRAP_S, GL_REPEAT);
-
- glBegin(GL_QUADS);
- {
- glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), 0));
- glVertex2f(vc[0], vc[2]);
-
- glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), 0), COMP_TEX_COORD_Y(tex->matrix(), h));
- glVertex2f(vc[0], vc[3]);
-
- glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), h));
- glVertex2f(vc[1], vc[3]);
-
- glTexCoord2f(COMP_TEX_COORD_X(tex->matrix(), w), COMP_TEX_COORD_Y(tex->matrix(), 0));
- glVertex2f(vc[1], vc[2]);
- }
- glEnd();
-
- tex->disable();
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glDisable(GL_BLEND);
- }
- }
- glPopMatrix();
-#else
return;
if (sources_.GetSource(local::RELAYOUT_TIMEOUT))
@@ -735,7 +623,6 @@ void UnityScreen::paintPanelShadow(const GLMatrix& matrix)
}
}
nuxEpilogue();
-#endif
}
void
@@ -756,90 +643,32 @@ UnityScreen::OnPanelStyleChanged()
panel_texture_has_changed_ = true;
}
-#ifdef USE_MODERN_COMPIZ_GL
void UnityScreen::paintDisplay()
-#else
-void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask)
-#endif
{
CompOutput *output = _last_output;
-#ifndef USE_MODERN_COMPIZ_GL
- bool was_bound = _fbo->bound ();
-
- if (nux::GetGraphicsDisplay()->GetGraphicsEngine()->UsingGLSLCodePath())
- {
- if (was_bound && launcher_controller_->IsOverlayOpen() && paint_panel_)
- {
- if (panel_texture_has_changed_ || !panel_texture_.IsValid())
- {
- panel_texture_.Release();
-
- nux::NBitmapData* bitmap = panel::Style::Instance().GetBackground(screen->width (), screen->height(), 1.0f);
- nux::BaseTexture* texture2D = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
- if (bitmap && texture2D)
- {
- texture2D->Update(bitmap);
- panel_texture_ = texture2D->GetDeviceTexture();
- texture2D->UnReference();
- delete bitmap;
- }
- panel_texture_has_changed_ = false;
- }
-
- if (panel_texture_.IsValid())
- {
- nux::GetGraphicsDisplay()->GetGraphicsEngine()->ResetModelViewMatrixStack();
- nux::GetGraphicsDisplay()->GetGraphicsEngine()->Push2DTranslationModelViewMatrix(0.0f, 0.0f, 0.0f);
- nux::GetGraphicsDisplay()->GetGraphicsEngine()->ResetProjectionMatrix();
- nux::GetGraphicsDisplay()->GetGraphicsEngine()->SetOrthographicProjectionMatrix(screen->width (), screen->height());
-
- nux::TexCoordXForm texxform;
- int panel_height = panel_style_.panel_height;
- nux::GetGraphicsDisplay()->GetGraphicsEngine()->QRP_GLSL_1Tex(0, 0, screen->width (), panel_height, panel_texture_, texxform, nux::color::White);
- }
- }
- }
+ DrawTopPanelBackground();
- _fbo->unbind ();
+ auto gpu_device = nux::GetGraphicsDisplay()->GetGpuDevice();
- /* Draw the bit of the relevant framebuffer for each output */
-
- if (was_bound)
- {
- GLMatrix sTransform;
- sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA);
- glPushMatrix ();
- glLoadMatrixf (sTransform.getMatrix ());
- _fbo->paint (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
- glPopMatrix ();
- }
-
- nux::ObjectPtr<nux::IOpenGLBaseTexture> device_texture =
- nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(_fbo->texture(),
- screen->width (), screen->height(), 1, nux::BITFMT_R8G8B8A8);
-#else
nux::ObjectPtr<nux::IOpenGLTexture2D> device_texture =
- nux::GetGraphicsDisplay()->GetGpuDevice()->CreateTexture2DFromID(gScreen->fbo ()->tex ()->name (),
- screen->width(), screen->height(), 1, nux::BITFMT_R8G8B8A8);
-#endif
+ gpu_device->CreateTexture2DFromID(gScreen->fbo ()->tex ()->name (),
+ screen->width(), screen->height(), 1, nux::BITFMT_R8G8B8A8);
- nux::GetGraphicsDisplay()->GetGpuDevice()->backup_texture0_ = device_texture;
+ gpu_device->backup_texture0_ = device_texture;
- nux::Geometry geo = nux::Geometry (0, 0, screen->width (), screen->height ());
- nux::Geometry oGeo = nux::Geometry (output->x (), output->y (), output->width (), output->height ());
+ nux::Geometry geo(0, 0, screen->width (), screen->height ());
+ nux::Geometry outputGeo(output->x (), output->y (), output->width (), output->height ());
BackgroundEffectHelper::monitor_rect_ = geo;
-#ifdef USE_MODERN_COMPIZ_GL
GLint fboID;
// Nux renders to the referenceFramebuffer when it's embedded.
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fboID);
- wt->GetWindowCompositor().SetReferenceFramebuffer(fboID, oGeo);
-#endif
+ wt->GetWindowCompositor().SetReferenceFramebuffer(fboID, outputGeo);
nuxPrologue();
_in_paint = true;
- wt->RenderInterfaceFromForeignCmd (&oGeo);
+ wt->RenderInterfaceFromForeignCmd (&outputGeo);
_in_paint = false;
nuxEpilogue();
@@ -853,56 +682,28 @@ void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transfo
{
GLMatrix oTransform;
UnityWindow *uTrayWindow = UnityWindow::get (tray);
-#ifndef USE_MODERN_COMPIZ_GL
- GLFragment::Attrib attrib (uTrayWindow->gWindow->lastPaintAttrib());
-#else
GLWindowPaintAttrib attrib (uTrayWindow->gWindow->lastPaintAttrib());
-#endif
unsigned int oldGlAddGeometryIndex = uTrayWindow->gWindow->glAddGeometryGetCurrentIndex ();
unsigned int oldGlDrawIndex = uTrayWindow->gWindow->glDrawGetCurrentIndex ();
-#ifndef USE_MODERN_COMPIZ_GL
- unsigned int oldGlDrawGeometryIndex = uTrayWindow->gWindow->glDrawGeometryGetCurrentIndex ();
-#endif
-#ifndef USE_MODERN_COMPIZ_GL
- attrib.setOpacity (OPAQUE);
- attrib.setBrightness (BRIGHT);
- attrib.setSaturation (COLOR);
-#else
attrib.opacity = OPAQUE;
attrib.brightness = BRIGHT;
attrib.saturation = COLOR;
-#endif
oTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
-#ifndef USE_MODERN_COMPIZ_GL
- glPushMatrix ();
- glLoadMatrixf (oTransform.getMatrix ());
-#endif
-
painting_tray_ = true;
/* force the use of the core functions */
uTrayWindow->gWindow->glDrawSetCurrentIndex (MAXSHORT);
uTrayWindow->gWindow->glAddGeometrySetCurrentIndex ( MAXSHORT);
-#ifndef USE_MODERN_COMPIZ_GL
- uTrayWindow->gWindow->glDrawGeometrySetCurrentIndex (MAXSHORT);
-#endif
uTrayWindow->gWindow->glDraw (oTransform, attrib, infiniteRegion,
PAINT_WINDOW_TRANSFORMED_MASK |
PAINT_WINDOW_BLEND_MASK |
PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK);
-#ifndef USE_MODERN_COMPIZ_GL
- uTrayWindow->gWindow->glDrawGeometrySetCurrentIndex (oldGlDrawGeometryIndex);
-#endif
uTrayWindow->gWindow->glAddGeometrySetCurrentIndex (oldGlAddGeometryIndex);
uTrayWindow->gWindow->glDrawSetCurrentIndex (oldGlDrawIndex);
painting_tray_ = false;
-
-#ifndef USE_MODERN_COMPIZ_GL
- glPopMatrix ();
-#endif
}
}
}
@@ -927,6 +728,53 @@ void UnityScreen::paintDisplay(const CompRegion& region, const GLMatrix& transfo
didShellRepaint = true;
}
+void UnityScreen::DrawTopPanelBackground()
+{
+ auto graphics_engine = nux::GetGraphicsDisplay()->GetGraphicsEngine();
+
+ if (!graphics_engine->UsingGLSLCodePath() || !launcher_controller_->IsOverlayOpen() || !paint_panel_)
+ return;
+
+ if (TopPanelBackgroundTextureNeedsUpdate())
+ UpdateTopPanelBackgroundTexture();
+
+ if (panel_texture_.IsValid())
+ {
+ graphics_engine->ResetModelViewMatrixStack();
+ graphics_engine->Push2DTranslationModelViewMatrix(0.0f, 0.0f, 0.0f);
+ graphics_engine->ResetProjectionMatrix();
+ graphics_engine->SetOrthographicProjectionMatrix(screen->width (), screen->height());
+
+ nux::TexCoordXForm texxform;
+ int panel_height = panel_style_.panel_height;
+ graphics_engine->QRP_GLSL_1Tex(0, 0, screen->width (), panel_height, panel_texture_, texxform, nux::color::White);
+ }
+}
+
+bool UnityScreen::TopPanelBackgroundTextureNeedsUpdate() const
+{
+ return panel_texture_has_changed_ || !panel_texture_.IsValid();
+}
+
+void UnityScreen::UpdateTopPanelBackgroundTexture()
+{
+ auto gpu_device = nux::GetGraphicsDisplay()->GetGpuDevice();
+ auto &panel_style = panel::Style::Instance();
+
+ panel_texture_.Release();
+
+ std::unique_ptr<nux::NBitmapData> bitmap(panel_style.GetBackground(screen->width(), screen->height(), 1.0f));
+ nux::ObjectPtr<nux::BaseTexture> texture2D(gpu_device->CreateSystemCapableTexture());
+
+ if (bitmap && texture2D)
+ {
+ texture2D->Update(bitmap.get());
+ panel_texture_ = texture2D->GetDeviceTexture();
+ }
+
+ panel_texture_has_changed_ = false;
+}
+
bool UnityScreen::forcePaintOnTop ()
{
return !allowWindowPaint ||
@@ -1055,8 +903,8 @@ void UnityScreen::leaveShowDesktopMode (CompWindow *w)
void UnityWindow::enterShowDesktop ()
{
if (!mShowdesktopHandler)
- mShowdesktopHandler = new ShowdesktopHandler (static_cast <ShowdesktopHandlerWindowInterface *> (this),
- static_cast <compiz::WindowInputRemoverLockAcquireInterface *> (this));
+ mShowdesktopHandler.reset(new ShowdesktopHandler(static_cast <ShowdesktopHandlerWindowInterface *>(this),
+ static_cast <compiz::WindowInputRemoverLockAcquireInterface *>(this)));
window->setShowDesktopMode (true);
mShowdesktopHandler->FadeOut ();
@@ -1177,15 +1025,14 @@ ShowdesktopHandlerWindowInterface::PostPaintAction UnityWindow::DoHandleAnimatio
return action;
}
-void UnityWindow::DoAddDamage ()
+void UnityWindow::DoAddDamage()
{
- cWindow->addDamage ();
+ cWindow->addDamage();
}
void UnityWindow::DoDeleteHandler ()
{
- delete mShowdesktopHandler;
- mShowdesktopHandler = NULL;
+ mShowdesktopHandler.reset();
window->updateFrameRegion ();
}
@@ -1207,15 +1054,74 @@ UnityWindow::GetNoCoreInstanceMask ()
return PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
}
-void UnityWindow::handleEvent (XEvent *event)
+bool UnityWindow::handleEvent(XEvent *event)
{
- if (screen->XShape () &&
- event->type == screen->shapeEvent () + ShapeNotify &&
- !event->xany.send_event)
+ bool handled = false;
+
+ switch(event->type)
{
- if (mShowdesktopHandler)
- mShowdesktopHandler->HandleShapeEvent ();
+ case MotionNotify:
+ if (close_icon_state_ != panel::WindowState::PRESSED)
+ {
+ panel::WindowState old_state = close_icon_state_;
+
+ if (close_button_geo_.IsPointInside(event->xmotion.x_root, event->xmotion.y_root))
+ {
+ close_icon_state_ = panel::WindowState::PRELIGHT;
+ }
+ else
+ {
+ close_icon_state_ = panel::WindowState::NORMAL;
+ }
+
+ if (old_state != close_icon_state_)
+ DoAddDamage();
+ }
+ break;
+
+ case ButtonPress:
+ if (event->xbutton.button == Button1 &&
+ close_button_geo_.IsPointInside(event->xbutton.x_root, event->xbutton.y_root))
+ {
+ close_icon_state_ = panel::WindowState::PRESSED;
+ DoAddDamage();
+ handled = true;
+ }
+ break;
+
+ case ButtonRelease:
+ {
+ bool was_pressed = (close_icon_state_ == panel::WindowState::PRESSED);
+
+ if (close_icon_state_ != panel::WindowState::NORMAL)
+ {
+ close_icon_state_ = panel::WindowState::NORMAL;
+ DoAddDamage();
+ }
+
+ if (was_pressed)
+ {
+ if (close_button_geo_.IsPointInside(event->xbutton.x_root, event->xbutton.y_root))
+ window->close(0);
+
+ handled = true;
+ }
+ }
+ break;
+
+ default:
+ if (!event->xany.send_event && screen->XShape() &&
+ event->type == screen->shapeEvent() + ShapeNotify)
+ {
+ if (mShowdesktopHandler)
+ {
+ mShowdesktopHandler->HandleShapeEvent();
+ handled = true;
+ }
+ }
}
+
+ return handled;
}
bool UnityScreen::shellCouldBeHidden(CompOutput const& output)
@@ -1281,26 +1187,6 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
_last_output = output;
paint_panel_ = false;
-#ifndef USE_MODERN_COMPIZ_GL
- /* bind the framebuffer here
- * - it will be unbound and flushed
- * to the backbuffer when some
- * plugin requests to draw a
- * a transformed screen or when
- * we have finished this draw cycle.
- * once an fbo is bound any further
- * attempts to bind it will only increment
- * its bind reference so make sure that
- * you always unbind as much as you bind
- *
- * But NOTE: It is only safe to bind the FBO if !shellCouldBeHidden.
- * Otherwise it's possible painting won't occur and that would
- * confuse the state of the FBO.
- */
- if (doShellRepaint && !shellCouldBeHidden(*output))
- _fbo->bind (nux::Geometry (output->x (), output->y (), output->width (), output->height ()));
-#endif
-
// CompRegion has no clear() method. So this is the fastest alternative.
fullscreenRegion = CompRegion();
nuxRegion = CompRegion();
@@ -1312,11 +1198,7 @@ bool UnityScreen::glPaintOutput(const GLScreenPaintAttrib& attrib,
doShellRepaint = false;
if (doShellRepaint)
-#ifdef USE_MODERN_COMPIZ_GL
paintDisplay();
-#else
- paintDisplay(region, transform, mask);
-#endif
return ret;
}
@@ -1346,10 +1228,6 @@ void UnityScreen::preparePaint(int ms)
for (ShowdesktopHandlerWindowInterface *wi : ShowdesktopHandler::animating_windows)
wi->HandleAnimations (ms);
-#ifndef USE_MODERN_COMPIZ_GL
- compizDamageNux(cScreen->currentDamage());
-#endif
-
didShellRepaint = false;
firstWindowAboveShell = NULL;
}
@@ -1476,7 +1354,6 @@ void UnityScreen::compizDamageNux(CompRegion const& damage)
/* Grab changed nux regions and add damage rects for them */
void UnityScreen::nuxDamageCompiz()
{
-#ifdef USE_MODERN_COMPIZ_GL
/*
* If Nux is going to redraw anything then we have to tell Compiz to
* redraw everything. This is because Nux has a bad habit (bug??) of drawing
@@ -1496,60 +1373,6 @@ void UnityScreen::nuxDamageCompiz()
cScreen->damageScreen();
cScreen->damageRegionSetEnabled(this, true);
}
-
-#else
-
- /*
- * WARNING: Nux bug LP: #1014610 (unbounded DrawList growth) will cause
- * this code to be called far too often in some cases and
- * Unity will appear to freeze for a while. Please ensure you
- * have Nux 3.0+ with the fix for LP: #1014610.
- */
-
- if (!launcher_controller_ || !dash_controller_)
- return;
-
- CompRegion nux_damage;
-
- std::vector<nux::Geometry> const& dirty = wt->GetDrawList();
-
- for (auto const& geo : dirty)
- nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
-
- if (launcher_controller_->IsOverlayOpen())
- {
- nux::BaseWindow* dash_window = dash_controller_->window();
- nux::Geometry const& geo = dash_window->GetAbsoluteGeometry();
- nux_damage += CompRegion(geo.x, geo.y, geo.width, geo.height);
- }
-
- auto const& launchers = launcher_controller_->launchers();
- for (auto const& launcher : launchers)
- {
- if (!launcher->Hidden())
- {
- nux::ObjectPtr<nux::View> tooltip = launcher->GetActiveTooltip();
-
- if (tooltip)
- {
- nux::Geometry const& g = tooltip->GetAbsoluteGeometry();
- nux_damage += CompRegion(g.x, g.y, g.width, g.height);
- }
-
- nux::ObjectPtr<LauncherDragWindow> const& dragged_icon = launcher->GetDraggedIcon();
-
- if (dragged_icon)
- {
- nux::Geometry const& g = dragged_icon->GetAbsoluteGeometry();
- nux_damage += CompRegion(g.x, g.y, g.width, g.height);
- }
- }
- }
-
- cScreen->damageRegionSetEnabled(this, false);
- cScreen->damageRegion(nux_damage);
- cScreen->damageRegionSetEnabled(this, true);
-#endif
}
/* handle X Events */
@@ -1564,9 +1387,6 @@ void UnityScreen::handleEvent(XEvent* event)
PluginAdapter::Default()->OnScreenGrabbed();
else if (event->xfocus.mode == NotifyUngrab)
PluginAdapter::Default()->OnScreenUngrabbed();
-#ifndef USE_MODERN_COMPIZ_GL
- cScreen->damageScreen(); // evil hack
-#endif
if (_key_nav_mode_requested)
{
// Close any overlay that is open.
@@ -1579,12 +1399,25 @@ void UnityScreen::handleEvent(XEvent* event)
}
_key_nav_mode_requested = false;
break;
+ case MotionNotify:
+ if (scale_highlighted_window_ && PluginAdapter::Default()->IsScaleActive())
+ {
+ if (CompWindow *w = screen->findWindow(scale_highlighted_window_))
+ skip_other_plugins = UnityWindow::get(w)->handleEvent(event);
+ }
+ break;
case ButtonPress:
if (super_keypressed_)
{
launcher_controller_->KeyNavTerminate(false);
EnableCancelAction(CancelActionTarget::LAUNCHER_SWITCHER, false);
}
+ if (scale_highlighted_window_ && PluginAdapter::Default()->IsScaleActive())
+ {
+ if (CompWindow *w = screen->findWindow(scale_highlighted_window_))
+ skip_other_plugins = UnityWindow::get(w)->handleEvent(event);
+ }
+
break;
case ButtonRelease:
if (switcher_controller_ && switcher_controller_->Visible())
@@ -1604,6 +1437,11 @@ void UnityScreen::handleEvent(XEvent* event)
}
}
}
+ else if (scale_highlighted_window_ && PluginAdapter::Default()->IsScaleActive())
+ {
+ if (CompWindow *w = screen->findWindow(scale_highlighted_window_))
+ UnityWindow::get(w)->handleEvent(event);
+ }
break;
case KeyPress:
{
@@ -1731,8 +1569,8 @@ void UnityScreen::handleCompizEvent(const char* plugin,
ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
}
- if (PluginAdapter::Default()->IsScaleActive() &&
- g_strcmp0(plugin, "scale") == 0 && super_keypressed_)
+ if (PluginAdapter::Default()->IsScaleActive() && g_strcmp0(plugin, "scale") == 0 &&
+ super_keypressed_)
{
scale_just_activated_ = true;
}
@@ -2513,11 +2351,7 @@ bool UnityWindow::glDraw(const GLMatrix& matrix,
!uScreen->fullscreenRegion.contains(window->geometry())
)
{
-#ifdef USE_MODERN_COMPIZ_GL
uScreen->paintDisplay();
-#else
- uScreen->paintDisplay(region, matrix, mask);
-#endif
}
if (window->type() == CompWindowTypeDesktopMask)
@@ -2542,6 +2376,40 @@ bool UnityWindow::glDraw(const GLMatrix& matrix,
}
void
+UnityScreen::OnMinimizeDurationChanged ()
+{
+ /* Update the compiz plugin setting with the new computed speed so that it
+ * will be used in the following minimizations */
+ CompPlugin *p = CompPlugin::find("animation");
+ if (p)
+ {
+ CompOption::Vector &opts = p->vTable->getOptions();
+
+ for (CompOption &o : opts)
+ {
+ if (o.name () == std::string ("minimize_durations"))
+ {
+ /* minimize_durations is a list value, but minimize applies only to
+ * normal windows, so there's always one value */
+ CompOption::Value& value = o.value();
+ CompOption::Value::Vector& list = value.list();
+ CompOption::Value::Vector::iterator i = list.begin();
+ if (i != list.end()) {
+ i->set(minimize_speed_controller->getDuration());
+ }
+ value.set(list);
+ screen->setOptionForPlugin(p->vTable->name().c_str(),
+ o.name().c_str(), value);
+ break;
+ }
+ }
+ }
+ else {
+ LOG_WARN(logger) << "Animation plugin not found. Can't set minimize speed.";
+ }
+}
+
+void
UnityWindow::minimize ()
{
if (!window->managed ())
@@ -2657,6 +2525,11 @@ void UnityWindow::windowNotify(CompWindowNotify n)
case CompWindowNotifyBeforeDestroy:
being_destroyed.emit();
break;
+ case CompWindowNotifyMinimize:
+ /* Updating the count in dconf will trigger a "changed" signal to which
+ * the method setting the new animation speed is attached */
+ UnityScreen::get(screen)->minimize_speed_controller->UpdateCount();
+ break;
default:
break;
}
@@ -2925,9 +2798,6 @@ void UnityScreen::optionChanged(CompOption* opt, UnityshellOptions::Options num)
case UnityshellOptions::AutomaximizeValue:
PluginAdapter::Default()->SetCoverageAreaBeforeAutomaximize(optionGetAutomaximizeValue() / 100.0f);
break;
- case UnityshellOptions::DevicesOption:
- unity::DevicesSettings::GetDefault().SetDevicesOption((unity::DevicesSettings::DevicesOption) optionGetDevicesOption());
- break;
case UnityshellOptions::AltTabTimeout:
switcher_controller_->detail_on_timeout = optionGetAltTabTimeout();
case UnityshellOptions::AltTabBiasViewport:
@@ -2998,14 +2868,6 @@ void UnityScreen::Relayout()
if (!needsRelayout)
return;
-#ifndef USE_MODERN_COMPIZ_GL
- if (GL::fbo)
- {
- uScreen->_fbo = ScreenEffectFramebufferObject::Ptr (new ScreenEffectFramebufferObject (glXGetProcAddressP, geometry));
- uScreen->_fbo->onScreenSizeChanged (geometry);
- }
-#endif
-
UScreen *uscreen = UScreen::GetDefault();
int primary_monitor = uscreen->GetPrimaryMonitor();
auto geo = uscreen->GetMonitorGeometry(primary_monitor);
@@ -3120,78 +2982,124 @@ void UnityScreen::InitHints()
{
// TODO move category text into a vector...
+ // Compiz' plug-in names
+ static const std::string COMPIZ_CORE_PLUGIN_NAME = "core";
+ static const std::string COMPIZ_EXPO_PLUGIN_NAME = "expo";
+ static const std::string COMPIZ_GRID_PLUGIN_NAME = "grid";
+ static const std::string COMPIZ_MOVE_PLUGIN_NAME = "move";
+ static const std::string COMPIZ_RESIZE_PLUGIN_NAME = "resize";
+ static const std::string COMPIZ_SCALE_PLUGIN_NAME = "scale";
+ static const std::string COMPIZ_UNITYSHELL_PLUGIN_NAME = "unityshell";
+ static const std::string COMPIZ_WALL_PLUGIN_NAME = "wall";
+
+ // Compiz Core Options
+ static const std::string COMPIZ_CORE_OPTION_SHOW_DESKTOP_KEY = "show_desktop_key";
+ static const std::string COMPIZ_CORE_OPTION_MAXIMIZE_WINDOW_KEY = "maximize_window_key";
+ static const std::string COMPIZ_CORE_OPTION_UNMAXIMIZE_WINDOW_KEY = "unmaximize_window_key";
+ static const std::string COMPIZ_CORE_OPTION_CLOSE_WINDOW_KEY = "close_window_key";
+ static const std::string COMPIZ_CORE_OPTION_WINDOW_MENU_KEY = "window_menu_key";
+
+ // Compiz Expo Options
+ static const std::string COMPIZ_EXPO_OPTION_EXPO_KEY = "expo_key";
+
+ // Compiz Grid Options
+ static const std::string COMPIZ_GRID_OPTION_PUT_LEFT_KEY = "put_left_key";
+
+ // Compiz Move Options
+ static const std::string COMPIZ_MOVE_OPTION_INITIATE_BUTTON = "initiate_button";
+
+ // Compiz Resize Options
+ static const std::string COMPIZ_RESIZE_OPTION_INITIATE_BUTTON = "initiate_button";
+
+ // Compiz Scale Options
+ static const std::string COMPIZ_SCALE_OPTION_INITIATE_ALL_KEY = "initiate_all_key";
+
+ // Compiz Unityshell Options
+ static const std::string COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER = "show_launcher";
+ static const std::string COMPIZ_UNITYSHELL_OPTION_KEYBOARD_FOCUS = "keyboard_focus";
+ static const std::string COMPIZ_UNITYSHELL_OPTION_LAUNCHER_SWITCHER_FORWARD = "launcher_switcher_forward";
+ static const std::string COMPIZ_UNITYSHELL_OPTION_SHOW_HUD = "show_hud";
+ static const std::string COMPIZ_UNITYSHELL_OPTION_PANEL_FIRST_MENU = "panel_first_menu";
+ static const std::string COMPIZ_UNITYSHELL_OPTION_ALT_TAB_FORWARD = "alt_tab_forward";
+ static const std::string COMPIZ_UNITYSHELL_OPTION_ALT_TAB_NEXT_WINDOW = "alt_tab_next_window";
+
+ // Compiz Wall Options
+ static const std::string COMPIZ_WALL_OPTION_LEFT_KEY = "left_key";
+ static const std::string COMPIZ_WALL_OPTION_LEFT_WINDOW_KEY = "left_window_key";
+
+
// Launcher...
- std::string const launcher(_("Launcher"));
+ static const std::string launcher(_("Launcher"));
hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" (Hold)"),
_("Opens the Launcher, displays shortcuts."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher" ));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", "",
_("Opens Launcher keyboard navigation mode."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "keyboard_focus"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_KEYBOARD_FOCUS));
hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", "",
_("Switches applications via the Launcher."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "launcher_switcher_forward"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_LAUNCHER_SWITCHER_FORWARD));
hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" + 1 to 9"),
_("Same as clicking on a Launcher icon."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", _(" + Shift + 1 to 9"),
_("Opens a new window in the app."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
hints_.push_back(std::make_shared<shortcut::Hint>(launcher, "", " + T",
_("Opens the Trash."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
// Dash...
- std::string const dash( _("Dash"));
+ static const std::string dash( _("Dash"));
hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", _(" (Tap)"),
_("Opens the Dash Home."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + A",
_("Opens the Dash App Lens."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + F",
_("Opens the Dash Files Lens."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + M",
_("Opens the Dash Music Lens."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", " + V",
_("Opens the Dash Video Lens."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_launcher"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_LAUNCHER));
hints_.push_back(std::make_shared<shortcut::Hint>(dash, "", "",
_("Switches between Lenses."),
@@ -3209,15 +3117,15 @@ void UnityScreen::InitHints()
_("Enter")));
// Menu Bar
- std::string const menubar(_("HUD & Menu Bar"));
+ static const std::string menubar(_("HUD & Menu Bar"));
hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", _(" (Tap)"),
_("Opens the HUD."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "show_hud"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_SHOW_HUD));
- hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", " (Hold)",
+ hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", _(" (Hold)"),
_("Reveals the application menu."),
shortcut::HARDCODED_OPTION,
"Alt"));
@@ -3225,8 +3133,8 @@ void UnityScreen::InitHints()
hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", "",
_("Opens the indicator menu."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "panel_first_menu"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_PANEL_FIRST_MENU));
hints_.push_back(std::make_shared<shortcut::Hint>(menubar, "", "",
_("Moves focus between indicators."),
@@ -3234,19 +3142,19 @@ void UnityScreen::InitHints()
_("Cursor Left or Right")));
// Switching
- std::string const switching(_("Switching"));
+ static const std::string switching(_("Switching"));
hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "",
_("Switches between applications."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "alt_tab_forward"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_ALT_TAB_FORWARD));
hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "",
_("Switches windows of current applications."),
shortcut::COMPIZ_KEY_OPTION,
- "unityshell",
- "alt_tab_next_window"));
+ COMPIZ_UNITYSHELL_PLUGIN_NAME,
+ COMPIZ_UNITYSHELL_OPTION_ALT_TAB_NEXT_WINDOW));
hints_.push_back(std::make_shared<shortcut::Hint>(switching, "", "",
_("Moves the focus."),
@@ -3254,69 +3162,71 @@ void UnityScreen::InitHints()
_("Cursor Left or Right")));
// Workspaces
- std::string const workspaces(_("Workspaces"));
+ static const std::string workspaces(_("Workspaces"));
hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", "",
_("Switches between workspaces."),
shortcut::COMPIZ_KEY_OPTION,
- "expo",
- "expo_key"));
+ COMPIZ_EXPO_PLUGIN_NAME,
+ COMPIZ_EXPO_OPTION_EXPO_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", _(" + Arrow Keys"),
_("Switches workspaces."),
shortcut::COMPIZ_METAKEY_OPTION,
- "wall",
- "left_key"));
+ COMPIZ_WALL_PLUGIN_NAME,
+ COMPIZ_WALL_OPTION_LEFT_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(workspaces, "", _(" + Arrow Keys"),
_("Moves focused window to another workspace."),
shortcut::COMPIZ_METAKEY_OPTION,
- "wall",
- "left_window_key"));
+ COMPIZ_WALL_PLUGIN_NAME,
+ COMPIZ_WALL_OPTION_LEFT_WINDOW_KEY));
// Windows
- std::string const windows(_("Windows"));
+ static const std::string windows(_("Windows"));
+
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
_("Spreads all windows in the current workspace."),
shortcut::COMPIZ_KEY_OPTION,
- "scale",
- "initiate_all_key"));
+ COMPIZ_SCALE_PLUGIN_NAME,
+ COMPIZ_SCALE_OPTION_INITIATE_ALL_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
_("Minimises all windows."),
shortcut::COMPIZ_KEY_OPTION,
- "core",
- "show_desktop_key"));
+ COMPIZ_CORE_PLUGIN_NAME,
+ COMPIZ_CORE_OPTION_SHOW_DESKTOP_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
_("Maximises the current window."),
shortcut::COMPIZ_KEY_OPTION,
- "core",
- "maximize_window_key"));
+ COMPIZ_CORE_PLUGIN_NAME,
+ COMPIZ_CORE_OPTION_MAXIMIZE_WINDOW_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
_("Restores or minimises the current window."),
shortcut::COMPIZ_KEY_OPTION,
- "core",
- "unmaximize_window_key"));
+ COMPIZ_CORE_PLUGIN_NAME,
+ COMPIZ_CORE_OPTION_UNMAXIMIZE_WINDOW_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" or Right"),
_("Semi-maximise the current window."),
shortcut::COMPIZ_KEY_OPTION,
- "grid",
- "put_left_key"));
+ COMPIZ_GRID_PLUGIN_NAME,
+ COMPIZ_GRID_OPTION_PUT_LEFT_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
_("Closes the current window."),
shortcut::COMPIZ_KEY_OPTION,
- "core",
- "close_window_key"));
+ COMPIZ_CORE_PLUGIN_NAME,
+ COMPIZ_CORE_OPTION_CLOSE_WINDOW_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
_("Opens the window accessibility menu."),
- shortcut::HARDCODED_OPTION,
- _("Alt + Space")));
+ shortcut::COMPIZ_KEY_OPTION,
+ COMPIZ_CORE_PLUGIN_NAME,
+ COMPIZ_CORE_OPTION_WINDOW_MENU_KEY));
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", "",
_("Places the window in corresponding position."),
@@ -3326,14 +3236,14 @@ void UnityScreen::InitHints()
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"),
_("Moves the window."),
shortcut::COMPIZ_MOUSE_OPTION,
- "move",
- "initiate_button"));
+ COMPIZ_MOVE_PLUGIN_NAME,
+ COMPIZ_MOVE_OPTION_INITIATE_BUTTON));
hints_.push_back(std::make_shared<shortcut::Hint>(windows, "", _(" Drag"),
_("Resizes the window."),
shortcut::COMPIZ_MOUSE_OPTION,
- "resize",
- "initiate_button"));
+ COMPIZ_RESIZE_PLUGIN_NAME,
+ COMPIZ_RESIZE_OPTION_INITIATE_BUTTON));
}
void UnityScreen::InitGesturesSupport()
@@ -3363,16 +3273,65 @@ void UnityScreen::InitGesturesSupport()
}
/* Window init */
+GLTexture::List UnityWindow::close_normal_tex_;
+GLTexture::List UnityWindow::close_prelight_tex_;
+GLTexture::List UnityWindow::close_pressed_tex_;
+
+struct UnityWindow::CairoContext
+{
+ CairoContext(int width, int height)
+ : pixmap_(XCreatePixmap(screen->dpy(), screen->root(), width, height, 32))
+ , texture_(GLTexture::bindPixmapToTexture(pixmap_, width, height, 32))
+ , surface_(nullptr)
+ , cr_(nullptr)
+ {
+ Screen *xscreen = ScreenOfDisplay(screen->dpy(), screen->screenNum());
+ XRenderPictFormat* format = XRenderFindStandardFormat(screen->dpy(), PictStandardARGB32);
+
+ if (texture_.empty())
+ return;
+
+ surface_ = cairo_xlib_surface_create_with_xrender_format(screen->dpy(), pixmap_,
+ xscreen, format,
+ width, height);
+ cr_ = cairo_create(surface_);
+
+ // clear
+ cairo_save(cr_);
+ cairo_set_operator(cr_, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cr_);
+ cairo_restore(cr_);
+ }
+
+ ~CairoContext ()
+ {
+ if (cr_)
+ cairo_destroy(cr_);
+
+ if (surface_)
+ cairo_surface_destroy(surface_);
+
+ texture_.clear();
+
+ if (pixmap_)
+ XFreePixmap(screen->dpy (), pixmap_);
+ }
+
+ Pixmap pixmap_;
+ GLTexture::List texture_;
+ cairo_surface_t* surface_;
+ cairo_t *cr_;
+};
+
UnityWindow::UnityWindow(CompWindow* window)
: BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window)
, PluginClassHandler<UnityWindow, CompWindow>(window)
, window(window)
, gWindow(GLWindow::get(window))
- , mMinimizeHandler()
- , mShowdesktopHandler(nullptr)
{
WindowInterface::setHandler(window);
GLWindowInterface::setHandler(gWindow);
+ ScaleWindowInterface::setHandler (ScaleWindow::get (window));
if (UnityScreen::get (screen)->optionGetShowMinimizedWindows () &&
window->mapNum ())
@@ -3415,6 +3374,320 @@ UnityWindow::UnityWindow(CompWindow* window)
}
}
}
+
+ WindowManager::Default()->initiate_spread.connect(sigc::mem_fun(this, &UnityWindow::OnInitiateSpreed));
+ WindowManager::Default()->terminate_spread.connect(sigc::mem_fun(this, &UnityWindow::OnTerminateSpreed));
+}
+
+void
+UnityWindow::DrawTexture(GLTexture* icon,
+ const GLWindowPaintAttrib& attrib,
+ const GLMatrix& transform,
+ unsigned int mask,
+ float x, float y,
+ int &maxWidth, int &maxHeight)
+{
+ if (icon)
+ {
+ int width, height;
+ width = icon->width();
+ height = icon->height();
+
+ if (height > maxHeight)
+ maxHeight = height;
+
+ if (width > maxWidth)
+ maxWidth = width;
+
+ CompRegion iconReg(0, 0, width, height);
+ GLTexture::MatrixList ml(1);
+
+ ml[0] = icon->matrix();
+ gWindow->vertexBuffer()->begin();
+ if (width && height)
+ gWindow->glAddGeometry(ml, iconReg, iconReg);
+
+ if (gWindow->vertexBuffer()->end())
+ {
+ GLMatrix wTransform(transform);
+
+ wTransform.translate(x, y, 0.0f);
+
+ gWindow->glDrawTexture(icon, wTransform, attrib, mask);
+ }
+ }
+}
+
+void
+UnityWindow::RenderText(UnityWindow::CairoContext const& context,
+ float x, float y,
+ float maxWidth, float maxHeight)
+{
+ panel::Style& style = panel::Style::Instance();
+ std::string fontDescription(style.GetFontDescription(panel::PanelItem::TITLE));
+
+ glib::Object<PangoLayout> layout(pango_cairo_create_layout(context.cr_));
+ std::shared_ptr<PangoFontDescription> font(pango_font_description_from_string(fontDescription.c_str()),
+ pango_font_description_free);
+
+ pango_layout_set_font_description(layout, font.get());
+
+ GdkScreen* gdkScreen = gdk_screen_get_default();
+ PangoContext* pCxt = pango_layout_get_context(layout);
+ int dpi = style.GetTextDPI();
+
+ pango_cairo_context_set_font_options(pCxt, gdk_screen_get_font_options(gdkScreen));
+ pango_cairo_context_set_resolution(pCxt, dpi / static_cast<float>(PANGO_SCALE));
+ pango_layout_context_changed(layout);
+
+ pango_layout_set_height(layout, maxHeight);
+ pango_layout_set_width(layout, -1); //avoid wrap lines
+ pango_layout_set_auto_dir(layout, false);
+ pango_layout_set_text(layout,
+ WindowManager::Default()->GetWindowName(window->id()).c_str(),
+ -1);
+
+ /* update the size of the pango layout */
+ pango_cairo_update_layout(context.cr_, layout);
+ cairo_set_operator(context.cr_, CAIRO_OPERATOR_OVER);
+ cairo_set_source_rgba(context.cr_,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0);
+
+ // alignment
+ PangoRectangle lRect;
+ int textWidth, textHeight;
+
+ pango_layout_get_extents(layout, NULL, &lRect);
+ textWidth = lRect.width / PANGO_SCALE;
+ textHeight = lRect.height / PANGO_SCALE;
+
+ y = ((maxHeight - textHeight) / 2.0) + y;
+ cairo_translate(context.cr_, x, y);
+
+ if (textWidth > maxWidth)
+ {
+ // apply a fade effect in the right corner
+ const int outPixels = textWidth - maxWidth;
+ const int fadingPixels = 35;
+ const int fadingWidth = outPixels < fadingPixels ? outPixels : fadingPixels;
+
+ cairo_push_group(context.cr_);
+ pango_cairo_show_layout(context.cr_, layout);
+ cairo_pop_group_to_source(context.cr_);
+
+ std::shared_ptr<cairo_pattern_t> linpat(cairo_pattern_create_linear(maxWidth - fadingWidth,
+ y, maxWidth, y),
+ cairo_pattern_destroy);
+ cairo_pattern_add_color_stop_rgba(linpat.get(), 0, 0, 0, 0, 1);
+ cairo_pattern_add_color_stop_rgba(linpat.get(), 1, 0, 0, 0, 0);
+ cairo_mask(context.cr_, linpat.get());
+ }
+ else
+ {
+ pango_cairo_show_layout(context.cr_, layout);
+ }
+}
+
+void
+UnityWindow::DrawWindowDecoration(GLWindowPaintAttrib const& attrib,
+ GLMatrix const& transform,
+ unsigned int mask,
+ bool highlighted,
+ int x, int y, unsigned width, unsigned height)
+{
+ // Paint a fake window decoration
+ CairoContext context(width, height);
+
+ cairo_save(context.cr_);
+ cairo_push_group(context.cr_);
+
+ // Round window decoration top border
+ const double aspect = 1.0;
+ const double corner_radius = height / 10.0;
+ const double radius = corner_radius / aspect;
+ const double degrees = M_PI / 180.0;
+
+ cairo_new_sub_path(context.cr_);
+
+ cairo_arc(context.cr_, radius, radius, radius, 180 * degrees, 270 * degrees);
+ cairo_arc(context.cr_, width - radius, radius, radius, -90 * degrees, 0 * degrees);
+ cairo_line_to(context.cr_, width, height);
+ cairo_line_to(context.cr_, 0, height);
+
+ cairo_close_path(context.cr_);
+ cairo_clip(context.cr_);
+
+ // Draw window decoration based on gtk style
+ auto& style = panel::Style::Instance();
+ gtk_render_background(style.GetStyleContext(), context.cr_, 0, 0, width, height);
+ gtk_render_frame(style.GetStyleContext(), context.cr_, 0, 0, width, height);
+
+ cairo_pop_group_to_source(context.cr_);
+
+ cairo_paint_with_alpha(context.cr_, 1.0);
+ cairo_restore(context.cr_);
+
+ if (highlighted)
+ {
+ // Draw windows title
+ const float xText = SCALE_ITEMS_PADDING * 2 + SCALE_CLOSE_ICON_SIZE;
+ RenderText(context, xText, 0.0, width - xText - SCALE_ITEMS_PADDING, height);
+ }
+
+ mask |= PAINT_WINDOW_BLEND_MASK;
+ int maxWidth, maxHeight;
+
+ for (GLTexture *icon : context.texture_)
+ DrawTexture(icon, attrib, transform, mask, x, y, maxWidth , maxHeight);
+}
+
+void UnityWindow::LoadCloseIcon(panel::WindowState state, GLTexture::List& texture)
+{
+ if (!texture.empty())
+ return;
+
+ auto& style = panel::Style::Instance();
+ auto const& files = style.GetWindowButtonFileNames(panel::WindowButtonType::CLOSE, state);
+
+ CompString pName("unityshell");
+ for (std::string const& file : files)
+ {
+ CompString fileName(file.c_str());
+ CompSize size(SCALE_CLOSE_ICON_SIZE, SCALE_CLOSE_ICON_SIZE);
+ texture = GLTexture::readImageToTexture(fileName, pName, size);
+ if (!texture.empty())
+ break;
+ }
+
+ if (texture.empty())
+ {
+ std::string suffix;
+ if (state == panel::WindowState::PRELIGHT)
+ suffix = "_prelight";
+ else if (state == panel::WindowState::PRESSED)
+ suffix = "_pressed";
+
+ CompString fileName((PKGDATADIR"/close_dash" + suffix + ".png").c_str());
+ CompSize size(SCALE_CLOSE_ICON_SIZE, SCALE_CLOSE_ICON_SIZE);
+ texture = GLTexture::readImageToTexture(fileName, pName, size);
+ }
+}
+
+void UnityWindow::SetupScaleHeaderStyle()
+{
+ LoadCloseIcon(panel::WindowState::NORMAL, close_normal_tex_);
+ LoadCloseIcon(panel::WindowState::PRELIGHT, close_prelight_tex_);
+ LoadCloseIcon(panel::WindowState::PRESSED, close_pressed_tex_);
+}
+
+void UnityWindow::scalePaintDecoration(GLWindowPaintAttrib const& attrib,
+ GLMatrix const& transform,
+ CompRegion const& region,
+ unsigned int mask)
+{
+ ScaleWindow *scale_win = ScaleWindow::get(window);
+ if (!scale_win)
+ return;
+
+ scale_win->scalePaintDecoration(attrib, transform, region, mask);
+
+ if (!scale_win->hasSlot()) // animation not finished
+ return;
+
+ UnityScreen* us = UnityScreen::get(screen);
+ const bool highlighted = (us->scale_highlighted_window_ == window->id());
+
+ ScalePosition const& pos = scale_win->getCurrentPosition();
+ auto const& border_rect = window->borderRect();
+ auto const& deco_ext = window->border();
+
+ const unsigned decoration_height = deco_ext.top;
+ unsigned width = (border_rect.width() + deco_ext.left + deco_ext.right) * pos.scale;
+ unsigned height = decoration_height * pos.scale;
+ int x = pos.x() + border_rect.x();
+ int y = pos.y() + border_rect.y() + decoration_height - height - 1;
+
+ // If window is highlighted, we draw the decoration at full size
+ if (highlighted)
+ height = decoration_height;
+
+ DrawWindowDecoration(attrib, transform, mask, highlighted, x, y, width, height);
+
+ if (highlighted)
+ {
+ x += SCALE_ITEMS_PADDING;
+ y += (height - SCALE_CLOSE_ICON_SIZE) / 2.0f;
+ int max_height = 0;
+ int max_width = 0;
+ mask |= PAINT_WINDOW_BLEND_MASK;
+
+ switch(close_icon_state_)
+ {
+ case panel::WindowState::NORMAL:
+ default:
+ for (GLTexture *icon : close_normal_tex_)
+ DrawTexture(icon, attrib, transform, mask, x, y, max_width , max_height);
+ break;
+
+ case panel::WindowState::PRELIGHT:
+ for (GLTexture *icon : close_prelight_tex_)
+ DrawTexture(icon, attrib, transform, mask, x, y, max_width , max_height);
+ break;
+
+ case panel::WindowState::PRESSED:
+ for (GLTexture *icon : close_pressed_tex_)
+ DrawTexture(icon, attrib, transform, mask, x, y, max_width , max_height);
+ break;
+ }
+
+ close_button_geo_.Set(x, y, max_height, max_width);
+ }
+ else if (!close_button_geo_.IsNull())
+ {
+ close_button_geo_.Set(0, 0, 0, 0);
+ }
+}
+
+void UnityWindow::scaleSelectWindow()
+{
+ ScaleWindow::get(window)->scaleSelectWindow();
+
+ UnityScreen* us = UnityScreen::get(screen);
+
+ if (us->scale_highlighted_window_ != window->id())
+ us->scale_highlighted_window_ = window->id();
+}
+
+void UnityWindow::OnInitiateSpreed()
+{
+ auto const windows = screen->windows();
+ if (std::find(windows.begin(), windows.end(), window) == windows.end())
+ return;
+
+ close_icon_state_ = panel::WindowState::NORMAL;
+ SetupScaleHeaderStyle();
+
+ WindowManager *wm = WindowManager::Default();
+ Window xid = window->id();
+
+ if (wm->IsWindowDecorated(xid))
+ wm->Decorate(xid);
+}
+
+void UnityWindow::OnTerminateSpreed()
+{
+ auto const windows = screen->windows();
+ if (std::find(windows.begin(), windows.end(), window) == windows.end())
+ return;
+
+ WindowManager *wm = WindowManager::Default();
+ Window xid = window->id();
+
+ if (wm->IsWindowDecorated(xid) && wm->IsWindowMaximized(xid))
+ wm->Undecorate(xid);
}
UnityWindow::~UnityWindow()
@@ -3437,13 +3710,10 @@ UnityWindow::~UnityWindow()
ShowdesktopHandler::animating_windows.remove (static_cast <ShowdesktopHandlerWindowInterface *> (this));
- if (mShowdesktopHandler)
- delete mShowdesktopHandler;
-
if (window->state () & CompWindowStateFullscreenMask)
UnityScreen::get (screen)->fullscreen_windows_.remove(window);
- PluginAdapter::Default ()->OnWindowClosed (window);
+ PluginAdapter::Default ()->OnWindowClosed(window);
}
/* vtable init */
@@ -3474,7 +3744,6 @@ bool UnityPluginVTable::init()
return true;
}
-
namespace
{
diff --git a/plugins/unityshell/src/unityshell.h b/plugins/unityshell/src/unityshell.h
index afc9b8da2..a1de06832 100644
--- a/plugins/unityshell/src/unityshell.h
+++ b/plugins/unityshell/src/unityshell.h
@@ -29,6 +29,7 @@
#include <sigc++/sigc++.h>
#include <boost/shared_ptr.hpp>
+#include <scale/scale.h>
#include <core/core.h>
#include <core/pluginclasshandler.h>
#include <composite/composite.h>
@@ -54,9 +55,6 @@
#include "UnityshellPrivate.h"
#include "UnityShowdesktopHandler.h"
#include "ThumbnailGenerator.h"
-#ifndef USE_MODERN_COMPIZ_GL
-#include "ScreenEffectFramebufferObject.h"
-#endif
#include "compizminimizedwindowhandler.h"
#include "BGHash.h"
@@ -65,6 +63,8 @@
#include "HudController.h"
#include "ThumbnailGenerator.h"
+#include "WindowMinimizeSpeedController.h"
+
namespace unity
{
@@ -94,11 +94,7 @@ public:
void nuxEpilogue();
/* nux draw wrapper */
-#ifdef USE_MODERN_COMPIZ_GL
void paintDisplay();
-#else
- void paintDisplay(const CompRegion& region, const GLMatrix& transform, unsigned int mask);
-#endif
void paintPanelShadow(const GLMatrix& matrix);
void setPanelShadowMatrix(const GLMatrix& matrix);
@@ -189,6 +185,8 @@ public:
void SetUpAndShowSwitcher(switcher::ShowMode show_mode = switcher::ShowMode::CURRENT_VIEWPORT);
+ void OnMinimizeDurationChanged();
+
switcher::Controller::Ptr switcher_controller();
launcher::Controller::Ptr launcher_controller();
@@ -243,6 +241,10 @@ private:
void InitGesturesSupport();
+ void DrawTopPanelBackground();
+ bool TopPanelBackgroundTextureNeedsUpdate() const;
+ void UpdateTopPanelBackgroundTexture();
+
nux::animation::TickSource tick_source_;
nux::animation::AnimationController animation_controller_;
@@ -306,12 +308,7 @@ private:
BGHash _bghash;
-#ifdef USE_MODERN_COMPIZ_GL
::GLFramebufferObject *oldFbo;
-#else
- ScreenEffectFramebufferObject::Ptr _fbo;
- GLuint _active_fbo;
-#endif
bool queryForShader ();
@@ -332,14 +329,13 @@ private:
bool scale_just_activated_;
-#ifndef USE_MODERN_COMPIZ_GL
- ScreenEffectFramebufferObject::GLXGetProcAddressProc glXGetProcAddressP;
-#endif
-
UBusManager ubus_manager_;
glib::SourceManager sources_;
unity::ThumbnailGenerator thumb_generator;
-
+
+ Window scale_highlighted_window_;
+
+ WindowMinimizeSpeedController* minimize_speed_controller;
friend class UnityWindow;
};
@@ -348,6 +344,7 @@ class UnityWindow :
public GLWindowInterface,
public ShowdesktopHandlerWindowInterface,
public compiz::WindowInputRemoverLockAcquireInterface,
+ public WrapableHandler<ScaleWindowInterface, 4>,
public BaseSwitchWindow,
public PluginClassHandler <UnityWindow, CompWindow>
{
@@ -377,11 +374,7 @@ public:
/* basic window draw function */
bool glDraw(const GLMatrix& matrix,
-#ifndef USE_MODERN_COMPIZ_GL
- GLFragment::Attrib& attrib,
-#else
const GLWindowPaintAttrib& attrib,
-#endif
const CompRegion& region,
unsigned intmask);
@@ -406,17 +399,25 @@ public:
void leaveShowDesktop ();
bool HandleAnimations (unsigned int ms);
- void handleEvent (XEvent *event);
+ bool handleEvent(XEvent *event);
typedef compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>
UnityMinimizedHandler;
std::unique_ptr <UnityMinimizedHandler> mMinimizeHandler;
-
- ShowdesktopHandler *mShowdesktopHandler;
+ std::unique_ptr <ShowdesktopHandler> mShowdesktopHandler;
//! Emited when CompWindowNotifyBeforeDestroy is received
sigc::signal<void> being_destroyed;
+
+ void scaleSelectWindow();
+ void scalePaintDecoration(const GLWindowPaintAttrib &,
+ const GLMatrix &,
+ const CompRegion &,
+ unsigned int);
+
private:
+ struct CairoContext;
+
void DoEnableFocus ();
void DoDisableFocus ();
@@ -436,6 +437,9 @@ private:
void DoShow ();
void DoNotifyShown ();
+ void OnInitiateSpreed();
+ void OnTerminateSpreed();
+
void DoAddDamage ();
ShowdesktopHandlerWindowInterface::PostPaintAction DoHandleAnimations (unsigned int ms);
@@ -447,7 +451,30 @@ private:
compiz::WindowInputRemoverLock::Ptr GetInputRemover ();
+ void DrawWindowDecoration(GLWindowPaintAttrib const& attrib,
+ GLMatrix const& transform,
+ unsigned int mask,
+ bool highlighted,
+ int x, int y, unsigned width, unsigned height);
+ void DrawTexture(GLTexture *icon,
+ const GLWindowPaintAttrib& attrib,
+ const GLMatrix& transform,
+ unsigned int mask,
+ float x, float y,
+ int &maxWidth, int &maxHeight);
+ void RenderText(CairoContext const& context,
+ float x, float y,
+ float maxWidth, float maxHeight);
+
+ void SetupScaleHeaderStyle();
+ void LoadCloseIcon(panel::WindowState state, GLTexture::List& texture);
+
+ static GLTexture::List close_normal_tex_;
+ static GLTexture::List close_prelight_tex_;
+ static GLTexture::List close_pressed_tex_;
compiz::WindowInputRemoverLock::Weak input_remover_;
+ panel::WindowState close_icon_state_;
+ nux::Geometry close_button_geo_;
glib::Source::UniquePtr focus_desktop_timeout_;
};
diff --git a/plugins/unityshell/unityshell.xml.in b/plugins/unityshell/unityshell.xml.in
index 1f0dab978..98571394a 100644
--- a/plugins/unityshell/unityshell.xml.in
+++ b/plugins/unityshell/unityshell.xml.in
@@ -394,26 +394,6 @@
<default>75</default>
</option>
- <option name="devices_option" type="int">
- <_short>Show Devices</_short>
- <_long>Show devices in the launcher</_long>
- <min>0</min>
- <max>2</max>
- <default>1</default>
- <desc>
- <value>0</value>
- <_name>Never</_name>
- </desc>
- <desc>
- <value>1</value>
- <_name>Only Mounted</_name>
- </desc>
- <desc>
- <value>2</value>
- <_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/po/POTFILES.in b/po/POTFILES.in
index 9b8c17cd5..494439443 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -11,11 +11,12 @@ hud/HudView.cpp
launcher/BFBLauncherIcon.cpp
launcher/BamfLauncherIcon.cpp
launcher/DesktopLauncherIcon.cpp
-launcher/DeviceLauncherIcon.cpp
+launcher/DeviceNotificationDisplayImp.cpp
launcher/LauncherController.cpp
launcher/SoftwareCenterLauncherIcon.cpp
launcher/SpacerLauncherIcon.cpp
launcher/TrashLauncherIcon.cpp
+launcher/VolumeLauncherIcon.cpp
panel/PanelMenuView.cpp
plugins/networkarearegion/networkarearegion.xml.in
plugins/unity-mt-grab-handles/unitymtgrabhandles.xml.in
diff --git a/services/CMakeLists.txt b/services/CMakeLists.txt
index 865aa4125..2da54dce0 100644
--- a/services/CMakeLists.txt
+++ b/services/CMakeLists.txt
@@ -2,7 +2,8 @@
# Panel Service
#
find_package(PkgConfig)
-pkg_check_modules(SERVICE_DEPS REQUIRED gtk+-3.0>=3.3 gobject-2.0 gio-2.0 gthread-2.0 indicator3-0.4>=0.4.90 x11)
+
+pkg_check_modules(SERVICE_DEPS REQUIRED gtk+-3.0>=3.3 gobject-2.0 gio-2.0 gthread-2.0 indicator3-0.4>=0.4.90 x11 atk-bridge-2.0)
execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} indicator3-0.4 --variable indicatordir OUTPUT_VARIABLE _indicatordir OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} indicator3-0.4 --variable iconsdir OUTPUT_VARIABLE _iconsdir OUTPUT_STRIP_TRAILING_WHITESPACE)
diff --git a/services/panel-a11y.c b/services/panel-a11y.c
index 6f870555b..a22b39b87 100644
--- a/services/panel-a11y.c
+++ b/services/panel-a11y.c
@@ -17,119 +17,16 @@
*/
#include <gio/gio.h>
+#include <atk-bridge.h>
#include "panel-a11y.h"
#include "panel-util-accessible.h"
static gboolean a11y_initialized = FALSE;
-#define INIT_METHOD "gnome_accessibility_module_init"
-#define DESKTOP_SCHEMA "org.gnome.desktop.interface"
-#define ACCESSIBILITY_ENABLED_KEY "toolkit-accessibility"
-#define AT_SPI_SCHEMA "org.a11y.atspi"
-#define ATK_BRIDGE_LOCATION_KEY "atk-bridge-location"
-
-
-/* This method is required because g_setting_new abort if the schema
- is not present. */
-static gboolean
-has_gsettings_schema (const gchar *schema)
-{
- const char * const *list_schemas = NULL;
- gboolean found = FALSE;
- int i = 0;
-
- list_schemas = g_settings_list_schemas ();
- for (i = 0; list_schemas [i]; i++)
- {
- if (!g_strcmp0 (list_schemas[i], schema))
- {
- found = TRUE;
- break;
- }
- }
-
- return found;
-}
-
-static gboolean
-should_enable_a11y (void)
-{
- GSettings *desktop_settings = NULL;
- gboolean value = FALSE;
-
- if (!has_gsettings_schema (DESKTOP_SCHEMA))
- return FALSE;
-
- desktop_settings = g_settings_new (DESKTOP_SCHEMA);
- value = g_settings_get_boolean (desktop_settings, ACCESSIBILITY_ENABLED_KEY);
-
- g_object_unref (desktop_settings);
-
- return value;
-}
-
-static gchar*
-get_atk_bridge_path (void)
-{
- GSettings *atspi_settings = NULL;
- GVariant *variant = NULL;
- char *value = NULL;
-
- if (!has_gsettings_schema (AT_SPI_SCHEMA))
- return NULL;
-
- atspi_settings = g_settings_new(AT_SPI_SCHEMA);
- variant = g_settings_get_value (atspi_settings, ATK_BRIDGE_LOCATION_KEY);
- value = g_variant_dup_bytestring (variant, NULL);
-
- g_variant_unref (variant);
- g_object_unref (atspi_settings);
-
- return value;
-}
-
-static gboolean
-a11y_invoke_module (const char *module_path)
-{
- GModule *handle;
- void (*invoke_fn) (void);
-
- if (!module_path)
- {
- g_warning ("Accessibility: invalid module path (NULL)");
-
- return FALSE;
- }
-
- if (!(handle = g_module_open (module_path, (GModuleFlags)0)))
- {
- g_warning ("Accessibility: failed to load module '%s': '%s'",
- module_path, g_module_error ());
-
- return FALSE;
- }
-
- if (!g_module_symbol (handle, INIT_METHOD, (gpointer *)&invoke_fn))
- {
- g_warning ("Accessibility: error library '%s' does not include "
- "method '%s' required for accessibility support",
- module_path, INIT_METHOD);
- g_module_close (handle);
-
- return FALSE;
- }
-
- invoke_fn ();
-
- return TRUE;
-}
-
void
panel_a11y_init (void)
{
- gchar *bridge_path = NULL;
-
if (a11y_initialized)
return;
@@ -137,20 +34,9 @@ panel_a11y_init (void)
g_unsetenv ("NO_AT_BRIDGE");
g_unsetenv ("NO_GAIL");
- if (!should_enable_a11y ())
- return;
-
/* Load PanelUtilAccessible class */
g_type_class_unref (g_type_class_ref (PANEL_TYPE_UTIL_ACCESSIBLE));
-
- bridge_path = get_atk_bridge_path ();
- if (a11y_invoke_module (bridge_path))
- {
- g_debug ("Unity accessibility started, using bridge on %s", bridge_path);
- }
-
- g_free (bridge_path);
- atk_get_root ();
+ atk_bridge_adaptor_init(NULL, NULL);
a11y_initialized = TRUE;
}
diff --git a/shortcuts/StandaloneShortcuts.cpp b/shortcuts/StandaloneShortcuts.cpp
index a9ae5edce..6285967ba 100644
--- a/shortcuts/StandaloneShortcuts.cpp
+++ b/shortcuts/StandaloneShortcuts.cpp
@@ -205,12 +205,11 @@ void ThreadWidgetInit(nux::NThread* thread, void* InitData)
"core",
"close_window_key")));
-
- // I don't know std::shared_ptr<shortcut::AbstractHint>(if it is really hardcoded, but I can't find where this option is stored.
hints.push_back(std::shared_ptr<shortcut::AbstractHint>(new shortcut::MockHint(_("Windows"), "", "",
_("Opens the window accessibility menu."),
- shortcut::HARDCODED_OPTION,
- "Alt+Space")));
+ shortcut::COMPIZ_KEY_OPTION,
+ "core",
+ "window_menu_key")));
hints.push_back(std::shared_ptr<shortcut::AbstractHint>(new shortcut::MockHint(_("Windows"), "", "",
_("Places the window in corresponding position."),
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 453e3082c..e8542d1fc 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -213,6 +213,7 @@ if (GTEST_SRC_DIR AND
test_icon_loader.cpp
test_im_text_entry.cpp
test_launcher_controller.cpp
+ test_launcher_drag_window.cpp
test_keyboard_util.cpp
test_panel_style.cpp
test_previews_application.cpp
@@ -227,6 +228,10 @@ if (GTEST_SRC_DIR AND
test_switcher_model.cpp
test_texture_cache.cpp
test_thumbnail_generator.cpp
+ test_launcher_minimize_speed.cpp
+ test_volume_imp.cpp
+ test_volume_launcher_icon.cpp
+ gmockmount.c
gmockvolume.c
${CMAKE_SOURCE_DIR}/dash/AbstractPlacesGroup.cpp
${CMAKE_SOURCE_DIR}/dash/DashViewPrivate.cpp
@@ -258,14 +263,15 @@ if (GTEST_SRC_DIR AND
${CMAKE_SOURCE_DIR}/launcher/DNDCollectionWindow.cpp
${CMAKE_SOURCE_DIR}/launcher/Decaymulator.cpp
${CMAKE_SOURCE_DIR}/launcher/DesktopLauncherIcon.cpp
- ${CMAKE_SOURCE_DIR}/launcher/DeviceLauncherIcon.cpp
${CMAKE_SOURCE_DIR}/launcher/DeviceLauncherSection.cpp
- ${CMAKE_SOURCE_DIR}/launcher/DevicesSettings.cpp
+ ${CMAKE_SOURCE_DIR}/launcher/DeviceNotificationDisplayImp.cpp
+ ${CMAKE_SOURCE_DIR}/launcher/DevicesSettingsImp.cpp
${CMAKE_SOURCE_DIR}/launcher/DndData.cpp
${CMAKE_SOURCE_DIR}/launcher/EdgeBarrierController.cpp
${CMAKE_SOURCE_DIR}/launcher/FavoriteStore.cpp
${CMAKE_SOURCE_DIR}/launcher/FavoriteStoreGSettings.cpp
${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp
+ ${CMAKE_SOURCE_DIR}/launcher/FileManagerOpenerImp.cpp
${CMAKE_SOURCE_DIR}/launcher/HudLauncherIcon.cpp
${CMAKE_SOURCE_DIR}/launcher/Launcher.cpp
${CMAKE_SOURCE_DIR}/launcher/LauncherController.cpp
@@ -296,6 +302,8 @@ if (GTEST_SRC_DIR AND
${CMAKE_SOURCE_DIR}/launcher/SwitcherView.cpp
${CMAKE_SOURCE_DIR}/launcher/Tooltip.cpp
${CMAKE_SOURCE_DIR}/launcher/TrashLauncherIcon.cpp
+ ${CMAKE_SOURCE_DIR}/launcher/VolumeImp.cpp
+ ${CMAKE_SOURCE_DIR}/launcher/VolumeLauncherIcon.cpp
${CMAKE_SOURCE_DIR}/launcher/VolumeMonitorWrapper.cpp
${CMAKE_SOURCE_DIR}/unity-shared/Animator.cpp
${CMAKE_SOURCE_DIR}/unity-shared/BackgroundEffectHelper.cpp
@@ -332,6 +340,7 @@ if (GTEST_SRC_DIR AND
${CMAKE_SOURCE_DIR}/unity-shared/UserThumbnailProvider.cpp
${CMAKE_SOURCE_DIR}/unity-shared/WindowManager.cpp
${CMAKE_SOURCE_DIR}/unity-shared/ubus-server.cpp
+ ${CMAKE_SOURCE_DIR}/plugins/unityshell/src/WindowMinimizeSpeedController.cpp
)
target_link_libraries(test-gtest gtest gmock ${LIBS})
add_test(UnityGTest test-gtest)
diff --git a/tests/autopilot/unity/emulators/workspace.py b/tests/autopilot/unity/emulators/workspace.py
index 773b968c1..7b02f10a8 100644
--- a/tests/autopilot/unity/emulators/workspace.py
+++ b/tests/autopilot/unity/emulators/workspace.py
@@ -10,7 +10,6 @@
from __future__ import absolute_import
-from autopilot.globals import global_context
from autopilot.keybindings import KeybindingsHelper
from autopilot.utilities import (
get_compiz_option,
diff --git a/tests/autopilot/unity/tests/test_hud.py b/tests/autopilot/unity/tests/test_hud.py
index 987a2b580..42261b459 100644
--- a/tests/autopilot/unity/tests/test_hud.py
+++ b/tests/autopilot/unity/tests/test_hud.py
@@ -247,11 +247,11 @@ class HudBehaviorTests(HudTestsBase):
self.mouse.click()
self.assertThat(self.hud.visible, Eventually(Equals(False)))
-
+
def test_hud_closes_click_after_text_removed(self):
"""Clicking outside of the hud after a search text has been entered and
then removed from the searchbox will make it close."""
-
+
self.hud.ensure_visible()
self.keyboard.type("Test")
self.keyboard.press_and_release("Escape")
@@ -259,7 +259,7 @@ class HudBehaviorTests(HudTestsBase):
(x,y,w,h) = self.hud.view.geometry
self.mouse.move(w/2, h+50)
self.mouse.click()
-
+
self.assertThat(self.hud.visible, Eventually(Equals(False)))
def test_alt_f4_close_hud(self):
@@ -276,49 +276,49 @@ class HudBehaviorTests(HudTestsBase):
self.hud.ensure_visible()
self.keyboard.press_and_release("Alt+F4")
self.assertThat(self.hud.visible, Eventually(Equals(False)))
-
+
def test_app_activate_on_enter(self):
"""Hud must close after activating a search item with Enter."""
- self.hud.ensure_visible()
-
+ self.hud.ensure_visible()
+
self.keyboard.type("Device > System Settings")
self.assertThat(self.hud.search_string, Eventually(Equals("Device > System Settings")))
-
+
self.keyboard.press_and_release("Enter")
-
+
app_found = self.bamf.wait_until_application_is_running("gnome-control-center.desktop", 5)
self.assertTrue(app_found)
self.addCleanup(self.close_all_app, "System Settings")
-
+
self.assertThat(self.hud.visible, Eventually(Equals(False)))
-
+
def test_hud_closes_on_escape(self):
"""Hud must close on escape after searchbox is cleared"""
self.hud.ensure_visible()
-
+
self.keyboard.type("ThisText")
self.keyboard.press_and_release("Escape")
self.keyboard.press_and_release("Escape")
-
+
self.assertThat(self.hud.visible, Eventually(Equals(False)))
-
+
def test_hud_closes_on_escape_shrunk(self):
"""Hud must close when escape key is pressed"""
self.hud.ensure_visible()
self.keyboard.press_and_release("Escape")
-
+
self.assertThat(self.hud.visible, Eventually(Equals(False)))
def test_alt_arrow_keys_not_eaten(self):
"""Tests that Alt+ArrowKey events are correctly passed to the
active window when Unity is not responding to them."""
-
+
self.start_app_window("Terminal")
-
+
#There's no easy way to read text from terminal, writing input
#to a text file and then reading from there works.
self.keyboard.type('echo "')
-
+
#Terminal is receiving input with Alt+Arrowkeys
self.keyboard.press("Alt")
self.keyboard.press_and_release("Up")
@@ -326,13 +326,13 @@ class HudBehaviorTests(HudTestsBase):
self.keyboard.press_and_release("Right")
self.keyboard.press_and_release("Left")
self.keyboard.release("Alt")
-
+
self.keyboard.type('" > /tmp/ap_test_alt_keys')
self.addCleanup(remove, '/tmp/ap_test_alt_keys')
self.keyboard.press_and_release("Enter")
-
+
file_contents = open('/tmp/ap_test_alt_keys', 'r').read().strip()
-
+
self.assertThat(file_contents, Equals('ABCD'))
def test_hud_closes_on_item_activated(self):
@@ -357,6 +357,41 @@ class HudBehaviorTests(HudTestsBase):
self.assertThat(self.hud.visible, Eventually(Equals(False)))
+ def test_mouse_changes_selected_hud_button(self):
+ """This tests moves the mouse from the top of the screen to the bottom, this must
+ change the selected button from 1 to 5.
+ """
+
+ self.hud.ensure_visible()
+
+ self.keyboard.type("a")
+ (x,y,w,h) = self.hud.view.geometry
+
+ self.mouse.move(w/2, 0)
+ self.assertThat(self.hud.view.selected_button, Eventually(Equals(1)))
+
+ self.mouse.move(w/2, h)
+ self.assertThat(self.hud.view.selected_button, Eventually(Equals(5)))
+
+ def test_keyboard_steals_focus_from_mouse(self):
+ """This tests moves the mouse from the top of the screen to the bottom,
+ then it presses the keyboard up 5 times, this must change the selected button from 5 to 1.
+ """
+
+ self.hud.ensure_visible()
+
+ self.keyboard.type("a")
+ (x,y,w,h) = self.hud.view.geometry
+
+ self.mouse.move(w/2, 0)
+ self.mouse.move(w/2, h)
+ self.assertThat(self.hud.view.selected_button, Eventually(Equals(5)))
+
+ for i in range(5):
+ self.keyboard.press_and_release('Up')
+
+ self.assertThat(self.hud.view.selected_button, Eventually(Equals(1)))
+
class HudLauncherInteractionsTests(HudTestsBase):
diff --git a/tests/autopilot/unity/tests/xim/__init__.py b/tests/autopilot/unity/tests/xim/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/autopilot/unity/tests/xim/__init__.py
diff --git a/tests/autopilot/unity/tests/xim/test_gcin.py b/tests/autopilot/unity/tests/xim/test_gcin.py
new file mode 100644
index 000000000..f7fe3f8a7
--- /dev/null
+++ b/tests/autopilot/unity/tests/xim/test_gcin.py
@@ -0,0 +1,72 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+# Copyright 2012 Canonical
+# Author: Brandon Schaefer
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+
+from __future__ import absolute_import
+
+from autopilot.matchers import Eventually
+from os import environ
+import subprocess
+from testtools.matchers import Equals
+
+from unity.tests import UnityTestCase
+
+
+class GcinTestCase(UnityTestCase):
+ """Tests the Input Method gcin."""
+
+ def setUp(self):
+ super(GcinTestCase, self).setUp()
+
+ # Check that gcin is set as the active IM through im-switch
+ if environ.get('XMODIFIERS', '') != "@im=gcin":
+ self.skip("Please make sure XMODIFIERS is set to @im=gcin. Set it using 'im-switch'.")
+
+ running_process = subprocess.check_output('ps -e', shell=True)
+ if 'gcin' not in running_process:
+ self.skip("gcin is not an active process, please start 'gcin' before running these tests.")
+
+ if 'ibus' in running_process:
+ self.skip("IBus is currently running, please close 'ibus-daemon' before running these tests.")
+
+
+class GcinTestHangul(GcinTestCase):
+ """Tests the Dash and Hud with gcin in hangul mode."""
+
+ scenarios = [
+ ('hangul', {'input': 'han geul ', 'result': u'\ud55c\uae00'}),
+ ('morning letters', {'input': 'a chimgeul ', 'result': u'\uc544\uce68\uae00'}),
+ ('national script', {'input': 'gug mun ', 'result': u'\uad6d\ubb38'}),
+ ]
+
+ def setUp(self):
+ super(GcinTestHangul, self).setUp()
+
+ def enter_hangul_mode(self):
+ """Ctrl+Space turns gcin on, Ctrl+Alt+/ turns hangul on."""
+ self.keyboard.press_and_release("Ctrl+Space")
+ self.keyboard.press_and_release("Ctrl+Alt+/")
+
+ def test_dash_input(self):
+ """Entering an input string through gcin will result in a Korean string result in the dash."""
+
+ self.dash.ensure_visible()
+ self.addCleanup(self.dash.ensure_hidden)
+ self.enter_hangul_mode()
+
+ self.keyboard.type(self.input)
+ self.assertThat(self.dash.search_string, Eventually(Equals(self.result)))
+
+ def test_hud_input(self):
+ """Entering an input string through gcin will result in a Korean string result in the hud."""
+
+ self.hud.ensure_visible()
+ self.addCleanup(self.hud.ensure_hidden)
+ self.enter_hangul_mode()
+
+ self.keyboard.type(self.input)
+ self.assertThat(self.hud.search_string, Eventually(Equals(self.result)))
diff --git a/tests/gmockmount.c b/tests/gmockmount.c
new file mode 100644
index 000000000..fd4c3d7a1
--- /dev/null
+++ b/tests/gmockmount.c
@@ -0,0 +1,167 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser 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 applicable version of the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of both the GNU Lesser 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 <glib.h>
+
+#include "gmockmount.h"
+
+static void g_mock_mount_iface_init (GMountIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GMockMount, g_mock_mount, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT,
+ g_mock_mount_iface_init))
+
+static void
+g_mock_mount_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (g_mock_mount_parent_class)->finalize (object);
+}
+
+static void
+g_mock_mount_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (g_mock_mount_parent_class)->dispose (object);
+}
+
+
+static void
+g_mock_mount_class_init (GMockMountClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_mock_mount_finalize;
+ gobject_class->dispose = g_mock_mount_dispose;
+}
+
+static void
+g_mock_mount_init (GMockMount *mock_mount)
+{}
+
+GMockMount *
+g_mock_mount_new ()
+{
+ GMockMount *mount;
+
+ mount = g_object_new (G_TYPE_MOCK_MOUNT, NULL);
+
+ return mount;
+}
+
+static GFile *
+g_mock_mount_get_root (GMount *mount)
+{
+ return g_file_new_for_path (ROOT_FILE_PATH);
+}
+
+static GIcon *
+g_mock_mount_get_icon (GMount *mount)
+{
+ return NULL;
+}
+
+static char *
+g_mock_mount_get_uuid (GMount *mount)
+{
+ return g_strdup ("");
+}
+
+static char *
+g_mock_mount_get_name (GMount *mount)
+{
+ return g_strdup ("");
+}
+
+static GDrive *
+g_mock_mount_get_drive (GMount *mount)
+{
+ return NULL;
+}
+
+static GVolume *
+g_mock_mount_get_volume (GMount *mount)
+{
+ return NULL;
+}
+
+static gboolean
+g_mock_mount_can_unmount (GMount *mount)
+{
+ return TRUE;
+}
+
+static gboolean
+g_mock_mount_can_eject (GMount *mount)
+{
+ return FALSE;
+}
+
+static void
+g_mock_mount_unmount (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+}
+
+static gboolean
+g_mock_mount_unmount_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ return TRUE;
+}
+
+static void
+g_mock_mount_eject (GMount *mount,
+ GMountUnmountFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+}
+
+static gboolean
+g_mock_mount_eject_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
+{
+ return TRUE;
+}
+
+
+static void
+g_mock_mount_iface_init (GMountIface *iface)
+{
+ iface->get_root = g_mock_mount_get_root;
+ iface->get_name = g_mock_mount_get_name;
+ iface->get_icon = g_mock_mount_get_icon;
+ iface->get_uuid = g_mock_mount_get_uuid;
+ iface->get_drive = g_mock_mount_get_drive;
+ iface->get_volume = g_mock_mount_get_volume;
+ iface->can_unmount = g_mock_mount_can_unmount;
+ iface->can_eject = g_mock_mount_can_eject;
+ iface->unmount = g_mock_mount_unmount;
+ iface->unmount_finish = g_mock_mount_unmount_finish;
+ iface->eject = g_mock_mount_eject;
+ iface->eject_finish = g_mock_mount_eject_finish;
+}
diff --git a/tests/gmockmount.h b/tests/gmockmount.h
new file mode 100644
index 000000000..b5eb6b5af
--- /dev/null
+++ b/tests/gmockmount.h
@@ -0,0 +1,55 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser 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 applicable version of the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of both the GNU Lesser 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>
+ *
+ */
+
+#ifndef UNITYSHELL_G_MOCK_MOUNT_H
+#define UNITYSHELL_G_MOCK_MOUNT_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define ROOT_FILE_PATH "/some/directory/testfile"
+#define ROOT_FILE_URI "file://" ROOT_FILE_PATH
+
+#define G_TYPE_MOCK_MOUNT (g_mock_mount_get_type ())
+#define G_MOCK_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOCK_MOUNT, GMockMount))
+#define G_MOCK_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOCK_MOUNT, GMockMountClass))
+#define G_IS_MOCK_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOCK_MOUNT))
+#define G_IS_MOCK_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOCK_MOUNT))
+
+typedef struct _GMockMount GMockMount;
+typedef struct _GMockMountClass GMockMountClass;
+
+struct _GMockMount {
+ GObject parent;
+};
+
+struct _GMockMountClass {
+ GObjectClass parent_class;
+};
+
+GType g_mock_mount_get_type (void) G_GNUC_CONST;
+GMockMount * g_mock_mount_new ();
+
+G_END_DECLS
+
+#endif // UNITYSHELL_G_MOCK_MOUNT_H
diff --git a/tests/gmockvolume.c b/tests/gmockvolume.c
index 5ee2d23a1..be667f2b8 100644
--- a/tests/gmockvolume.c
+++ b/tests/gmockvolume.c
@@ -22,13 +22,13 @@
#include <glib.h>
+#include "gmockmount.h"
#include "gmockvolume.h"
-static void g_mock_volume_volume_iface_init (GVolumeIface *iface);
+static void g_mock_volume_iface_init (GVolumeIface *iface);
G_DEFINE_TYPE_WITH_CODE (GMockVolume, g_mock_volume, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME,
- g_mock_volume_volume_iface_init))
+ G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME, g_mock_volume_iface_init))
static void
g_mock_volume_finalize (GObject *object)
@@ -37,44 +37,119 @@ g_mock_volume_finalize (GObject *object)
}
static void
+g_mock_volume_dispose (GObject *object)
+{
+ GMockVolume *self = G_MOCK_VOLUME (object);
+
+ self->can_eject = FALSE;
+
+ if (self->name)
+ {
+ g_free(self->name);
+ self->name = NULL;
+ }
+
+ if (self->icon)
+ {
+ g_object_unref(self->icon);
+ self->icon = NULL;
+ }
+
+ if (self->uuid)
+ {
+ g_free(self->uuid);
+ self->uuid = NULL;
+ }
+
+ if (self->mount)
+ {
+ g_object_unref(self->mount);
+ self->mount = NULL;
+ }
+
+ G_OBJECT_CLASS (g_mock_volume_parent_class)->dispose (object);
+}
+
+
+static void
g_mock_volume_class_init (GMockVolumeClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = g_mock_volume_finalize;
+ gobject_class->dispose = g_mock_volume_dispose;
}
static void
g_mock_volume_init (GMockVolume *mock_volume)
{
+ mock_volume->name = g_strdup("");
+ mock_volume->icon = g_icon_new_for_string("", NULL);
+ mock_volume->uuid = g_strdup("");
+ mock_volume->mount = NULL;
}
GMockVolume *
g_mock_volume_new ()
{
GMockVolume *volume;
-
+
volume = g_object_new (G_TYPE_MOCK_VOLUME, NULL);
return volume;
}
+void
+g_mock_volume_set_name (GMockVolume *volume, const char* name)
+{
+ if (volume->name)
+ g_free(volume->name);
+
+ volume->name = g_strdup (name);
+}
+
static char *
g_mock_volume_get_name (GVolume *volume)
{
- return g_strdup ("");
+ GMockVolume *self = G_MOCK_VOLUME (volume);
+ return g_strdup (self->name);
+}
+
+void
+g_mock_volume_set_icon (GMockVolume *volume, GIcon *icon)
+{
+ if (volume->icon)
+ g_object_unref(volume->icon);
+
+ volume->icon = icon;
}
+
static GIcon *
g_mock_volume_get_icon (GVolume *volume)
{
- return g_icon_new_for_string("", NULL);
+ GMockVolume *self = G_MOCK_VOLUME (volume);
+
+ if (self->icon)
+ return g_object_ref (self->icon);
+ else
+ return NULL;
+}
+
+void
+g_mock_volume_set_uuid (GMockVolume *volume, const char* uuid)
+{
+ if (volume->uuid)
+ g_free(volume->uuid);
+
+ volume->uuid = g_strdup (uuid);
}
static char *
g_mock_volume_get_uuid (GVolume *volume)
{
- return NULL;
+ GMockVolume *self = G_MOCK_VOLUME (volume);
+ return g_strdup (self->uuid);
}
static GDrive *
@@ -83,10 +158,23 @@ g_mock_volume_get_drive (GVolume *volume)
return NULL;
}
+void
+g_mock_volume_set_mount (GMockVolume *volume, GMount *mount)
+{
+ if (volume->mount)
+ g_object_unref(volume->mount);
+
+ volume->mount = mount;
+}
+
static GMount *
g_mock_volume_get_mount (GVolume *volume)
{
- return NULL;
+ GMockVolume *self = G_MOCK_VOLUME (volume);
+ if (self->mount)
+ return g_object_ref (self->mount);
+ else
+ return NULL;
}
static gboolean
@@ -98,7 +186,14 @@ g_mock_volume_can_mount (GVolume *volume)
static gboolean
g_mock_volume_can_eject (GVolume *volume)
{
- return FALSE;
+ GMockVolume *self = G_MOCK_VOLUME (volume);
+ return self->can_eject;
+}
+
+void
+g_mock_volume_set_can_eject (GMockVolume* mock_volume, gboolean can_eject)
+{
+ mock_volume->can_eject = can_eject;
}
static gboolean
@@ -115,6 +210,11 @@ g_mock_volume_mount (GVolume *volume,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ g_mock_volume_set_mount(G_MOCK_VOLUME(volume), G_MOUNT(g_mock_mount_new()));
+
+ callback(NULL,
+ G_ASYNC_RESULT (g_simple_async_result_new (NULL, NULL, NULL, NULL)),
+ user_data);
}
static gboolean
@@ -132,7 +232,10 @@ g_mock_volume_eject (GVolume *volume,
GAsyncReadyCallback callback,
gpointer user_data)
{
-}
+
+ callback(NULL,
+ G_ASYNC_RESULT (g_simple_async_result_new (NULL, NULL, NULL, NULL)),
+ user_data);}
static gboolean
g_mock_volume_eject_finish (GVolume *volume,
@@ -146,6 +249,11 @@ static gchar *
g_mock_volume_get_identifier (GVolume *volume,
const gchar *kind)
{
+ GMockVolume *self = G_MOCK_VOLUME (volume);
+
+ if (!g_strcmp0 (kind, G_VOLUME_IDENTIFIER_KIND_UUID))
+ return g_strdup (self->uuid);
+
return NULL;
}
@@ -156,7 +264,7 @@ g_mock_volume_enumerate_identifiers (GVolume *volume)
}
static void
-g_mock_volume_volume_iface_init (GVolumeIface *iface)
+g_mock_volume_iface_init (GVolumeIface *iface)
{
iface->get_name = g_mock_volume_get_name;
iface->get_icon = g_mock_volume_get_icon;
@@ -173,4 +281,3 @@ g_mock_volume_volume_iface_init (GVolumeIface *iface)
iface->get_identifier = g_mock_volume_get_identifier;
iface->enumerate_identifiers = g_mock_volume_enumerate_identifiers;
}
-
diff --git a/tests/gmockvolume.h b/tests/gmockvolume.h
index 0c9ee118a..bec8e0962 100644
--- a/tests/gmockvolume.h
+++ b/tests/gmockvolume.h
@@ -38,14 +38,26 @@ typedef struct _GMockVolumeClass GMockVolumeClass;
struct _GMockVolume {
GObject parent;
+
+ gboolean can_eject;
+ char *name;
+ GIcon *icon;
+ char *uuid;
+ GMount *mount;
};
struct _GMockVolumeClass {
GObjectClass parent_class;
};
-GType g_mock_volume_get_type (void) G_GNUC_CONST;
-GMockVolume * g_mock_volume_new ();
+GType g_mock_volume_get_type (void) G_GNUC_CONST;
+GMockVolume * g_mock_volume_new ();
+
+void g_mock_volume_set_can_eject (GMockVolume* volume, gboolean can_eject);
+void g_mock_volume_set_name (GMockVolume *volume, const char *name);
+void g_mock_volume_set_icon (GMockVolume *volume, GIcon *icon);
+void g_mock_volume_set_uuid (GMockVolume *volume, const char *uuid);
+void g_mock_volume_set_mount (GMockVolume *volume, GMount *mount);
G_END_DECLS
diff --git a/tests/test_device_launcher_section.cpp b/tests/test_device_launcher_section.cpp
index b00bbfc72..055a1156e 100644
--- a/tests/test_device_launcher_section.cpp
+++ b/tests/test_device_launcher_section.cpp
@@ -24,6 +24,7 @@
using namespace testing;
#include "DeviceLauncherSection.h"
+#include "DevicesSettings.h"
#include "AbstractVolumeMonitorWrapper.h"
using namespace unity;
using namespace unity::launcher;
@@ -74,12 +75,20 @@ public:
glib::Object<GVolume> volume2;
};
+class MockDevicesSettings : public DevicesSettings
+{
+ MOCK_CONST_METHOD1(IsABlacklistedDevice, bool(std::string const& uuid));
+ MOCK_METHOD1(TryToBlacklist, void(std::string const& uuid));
+ MOCK_METHOD1(TryToUnblacklist, void(std::string const& uuid));
+};
+
class TestDeviceLauncherSection : public Test
{
public:
TestDeviceLauncherSection()
: monitor_(new MockVolumeMonitorWrapper)
- , section_(monitor_)
+ , devices_settings_(new MockDevicesSettings)
+ , section_(monitor_, devices_settings_)
{}
void SetUp()
@@ -89,6 +98,7 @@ public:
}
MockVolumeMonitorWrapper::Ptr monitor_;
+ DevicesSettings::Ptr devices_settings_;
DeviceLauncherSection section_;
};
diff --git a/tests/test_edge_barrier_controller.cpp b/tests/test_edge_barrier_controller.cpp
index f00ac2bf1..3ea731e30 100644
--- a/tests/test_edge_barrier_controller.cpp
+++ b/tests/test_edge_barrier_controller.cpp
@@ -156,9 +156,9 @@ TEST_F(TestEdgeBarrierController, ProcessHandledEventOnReleasedBarrier)
bc.Subscribe(&handling_subscriber, monitor);
MockPointerBarrier owner(monitor, true);
- auto breaking_barrier_event = MakeBarrierEvent(0, true);
+ auto breaking_barrier_event = MakeBarrierEvent(5, true);
- EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);
+ EXPECT_CALL(owner, ReleaseBarrier(5)).Times(1);
bc.ProcessBarrierEvent(&owner, breaking_barrier_event);
}
@@ -239,7 +239,7 @@ TEST_F(TestEdgeBarrierController, BreakingEdgeTemporaryReleasesBarrierForNotHand
bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(6, false));
}
-TEST_F(TestEdgeBarrierController, BreakingEdgeDontReleasesBarrierForHandledEvents)
+TEST_F(TestEdgeBarrierController, BreakingEdgeTemporaryReleasesBarrierForHandledEvents)
{
MockPointerBarrier owner;
int monitor = 0;
@@ -250,7 +250,7 @@ TEST_F(TestEdgeBarrierController, BreakingEdgeDontReleasesBarrierForHandledEvent
ASSERT_TRUE(owner.released());
subscribers_[monitor].handles_ = true;
- EXPECT_CALL(owner, ReleaseBarrier(_)).Times(0);
+ EXPECT_CALL(owner, ReleaseBarrier(6)).Times(1);
bc.ProcessBarrierEvent(&owner, MakeBarrierEvent(6, true));
}
diff --git a/tests/test_glib_source.cpp b/tests/test_glib_source.cpp
index a654fa8fa..54718c91e 100644
--- a/tests/test_glib_source.cpp
+++ b/tests/test_glib_source.cpp
@@ -247,11 +247,14 @@ TEST(TestGLibTimeout, RemovePtrOnCallback)
unsigned int local_callback_call_count = 0;
Source::UniquePtr timeout(new Timeout(10, [&] {
+ unsigned int id = timeout->Id();
local_callback_called = true;
- ++local_callback_call_count;
- timeout.reset();
+ local_callback_call_count++;
- // this function would be called more than once if we had not removed the source.
+ timeout.reset();
+ // resetting the ptr should destroy the source.
+ EXPECT_TRUE(g_main_context_find_source_by_id(NULL, id) == nullptr);
+ // this function would be called more than once (local_callback_call_count > 1) if we had not removed the source.
return true;
}));
@@ -262,6 +265,31 @@ TEST(TestGLibTimeout, RemovePtrOnCallback)
EXPECT_EQ(local_callback_call_count, 1);
}
+TEST(TestGLibTimeout, AutoRemoveSourceOnCallback)
+{
+ bool local_callback_called = false;
+ unsigned int local_callback_call_count = 0;
+
+ Source::UniquePtr timeout(new Timeout(10, [&] {
+ local_callback_called = true;
+ ++local_callback_call_count;
+
+ // return false to remove source.
+ return false;
+ }));
+ unsigned int id = timeout->Id();
+
+ Utils::WaitForTimeoutMSec(100);
+
+ timeout.reset();
+ EXPECT_EQ(local_callback_called, true);
+ EXPECT_EQ(local_callback_call_count, 1);
+
+ // source should be removed by now.
+ EXPECT_TRUE(g_main_context_find_source_by_id(NULL, id) == nullptr);
+}
+
+
// GLib TimeoutSeconds tests
TEST(TestGLibTimeoutSeconds, Construction)
diff --git a/tests/test_home_lens.cpp b/tests/test_home_lens.cpp
index 9e5105850..a1cfc57e7 100644
--- a/tests/test_home_lens.cpp
+++ b/tests/test_home_lens.cpp
@@ -18,6 +18,7 @@
#include "test_utils.h"
using namespace std;
+using namespace unity;
using namespace unity::dash;
namespace
@@ -61,6 +62,7 @@ public:
: Lens(id, "", "", name, "lens-icon.png",
description, search_hint, true, "",
ModelType::LOCAL)
+ , num_results_(-1)
{
search_in_global(true);
connected.SetGetterFunction(sigc::mem_fun(this, &StaticTestLens::force_connected));
@@ -101,28 +103,37 @@ public:
row_buf[1] = g_variant_new_string("");
row_buf[3] = g_variant_new_string("");
- row_buf[4] = g_variant_new_string("");
row_buf[5] = g_variant_new_string("");
row_buf[6] = g_variant_new_string("");
row_buf[7] = NULL;
unsigned int i;
- for (i = 0; i < search_string.size(); i++)
+ unsigned int results_count = search_string.size();
+ if (num_results_ >= 0) results_count = static_cast<unsigned>(num_results_);
+ for (i = 0; i < results_count; i++)
{
ostringstream uri;
- uri << "uri+" << search_string.at(i) << "+" << id();
+ char res_id(i >= search_string.size() ? '-' : search_string.at(i));
+ uri << "uri+" << res_id << "+" << id();
row_buf[0] = g_variant_new_string(uri.str().c_str());
row_buf[2] = g_variant_new_uint32(i % 3);
+ glib::String name(g_strdup_printf("%s - %d",
+ results_base_name_.empty() ?
+ search_string.c_str() : results_base_name_.c_str(),
+ i));
+ row_buf[4] = g_variant_new_string(name);
dee_model_append_row(model, row_buf);
}
g_free(row_buf);
+
+ global_search_finished.emit(Hints());
}
void GlobalSearch(string const& search_string)
{
- /* Dispatch search async, because that's */
+ /* Dispatch search async, because that's what it'd normally do */
LensSearchClosure* closure = g_new0(LensSearchClosure, 1);
closure->lens = this;
closure->search_string = g_strdup(search_string.c_str());
@@ -144,6 +155,19 @@ public:
}
+ void SetResultsBaseName(string const& name)
+ {
+ results_base_name_ = name;
+ }
+
+ void SetNumResults(int count)
+ {
+ num_results_ = count;
+ }
+
+private:
+ string results_base_name_;
+ int num_results_;
};
static gboolean dispatch_global_search(gpointer userdata)
@@ -213,6 +237,25 @@ private:
Lens::Ptr lens_2_;
};
+class ThreeStaticTestLenses : public StaticTestLenses
+{
+public:
+ ThreeStaticTestLenses()
+ : lens_1_(new StaticTestLens("first.lens", "First Lens", "The very first lens", "First search hint"))
+ , lens_2_(new StaticTestLens("second.lens", "Second Lens", "The second lens", "Second search hint"))
+ , lens_3_(new StaticTestLens("applications.lens", "Applications", "The applications lens", "Search applications"))
+ {
+ list_.push_back(lens_1_);
+ list_.push_back(lens_2_);
+ list_.push_back(lens_3_);
+ }
+
+private:
+ Lens::Ptr lens_1_;
+ Lens::Ptr lens_2_;
+ Lens::Ptr lens_3_;
+};
+
TEST(TestHomeLens, TestConstruction)
{
HomeLens home_lens_("name", "description", "searchhint");
@@ -354,7 +397,13 @@ TEST(TestHomeLens, TestOneSearch)
home_lens_.Search("ape");
- Utils::WaitForTimeoutMSec();
+ bool finished = false;
+ home_lens_.search_finished.connect([&finished] (Lens::Hints const& hints)
+ {
+ finished = true;
+ });
+
+ Utils::WaitUntil(finished);
/* Validate counts */
EXPECT_EQ(dee_model_get_n_rows(results), 6); // 3 hits from each lens
@@ -388,4 +437,210 @@ TEST(TestHomeLens, TestOneSearch)
EXPECT_EQ(cat_shared, dee_model_get_uint32(results, iter, CAT_COLUMN));
}
+TEST(TestHomeLens, TestOrderingAfterSearch)
+{
+ HomeLens home_lens_("name", "description", "searchhint",
+ HomeLens::MergeMode::OWNER_LENS);
+ ThreeStaticTestLenses lenses_;
+ DeeModel* results = home_lens_.results()->model();
+ DeeModel* cats = home_lens_.categories()->model();
+ DeeModel* filters = home_lens_.filters()->model();
+ DeeModelIter* iter;
+ unsigned int lens1_cat = 0;
+ // the lens is added as third, so must have cat == 2
+ unsigned int apps_lens_cat = 2;
+ const unsigned int URI_COLUMN = 0;
+ const unsigned int CAT_COLUMN = 2;
+
+ home_lens_.AddLenses(lenses_);
+
+ bool order_changed = false;
+ home_lens_.categories_reordered.connect([&order_changed] ()
+ {
+ order_changed = true;
+ });
+
+ home_lens_.Search("ape");
+
+ bool finished = false;
+ home_lens_.search_finished.connect([&finished] (Lens::Hints const& hints)
+ {
+ finished = true;
+ });
+ Utils::WaitUntil(finished);
+
+ /* Validate counts */
+ EXPECT_EQ(dee_model_get_n_rows(results), 9); // 3 hits from each lens
+ EXPECT_EQ(dee_model_get_n_rows(cats), 3); // 3 cats since we are merging categories by lens
+ EXPECT_EQ(dee_model_get_n_rows(filters), 0); // We ignore filters deliberately currently
+
+ /* Validate the category order */
+ auto order = home_lens_.GetCategoriesOrder();
+
+ /* The home lens includes applications lens which contains exact match, must
+ * be first category */
+ EXPECT_EQ(order.at(0), apps_lens_cat);
+
+ /* Plus the categories reordered should have been emitted */
+ EXPECT_EQ(order_changed, true);
+
+ /* The model will not be sorted acording to the categories though. */
+ iter = dee_model_get_iter_at_row(results, 0);
+ EXPECT_EQ(string("uri+a+first.lens"), string(dee_model_get_string(results, iter, URI_COLUMN)));
+ EXPECT_EQ( dee_model_get_uint32(results, iter, CAT_COLUMN), lens1_cat);
+}
+
+TEST(TestHomeLens, TestOrderingWithExactAppsMatch)
+{
+ HomeLens home_lens_("name", "description", "searchhint",
+ HomeLens::MergeMode::OWNER_LENS);
+ ThreeStaticTestLenses lenses_;
+ // the lens is added as third, so must have cat == 2
+ unsigned int apps_lens_cat = 2;
+
+ home_lens_.AddLenses(lenses_);
+ Lens::Ptr apps_lens = lenses_.GetLens("applications.lens");
+
+ auto static_lens = dynamic_pointer_cast<StaticTestLens>(apps_lens);
+ static_lens->SetNumResults(1);
+
+ bool order_changed = false;
+ home_lens_.categories_reordered.connect([&order_changed] ()
+ {
+ order_changed = true;
+ });
+
+ home_lens_.Search("ape");
+
+ bool finished = false;
+ home_lens_.search_finished.connect([&finished] (Lens::Hints const& hints)
+ {
+ finished = true;
+ });
+ Utils::WaitUntil(finished);
+
+ /* Validate counts */
+ EXPECT_EQ(home_lens_.results()->count(), 7); // 3+3+1 hits
+ EXPECT_EQ(home_lens_.categories()->count(), 3); // 3 cats since we are merging categories by lens
+ EXPECT_EQ(home_lens_.filters()->count(), 0); // We ignore filters deliberately currently
+
+ /* Validate the category order */
+ auto order = home_lens_.GetCategoriesOrder();
+
+ /* The home lens includes applications lens and it contains exact match,
+ * so must be the first category, even though there are fewer results than
+ * in the other categories */
+ EXPECT_EQ(order.at(0), apps_lens_cat);
+
+ /* Plus the categories reordered should have been emitted */
+ EXPECT_EQ(order_changed, true);
+}
+
+TEST(TestHomeLens, TestOrderingWithoutExactAppsMatch)
+{
+ HomeLens home_lens_("name", "description", "searchhint",
+ HomeLens::MergeMode::OWNER_LENS);
+ ThreeStaticTestLenses lenses_;
+ // the lens is added as third, so must have cat == 2
+ unsigned int apps_lens_cat = 2;
+
+ home_lens_.AddLenses(lenses_);
+ Lens::Ptr apps_lens = lenses_.GetLens("applications.lens");
+
+ auto static_lens = dynamic_pointer_cast<StaticTestLens>(apps_lens);
+ static_lens->SetResultsBaseName("noapes");
+ static_lens->SetNumResults(1);
+
+ bool order_changed = false;
+ home_lens_.categories_reordered.connect([&order_changed] ()
+ {
+ order_changed = true;
+ });
+
+ home_lens_.Search("ape");
+
+ bool finished = false;
+ home_lens_.search_finished.connect([&finished] (Lens::Hints const& hints)
+ {
+ finished = true;
+ });
+ Utils::WaitUntil(finished);
+
+ /* Validate counts */
+ EXPECT_EQ(home_lens_.results()->count(), 7); // 3+3+1 hits
+ EXPECT_EQ(home_lens_.categories()->count(), 3); // 3 cats since we are merging categories by lens
+ EXPECT_EQ(home_lens_.filters()->count(), 0); // We ignore filters deliberately currently
+
+ /* Validate the category order */
+ auto order = home_lens_.GetCategoriesOrder();
+
+ /* The home lens includes applications lens but it doesn't contain exact
+ * match, so can't be the first category */
+ EXPECT_NE(order.at(0), apps_lens_cat);
+
+ /* Plus the categories reordered should have been emitted */
+ EXPECT_EQ(order_changed, true);
+}
+
+TEST(TestHomeLens, TestOrderingByNumResults)
+{
+ HomeLens home_lens_("name", "description", "searchhint",
+ HomeLens::MergeMode::OWNER_LENS);
+ ThreeStaticTestLenses lenses_;
+ unsigned int lens1_cat = 0;
+ unsigned int lens2_cat = 1;
+ // the lens is added as third, so must have cat == 2
+ unsigned int apps_lens_cat = 2;
+
+ home_lens_.AddLenses(lenses_);
+
+ Lens::Ptr lens = lenses_.GetLensAtIndex(2);
+ auto static_lens = dynamic_pointer_cast<StaticTestLens>(lens);
+ static_lens->SetResultsBaseName("noapes"); // no exact match in apps lens
+ static_lens->SetNumResults(2);
+
+ static_lens = dynamic_pointer_cast<StaticTestLens>(lenses_.GetLensAtIndex(0));
+ static_lens->SetNumResults(1);
+ static_lens = dynamic_pointer_cast<StaticTestLens>(lenses_.GetLensAtIndex(1));
+ static_lens->SetNumResults(3);
+
+ bool order_changed = false;
+ home_lens_.categories_reordered.connect([&order_changed] ()
+ {
+ order_changed = true;
+ });
+
+ home_lens_.Search("ape");
+
+ bool finished = false;
+ home_lens_.search_finished.connect([&finished] (Lens::Hints const& hints)
+ {
+ finished = true;
+ });
+ Utils::WaitUntil(finished);
+
+ /*
+ * lens1 -> 1 result
+ * lens2 -> 3 results
+ * lens3 -> 2 results (apps.lens)
+ */
+
+ /* Validate counts */
+ EXPECT_EQ(home_lens_.results()->count(), 6); // 1+3+2 hits
+ EXPECT_EQ(home_lens_.categories()->count(), 3); // 3 cats since we are merging categories by lens
+ EXPECT_EQ(home_lens_.filters()->count(), 0); // We ignore filters deliberately currently
+
+ /* Validate the category order */
+ auto order = home_lens_.GetCategoriesOrder();
+
+ /* The home lens includes applications lens but it doesn't contain exact
+ * match, so can't be the first category */
+ EXPECT_EQ(order.at(0), lens2_cat);
+ EXPECT_EQ(order.at(1), apps_lens_cat);
+ EXPECT_EQ(order.at(2), lens1_cat);
+
+ /* Plus the categories reordered should have been emitted */
+ EXPECT_EQ(order_changed, true);
+}
+
}
diff --git a/tests/test_launcher.cpp b/tests/test_launcher.cpp
index b6f6e22ad..ae8f7bb4e 100644
--- a/tests/test_launcher.cpp
+++ b/tests/test_launcher.cpp
@@ -15,10 +15,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
#include <list>
#include <gmock/gmock.h>
+#include "test_uscreen_mock.h"
using namespace testing;
#include <Nux/Nux.h>
@@ -29,6 +31,7 @@ using namespace testing;
#include "launcher/Launcher.h"
#include "unity-shared/PanelStyle.h"
#include "unity-shared/UnitySettings.h"
+#include "unity-shared/IconRenderer.h"
#include "test_utils.h"
using namespace unity;
@@ -54,29 +57,76 @@ public:
class TestLauncher : public Test
{
public:
+ class MockLauncher : public launcher::Launcher
+ {
+ public:
+ MockLauncher(nux::BaseWindow* parent, nux::ObjectPtr<DNDCollectionWindow> const& collection_window)
+ : Launcher(parent, collection_window)
+ {}
+
+ AbstractLauncherIcon::Ptr MouseIconIntersection(int x, int y)
+ {
+ for (auto const& icon : *_model)
+ {
+ auto const& center = icon->GetCenter(monitor());
+
+ if (y > center.y - GetIconSize()/2.0f && y < center.y + GetIconSize()/2.0f)
+ return icon;
+ }
+
+ return AbstractLauncherIcon::Ptr();
+ }
+
+ float IconBackgroundIntensity(AbstractLauncherIcon::Ptr icon, timespec const& current) const
+ {
+ return Launcher::IconBackgroundIntensity(icon, current);
+ }
+
+ void StartIconDrag(AbstractLauncherIcon::Ptr icon)
+ {
+ Launcher::StartIconDrag(icon);
+ }
+
+ void ShowDragWindow()
+ {
+ Launcher::ShowDragWindow();
+ }
+
+ void UpdateDragWindowPosition(int x, int y)
+ {
+ Launcher::UpdateDragWindowPosition(x, y);
+ }
+
+ void HideDragWindow()
+ {
+ Launcher::HideDragWindow();
+ }
+
+ void ResetMouseDragState()
+ {
+ Launcher::ResetMouseDragState();
+ }
+ };
+
TestLauncher()
: parent_window_(new nux::BaseWindow("TestLauncherWindow"))
, dnd_collection_window_(new DNDCollectionWindow)
, model_(new LauncherModel)
, options_(new Options)
- , launcher_(new Launcher(parent_window_, dnd_collection_window_))
+ , launcher_(new MockLauncher(parent_window_, dnd_collection_window_))
{
launcher_->options = options_;
launcher_->SetModel(model_);
}
- float IconBackgroundIntensity(AbstractLauncherIcon::Ptr icon, timespec const& current) const
- {
- return launcher_->IconBackgroundIntensity(icon, current);
- }
-
+ MockUScreen uscreen;
nux::BaseWindow* parent_window_;
nux::ObjectPtr<DNDCollectionWindow> dnd_collection_window_;
Settings settings;
panel::Style panel_style;
LauncherModel::Ptr model_;
Options::Ptr options_;
- nux::ObjectPtr<Launcher> launcher_;
+ nux::ObjectPtr<MockLauncher> launcher_;
};
TEST_F(TestLauncher, TestQuirksDuringDnd)
@@ -149,10 +199,66 @@ TEST_F(TestLauncher, TestIconBackgroundIntensity)
timespec current;
clock_gettime(CLOCK_MONOTONIC, &current);
- EXPECT_THAT(IconBackgroundIntensity(first, current), Gt(0.0f));
- EXPECT_THAT(IconBackgroundIntensity(second, current), Gt(0.0f));
- EXPECT_EQ(IconBackgroundIntensity(third, current), 0.0f);
+ EXPECT_THAT(launcher_->IconBackgroundIntensity(first, current), Gt(0.0f));
+ EXPECT_THAT(launcher_->IconBackgroundIntensity(second, current), Gt(0.0f));
+ EXPECT_EQ(launcher_->IconBackgroundIntensity(third, current), 0.0f);
}
+TEST_F(TestLauncher, DragLauncherIconCancelRestoresIconOrder)
+{
+ MockMockLauncherIcon::Ptr icon1(new MockMockLauncherIcon);
+ MockMockLauncherIcon::Ptr icon2(new MockMockLauncherIcon);
+ MockMockLauncherIcon::Ptr icon3(new MockMockLauncherIcon);
+
+ model_->AddIcon(icon1);
+ model_->AddIcon(icon2);
+ model_->AddIcon(icon3);
+
+ // Set the icon centers
+ int icon_size = launcher_->GetIconSize();
+ icon1->SetCenter(nux::Point3(icon_size/2.0f, icon_size/2.0f * 1 + 1, 0), launcher_->monitor(), launcher_->GetGeometry());
+ icon2->SetCenter(nux::Point3(icon_size/2.0f, icon_size/2.0f * 2 + 1, 0), launcher_->monitor(), launcher_->GetGeometry());
+ icon3->SetCenter(nux::Point3(icon_size/2.0f, icon_size/2.0f * 3 + 1, 0), launcher_->monitor(), launcher_->GetGeometry());
+
+ // Start dragging icon2
+ launcher_->StartIconDrag(icon2);
+ launcher_->ShowDragWindow();
+
+ // Moving icon2 at the end
+ auto const& center3 = icon3->GetCenter(launcher_->monitor());
+ launcher_->UpdateDragWindowPosition(center3.x, center3.y);
+
+ auto it = model_->begin();
+ ASSERT_EQ(*it, icon1); it++;
+ ASSERT_EQ(*it, icon3); it++;
+ ASSERT_EQ(*it, icon2);
+
+ // Moving icon2 at the begin
+ auto const& center1 = icon1->GetCenter(launcher_->monitor());
+ launcher_->UpdateDragWindowPosition(center1.x, center1.y);
+
+ it = model_->begin();
+ ASSERT_EQ(*it, icon2); it++;
+ ASSERT_EQ(*it, icon1); it++;
+ ASSERT_EQ(*it, icon3);
+
+ bool model_saved = false;
+ model_->saved.connect([&model_saved] { model_saved = true; });
+
+ // Emitting the drag cancel request
+ launcher_->GetDraggedIcon()->drag_cancel_request.emit();
+
+ // The icon order should be reset
+ it = model_->begin();
+ ASSERT_EQ(*it, icon1); it++;
+ ASSERT_EQ(*it, icon2); it++;
+ ASSERT_EQ(*it, icon3);
+
+ EXPECT_FALSE(model_saved);
+
+ launcher_->HideDragWindow();
}
+
}
+}
+
diff --git a/tests/test_launcher_controller.cpp b/tests/test_launcher_controller.cpp
index 16fbbf5ee..a4d5fc660 100644
--- a/tests/test_launcher_controller.cpp
+++ b/tests/test_launcher_controller.cpp
@@ -52,7 +52,6 @@ private:
class MockBamfLauncherIcon : public BamfLauncherIcon
{
public:
- //typedef nux::ObjectPtr<MockMockLauncherIcon> Ptr;
MockBamfLauncherIcon(BamfApplication* app)
: BamfLauncherIcon(app) {}
@@ -71,7 +70,6 @@ public:
virtual void SetUp()
{
- lc.options = std::make_shared<Options>();
lc.multiple_launchers = true;
}
@@ -98,6 +96,8 @@ TEST_F(TestLauncherController, Construction)
{
EXPECT_NE(lc.options(), nullptr);
EXPECT_TRUE(lc.multiple_launchers());
+ ASSERT_EQ(lc.launchers().size(), 1);
+ EXPECT_EQ(lc.launcher().monitor(), 0);
}
TEST_F(TestLauncherController, MultimonitorMultipleLaunchers)
@@ -230,4 +230,65 @@ TEST_F(TestLauncherController, OnlyUnstickIconOnFavoriteRemoval)
favorite_store.favorite_removed.emit(USC_DESKTOP);
}
+TEST_F(TestLauncherController, EnabledStrutsByDefault)
+{
+ EXPECT_EQ(lc.launcher().options()->hide_mode, LAUNCHER_HIDE_NEVER);
+ EXPECT_TRUE(lc.launcher().GetParent()->InputWindowStrutsEnabled());
+}
+
+TEST_F(TestLauncherController, EnabledStrutsOnNeverHide)
+{
+ lc.multiple_launchers = true;
+ uscreen.SetupFakeMultiMonitor();
+ lc.options()->hide_mode = LAUNCHER_HIDE_NEVER;
+
+ for (int i = 0; i < max_num_monitors; ++i)
+ ASSERT_TRUE(lc.launchers()[i]->GetParent()->InputWindowStrutsEnabled());
+}
+
+TEST_F(TestLauncherController, DisabledStrutsOnAutoHide)
+{
+ lc.multiple_launchers = true;
+ uscreen.SetupFakeMultiMonitor();
+ lc.options()->hide_mode = LAUNCHER_HIDE_AUTOHIDE;
+
+ for (int i = 0; i < max_num_monitors; ++i)
+ ASSERT_FALSE(lc.launchers()[i]->GetParent()->InputWindowStrutsEnabled());
+}
+
+TEST_F(TestLauncherController, EnabledStrutsAddingNewLaunchersOnAutoHide)
+{
+ // This makes the controller to add multiple launchers
+ lc.multiple_launchers = true;
+ lc.options()->hide_mode = LAUNCHER_HIDE_NEVER;
+ uscreen.SetupFakeMultiMonitor();
+
+ // This makes the controller to remove unneeded launchers
+ lc.multiple_launchers = false;
+
+ // This makes the controller to add again new launchers
+ lc.multiple_launchers = true;
+
+ for (int i = 0; i < max_num_monitors; ++i)
+ ASSERT_TRUE(lc.launchers()[i]->GetParent()->InputWindowStrutsEnabled());
+}
+
+TEST_F(TestLauncherController, DisabledStrutsAddingNewLaunchersOnNeverHide)
+{
+ // This makes the controller to add multiple launchers
+ lc.multiple_launchers = true;
+ lc.options()->hide_mode = LAUNCHER_HIDE_AUTOHIDE;
+ uscreen.SetupFakeMultiMonitor();
+
+ // This makes the controller to remove unneeded launchers
+ lc.multiple_launchers = false;
+
+ // This makes the controller to add again new launchers
+ lc.multiple_launchers = true;
+
+ for (int i = 0; i < max_num_monitors; ++i)
+ ASSERT_FALSE(lc.launchers()[i]->GetParent()->InputWindowStrutsEnabled());
}
+
+}
+
diff --git a/tests/test_launcher_drag_window.cpp b/tests/test_launcher_drag_window.cpp
new file mode 100644
index 000000000..2a5186d18
--- /dev/null
+++ b/tests/test_launcher_drag_window.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
+ */
+
+#include <gmock/gmock.h>
+
+#include "LauncherDragWindow.h"
+#include "WindowManager.h"
+
+using namespace unity::launcher;
+using namespace testing;
+
+namespace
+{
+const int ICON_WIDTH = 10;
+const int ICON_HEIGHT = 15;
+}
+
+namespace unity
+{
+namespace launcher
+{
+struct TestLauncherDragWindow : public testing::Test
+{
+ TestLauncherDragWindow()
+ : drag_window(nux::ObjectPtr<nux::IOpenGLBaseTexture>(new nux::IOpenGLBaseTexture(nux::RTTEXTURE, ICON_WIDTH, ICON_HEIGHT, 24, 1, nux::BITFMT_B8G8R8A8)))
+ {}
+
+ LauncherDragWindow drag_window;
+};
+}
+
+TEST_F(TestLauncherDragWindow, Construction)
+{
+ EXPECT_EQ(drag_window.GetBaseWidth(), ICON_WIDTH);
+ EXPECT_EQ(drag_window.GetBaseHeight(), ICON_HEIGHT);
+ EXPECT_FALSE(drag_window.Animating());
+ EXPECT_FALSE(drag_window.Cancelled());
+}
+
+TEST_F(TestLauncherDragWindow, EscapeRequestsCancellation)
+{
+ nux::Event cancel;
+ cancel.type = nux::NUX_KEYDOWN;
+ cancel.x11_keysym = NUX_VK_ESCAPE;
+ bool got_signal;
+
+ drag_window.drag_cancel_request.connect([&got_signal] { got_signal = true; });
+ drag_window.GrabKeyboard();
+ nux::GetWindowCompositor().ProcessEvent(cancel);
+
+ EXPECT_TRUE(got_signal);
+ EXPECT_TRUE(drag_window.Cancelled());
+}
+
+TEST_F(TestLauncherDragWindow, CancelsOnWindowMapped)
+{
+ bool got_signal;
+ drag_window.drag_cancel_request.connect([&got_signal] { got_signal = true; });
+ WindowManager::Default()->window_mapped.emit(0);
+
+ EXPECT_TRUE(got_signal);
+ EXPECT_TRUE(drag_window.Cancelled());
+}
+
+TEST_F(TestLauncherDragWindow, CancelsOnWindowUnmapped)
+{
+ bool got_signal;
+ drag_window.drag_cancel_request.connect([&got_signal] { got_signal = true; });
+ WindowManager::Default()->window_unmapped.emit(0);
+
+ EXPECT_TRUE(got_signal);
+ EXPECT_TRUE(drag_window.Cancelled());
+}
+
+}
diff --git a/tests/test_launcher_minimize_speed.cpp b/tests/test_launcher_minimize_speed.cpp
new file mode 100644
index 000000000..a24e3b90d
--- /dev/null
+++ b/tests/test_launcher_minimize_speed.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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: Ugo Riboni <ugo.riboni@canonical.com>
+ *
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+#include <gtest/gtest.h>
+
+#include "plugins/unityshell/src/WindowMinimizeSpeedController.h"
+
+using namespace unity;
+using namespace testing;
+
+namespace
+{
+
+const gchar* SCHEMA_DIRECTORY = BUILDDIR"/settings";
+
+class TestLauncherMinimizeSpeed : public Test
+{
+public:
+ glib::Object<GSettings> mSettings;
+ WindowMinimizeSpeedController* mController;
+
+ /* override */ void SetUp()
+ {
+ g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIRECTORY, true);
+ g_setenv("GSETTINGS_BACKEND", "memory", TRUE);
+ mSettings = g_settings_new("com.canonical.Unity");
+ mController = new WindowMinimizeSpeedController();
+ }
+
+ /* override */ void TearDown()
+ {
+ g_setenv("GSETTINGS_SCHEMA_DIR", "", true);
+ g_unsetenv("GSETTINGS_BACKEND");
+ delete mController;
+ }
+};
+
+TEST_F(TestLauncherMinimizeSpeed, TestSlowest)
+{
+ g_settings_set_int(mSettings, "minimize-count", 0);
+ g_settings_set_int(mSettings, "minimize-speed-threshold", 10);
+ g_settings_set_int(mSettings, "minimize-fast-duration", 200);
+ g_settings_set_int(mSettings, "minimize-slow-duration", 1200);
+
+ EXPECT_TRUE(mController->getDuration() == 1200);
+}
+
+TEST_F(TestLauncherMinimizeSpeed, TestFastest)
+{
+ g_settings_set_int(mSettings, "minimize-count", 10);
+ g_settings_set_int(mSettings, "minimize-speed-threshold", 10);
+ g_settings_set_int(mSettings, "minimize-fast-duration", 200);
+ g_settings_set_int(mSettings, "minimize-slow-duration", 1200);
+
+ EXPECT_TRUE(mController->getDuration() == 200);
+}
+
+TEST_F(TestLauncherMinimizeSpeed, TestHalfway)
+{
+ g_settings_set_int(mSettings, "minimize-count", 5);
+ g_settings_set_int(mSettings, "minimize-speed-threshold", 10);
+ g_settings_set_int(mSettings, "minimize-fast-duration", 200);
+ g_settings_set_int(mSettings, "minimize-slow-duration", 1200);
+
+ EXPECT_TRUE(mController->getDuration() == 700);
+}
+
+TEST_F(TestLauncherMinimizeSpeed, TestOvershoot)
+{
+ g_settings_set_int(mSettings, "minimize-count", 20);
+ g_settings_set_int(mSettings, "minimize-speed-threshold", 10);
+ g_settings_set_int(mSettings, "minimize-fast-duration", 200);
+ g_settings_set_int(mSettings, "minimize-slow-duration", 1200);
+
+ EXPECT_TRUE(mController->getDuration() == 200);
+}
+
+TEST_F(TestLauncherMinimizeSpeed, TestSignal)
+{
+
+ bool signal_emitted = false;
+ mController->DurationChanged.connect([&] () {
+ signal_emitted = true;
+ });
+
+ g_settings_set_int(mSettings, "minimize-count", 5);
+ EXPECT_TRUE(signal_emitted);
+}
+
+TEST_F(TestLauncherMinimizeSpeed, TestInvalidFastSlow)
+{
+ g_settings_set_int(mSettings, "minimize-fast-duration", 2000);
+ g_settings_set_int(mSettings, "minimize-slow-duration", 100);
+
+ bool signal_emitted = false;
+ mController->DurationChanged.connect([&] () {
+ signal_emitted = true;
+ });
+
+ g_settings_set_int(mSettings, "minimize-count", 5);
+ EXPECT_FALSE(signal_emitted);
+}
+} \ No newline at end of file
diff --git a/tests/test_launcher_model.cpp b/tests/test_launcher_model.cpp
index 476c37fb7..a56c929cf 100644
--- a/tests/test_launcher_model.cpp
+++ b/tests/test_launcher_model.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Canonical Ltd.
+ * Copyright 2011-2012 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
@@ -15,7 +15,7 @@
* <http://www.gnu.org/licenses/>
*
* Authored by: Jason Smith <jason.smith@canonical.com>
- *
+ * Marco Trevisan <marco.trevisan@canonical.com>
*/
#include <gtest/gtest.h>
@@ -32,185 +32,308 @@ using namespace unity::launcher;
namespace
{
-class EventListener
+class TestLauncherModel : public testing::Test
{
- public:
- EventListener()
- {
- icon_added = false;
- icon_removed = false;
- }
-
- void OnIconAdded (AbstractLauncherIcon::Ptr icon)
- {
- icon_added = true;
- }
-
- void OnIconRemoved (AbstractLauncherIcon::Ptr icon)
- {
- icon_removed = true;
- }
-
- bool icon_added;
- bool icon_removed;
+public:
+ TestLauncherModel()
+ : icon1(new MockLauncherIcon())
+ , icon2(new MockLauncherIcon())
+ , icon3(new MockLauncherIcon())
+ , icon4(new MockLauncherIcon())
+ {}
+
+ AbstractLauncherIcon::Ptr icon1;
+ AbstractLauncherIcon::Ptr icon2;
+ AbstractLauncherIcon::Ptr icon3;
+ AbstractLauncherIcon::Ptr icon4;
+
+ LauncherModel model;
};
-//bool seen_result;
-TEST(TestLauncherModel, TestConstructor)
+TEST_F(TestLauncherModel, Constructor)
{
- LauncherModel::Ptr model(new LauncherModel());
- EXPECT_EQ(model->Size(), 0);
+ EXPECT_EQ(model.Size(), 0);
}
-TEST(TestLauncherModel, TestAdd)
+TEST_F(TestLauncherModel, Add)
{
- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
- LauncherModel::Ptr model(new LauncherModel());
+ model.AddIcon(icon1);
+ EXPECT_EQ(model.Size(), 1);
- EXPECT_EQ(model->Size(), 0);
- model->AddIcon(first);
- EXPECT_EQ(model->Size(), 1);
+ model.AddIcon(icon1);
+ EXPECT_EQ(model.Size(), 1);
+
+ model.AddIcon(AbstractLauncherIcon::Ptr());
+ EXPECT_EQ(model.Size(), 1);
}
-TEST(TestLauncherModel, TestRemove)
+TEST_F(TestLauncherModel, Remove)
{
- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
- LauncherModel::Ptr model(new LauncherModel());
+ model.AddIcon(icon1);
+ EXPECT_EQ(model.Size(), 1);
- EXPECT_EQ(model->Size(), 0);
- model->AddIcon(first);
- EXPECT_EQ(model->Size(), 1);
- model->RemoveIcon(first);
- EXPECT_EQ(model->Size(), 0);
+ model.RemoveIcon(icon1);
+ EXPECT_EQ(model.Size(), 0);
}
-TEST(TestLauncherModel, TestAddSignal)
+TEST_F(TestLauncherModel, AddSignal)
{
- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
- LauncherModel::Ptr model(new LauncherModel());
+ bool icon_added = false;
+ model.icon_added.connect([&icon_added] (AbstractLauncherIcon::Ptr) { icon_added = true; });
- EventListener *listener = new EventListener();
+ model.AddIcon(icon1);
+ EXPECT_TRUE(icon_added);
- model->icon_added.connect(sigc::mem_fun(listener, &EventListener::OnIconAdded));
- model->AddIcon(first);
- EXPECT_EQ(listener->icon_added, true);
+ icon_added = false;
+ model.AddIcon(icon1);
+ EXPECT_FALSE(icon_added);
- delete listener;
+ icon_added = false;
+ model.AddIcon(AbstractLauncherIcon::Ptr());
+ EXPECT_FALSE(icon_added);
}
-TEST(TestLauncherModel, TestRemoveSignal)
+TEST_F(TestLauncherModel, RemoveSignal)
{
- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
- LauncherModel::Ptr model(new LauncherModel());
-
- EventListener *listener = new EventListener();
-
- model->icon_removed.connect(sigc::mem_fun(listener, &EventListener::OnIconRemoved));
- model->AddIcon(first);
- EXPECT_EQ(listener->icon_removed, false);
- model->RemoveIcon(first);
- EXPECT_EQ(listener->icon_removed, true);
+ bool icon_removed = false;
+ model.icon_removed.connect([&icon_removed] (AbstractLauncherIcon::Ptr) { icon_removed = true; });
- delete listener;
+ model.AddIcon(icon1);
+ EXPECT_FALSE(icon_removed);
+ model.RemoveIcon(icon1);
+ EXPECT_TRUE(icon_removed);
}
-TEST(TestLauncherModel, TestSort)
+TEST_F(TestLauncherModel, Sort)
{
- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr second(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr third(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr fourth(new MockLauncherIcon());
+ icon2->SetSortPriority(0);
+ model.AddIcon(icon2);
- LauncherModel::Ptr model(new LauncherModel());
+ icon1->SetSortPriority(-1);
+ model.AddIcon(icon1);
- third->SetSortPriority(0);
- model->AddIcon(third);
+ icon4->SetSortPriority(2);
+ model.AddIcon(icon4);
- first->SetSortPriority(-1);
- model->AddIcon(first);
-
- fourth->SetSortPriority(2);
- model->AddIcon(fourth);
-
- second->SetSortPriority(0);
- model->AddIcon(second);
+ icon3->SetSortPriority(0);
+ model.AddIcon(icon3);
LauncherModel::iterator it;
- it = model->begin();
+ it = model.begin();
- EXPECT_EQ(first, *it);
+ EXPECT_EQ(icon1, *it);
it++;
- EXPECT_EQ(second, *it);
+ EXPECT_EQ(icon2, *it);
it++;
- EXPECT_EQ(third, *it);
+ EXPECT_EQ(icon3, *it);
it++;
- EXPECT_EQ(fourth, *it);
+ EXPECT_EQ(icon4, *it);
}
-TEST(TestLauncherModel, TestReorderBefore)
+TEST_F(TestLauncherModel, ModelKeepsPriorityDeltas)
{
- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr second(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr third(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr fourth(new MockLauncherIcon());
+ icon2->SetSortPriority(0);
+ icon1->SetSortPriority(-1);
+ icon4->SetSortPriority(2);
+ icon3->SetSortPriority(0);
+
+ model.AddIcon(icon2);
+ model.AddIcon(icon1);
+ model.AddIcon(icon4);
+ model.AddIcon(icon3);
+
+ auto it = model.begin();
+ EXPECT_EQ(icon1, *it);
+ it++;
+ EXPECT_EQ(icon2, *it);
+ it++;
+ EXPECT_EQ(icon3, *it);
+ it++;
+ EXPECT_EQ(icon4, *it);
- LauncherModel::Ptr model(new LauncherModel());
+ EXPECT_GT(icon2->SortPriority(), icon1->SortPriority());
+ EXPECT_EQ(icon2->SortPriority(), icon3->SortPriority());
+ EXPECT_LT(icon3->SortPriority(), icon4->SortPriority());
+}
- first->SetSortPriority(0);
- second->SetSortPriority(1);
- third->SetSortPriority(2);
- fourth->SetSortPriority(3);
+TEST_F(TestLauncherModel, ReorderBefore)
+{
+ icon1->SetSortPriority(0);
+ icon2->SetSortPriority(1);
+ icon3->SetSortPriority(2);
+ icon4->SetSortPriority(3);
- model->AddIcon(first);
- model->AddIcon(second);
- model->AddIcon(third);
- model->AddIcon(fourth);
+ model.AddIcon(icon1);
+ model.AddIcon(icon2);
+ model.AddIcon(icon3);
+ model.AddIcon(icon4);
- model->ReorderBefore(third, second, false);
+ model.ReorderBefore(icon3, icon2, false);
LauncherModel::iterator it;
- it = model->begin();
+ it = model.begin();
- EXPECT_EQ(first, *it);
+ EXPECT_EQ(icon1, *it);
it++;
- EXPECT_EQ(third, *it);
+ EXPECT_EQ(icon3, *it);
it++;
- EXPECT_EQ(second, *it);
+ EXPECT_EQ(icon2, *it);
it++;
- EXPECT_EQ(fourth, *it);
+ EXPECT_EQ(icon4, *it);
}
-TEST(TestLauncherModel, TestReorderSmart)
+TEST_F(TestLauncherModel, ReorderAfter)
{
- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr second(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr third(new MockLauncherIcon());
- AbstractLauncherIcon::Ptr fourth(new MockLauncherIcon());
+ model.AddIcon(icon1);
+ model.AddIcon(icon3);
+ model.AddIcon(icon2);
+ model.AddIcon(icon4);
+
+ model.ReorderAfter(icon3, icon2);
+
+ LauncherModel::iterator it;
+ it = model.begin();
- LauncherModel::Ptr model(new LauncherModel());
+ EXPECT_EQ(icon1, *it);
+ it++;
+ EXPECT_EQ(icon2, *it);
+ it++;
+ EXPECT_EQ(icon3, *it);
+ it++;
+ EXPECT_EQ(icon4, *it);
+}
- first->SetSortPriority(0);
- second->SetSortPriority(1);
- third->SetSortPriority(2);
- fourth->SetSortPriority(3);
+TEST_F(TestLauncherModel, ReorderSmart)
+{
+ icon1->SetSortPriority(0);
+ icon2->SetSortPriority(1);
+ icon3->SetSortPriority(2);
+ icon4->SetSortPriority(3);
- model->AddIcon(first);
- model->AddIcon(second);
- model->AddIcon(third);
- model->AddIcon(fourth);
+ model.AddIcon(icon1);
+ model.AddIcon(icon2);
+ model.AddIcon(icon3);
+ model.AddIcon(icon4);
- model->ReorderSmart(third, second, false);
+ model.ReorderSmart(icon3, icon2, false);
LauncherModel::iterator it;
- it = model->begin();
+ it = model.begin();
+
+ EXPECT_EQ(icon1, *it);
+ it++;
+ EXPECT_EQ(icon3, *it);
+ it++;
+ EXPECT_EQ(icon2, *it);
+ it++;
+ EXPECT_EQ(icon4, *it);
+}
- EXPECT_EQ(first, *it);
+TEST_F(TestLauncherModel, OrderByType)
+{
+ AbstractLauncherIcon::Ptr icon1(new MockLauncherIcon(AbstractLauncherIcon::IconType::HOME));
+ AbstractLauncherIcon::Ptr icon2(new MockLauncherIcon(AbstractLauncherIcon::IconType::APPLICATION));
+ AbstractLauncherIcon::Ptr icon3(new MockLauncherIcon(AbstractLauncherIcon::IconType::EXPO));
+ AbstractLauncherIcon::Ptr icon4(new MockLauncherIcon(AbstractLauncherIcon::IconType::DEVICE));
+ AbstractLauncherIcon::Ptr icon5(new MockLauncherIcon(AbstractLauncherIcon::IconType::TRASH));
+
+ model.AddIcon(icon3);
+ model.AddIcon(icon4);
+ model.AddIcon(icon2);
+ model.AddIcon(icon1);
+ model.AddIcon(icon5);
+
+ auto it = model.begin();
+ EXPECT_EQ(icon1, *it);
+ it++;
+ EXPECT_EQ(icon2, *it);
it++;
- EXPECT_EQ(third, *it);
+ EXPECT_EQ(icon3, *it);
it++;
- EXPECT_EQ(second, *it);
+ EXPECT_EQ(icon4, *it);
it++;
- EXPECT_EQ(fourth, *it);
+ EXPECT_EQ(icon5, *it);
+ it++;
+ EXPECT_EQ(it, model.end());
+
+ auto it_main = model.main_begin();
+ EXPECT_EQ(icon1, *it_main);
+ it_main++;
+ EXPECT_EQ(icon2, *it_main);
+ it_main++;
+ EXPECT_EQ(icon3, *it_main);
+ it_main++;
+ EXPECT_EQ(icon4, *it_main);
+ it_main++;
+ EXPECT_EQ(it_main, model.main_end());
+
+ auto it_shelf = model.shelf_begin();
+ EXPECT_EQ(icon5, *it_shelf);
+ it_shelf++;
+ EXPECT_EQ(it_shelf, model.shelf_end());
+}
+
+TEST_F(TestLauncherModel, GetClosestIcon)
+{
+ model.AddIcon(icon1);
+ model.AddIcon(icon2);
+ model.AddIcon(icon3);
+ model.AddIcon(icon4);
+
+ bool before;
+ EXPECT_EQ(model.GetClosestIcon(icon1, before), icon2);
+ EXPECT_FALSE(before);
+
+ EXPECT_EQ(model.GetClosestIcon(icon2, before), icon1);
+ EXPECT_TRUE(before);
+
+ EXPECT_EQ(model.GetClosestIcon(icon3, before), icon2);
+ EXPECT_TRUE(before);
+
+ EXPECT_EQ(model.GetClosestIcon(icon4, before), icon3);
+ EXPECT_TRUE(before);
+}
+
+TEST_F(TestLauncherModel, GetClosestIconWithOneIcon)
+{
+ model.AddIcon(icon1);
+
+ bool before;
+ EXPECT_EQ(model.GetClosestIcon(icon1, before), nullptr);
+ EXPECT_TRUE(before);
+}
+
+TEST_F(TestLauncherModel, IconIndex)
+{
+ model.AddIcon(icon1);
+ model.AddIcon(icon2);
+ model.AddIcon(icon3);
+ model.AddIcon(icon4);
+
+ EXPECT_EQ(model.IconIndex(icon1), 0);
+ EXPECT_EQ(model.IconIndex(icon2), 1);
+ EXPECT_EQ(model.IconIndex(icon3), 2);
+ EXPECT_EQ(model.IconIndex(icon4), 3);
+
+ AbstractLauncherIcon::Ptr icon5(new MockLauncherIcon());
+ EXPECT_EQ(model.IconIndex(icon5), -1);
+}
+
+TEST_F(TestLauncherModel, IconHasSister)
+{
+ model.AddIcon(icon1);
+ EXPECT_FALSE(model.IconHasSister(icon1));
+
+ model.AddIcon(icon2);
+ model.AddIcon(icon3);
+ model.AddIcon(icon4);
+
+ EXPECT_TRUE(model.IconHasSister(icon1));
+ EXPECT_TRUE(model.IconHasSister(icon2));
+ EXPECT_TRUE(model.IconHasSister(icon3));
+ EXPECT_TRUE(model.IconHasSister(icon4));
+
+ EXPECT_FALSE(AbstractLauncherIcon::Ptr());
}
}
diff --git a/tests/test_lens.cpp b/tests/test_lens.cpp
index c0c2f678b..79decb031 100644
--- a/tests/test_lens.cpp
+++ b/tests/test_lens.cpp
@@ -273,6 +273,47 @@ TEST_F(TestLens, TestPreviewAction)
Utils::WaitUntil(action_executed);
}
+TEST_F(TestLens, TestPreviewActionWithHints)
+{
+ std::string uri = PopulateAndGetFirstResultURI();
+ bool previewed = false;
+ Preview::Ptr preview;
+
+ auto preview_cb = [&previewed, &uri, &preview]
+ (std::string const& uri_,
+ Preview::Ptr const& preview_)
+ {
+ EXPECT_EQ(uri, uri_);
+ EXPECT_EQ(preview_->renderer_name, "preview-movie");
+
+ preview = preview_;
+ previewed = true;
+ };
+
+ lens_->preview_ready.connect(preview_cb);
+ lens_->Preview(uri);
+
+ Utils::WaitUntil(previewed);
+
+ bool action_executed = false;
+ auto activated_cb = [&action_executed] (std::string const& uri,
+ HandledType handled_type,
+ Lens::Hints const& hints)
+ {
+ EXPECT_EQ(handled_type, HandledType::SHOW_DASH);
+ action_executed = true;
+ };
+
+ lens_->activated.connect(activated_cb);
+ EXPECT_GT(preview->GetActions().size(), (unsigned)0);
+ auto action = preview->GetActions()[0];
+ auto hints = Lens::Hints();
+ hints["passing-test-hint"] = g_variant_new_boolean(TRUE);
+ preview->PerformAction(action->id, hints);
+
+ Utils::WaitUntil(action_executed);
+}
+
TEST_F(TestLens, TestEmitClosedSignal)
{
std::string uri = PopulateAndGetFirstResultURI();
diff --git a/tests/test_volume_imp.cpp b/tests/test_volume_imp.cpp
new file mode 100644
index 000000000..a6c8e444e
--- /dev/null
+++ b/tests/test_volume_imp.cpp
@@ -0,0 +1,163 @@
+/*
+ * 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 <memory>
+
+#include <gmock/gmock.h>
+using namespace testing;
+
+#include "gmockmount.h"
+#include "gmockvolume.h"
+#include "launcher/VolumeImp.h"
+#include "test_utils.h"
+using namespace unity;
+
+namespace
+{
+
+class MockFileManagerOpener : public launcher::FileManagerOpener
+{
+public:
+ typedef std::shared_ptr<MockFileManagerOpener> Ptr;
+
+ MOCK_METHOD1(Open, void(std::string const& uri));
+};
+
+class MockDeviceNotificationDisplay : public launcher::DeviceNotificationDisplay
+{
+public:
+ typedef std::shared_ptr<MockDeviceNotificationDisplay> Ptr;
+
+ MOCK_METHOD2(Display, void(std::string const& icon_name, std::string const& device_name));
+};
+
+class TestVolumeImp : public Test
+{
+public:
+ void SetUp()
+ {
+ gvolume_ = g_mock_volume_new();
+ file_manager_opener_.reset(new MockFileManagerOpener);
+ device_notification_display_.reset(new MockDeviceNotificationDisplay);
+ volume_.reset(new launcher::VolumeImp(glib::Object<GVolume>(G_VOLUME(gvolume_.RawPtr()), glib::AddRef()),
+ file_manager_opener_, device_notification_display_));
+ }
+
+ glib::Object<GMockVolume> gvolume_;
+ MockFileManagerOpener::Ptr file_manager_opener_;
+ MockDeviceNotificationDisplay::Ptr device_notification_display_;
+ launcher::VolumeImp::Ptr volume_;
+};
+
+TEST_F(TestVolumeImp, TestCtor)
+{
+ EXPECT_FALSE(volume_->IsMounted());
+}
+
+TEST_F(TestVolumeImp, TestCanBeEjected)
+{
+ EXPECT_FALSE(volume_->CanBeEjected());
+
+ g_mock_volume_set_can_eject(gvolume_, TRUE);
+ EXPECT_TRUE(volume_->CanBeEjected());
+}
+
+TEST_F(TestVolumeImp, TestGetName)
+{
+ std::string const volume_name("Test Device");
+
+ // g_mock_volume_set_name is equivalent to
+ // EXPECT_CALL(gvolume_, g_volume_get_name) ...
+ g_mock_volume_set_name(gvolume_, volume_name.c_str());
+ EXPECT_EQ(volume_->GetName(), volume_name);
+}
+
+TEST_F(TestVolumeImp, TestGetIconName)
+{
+ std::string const icon_name("gnome-dev-cdrom");
+
+ g_mock_volume_set_icon(gvolume_, g_icon_new_for_string(icon_name.c_str(), NULL));
+ EXPECT_EQ(volume_->GetIconName(), icon_name);
+}
+
+TEST_F(TestVolumeImp, TestGetIdentifier)
+{
+ std::string const uuid("0123456789abc");
+
+ g_mock_volume_set_uuid(gvolume_, uuid.c_str());
+ EXPECT_EQ(volume_->GetIdentifier(), uuid);
+}
+
+TEST_F(TestVolumeImp, TestIsMounted)
+{
+ g_mock_volume_set_mount(gvolume_, nullptr);
+ ASSERT_FALSE(volume_->IsMounted());
+
+ g_mock_volume_set_mount(gvolume_, G_MOUNT(g_mock_mount_new()));
+ EXPECT_TRUE(volume_->IsMounted());
+}
+
+TEST_F(TestVolumeImp, TestEjectAndShowNotification)
+{
+ g_mock_volume_set_can_eject(gvolume_, TRUE);
+
+ EXPECT_CALL(*device_notification_display_, Display(volume_->GetIconName(), volume_->GetName()))
+ .Times(1);
+
+ volume_->EjectAndShowNotification();
+}
+
+TEST_F(TestVolumeImp, TestMountAndOpenInFileManager)
+{
+ EXPECT_CALL(*file_manager_opener_, Open(ROOT_FILE_URI))
+ .Times(1);
+
+ volume_->MountAndOpenInFileManager();
+ EXPECT_TRUE(volume_->IsMounted());
+
+ EXPECT_CALL(*file_manager_opener_, Open(ROOT_FILE_URI))
+ .Times(1);
+
+ volume_->MountAndOpenInFileManager();
+ EXPECT_TRUE(volume_->IsMounted());
+}
+
+TEST_F(TestVolumeImp, TestChangedSignal)
+{
+ bool callback_called = false;
+ volume_->changed.connect([&]() {
+ callback_called = true;
+ });
+
+ g_signal_emit_by_name(gvolume_, "changed", nullptr);
+ Utils::WaitUntil(callback_called);
+}
+
+TEST_F(TestVolumeImp, TestRemovedSignal)
+{
+ bool callback_called = false;
+ volume_->removed.connect([&]() {
+ callback_called = true;
+ });
+
+ g_signal_emit_by_name(gvolume_, "removed", nullptr);
+ Utils::WaitUntil(callback_called);
+}
+
+}
diff --git a/tests/test_volume_launcher_icon.cpp b/tests/test_volume_launcher_icon.cpp
new file mode 100644
index 000000000..287a9558c
--- /dev/null
+++ b/tests/test_volume_launcher_icon.cpp
@@ -0,0 +1,498 @@
+/*
+ * 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 <gmock/gmock.h>
+using namespace testing;
+
+#include "launcher/DevicesSettings.h"
+#include "launcher/Volume.h"
+#include "launcher/VolumeLauncherIcon.h"
+#include "test_utils.h"
+using namespace unity;
+using namespace unity::launcher;
+
+namespace
+{
+
+class MockVolume : public Volume
+{
+public:
+ typedef std::shared_ptr<MockVolume> Ptr;
+
+ MOCK_CONST_METHOD0(CanBeRemoved, bool(void));
+ MOCK_CONST_METHOD0(CanBeStopped, bool(void));
+ MOCK_CONST_METHOD0(GetName, std::string(void));
+ MOCK_CONST_METHOD0(GetIconName, std::string(void));
+ MOCK_CONST_METHOD0(GetIdentifier, std::string(void));
+ MOCK_CONST_METHOD0(HasSiblings, bool(void));
+ MOCK_CONST_METHOD0(CanBeEjected, bool(void));
+ MOCK_CONST_METHOD0(IsMounted, bool(void));
+
+ MOCK_METHOD0(EjectAndShowNotification, void(void));
+ MOCK_METHOD0(MountAndOpenInFileManager, void(void));
+ MOCK_METHOD0(StopDrive, void(void));
+ MOCK_METHOD0(Unmount, void(void));
+};
+
+class MockDevicesSettings : public DevicesSettings
+{
+public:
+ typedef std::shared_ptr<MockDevicesSettings> Ptr;
+
+ MOCK_CONST_METHOD1(IsABlacklistedDevice, bool(std::string const& uuid));
+ MOCK_METHOD1(TryToBlacklist, void(std::string const& uuid));
+ MOCK_METHOD1(TryToUnblacklist, void(std::string const& uuid));
+};
+
+
+class TestVolumeLauncherIcon : public Test
+{
+public:
+ virtual void SetUp()
+ {
+ volume_.reset(new MockVolume);
+ settings_.reset(new MockDevicesSettings);
+
+ SetupVolumeDefaultBehavior();
+ SetupSettingsDefaultBehavior();
+ }
+
+ void CreateIcon()
+ {
+ icon_ = new VolumeLauncherIcon(volume_, settings_);
+ }
+
+ void SetupSettingsDefaultBehavior()
+ {
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
+ .WillRepeatedly(Return(false));
+ }
+
+ void SetupVolumeDefaultBehavior()
+ {
+ EXPECT_CALL(*volume_, CanBeRemoved())
+ .WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*volume_, CanBeStopped())
+ .WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*volume_, GetName())
+ .WillRepeatedly(Return("Test Name"));
+
+ EXPECT_CALL(*volume_, GetIconName())
+ .WillRepeatedly(Return("Test Icon Name"));
+
+ EXPECT_CALL(*volume_, GetIdentifier())
+ .WillRepeatedly(Return("Test Identifier"));
+
+ EXPECT_CALL(*volume_, HasSiblings())
+ .WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*volume_, CanBeEjected())
+ .WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(true));
+ }
+
+ glib::Object<DbusmenuMenuitem> GetMenuItemAtIndex(int index)
+ {
+ auto menuitems = icon_->GetMenus();
+ auto menuitem = menuitems.begin();
+ std::advance(menuitem, index);
+
+ return *menuitem;
+ }
+
+ MockVolume::Ptr volume_;
+ MockDevicesSettings::Ptr settings_;
+ VolumeLauncherIcon::Ptr icon_;
+};
+
+TEST_F(TestVolumeLauncherIcon, TestIconType)
+{
+ CreateIcon();
+ EXPECT_EQ(icon_->GetIconType(), AbstractLauncherIcon::IconType::DEVICE);
+}
+
+TEST_F(TestVolumeLauncherIcon, TestQuirks)
+{
+ CreateIcon();
+
+ EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestTooltipText)
+{
+ CreateIcon();
+
+ ASSERT_EQ(icon_->tooltip_text, "Test Name");
+}
+
+TEST_F(TestVolumeLauncherIcon, TestIconName)
+{
+ CreateIcon();
+
+ ASSERT_EQ(icon_->icon_name, "Test Icon Name");
+}
+
+TEST_F(TestVolumeLauncherIcon, TestVisibility_InitiallyMountedVolume)
+{
+ CreateIcon();
+
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestVisibility_InitiallyMountedBlacklistedVolume)
+{
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+
+TEST_F(TestVolumeLauncherIcon, TestVisibility_InitiallyUnmountedVolume)
+{
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(false));
+
+ CreateIcon();
+
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+
+TEST_F(TestVolumeLauncherIcon, TestVisibility_InitiallyUnmountedBlacklistedVolume)
+{
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestSettingsChangedSignal)
+{
+ CreateIcon();
+
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
+ .WillRepeatedly(Return(true));
+ settings_->changed.emit();
+
+ EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestVisibilityAfterUnmount)
+{
+ CreateIcon();
+
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*settings_, TryToBlacklist(_))
+ .Times(0);
+
+ volume_->changed.emit();
+ Utils::WaitForTimeout(1);
+
+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestVisibilityAfterUnmount_BlacklistedVolume)
+{
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(false));
+
+ EXPECT_CALL(*settings_, TryToUnblacklist(_))
+ .Times(0);
+
+ volume_->changed.emit();
+ Utils::WaitForTimeout(1);
+
+ EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_VolumeWithoutIdentifier)
+{
+ EXPECT_CALL(*volume_, GetIdentifier())
+ .WillRepeatedly(Return(""));
+
+ CreateIcon();
+
+ for (auto menuitem : icon_->GetMenus())
+ ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unlock from Launcher");
+}
+
+TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_Success)
+{
+ CreateIcon();
+
+ auto menuitem = GetMenuItemAtIndex(0);
+
+ ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unlock from Launcher");
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
+
+ EXPECT_CALL(*settings_, TryToBlacklist(_))
+ .Times(1);
+
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
+ .WillRepeatedly(Return(true));
+
+ dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+ settings_->changed.emit(); // TryToBlacklist() works if DevicesSettings emits a changed signal.
+ Utils::WaitForTimeout(1);
+
+ ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_Failure)
+{
+ CreateIcon();
+
+ auto menuitem = GetMenuItemAtIndex(0);
+
+ ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unlock from Launcher");
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
+
+ EXPECT_CALL(*settings_, TryToBlacklist(_))
+ .Times(1);
+
+ dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+ Utils::WaitForTimeout(1);
+
+ ASSERT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
+}
+
+TEST_F(TestVolumeLauncherIcon, TestOpenMenuItem)
+{
+ CreateIcon();
+
+ auto menuitem = GetMenuItemAtIndex(1);
+
+ ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Open");
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
+
+ EXPECT_CALL(*volume_, MountAndOpenInFileManager())
+ .Times(1);
+
+ dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+ Utils::WaitForTimeout(1);
+}
+
+TEST_F(TestVolumeLauncherIcon, TestEjectMenuItem_NotEjectableVolume)
+{
+ CreateIcon();
+
+ for (auto menuitem : icon_->GetMenus())
+ ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Eject");
+}
+
+TEST_F(TestVolumeLauncherIcon, TestEjectMenuItem)
+{
+ EXPECT_CALL(*volume_, CanBeEjected())
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ auto menuitem = GetMenuItemAtIndex(2);
+
+ EXPECT_CALL(*volume_, EjectAndShowNotification())
+ .Times(1);
+
+ ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Eject");
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
+
+ dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+ Utils::WaitForTimeout(1);
+}
+
+TEST_F(TestVolumeLauncherIcon, TestEjectMenuItem_NotStoppableVolume)
+{
+ CreateIcon();
+
+ for (auto menuitem : icon_->GetMenus())
+ ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Safely remove");
+}
+
+TEST_F(TestVolumeLauncherIcon, TestSafelyRemoveMenuItem)
+{
+ EXPECT_CALL(*volume_, CanBeStopped())
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ auto menuitem = GetMenuItemAtIndex(2);
+
+ EXPECT_CALL(*volume_, StopDrive())
+ .Times(1);
+
+ ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Safely remove");
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
+
+ dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+ Utils::WaitForTimeout(1);
+}
+
+TEST_F(TestVolumeLauncherIcon, TestUnmountMenuItem_UnmountedVolume)
+{
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(false));
+
+ CreateIcon();
+
+ for (auto menuitem : icon_->GetMenus())
+ ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unmount");
+}
+
+
+TEST_F(TestVolumeLauncherIcon, TestUnmountMenuItem_EjectableVolume)
+{
+ EXPECT_CALL(*volume_, CanBeEjected())
+ .WillRepeatedly(Return(true));
+
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ for (auto menuitem : icon_->GetMenus())
+ ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unmount");
+}
+
+TEST_F(TestVolumeLauncherIcon, TestUnmountMenuItem_StoppableVolume)
+{
+ EXPECT_CALL(*volume_, CanBeStopped())
+ .WillRepeatedly(Return(true));
+
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ for (auto menuitem : icon_->GetMenus())
+ ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unmount");
+}
+
+TEST_F(TestVolumeLauncherIcon, TestUnmountMenuItem)
+{
+ EXPECT_CALL(*volume_, IsMounted())
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ auto menuitem = GetMenuItemAtIndex(2);
+
+ EXPECT_CALL(*volume_, Unmount())
+ .Times(1);
+
+ ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unmount");
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
+
+ dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
+ Utils::WaitForTimeout(1);
+}
+
+TEST_F(TestVolumeLauncherIcon, TestCanBeEject)
+{
+ CreateIcon();
+
+ EXPECT_CALL(*volume_, CanBeEjected())
+ .WillRepeatedly(Return(true));
+ ASSERT_TRUE(icon_->CanEject());
+
+ EXPECT_CALL(*volume_, CanBeEjected())
+ .WillRepeatedly(Return(false));
+ ASSERT_FALSE(icon_->CanEject());
+
+}
+
+TEST_F(TestVolumeLauncherIcon, TestEject)
+{
+ EXPECT_CALL(*volume_, CanBeEjected())
+ .WillRepeatedly(Return(true));
+
+ CreateIcon();
+
+ EXPECT_CALL(*volume_, EjectAndShowNotification())
+ .Times(1);
+
+ icon_->EjectAndShowNotification();
+}
+
+TEST_F(TestVolumeLauncherIcon, OnRemoved)
+{
+ CreateIcon();
+
+ EXPECT_CALL(*settings_, TryToBlacklist(_))
+ .Times(0);
+ EXPECT_CALL(*settings_, TryToUnblacklist(_))
+ .Times(0);
+
+ volume_->removed.emit();
+}
+
+TEST_F(TestVolumeLauncherIcon, OnRemoved_RemovabledVolume)
+{
+ EXPECT_CALL(*volume_, CanBeRemoved())
+ .WillRepeatedly(Return(true));
+ CreateIcon();
+
+ EXPECT_CALL(*settings_, TryToBlacklist(_))
+ .Times(0);
+ EXPECT_CALL(*settings_, TryToUnblacklist(_))
+ .Times(0);
+
+ volume_->removed.emit();
+}
+
+TEST_F(TestVolumeLauncherIcon, OnRemoved_RemovableAndBlacklistedVolume)
+{
+ EXPECT_CALL(*volume_, CanBeRemoved())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
+ .WillRepeatedly(Return(true));
+ CreateIcon();
+
+ EXPECT_CALL(*settings_, TryToBlacklist(_))
+ .Times(0);
+ EXPECT_CALL(*settings_, TryToUnblacklist(_))
+ .Times(1);
+
+ volume_->removed.emit();
+}
+
+}
diff --git a/tools/convert-files/compiz-profile-active-unity.convert b/tools/convert-files/compiz-profile-active-unity.convert
index 15e14d36a..5c1dfc51a 100644
--- a/tools/convert-files/compiz-profile-active-unity.convert
+++ b/tools/convert-files/compiz-profile-active-unity.convert
@@ -23,7 +23,7 @@ reveal-pressure = /apps/compiz-1/plugins/unityshell/screen0/options/reveal_press
decay-rate = /apps/compiz-1/plugins/unityshell/screen0/options/decay_rate
stop-velocity = /apps/compiz-1/plugins/unityshell/screen0/options/stop_velocity
autohide-animation = /apps/compiz-1/plugins/unityshell/screen0/options/autohide_animation
-alt-tab-bias_viewport = /apps/compiz-1/plugins/unityshell/screen0/options/alt_tab_bias_viewport
+alt-tab-bias-viewport = /apps/compiz-1/plugins/unityshell/screen0/options/alt_tab_bias_viewport
edge-responsiveness = /apps/compiz-1/plugins/unityshell/screen0/options/edge_responsiveness
automaximize-value = /apps/compiz-1/plugins/unityshell/screen0/options/automaximize_value
background-color = /apps/compiz-1/plugins/unityshell/screen0/options/background_color
@@ -36,11 +36,11 @@ menus-discovery-duration = /apps/compiz-1/plugins/unityshell/screen0/options/men
alt-tab-prev-window = /apps/compiz-1/plugins/unityshell/screen0/options/alt_tab_prev_window
devices-option = /apps/compiz-1/plugins/unityshell/screen0/options/devices_option
reveal-trigger = /apps/compiz-1/plugins/unityshell/screen0/options/reveal_trigger
-panel-first_menu = /apps/compiz-1/plugins/unityshell/screen0/options/panel_first_menu
+panel-first-menu = /apps/compiz-1/plugins/unityshell/screen0/options/panel_first_menu
icon-size = /apps/compiz-1/plugins/unityshell/screen0/options/icon_size
backlight-mode = /apps/compiz-1/plugins/unityshell/screen0/options/backlight_mode
menus-fadein = /apps/compiz-1/plugins/unityshell/screen0/options/menus_fadein
-alt-tab-detail_start = /apps/compiz-1/plugins/unityshell/screen0/options/alt_tab_detail_start
+alt-tab-detail-start = /apps/compiz-1/plugins/unityshell/screen0/options/alt_tab_detail_start
show-desktop-icon = /apps/compiz-1/plugins/unityshell/screen0/options/show_desktop_icon
alt-tab-next-window = /apps/compiz-1/plugins/unityshell/screen0/options/alt_tab_next_window
launcher-opacity = /apps/compiz-1/plugins/unityshell/screen0/options/launcher_opacity
@@ -53,7 +53,7 @@ menus-fadeout = /apps/compiz-1/plugins/unityshell/screen0/options/menus_fadeout
active-plugins = /apps/compiz-1/plugins/core/screen0/options/active_plugins
vsize = /apps/compiz-1/plugins/core/screen0/options/vsize
hsize = /apps/compiz-1/plugins/core/screen0/options/vsize
-close_window_button = /apps/compiz-1/plugins/core/screen0/options/close_window_button
+close-window-button = /apps/compiz-1/plugins/core/screen0/options/close_window_button
close-window-key = /apps/compiz-1/plugins/core/screen0/options/close_window_key
lower-window-button = /apps/compiz-1/plugins/core/screen0/options/lower_window_button
lower-window-key = /apps/compiz-1/plugins/core/screen0/options/lower_window_key
@@ -66,7 +66,7 @@ raise-window-button = /apps/compiz-1/plugins/core/screen0/options/raise_window_b
raise-window-key = /apps/compiz-1/plugins/core/screen0/options/raise_window_key
show-desktop-edge = /apps/compiz-1/plugins/core/screen0/options/show_desktop_edge
show-desktop-key = /apps/compiz-1/plugins/core/screen0/options/show_desktop_key
-toggle-window_maximized-button = /apps/compiz-1/plugins/core/screen0/options/toggle_window_maximized_button
+toggle-window-maximized-button = /apps/compiz-1/plugins/core/screen0/options/toggle_window_maximized_button
toggle-window-maximized-horizontally-key = /apps/compiz-1/plugins/core/screen0/options/toggle_window_maximized_horizontally_key
toggle-window-maximized-key = /apps/compiz-1/plugins/core/screen0/options/toggle_window_maximized_key
toggle-window-maximized-vertically-key = /apps/compiz-1/plugins/core/screen0/options/toggle_window_maximized_vertically_key
@@ -154,8 +154,7 @@ right-edge-action = /apps/compiz-1/plugins/grid/screen0/options/right_edge_actio
right-edge-threshold = /apps/compiz-1/plugins/grid/screen0/options/right_edge_threshold
snapback-windows = /apps/compiz-1/plugins/grid/screen0/options/snapback_windows
snapoff-maximized = /apps/compiz-1/plugins/grid/screen0/options/snapoff_maximized
-top-edge_action = /apps/compiz-1/plugins/grid/screen0/options/top_edge_action
-top-edge_threshold = /apps/compiz-1/plugins/grid/screen0/options/top_edge_threshold
+top-edge-action = /apps/compiz-1/plugins/grid/screen0/options/top_edge_action
+top-edge-threshold = /apps/compiz-1/plugins/grid/screen0/options/top_edge_threshold
top-left-corner-action = /apps/compiz-1/plugins/grid/screen0/options/top_left_corner_action
top-right-corner-action = /apps/compiz-1/plugins/grid/screen0/options/top_right_corner_action
-
diff --git a/tools/convert-files/compiz-profile-unity.convert b/tools/convert-files/compiz-profile-unity.convert
index c97669d29..36fcc9ee2 100644
--- a/tools/convert-files/compiz-profile-unity.convert
+++ b/tools/convert-files/compiz-profile-unity.convert
@@ -23,7 +23,7 @@ reveal-pressure = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0
decay-rate = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/decay_rate
stop-velocity = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/stop_velocity
autohide-animation = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/autohide_animation
-alt-tab-bias_viewport = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/alt_tab_bias_viewport
+alt-tab-bias-viewport = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/alt_tab_bias_viewport
edge-responsiveness = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/edge_responsiveness
automaximize-value = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/automaximize_value
background-color = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/background_color
@@ -36,11 +36,11 @@ menus-discovery-duration = /apps/compizconfig-1/profiles/unity/plugins/unityshel
alt-tab-prev-window = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/alt_tab_prev_window
devices-option = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/devices_option
reveal-trigger = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/reveal_trigger
-panel-first_menu = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/panel_first_menu
+panel-first-menu = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/panel_first_menu
icon-size = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/icon_size
backlight-mode = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/backlight_mode
menus-fadein = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/menus_fadein
-alt-tab-detail_start = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/alt_tab_detail_start
+alt-tab-detail-start = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/alt_tab_detail_start
show-desktop-icon = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/show_desktop_icon
alt-tab-next-window = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/alt_tab_next_window
launcher-opacity = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/options/launcher_opacity
@@ -53,7 +53,7 @@ menus-fadeout = /apps/compizconfig-1/profiles/unity/plugins/unityshell/screen0/o
active-plugins = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/active_plugins
vsize = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/vsize
hsize = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/vsize
-close_window_button = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/close_window_button
+close-window-button = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/close_window_button
close-window-key = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/close_window_key
lower-window-button = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/lower_window_button
lower-window-key = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/lower_window_key
@@ -66,7 +66,7 @@ raise-window-button = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/o
raise-window-key = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/raise_window_key
show-desktop-edge = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/show_desktop_edge
show-desktop-key = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/show_desktop_key
-toggle-window_maximized-button = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/toggle_window_maximized_button
+toggle-window-maximized-button = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/toggle_window_maximized_button
toggle-window-maximized-horizontally-key = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/toggle_window_maximized_horizontally_key
toggle-window-maximized-key = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/toggle_window_maximized_key
toggle-window-maximized-vertically-key = /apps/compizconfig-1/profiles/unity/plugins/core/screen0/options/toggle_window_maximized_vertically_key
@@ -154,8 +154,7 @@ right-edge-action = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/opt
right-edge-threshold = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/right_edge_threshold
snapback-windows = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/snapback_windows
snapoff-maximized = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/snapoff_maximized
-top-edge_action = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/top_edge_action
-top-edge_threshold = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/top_edge_threshold
+top-edge-action = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/top_edge_action
+top-edge-threshold = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/top_edge_threshold
top-left-corner-action = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/top_left_corner_action
top-right-corner-action = /apps/compizconfig-1/profiles/unity/plugins/grid/screen0/options/top_right_corner_action
-
diff --git a/tools/unity.cmake b/tools/unity.cmake
index af7871855..69bf4c1e5 100755
--- a/tools/unity.cmake
+++ b/tools/unity.cmake
@@ -18,7 +18,6 @@
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-import gconf
import glib
import glob
from optparse import OptionParser
@@ -64,47 +63,6 @@ def set_unity_env ():
print "WARNING: no DISPLAY variable set, setting it to :0"
os.environ['DISPLAY'] = ':0'
-def reset_unity_compiz_profile ():
- '''reset the compiz/unity profile to a vanilla one'''
-
- client = gconf.client_get_default()
-
- if not client:
- print "WARNING: no gconf client found. No reset will be done"
- return
-
- # get current compiz profile to know if we need to switch or not
- # as compiz is setting that as a default key schema each time you
- # change the profile, the key isn't straightforward to get and set
- # as compiz set a new schema instead of a value..
- try:
- current_profile_schema = client.get_schema("/apps/compizconfig-1/current_profile")
- except (glib.GError, AttributeError), e:
- print "WARNING: environment is incorrect: %s\nDid you just try to reset in a tty?" % e
- return
-
- # default value to not force reset if current_profile is unset
- if not current_profile_schema:
- print "WARNING: no current gconf profile set, assuming unity"
- current_profile_str = 'unity'
- current_profile_gconfvalue = None
- else:
- current_profile_gconfvalue = current_profile_schema.get_default_value()
- current_profile_str = current_profile_gconfvalue.get_string()
-
- if current_profile_str == 'unity':
- print "WARNING: Unity currently default profile, so switching to metacity while resetting the values"
- subprocess.Popen(["metacity", "--replace"]) #TODO: check if compiz is indeed running
- # wait for compiz to stop
- time.sleep(2)
- if current_profile_gconfvalue:
- current_profile_gconfvalue.set_string('fooo')
- current_profile_schema.set_default_value(current_profile_gconfvalue)
- client.set_schema("/apps/compizconfig-1/current_profile", current_profile_schema)
- # the python binding doesn't recursive-unset right
- subprocess.Popen(["gconftool-2", "--recursive-unset", "/apps/compiz-1"]).communicate()
- subprocess.Popen(["gconftool-2", "--recursive-unset", "/apps/compizconfig-1/profiles/unity"]).communicate()
-
def reset_launcher_icons ():
'''Reset the default launcher icon and restart it.'''
subprocess.Popen(["gsettings", "reset" ,"com.canonical.Unity.Launcher" , "favorites"])
@@ -203,8 +161,6 @@ if __name__ == '__main__':
help="Store log under filename.")
parser.add_option("--replace", action="store_true",
help="Run unity /!\ This is for compatibility with other desktop interfaces and acts the same as running unity without --replace")
- parser.add_option("--reset", action="store_true",
- help="Reset the unity profile in compiz and restart it.")
parser.add_option("--reset-icons", action="store_true",
help="Reset the default launcher icon.")
parser.add_option("-v", "--verbose", action="store_true",
@@ -216,9 +172,6 @@ if __name__ == '__main__':
if options.distro:
sys.exit(reset_to_distro())
- if options.reset:
- reset_unity_compiz_profile ()
-
if options.reset_icons:
reset_launcher_icons ()
diff --git a/unity-shared/BGHash.cpp b/unity-shared/BGHash.cpp
index fc299bc98..4f66a873a 100644
--- a/unity-shared/BGHash.cpp
+++ b/unity-shared/BGHash.cpp
@@ -46,17 +46,17 @@ void BGHash::OverrideColor(nux::Color const& color)
{
override_color_ = color;
- if (override_color_.alpha)
- {
- TransitionToNewColor(override_color_);
- return;
- }
-
RefreshColor();
}
void BGHash::RefreshColor()
{
+ if (override_color_.alpha > 0.0f)
+ {
+ TransitionToNewColor(override_color_);
+ return;
+ }
+
Atom real_type;
gint result;
gint real_format;
diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt
index d1b06f000..c2c5b9562 100644
--- a/unity-shared/CMakeLists.txt
+++ b/unity-shared/CMakeLists.txt
@@ -18,8 +18,6 @@ add_definitions (${CFLAGS})
set (LIBS ${CACHED_UNITY_DEPS_LIBRARIES} ${UNITY_STANDALONE_LADD})
-link_libraries (${LIBS})
-
set (LIB_PATHS ${CACHED_UNITY_DEPS_LIBRARY_DIRS})
link_directories (${CMAKE_BINARY_DIR}/UnityCore ${LIB_PATHS})
@@ -70,6 +68,7 @@ set (UNITY_SHARED_SOURCES
)
add_library (unity-shared STATIC ${UNITY_SHARED_SOURCES})
+target_link_libraries (unity-shared ${LIBS})
add_dependencies (unity-shared unity-core-${UNITY_API_VERSION})
#
@@ -81,6 +80,8 @@ set (UNITY_SHARED_COMPIZ_SOURCES
PluginAdapterCompiz.cpp
)
add_library (unity-shared-compiz STATIC ${UNITY_SHARED_COMPIZ_SOURCES})
+target_link_libraries (unity-shared-compiz ${LIBS})
+
add_dependencies (unity-shared-compiz unity-shared)
# standalone
@@ -88,6 +89,7 @@ set (UNITY_SHARED_STANDALONE_SOURCES
PluginAdapterStandalone.cpp
)
add_library (unity-shared-standalone STATIC ${UNITY_SHARED_STANDALONE_SOURCES})
+target_link_libraries (unity-shared-standalone ${LIBS})
add_dependencies (unity-shared-standalone unity-shared)
diff --git a/unity-shared/CoverArt.cpp b/unity-shared/CoverArt.cpp
index 000be4dd2..ac8044e5a 100644
--- a/unity-shared/CoverArt.cpp
+++ b/unity-shared/CoverArt.cpp
@@ -286,6 +286,7 @@ void CoverArt::TextureLoaded(std::string const& texid, unsigned size, glib::Obje
return;
}
texture_screenshot_.Adopt(nux::CreateTexture2DFromPixbuf(pixbuf, true));
+ QueueDraw();
}
void CoverArt::Draw(nux::GraphicsEngine& gfx_engine, bool force_draw)
diff --git a/unity-shared/PanelStyle.cpp b/unity-shared/PanelStyle.cpp
index 142095396..2d64af4f0 100644
--- a/unity-shared/PanelStyle.cpp
+++ b/unity-shared/PanelStyle.cpp
@@ -182,9 +182,17 @@ nux::NBitmapData* Style::GetBackground(int width, int height, float opacity)
return context.GetBitmap();
}
-nux::BaseTexture* Style::GetWindowButton(WindowButtonType type, WindowState state)
+/*!
+ Return a vector with the possible file names sorted by priority
+
+ @param type The type of the button.
+ @param state The button state.
+
+ @return A vector of strings with the possible file names sorted by priority.
+*/
+std::vector<std::string> Style::GetWindowButtonFileNames(WindowButtonType type, WindowState state)
{
- nux::BaseTexture* texture = NULL;
+ std::vector<std::string> files;
std::string names[] = { "close", "minimize", "unmaximize", "maximize" };
std::string states[] = { "", "_focused_prelight", "_focused_pressed", "_unfocused",
"_unfocused", "_unfocused_prelight", "_unfocused_pressed"};
@@ -200,38 +208,40 @@ nux::BaseTexture* Style::GetWindowButton(WindowButtonType type, WindowState stat
glib::String filename(g_build_filename(home_dir, ".themes", _theme_name.c_str(), subpath.str().c_str(), NULL));
if (g_file_test(filename.Value(), G_FILE_TEST_EXISTS))
- {
- glib::Error error;
-
- // Found a file, try loading the pixbuf
- glib::Object<GdkPixbuf> pixbuf(gdk_pixbuf_new_from_file(filename.Value(), &error));
- if (error)
- LOG_WARNING(logger) << "Unable to load window button " << filename.Value() << ": " << error.Message();
- else
- texture = nux::CreateTexture2DFromPixbuf(pixbuf, true);
- }
+ files.push_back (filename.Value());
}
- // texture is NULL if the pixbuf is not loaded
- if (!texture)
- {
- const char* var = g_getenv("GTK_DATA_PREFIX");
- if (!var)
- var = "/usr";
+ const char* var = g_getenv("GTK_DATA_PREFIX");
+ if (!var)
+ var = "/usr";
- glib::String filename(g_build_filename(var, "share", "themes", _theme_name.c_str(), subpath.str().c_str(), NULL));
+ glib::String filename(g_build_filename(var, "share", "themes", _theme_name.c_str(), subpath.str().c_str(), NULL));
+ if (g_file_test(filename.Value(), G_FILE_TEST_EXISTS))
+ files.push_back (filename.Value());
- if (g_file_test(filename.Value(), G_FILE_TEST_EXISTS))
- {
- glib::Error error;
+ return files;
+}
+
+nux::BaseTexture* Style::GetWindowButton(WindowButtonType type, WindowState state)
+{
+ nux::BaseTexture* texture = NULL;
- // Found a file, try loading the pixbuf
- glib::Object<GdkPixbuf> pixbuf(gdk_pixbuf_new_from_file(filename.Value(), &error));
+ std::vector<std::string> files = GetWindowButtonFileNames (type, state);
+ for (unsigned int i=0; i < files.size(); i++)
+ {
+ glib::Error error;
+ // Try loading the pixbuf
+ glib::Object<GdkPixbuf> pixbuf(gdk_pixbuf_new_from_file(files[i].c_str (), &error));
if (error)
- LOG_WARNING(logger) << "Unable to load window button " << filename.Value() << ": " << error.Message();
+ {
+ LOG_WARNING(logger) << "Unable to load window button " << files[i] << ": " << error.Message();
+ }
else
+ {
texture = nux::CreateTexture2DFromPixbuf(pixbuf, true);
- }
+ if (texture)
+ break;
+ }
}
if (!texture)
diff --git a/unity-shared/PanelStyle.h b/unity-shared/PanelStyle.h
index b5640c18e..b73c05f74 100644
--- a/unity-shared/PanelStyle.h
+++ b/unity-shared/PanelStyle.h
@@ -71,6 +71,7 @@ public:
GtkStyleContext* GetStyleContext();
nux::NBitmapData* GetBackground(int width, int height, float opacity);
nux::BaseTexture* GetWindowButton(WindowButtonType type, WindowState state);
+ std::vector<std::string> GetWindowButtonFileNames(WindowButtonType type, WindowState state);
nux::BaseTexture* GetFallbackWindowButton(WindowButtonType type, WindowState state);
glib::Object<GdkPixbuf> GetHomeButton();
std::string GetFontDescription(PanelItem item);
diff --git a/unity-shared/PluginAdapter.h b/unity-shared/PluginAdapter.h
index 8c9882bd1..a6fda2bcf 100644
--- a/unity-shared/PluginAdapter.h
+++ b/unity-shared/PluginAdapter.h
@@ -154,6 +154,7 @@ public:
nux::Geometry GetWindowSavedGeometry(guint32 xid) const;
nux::Geometry GetScreenGeometry() const;
nux::Geometry GetWorkAreaGeometry(guint32 xid = 0) const;
+ std::string GetWindowName(guint32 xid) const;
void CheckWindowIntersections(nux::Geometry const& region, bool &active, bool &any);
@@ -177,6 +178,9 @@ private:
bool CheckWindowIntersection(nux::Geometry const& region, CompWindow* window) const;
void SetMwmWindowHints(Window xid, MotifWmHints* new_hints);
+ std::string GetTextProperty(guint32 xid, Atom atom) const;
+ std::string GetUtf8Property(guint32 xid, Atom atom) const;
+
CompScreen* m_Screen;
MultiActionList m_ExpoActionList;
MultiActionList m_ScaleActionList;
diff --git a/unity-shared/PluginAdapterCompiz.cpp b/unity-shared/PluginAdapterCompiz.cpp
index 1c67e9659..fe1c978cc 100644
--- a/unity-shared/PluginAdapterCompiz.cpp
+++ b/unity-shared/PluginAdapterCompiz.cpp
@@ -1335,3 +1335,70 @@ PluginAdapter::AddProperties(GVariantBuilder* builder)
.add("viewport_switch_running", IsViewPortSwitchStarted())
.add("showdesktop_active", _in_show_desktop);
}
+
+std::string
+PluginAdapter::GetWindowName(guint32 xid) const
+{
+ std::string name;
+ Atom visibleNameAtom;
+
+ visibleNameAtom = XInternAtom(m_Screen->dpy(), "_NET_WM_VISIBLE_NAME", 0);
+ name = GetUtf8Property(xid, visibleNameAtom);
+ if (name.empty())
+ {
+ Atom wmNameAtom = XInternAtom(m_Screen->dpy(), "_NET_WM_NAME", 0);
+ name = GetUtf8Property(xid, wmNameAtom);
+ }
+
+ if (name.empty())
+ name = GetTextProperty(xid, XA_WM_NAME);
+
+ return name;
+}
+
+std::string
+PluginAdapter::GetUtf8Property(guint32 xid, Atom atom) const
+{
+ Atom type;
+ int result, format;
+ unsigned long nItems, bytesAfter;
+ char *val;
+ std::string retval;
+ Atom utf8StringAtom;
+
+ utf8StringAtom = XInternAtom(m_Screen->dpy(), "UTF8_STRING", 0);
+ result = XGetWindowProperty(m_Screen->dpy(), xid, atom, 0L, 65536, False,
+ utf8StringAtom, &type, &format, &nItems,
+ &bytesAfter, reinterpret_cast<unsigned char **>(&val));
+
+ if (result != Success)
+ return retval;
+
+ if (type == utf8StringAtom && format == 8 && val && nItems > 0)
+ {
+ retval = std::string(val, nItems);
+ }
+ if (val)
+ XFree(val);
+
+ return retval;
+}
+
+std::string
+PluginAdapter::GetTextProperty(guint32 id, Atom atom) const
+{
+ XTextProperty text;
+ std::string retval;
+
+ text.nitems = 0;
+ if (XGetTextProperty(m_Screen->dpy(), id, &text, atom))
+ {
+ if (text.value)
+ {
+ retval = std::string(reinterpret_cast<char*>(text.value), text.nitems);
+ XFree (text.value);
+ }
+ }
+
+ return retval;
+}
diff --git a/unity-shared/PluginAdapterStandalone.cpp b/unity-shared/PluginAdapterStandalone.cpp
index 9ba893021..9e31f2a1b 100644
--- a/unity-shared/PluginAdapterStandalone.cpp
+++ b/unity-shared/PluginAdapterStandalone.cpp
@@ -458,3 +458,9 @@ PluginAdapter::AddProperties(GVariantBuilder* builder)
.add("viewport_switch_running", IsViewPortSwitchStarted())
.add("showdesktop_active", _in_show_desktop);
}
+
+std::string
+PluginAdapter::GetWindowName(guint32 xid) const
+{
+ return "";
+}
diff --git a/unity-shared/PreviewStyle.cpp b/unity-shared/PreviewStyle.cpp
index 9d44dc539..ef8df611f 100644
--- a/unity-shared/PreviewStyle.cpp
+++ b/unity-shared/PreviewStyle.cpp
@@ -39,6 +39,9 @@ namespace
{
Style* style_instance = nullptr;
+const int preview_width = 770;
+const int preview_height = 380;
+
nux::logging::Logger logger("unity.dash.previews.style");
typedef nux::ObjectPtr<nux::BaseTexture> BaseTexturePtr;
@@ -159,9 +162,14 @@ int Style::GetNavigatorIconSize() const
return 24;
}
-float Style::GetPreviewAspectRatio() const
+int Style::GetPreviewWidth() const
{
- return static_cast<float>(796)/390;
+ return preview_width;
+}
+
+int Style::GetPreviewHeight() const
+{
+ return preview_height;
}
int Style::GetDetailsTopMargin() const
@@ -186,7 +194,7 @@ int Style::GetDetailsLeftMargin() const
int Style::GetPanelSplitWidth() const
{
- return 16;
+ return 10;
}
int Style::GetAppIconAreaWidth() const
diff --git a/unity-shared/PreviewStyle.h b/unity-shared/PreviewStyle.h
index 3bfff9fd6..ac197f29d 100644
--- a/unity-shared/PreviewStyle.h
+++ b/unity-shared/PreviewStyle.h
@@ -60,7 +60,8 @@ public:
int GetNavigatorWidth() const;
int GetNavigatorIconSize() const;
- float GetPreviewAspectRatio() const;
+ int GetPreviewWidth() const;
+ int GetPreviewHeight() const;
int GetDetailsTopMargin() const;
int GetDetailsBottomMargin() const;
diff --git a/unity-shared/WindowManager.cpp b/unity-shared/WindowManager.cpp
index 5f5cd6519..df983217c 100644
--- a/unity-shared/WindowManager.cpp
+++ b/unity-shared/WindowManager.cpp
@@ -240,6 +240,11 @@ class WindowManagerDummy : public WindowManager
void AddProperties(GVariantBuilder* builder)
{
}
+
+ std::string GetWindowName(guint32 xid) const
+ {
+ return "unknown";
+ }
};
WindowManager*
diff --git a/unity-shared/WindowManager.h b/unity-shared/WindowManager.h
index 84ae82485..204c9439c 100644
--- a/unity-shared/WindowManager.h
+++ b/unity-shared/WindowManager.h
@@ -111,6 +111,8 @@ public:
virtual bool saveInputFocus() = 0;
virtual bool restoreInputFocus() = 0;
+ virtual std::string GetWindowName(guint32 xid) const = 0;
+
// Signals
sigc::signal<void, guint32> window_mapped;
sigc::signal<void, guint32> window_unmapped;