Merge lp:~3v1n0/unity/launcher-draggable-icons into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: 2689
Merged at revision: 2713
Proposed branch: lp:~3v1n0/unity/launcher-draggable-icons
Merge into: lp:unity
Diff against target: 7548 lines (+3855/-1096)
72 files modified
UnityCore/DesktopUtilities.cpp (+29/-9)
UnityCore/DesktopUtilities.h (+1/-0)
UnityCore/GLibDBusProxy.cpp (+0/-4)
com.canonical.Unity.gschema.xml (+3/-3)
launcher/AbstractLauncherIcon.h (+16/-2)
launcher/BFBLauncherIcon.cpp (+1/-0)
launcher/BamfLauncherIcon.cpp (+31/-48)
launcher/BamfLauncherIcon.h (+0/-1)
launcher/CMakeLists.txt (+1/-0)
launcher/DesktopLauncherIcon.cpp (+19/-6)
launcher/DesktopLauncherIcon.h (+4/-12)
launcher/DeviceLauncherSection.cpp (+14/-7)
launcher/DeviceLauncherSection.h (+3/-5)
launcher/DndData.cpp (+5/-5)
launcher/DndData.h (+1/-1)
launcher/ExpoLauncherIcon.cpp (+64/-0)
launcher/ExpoLauncherIcon.h (+45/-0)
launcher/FavoriteStore.cpp (+93/-4)
launcher/FavoriteStore.h (+21/-8)
launcher/FavoriteStoreGSettings.cpp (+67/-68)
launcher/FavoriteStoreGSettings.h (+7/-4)
launcher/FavoriteStorePrivate.cpp (+14/-0)
launcher/FavoriteStorePrivate.h (+3/-1)
launcher/HudLauncherIcon.cpp (+2/-1)
launcher/Launcher.cpp (+82/-108)
launcher/Launcher.h (+5/-8)
launcher/LauncherController.cpp (+526/-341)
launcher/LauncherController.h (+1/-3)
launcher/LauncherControllerPrivate.h (+28/-41)
launcher/LauncherIcon.cpp (+31/-4)
launcher/LauncherIcon.h (+5/-9)
launcher/LauncherModel.cpp (+34/-32)
launcher/MockLauncherIcon.h (+11/-15)
launcher/SoftwareCenterLauncherIcon.cpp (+27/-38)
launcher/SoftwareCenterLauncherIcon.h (+1/-1)
launcher/SpacerLauncherIcon.cpp (+1/-1)
launcher/SpacerLauncherIcon.h (+0/-4)
launcher/StandaloneLauncher.cpp (+1/-1)
launcher/TrashLauncherIcon.cpp (+1/-0)
launcher/VolumeLauncherIcon.cpp (+34/-4)
launcher/VolumeLauncherIcon.h (+3/-0)
manual-tests/Launcher.txt (+15/-0)
panel/PanelMenuView.h (+0/-1)
plugins/unityshell/src/unityshell.cpp (+5/-7)
plugins/unityshell/unityshell.xml.in (+0/-6)
tests/CMakeLists.txt (+19/-11)
tests/gmockvolume.c (+3/-2)
tests/test_bamf_launcher_icon.cpp (+70/-2)
tests/test_bfb_launcher_icon.cpp (+11/-8)
tests/test_desktop_launcher_icon.cpp (+80/-0)
tests/test_desktop_utilities.cpp (+52/-22)
tests/test_device_launcher_section.cpp (+19/-54)
tests/test_expo_launcher_icon.cpp (+58/-0)
tests/test_favorite_store.cpp (+111/-0)
tests/test_favorite_store_gsettings.cpp (+52/-29)
tests/test_hud_launcher_icon.cpp (+53/-0)
tests/test_launcher.cpp (+226/-15)
tests/test_launcher_controller.cpp (+1246/-44)
tests/test_launcher_icon.cpp (+113/-0)
tests/test_launcher_model.cpp (+182/-40)
tests/test_main.cpp (+1/-0)
tests/test_main_xless.cpp (+1/-1)
tests/test_mock_devices.h (+93/-0)
tests/test_software_center_launcher_icon.cpp (+74/-0)
tests/test_trash_launcher_icon.cpp (+39/-0)
tests/test_volume_launcher_icon.cpp (+67/-46)
unity-shared/PluginAdapter.h (+2/-0)
unity-shared/PluginAdapterCompiz.cpp (+5/-0)
unity-shared/PluginAdapterStandalone.cpp (+15/-7)
unity-shared/WindowManager.cpp (+5/-0)
unity-shared/WindowManager.h (+1/-0)
unity-standalone/StandaloneUnity.cpp (+2/-2)
To merge this branch: bzr merge lp:~3v1n0/unity/launcher-draggable-icons
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Approve
Brandon Schaefer (community) Approve
Review via email: mp+123311@code.launchpad.net

Commit message

LauncherController, FavoriteStore, Launcher, Icons: always use sort priority based on favorites to get positioned on launcher

Description of the change

This is the continuum of the work started in lp:~3v1n0/unity/keep-priority-launcher-model, here we use the launcher icons priority to correctly order the icons in the launcher, based on the position that they have in the favorite store.

The unity launcher favorite store now handles not only desktop paths or id but also (mostly) icons uris (such as application://desktop-id or unity://desktop-icon or device://uuid); these values are used by LauncherController to dispose these icons in the launchers.

To do this, I had to change AbstractLauncherIcon to define a position property that now LauncherModel uses together with the icon priority (that is now set by default to the icon type but then can change during the usage, or based on favorites).

The icons ordering has changed a lot: now the favorites control everything (except BFB and trash) and we add the icons based on their defined position. Added two special places: "unity://running-apps" and "unity://devices" that optionally defines where these kind of icons should be placed. This is not strict by the way, because if these uris are not defined we add them by default at the bottom of the launcher main model.

When a new Device or Application icon is added to the launcher, we append it to the list of the non-sticky devices or applications.

Favorites reordering, removal or additions have been refactored to fit to our new system; when we save the favorites, the position of the "running-apps" or "attached-devices" is computed based on where the first icon of this type is placed.

The expo icon is handled differently, since it is not added if we have no workspaces available; it also updates its visibility based on the workspaces settings.

SoftwareCenterLauncher icons are now handled differently: we now fully consider them as sticky application icons, so we firstly add them to the model (setting their priority based on the last sticky icon we have), then we animate them. They already know where they should go, based on model calculations (also fixed a bug that caused them not to get the overlay shourtcut when added).

See other commit messages for more info, they should be quite comprehensive.

----

Testing: updated and added a lot of new unit tests to cover (hopefully) all the changes I've done (that's mostly why this diff is so big, since the real changes are less than the half of the changed code) and to test the areas that we never tested before, just few stats:

test-gtest: added 13 new test cases (+5%)
test-gtest-xless: added 94 new test cases (+56%)

To post a comment you must log in.
Revision history for this message
Andrea Azzarone (azzar1) wrote :

340 +std::string DesktopLauncherIcon::GetRemoteUri()
341 +{
342 + return "unity://desktop-icon";
343 +}

 +bool DesktopLauncherIcon::ShowInSwitcher(bool current)
351 +{
352 + return show_in_switcher_;
353 +}

Can we make these methods const?

---

+#ifndef EXPO_LAUNCHER_ICON_H

I'd prefer UNITYSHELL_EXPO... But it's not blocking :)

...

+FavoriteStore* favoritestore_instance = nullptr;

FavoriteStore should not be a singleton. You can use DI in launcher::Controller.

---

621 +bool FavoriteStore::IsValidFavoriteUri(std::string const& uri)
622 +{
623 + if (uri.empty())
624 + return false;
625 +
626 + if (uri.find(URI_PREFIX_APP) == 0 || uri.find(URI_PREFIX_FILE) == 0)
627 + {
628 + return internal::impl::IsDesktopFilePath(uri);
629 + }

Can this method be const? Also you know we prefer to use operator ! :)

+ const std::string prefix_separator = "://";
 + const std::string proto_separator = "://";
813 + const std::string desktop_ext = ".desktop";

I'd make it static or I'd move it out of the function.

//auto const& system_dirs = DesktopUtilities::GetDataDirectories();

Remove it if you don't need it.

+bool FavoriteStoreGSettings::IsFavorite(std::string const& icon_uri)

const :)

+ const std::string desktop_ext = ".desktop";

Make it static.

1199 - if (max > 0.0f)
1200 - {
1201 - color = color * (1.0f / max);
1202 - }
1203 + color = color * (1.0f / max);

Why have you done this?

* I'll continue the review later *

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> 340 +std::string DesktopLauncherIcon::GetRemoteUri()
> 341 +{
> 342 + return "unity://desktop-icon";
> 343 +}
>
> +bool DesktopLauncherIcon::ShowInSwitcher(bool current)
> 351 +{
> 352 + return show_in_switcher_;
> 353 +}
>
> Can we make these methods const?

The first one no (due to BamfLauncherIcon). Probably it should be fixed there as well... I'll see.

> +FavoriteStore* favoritestore_instance = nullptr;
>
> FavoriteStore should not be a singleton. You can use DI in
> launcher::Controller.

I kept it in this way since it used to be like that, also it made testing easier (not to mention that it was a singleton because it was used also in the icons).
However, I could probably avoid to use it in this manner by adding a new icon signal and then using launcher::Controller. I see how it impacts on tests.

> 621 +bool FavoriteStore::IsValidFavoriteUri(std::string const& uri)
> 622 +{
> 623 + if (uri.empty())
> 624 + return false;
> 625 +
> 626 + if (uri.find(URI_PREFIX_APP) == 0 || uri.find(URI_PREFIX_FILE) ==
> 0)
> 627 + {
> 628 + return internal::impl::IsDesktopFilePath(uri);
> 629 + }
>
> Can this method be const? Also you know we prefer to use operator ! :)

A static method? :)
We use the operator! when a method returns false, but find returns the position of the found item, and we want to make sure that our strings starts with it.

> + const std::string prefix_separator = "://";
> + const std::string proto_separator = "://";
> 813 + const std::string desktop_ext = ".desktop";
>
> I'd make it static or I'd move it out of the function.

Yeah, probably... I thought the same.

> +bool FavoriteStoreGSettings::IsFavorite(std::string const& icon_uri)
>
> const :)

Yeah, I fogot to do it also for FavoritePosition.

> 1199 - if (max > 0.0f)
> 1200 - {
> 1201 - color = color * (1.0f / max);
> 1202 - }
> 1203 + color = color * (1.0f / max);
>
> Why have you done this?

Mhm, probably I made a wrong merge. Thanks for pointing out.

> * I'll continue the review later *

Nice, thanks ;)

Revision history for this message
Łukasz Zemczak (sil2100) wrote :

What about the switcher icon? Is it also handled now by the favorites?

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> What about the switcher icon? Is it also handled now by the favorites?

Yep, the special uri unity://expo-icon controls it, however it wont' be visible if the WS have been disabled.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> > 340 +std::string DesktopLauncherIcon::GetRemoteUri()
> > 341 +{
> > 342 + return "unity://desktop-icon";
> > 343 +}
> >
> > +bool DesktopLauncherIcon::ShowInSwitcher(bool current)
> > 351 +{
> > 352 + return show_in_switcher_;
> > 353 +}
> >
> > Can we make these methods const?
>
> The first one no (due to BamfLauncherIcon). Probably it should be fixed there
> as well... I'll see.
>
>
> > +FavoriteStore* favoritestore_instance = nullptr;
> >
> > FavoriteStore should not be a singleton. You can use DI in
> > launcher::Controller.
>
> I kept it in this way since it used to be like that, also it made testing
> easier (not to mention that it was a singleton because it was used also in the
> icons).

Really singleton makes testing easier? :) You can pass it to the icons using the ctor.

> However, I could probably avoid to use it in this manner by adding a new icon
> signal and then using launcher::Controller. I see how it impacts on tests.
>
> > 621 +bool FavoriteStore::IsValidFavoriteUri(std::string const& uri)
> > 622 +{
> > 623 + if (uri.empty())
> > 624 + return false;
> > 625 +
> > 626 + if (uri.find(URI_PREFIX_APP) == 0 || uri.find(URI_PREFIX_FILE) ==
> > 0)
> > 627 + {
> > 628 + return internal::impl::IsDesktopFilePath(uri);
> > 629 + }
> >
> > Can this method be const? Also you know we prefer to use operator ! :)
>
> A static method? :)

Whops :) sorry

> We use the operator! when a method returns false, but find returns the
> position of the found item, and we want to make sure that our strings starts
> with it.
>

ok

>
> > + const std::string prefix_separator = "://";
> > + const std::string proto_separator = "://";
> > 813 + const std::string desktop_ext = ".desktop";
> >
> > I'd make it static or I'd move it out of the function.
>
> Yeah, probably... I thought the same.
>
>
> > +bool FavoriteStoreGSettings::IsFavorite(std::string const& icon_uri)
> >
> > const :)
>
> Yeah, I fogot to do it also for FavoritePosition.
>
>
> > 1199 - if (max > 0.0f)
> > 1200 - {
> > 1201 - color = color * (1.0f / max);
> > 1202 - }
> > 1203 + color = color * (1.0f / max);
> >
> > Why have you done this?
>
> Mhm, probably I made a wrong merge. Thanks for pointing out.
>
>
> > * I'll continue the review later *
>
> Nice, thanks ;)

Revision history for this message
Andrea Azzarone (azzar1) wrote :

1959 - uscreen->resuming.connect([&]() -> void {
1960 - for (auto launcher : launchers)
1961 - launcher->QueueDraw();
1962 - });

Why have you removed this code?

In volume VolumeLauncherIcon you are calling parent_->UnStick(); before TryToUnblacklist. I think you should call it when you receive the changed signal from device_settings.

+ void Stick(bool save = true);

You should not use default values for virtual function (consider NVI to fix this "issue").

200 +#ifndef TEST_MOCK_DEVICES_H
4201 +#define TEST_MOCK_DEVICES_H

Why do you need this guards?

Revision history for this message
Andrea Azzarone (azzar1) wrote :

*these

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> 1959 - uscreen->resuming.connect([&]() -> void {
> 1960 - for (auto launcher : launchers)
> 1961 - launcher->QueueDraw();
> 1962 - });
>
> Why have you removed this code?

This code was added in order to workaround a nvidia redraw issue that we had on resuming, but since now we properly fixed the issue, we can safely remove this hack (tested here on one machine that was affected).

> In volume VolumeLauncherIcon you are calling parent_->UnStick(); before
> TryToUnblacklist. I think you should call it when you receive the changed
> signal from device_settings.

Why on changed signal?

> + void Stick(bool save = true);
>
> You should not use default values for virtual function (consider NVI to fix
> this "issue").

Yeah, this is not the best thing ever... It was introduced a lot time ago, probably it's better to split it into two methods (Stick and StickAndSave)

> 200 +#ifndef TEST_MOCK_DEVICES_H
> 4201 +#define TEST_MOCK_DEVICES_H
>
> Why do you need this guards?

Well, to avoid the redefinition of these objects. These won't probably be ever broken, but they won't surely create any issue.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> > 1959 - uscreen->resuming.connect([&]() -> void {
> > 1960 - for (auto launcher : launchers)
> > 1961 - launcher->QueueDraw();
> > 1962 - });
> >
> > Why have you removed this code?
>
> This code was added in order to workaround a nvidia redraw issue that we had
> on resuming, but since now we properly fixed the issue, we can safely remove
> this hack (tested here on one machine that was affected).
>

Cool.

>
> > In volume VolumeLauncherIcon you are calling parent_->UnStick(); before
> > TryToUnblacklist. I think you should call it when you receive the changed
> > signal from device_settings.
>
> Why on changed signal?
>

This is how it works now. When you call TryToUnblacklist devices_settings emit a changed signal. In the changed signal handler of VoluleLauncherIcon we update the visibility. Before we had ignore_signals inside device_settings and was error prone.

>
> > + void Stick(bool save = true);
> >
> > You should not use default values for virtual function (consider NVI to fix
> > this "issue").
>
> Yeah, this is not the best thing ever... It was introduced a lot time ago,
> probably it's better to split it into two methods (Stick and StickAndSave)
>
>
> > 200 +#ifndef TEST_MOCK_DEVICES_H
> > 4201 +#define TEST_MOCK_DEVICES_H
> >
> > Why do you need this guards?
>
> Well, to avoid the redefinition of these objects. These won't probably be ever
> broken, but they won't surely create any issue.

Yeah but i don't like it in a cpp file :) Use an unnamed namespace.

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

One question...

Is this intended?

Setup:
Open gedit
Move it to the top of the launcher
Make sure it is not locked to the launcher

Then:
Open the gnome-cacluator
Make sure it is on the bottom of the launcher
Right click and lock it to the launcher

Result:
The gnome-calc moves below the gedit icon that is not locked to the launcher...

Just wanted to double check that is expected :).

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Other then that question, all the code looks good, the tests pass, and testing it manually also works :).

+1

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/1329/console reported an error when processing this lp:~3v1n0/unity/launcher-draggable-icons branch.
Not merging it.

Revision history for this message
Andrea Azzarone (azzar1) :
review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/1336/console reported an error when processing this lp:~3v1n0/unity/launcher-draggable-icons branch.
Not merging it.

2689. By Marco Trevisan (Treviño)

Tests: move the .desktop applications in a data dir so that it's more XDG compliant

Fix the TestDesktopUtilities tests so that it won't depend on system changes

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UnityCore/DesktopUtilities.cpp'
2--- UnityCore/DesktopUtilities.cpp 2012-06-01 09:33:15 +0000
3+++ UnityCore/DesktopUtilities.cpp 2012-09-18 15:51:21 +0000
4@@ -19,8 +19,10 @@
5 */
6
7 #include <algorithm>
8+#include <memory>
9
10 #include <glib.h>
11+#include <gio/gdesktopappinfo.h>
12
13 #include "DesktopUtilities.h"
14 #include "GLibWrapper.h"
15@@ -119,23 +121,41 @@
16 return GetDesktopID(data_dirs, desktop_path);
17 }
18
19+std::string DesktopUtilities::GetDesktopPathById(std::string const& desktop_id)
20+{
21+ if (desktop_id.empty())
22+ return "";
23+
24+ glib::Object<GDesktopAppInfo> info;
25+
26+ if (desktop_id.find(G_DIR_SEPARATOR_S) != std::string::npos)
27+ info = g_desktop_app_info_new_from_filename(desktop_id.c_str());
28+ else
29+ info = g_desktop_app_info_new(desktop_id.c_str());
30+
31+ if (info)
32+ {
33+ const char* filename = g_desktop_app_info_get_filename(info);
34+
35+ if (filename)
36+ return filename;
37+ }
38+
39+ return "";
40+}
41
42 std::string DesktopUtilities::GetBackgroundColor(std::string const& desktop_path)
43 {
44- GKeyFile* key_file = g_key_file_new();
45+ std::shared_ptr<GKeyFile> key_file(g_key_file_new(), g_key_file_free);
46
47 glib::Error error;
48- g_key_file_load_from_file(key_file, desktop_path.c_str(), static_cast<GKeyFileFlags>(0), &error);
49+ g_key_file_load_from_file(key_file.get(), desktop_path.c_str(), static_cast<GKeyFileFlags>(0), &error);
50
51 if (error)
52- {
53- g_key_file_free(key_file);
54 return "";
55- }
56-
57- glib::String value(g_key_file_get_string(key_file, "Desktop Entry", "X-Unity-IconBackgroundColor", &error));
58-
59- g_key_file_free(key_file);
60+
61+ glib::String value(g_key_file_get_string(key_file.get(), "Desktop Entry", "X-Unity-IconBackgroundColor", &error));
62+
63 return value.Str();
64 }
65
66
67=== modified file 'UnityCore/DesktopUtilities.h'
68--- UnityCore/DesktopUtilities.h 2012-05-25 07:37:21 +0000
69+++ UnityCore/DesktopUtilities.h 2012-09-18 15:51:21 +0000
70@@ -36,6 +36,7 @@
71 static std::string GetDesktopID(std::string const& desktop_path);
72 static std::string GetDesktopID(std::vector<std::string> const& default_paths,
73 std::string const& desktop_path);
74+ static std::string GetDesktopPathById(std::string const& desktop_id);
75
76 static std::string GetBackgroundColor(std::string const& desktop_path);
77 };
78
79=== modified file 'UnityCore/GLibDBusProxy.cpp'
80--- UnityCore/GLibDBusProxy.cpp 2012-07-17 13:42:48 +0000
81+++ UnityCore/GLibDBusProxy.cpp 2012-09-18 15:51:21 +0000
82@@ -90,7 +90,6 @@
83
84 glib::Object<GDBusProxy> proxy_;
85 glib::Object<GCancellable> cancellable_;
86- guint watcher_id_;
87 bool connected_;
88
89 glib::Signal<void, GDBusProxy*, char*, char*, GVariant*> g_signal_connection_;
90@@ -113,7 +112,6 @@
91 , bus_type_(bus_type)
92 , flags_(flags)
93 , cancellable_(g_cancellable_new())
94- , watcher_id_(0)
95 , connected_(false)
96 {
97 StartReconnectionTimeout();
98@@ -122,8 +120,6 @@
99 DBusProxy::Impl::~Impl()
100 {
101 g_cancellable_cancel(cancellable_);
102- if (watcher_id_)
103- g_bus_unwatch_name(watcher_id_);
104 }
105
106 void DBusProxy::Impl::StartReconnectionTimeout()
107
108=== modified file 'com.canonical.Unity.gschema.xml'
109--- com.canonical.Unity.gschema.xml 2012-08-31 09:15:33 +0000
110+++ com.canonical.Unity.gschema.xml 2012-09-18 15:51:21 +0000
111@@ -44,9 +44,9 @@
112 </schema>
113 <schema path="/com/canonical/unity/launcher/" id="com.canonical.Unity.Launcher" gettext-domain="unity">
114 <key type="as" name="favorites">
115- <default>[ 'ubiquity-gtkui.desktop', 'nautilus-home.desktop', 'firefox.desktop', 'libreoffice-writer.desktop', 'libreoffice-calc.desktop', 'libreoffice-impress.desktop', 'ubuntu-software-center.desktop', 'ubuntuone-installer.desktop', 'gnome-control-center.desktop' ]</default>
116- <summary>List of desktop file ids for favorites on the launcher.</summary>
117- <description>These applications are shown in the Launcher by default.</description>
118+ <default>[ 'application://ubiquity-gtkui.desktop', 'application://nautilus-home.desktop', 'application://firefox.desktop', 'application://libreoffice-writer.desktop', 'application://libreoffice-calc.desktop', 'application://libreoffice-impress.desktop', 'application://ubuntu-software-center.desktop', 'application://ubuntuone-installer.desktop', 'application://gnome-control-center.desktop', 'unity://running-apps', 'unity://expo-icon', 'unity://devices' ]</default>
119+ <summary>List of items that should be shown by default in the launcher</summary>
120+ <description>These items can be application://desktop-id.desktop, device://uiid and unity://special-id (including unity://running-apps that specifies the position of the ran applications, unity://devices the position of the attached devices, unity://expo-icon the position of the workspace switcher and unity://show-desktop-icon the position of the show-desktop icon); the order of this list determines the launcher items position.</description>
121 </key>
122 <key type="s" name="favorite-migration">
123 <default>''</default>
124
125=== modified file 'launcher/AbstractLauncherIcon.h'
126--- launcher/AbstractLauncherIcon.h 2012-08-15 02:51:33 +0000
127+++ launcher/AbstractLauncherIcon.h 2012-09-18 15:51:21 +0000
128@@ -93,6 +93,7 @@
129 DESKTOP,
130 PLACE,
131 DEVICE,
132+ SPACER,
133 TRASH,
134 END
135 };
136@@ -117,10 +118,18 @@
137 LAST
138 };
139
140+ enum class Position
141+ {
142+ BEGIN,
143+ FLOATING,
144+ END
145+ };
146+
147 virtual ~AbstractLauncherIcon() {}
148
149 nux::Property<std::string> tooltip_text;
150 nux::Property<bool> tooltip_enabled;
151+ nux::Property<Position> position;
152
153 virtual void HideTooltip() = 0;
154
155@@ -158,8 +167,6 @@
156
157 virtual const bool WindowVisibleOnViewport() = 0;
158
159- virtual bool IsSpacer() = 0;
160-
161 virtual float PresentUrgency() = 0;
162
163 virtual float GetProgress() = 0;
164@@ -211,6 +218,11 @@
165
166 virtual void UnStick() = 0;
167
168+ static int DefaultPriority(IconType type)
169+ {
170+ return static_cast<int>(type) * 1000;
171+ }
172+
173 sigc::signal<void, int, int, unsigned long> mouse_down;
174 sigc::signal<void, int, int, unsigned long> mouse_up;
175 sigc::signal<void, int, int, unsigned long> mouse_click;
176@@ -221,6 +233,8 @@
177 sigc::signal<void, AbstractLauncherIcon::Ptr> remove;
178 sigc::signal<void, nux::ObjectPtr<nux::View>> tooltip_visible;
179 sigc::signal<void> visibility_changed;
180+ sigc::signal<void> position_saved;
181+ sigc::signal<void> position_forgot;
182
183 sigc::connection needs_redraw_connection;
184 sigc::connection on_icon_added_connection;
185
186=== modified file 'launcher/BFBLauncherIcon.cpp'
187--- launcher/BFBLauncherIcon.cpp 2012-08-15 02:51:33 +0000
188+++ launcher/BFBLauncherIcon.cpp 2012-09-18 15:51:21 +0000
189@@ -36,6 +36,7 @@
190 {
191 tooltip_text = _("Dash Home");
192 icon_name = PKGDATADIR"/launcher_bfb.png";
193+ position = Position::BEGIN;
194 SetQuirk(Quirk::VISIBLE, true);
195 SetQuirk(Quirk::RUNNING, false);
196
197
198=== modified file 'launcher/BamfLauncherIcon.cpp'
199--- launcher/BamfLauncherIcon.cpp 2012-08-21 21:46:54 +0000
200+++ launcher/BamfLauncherIcon.cpp 2012-09-18 15:51:21 +0000
201@@ -74,11 +74,7 @@
202 tooltip_text = BamfName();
203 icon_name = (icon ? icon.Str() : DEFAULT_ICON);
204
205- if (IsSticky())
206- SetQuirk(Quirk::VISIBLE, true);
207- else
208- SetQuirk(Quirk::VISIBLE, bamf_view_user_visible(bamf_view));
209-
210+ SetQuirk(Quirk::VISIBLE, bamf_view_user_visible(bamf_view));
211 SetQuirk(Quirk::ACTIVE, bamf_view_is_active(bamf_view));
212 SetQuirk(Quirk::RUNNING, bamf_view_is_running(bamf_view));
213
214@@ -95,7 +91,7 @@
215 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-removed",
216 [&] (BamfView*, BamfView*) { EnsureWindowState(); });
217 _gsignals.Add(sig);
218-
219+
220 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-moved",
221 [&] (BamfView *, BamfView *) {
222 EnsureWindowState();
223@@ -173,9 +169,12 @@
224
225 BamfLauncherIcon::~BamfLauncherIcon()
226 {
227- if (_bamf_app)
228+ if (_bamf_app.IsType(BAMF_TYPE_APPLICATION))
229+ {
230+ bamf_view_set_sticky(BAMF_VIEW(_bamf_app.RawPtr()), FALSE);
231 g_object_set_qdata(G_OBJECT(_bamf_app.RawPtr()),
232 g_quark_from_static_string("unity-seen"), nullptr);
233+ }
234 }
235
236 void BamfLauncherIcon::Remove()
237@@ -201,11 +200,6 @@
238 return bamf_view_is_sticky(BAMF_VIEW(_bamf_app.RawPtr()));
239 }
240
241-bool BamfLauncherIcon::IsVisible() const
242-{
243- return GetQuirk(Quirk::VISIBLE);
244-}
245-
246 bool BamfLauncherIcon::IsActive() const
247 {
248 return GetQuirk(Quirk::ACTIVE);
249@@ -235,7 +229,6 @@
250 wm->Activate(arg.target);
251 return;
252 }
253-
254
255 /* We should check each child to see if there is
256 * an unmapped (!= minimized) window around and
257@@ -638,22 +631,22 @@
258 GList* children;
259
260 BamfView *focusable_child = BAMF_VIEW (bamf_application_get_focusable_child (_bamf_app.RawPtr()));
261-
262+
263 if (focusable_child != NULL)
264 {
265 Window xid;
266-
267+
268 if (BAMF_IS_WINDOW (focusable_child))
269 xid = bamf_window_get_xid (BAMF_WINDOW(focusable_child));
270 else if (BAMF_IS_TAB (focusable_child))
271 {
272 BamfTab *focusable_tab = BAMF_TAB (focusable_child);
273-
274+
275 xid = bamf_tab_get_xid (focusable_tab);
276-
277+
278 bamf_tab_raise (focusable_tab);
279 }
280-
281+
282 windows.push_back(xid);
283 return windows;
284 }
285@@ -662,7 +655,7 @@
286 if (g_strcmp0 (bamf_application_get_application_type (_bamf_app.RawPtr()), "webapp") == 0)
287 {
288 OpenInstanceLauncherIcon(arg);
289-
290+
291 return windows;
292 }
293 }
294@@ -762,13 +755,13 @@
295 {
296 /* BamfTab does not support the monitor interface...so a bit of a nasty hack here. */
297 xid = bamf_tab_get_xid (static_cast<BamfTab*>(l->data));
298-
299+
300 if (WindowManager::Default()->IsWindowOnCurrentDesktop(xid) == false)
301 continue;
302-
303+
304 for (int j = 0; j < max_num_monitors; j++)
305 monitors[j] = true;
306-
307+
308 continue;
309 }
310
311@@ -939,30 +932,28 @@
312
313 void BamfLauncherIcon::Stick(bool save)
314 {
315+ SimpleLauncherIcon::Stick(save);
316+
317 if (IsSticky())
318 return;
319
320- std::string const& desktop_file = DesktopFile();
321 bamf_view_set_sticky(BAMF_VIEW(_bamf_app.RawPtr()), true);
322-
323- if (save && !desktop_file.empty())
324- FavoriteStore::Instance().AddFavorite(desktop_file, -1);
325 }
326
327 void BamfLauncherIcon::UnStick()
328 {
329+ SimpleLauncherIcon::UnStick();
330+
331 if (!IsSticky())
332 return;
333
334- std::string const& desktop_file = DesktopFile();
335 BamfView* view = BAMF_VIEW(_bamf_app.RawPtr());
336 bamf_view_set_sticky(view, false);
337
338- if (bamf_view_is_closed(view) || !bamf_view_user_visible(view))
339+ SetQuirk(Quirk::VISIBLE, bamf_view_user_visible(view));
340+
341+ if (bamf_view_is_closed(view))
342 Remove();
343-
344- if (!desktop_file.empty())
345- FavoriteStore::Instance().RemoveFavorite(desktop_file);
346 }
347
348 void BamfLauncherIcon::ToggleSticky()
349@@ -1227,12 +1218,11 @@
350 {
351 if (_remote_uri.empty())
352 {
353- const std::string prefix = "application://";
354 std::string const& desktop_id = GetDesktopID();
355
356 if (!desktop_id.empty())
357 {
358- _remote_uri = prefix + desktop_id;
359+ _remote_uri = FavoriteStore::URI_PREFIX_APP + desktop_id;
360 }
361 }
362
363@@ -1384,32 +1374,25 @@
364 if (desktop_file.empty())
365 return;
366
367- GKeyFile* key_file = g_key_file_new();
368+ std::shared_ptr<GKeyFile> key_file(g_key_file_new(), g_key_file_free);
369 glib::Error error;
370
371- g_key_file_load_from_file(key_file, desktop_file.c_str(), (GKeyFileFlags) 0, &error);
372+ g_key_file_load_from_file(key_file.get(), desktop_file.c_str(), (GKeyFileFlags) 0, &error);
373
374 if (error)
375- {
376- g_key_file_free(key_file);
377 return;
378- }
379-
380- char** mimes = g_key_file_get_string_list(key_file, "Desktop Entry", "MimeType", nullptr, nullptr);
381+
382+ std::shared_ptr<char*> mimes(g_key_file_get_string_list(key_file.get(), "Desktop Entry", "MimeType", nullptr, nullptr),
383+ g_strfreev);
384+
385 if (!mimes)
386- {
387- g_key_file_free(key_file);
388 return;
389- }
390
391- for (int i = 0; mimes[i]; i++)
392+ for (int i = 0; mimes.get()[i]; i++)
393 {
394- unity::glib::String super_type(g_content_type_from_mime_type(mimes[i]));
395+ unity::glib::String super_type(g_content_type_from_mime_type(mimes.get()[i]));
396 _supported_types.insert(super_type.Str());
397 }
398-
399- g_key_file_free(key_file);
400- g_strfreev(mimes);
401 }
402 }
403
404
405=== modified file 'launcher/BamfLauncherIcon.h'
406--- launcher/BamfLauncherIcon.h 2012-08-20 06:37:21 +0000
407+++ launcher/BamfLauncherIcon.h 2012-09-18 15:51:21 +0000
408@@ -48,7 +48,6 @@
409 std::string DesktopFile();
410
411 bool IsSticky() const;
412- bool IsVisible() const;
413 bool IsActive() const;
414 bool IsRunning() const;
415 bool IsUrgent() const;
416
417=== modified file 'launcher/CMakeLists.txt'
418--- launcher/CMakeLists.txt 2012-08-25 15:54:29 +0000
419+++ launcher/CMakeLists.txt 2012-09-18 15:51:21 +0000
420@@ -42,6 +42,7 @@
421 DevicesSettingsImp.cpp
422 DndData.cpp
423 EdgeBarrierController.cpp
424+ ExpoLauncherIcon.cpp
425 FavoriteStore.cpp
426 FavoriteStoreGSettings.cpp
427 FavoriteStorePrivate.cpp
428
429=== modified file 'launcher/DesktopLauncherIcon.cpp'
430--- launcher/DesktopLauncherIcon.cpp 2012-08-02 13:16:06 +0000
431+++ launcher/DesktopLauncherIcon.cpp 2012-09-18 15:51:21 +0000
432@@ -19,6 +19,7 @@
433
434 #include "DesktopLauncherIcon.h"
435 #include "unity-shared/WindowManager.h"
436+#include "FavoriteStore.h"
437
438 #include <glib/gi18n-lib.h>
439
440@@ -28,17 +29,14 @@
441 {
442
443 DesktopLauncherIcon::DesktopLauncherIcon()
444- : SimpleLauncherIcon(IconType::DESKTOP)
445- , show_in_switcher_(true)
446+ : SimpleLauncherIcon(IconType::DESKTOP)
447+ , show_in_switcher_(true)
448 {
449 tooltip_text = _("Show Desktop");
450 icon_name = "desktop";
451 SetQuirk(Quirk::VISIBLE, true);
452 SetQuirk(Quirk::RUNNING, false);
453-}
454-
455-DesktopLauncherIcon::~DesktopLauncherIcon()
456-{
457+ SetShortcut('d');
458 }
459
460 void
461@@ -53,5 +51,20 @@
462 return "DesktopLauncherIcon";
463 }
464
465+std::string DesktopLauncherIcon::GetRemoteUri()
466+{
467+ return FavoriteStore::URI_PREFIX_UNITY + "desktop-icon";
468+}
469+
470+void DesktopLauncherIcon::SetShowInSwitcher(bool show_in_switcher)
471+{
472+ show_in_switcher_ = show_in_switcher;
473+}
474+
475+bool DesktopLauncherIcon::ShowInSwitcher(bool current)
476+{
477+ return show_in_switcher_;
478+}
479+
480 } // namespace launcher
481 } // namespace unity
482
483=== modified file 'launcher/DesktopLauncherIcon.h'
484--- launcher/DesktopLauncherIcon.h 2012-05-07 19:52:54 +0000
485+++ launcher/DesktopLauncherIcon.h 2012-09-18 15:51:21 +0000
486@@ -29,24 +29,16 @@
487
488 class DesktopLauncherIcon : public SimpleLauncherIcon
489 {
490-
491 public:
492 DesktopLauncherIcon();
493- ~DesktopLauncherIcon();
494-
495- void SetShowInSwitcher(bool show_in_switcher)
496- {
497- show_in_switcher_ = show_in_switcher;
498- }
499-
500- bool ShowInSwitcher(bool current)
501- {
502- return show_in_switcher_;
503- }
504+
505+ void SetShowInSwitcher(bool show_in_switcher);
506+ bool ShowInSwitcher(bool current);
507
508 protected:
509 void ActivateLauncherIcon(ActionArg arg);
510 std::string GetName() const;
511+ std::string GetRemoteUri();
512
513 private:
514 bool show_in_switcher_;
515
516=== modified file 'launcher/DeviceLauncherSection.cpp'
517--- launcher/DeviceLauncherSection.cpp 2012-08-28 17:28:02 +0000
518+++ launcher/DeviceLauncherSection.cpp 2012-09-18 15:51:21 +0000
519@@ -38,10 +38,7 @@
520 monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded));
521 monitor_->volume_removed.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeRemoved));
522
523- device_populate_idle_.Run([this] () {
524- PopulateEntries();
525- return false;
526- });
527+ PopulateEntries();
528 }
529
530 void DeviceLauncherSection::PopulateEntries()
531@@ -60,11 +57,11 @@
532 if (map_.find(volume) != map_.end())
533 return;
534
535- VolumeLauncherIcon::Ptr icon(new VolumeLauncherIcon(std::make_shared<VolumeImp>(volume, file_manager_opener_, device_notification_display_),
536- devices_settings_));
537+ auto vol = std::make_shared<VolumeImp>(volume, file_manager_opener_, device_notification_display_);
538+ VolumeLauncherIcon::Ptr icon(new VolumeLauncherIcon(vol, devices_settings_));
539
540 map_[volume] = icon;
541- IconAdded.emit(icon);
542+ icon_added.emit(icon);
543 }
544
545 void DeviceLauncherSection::OnVolumeRemoved(glib::Object<GVolume> const& volume)
546@@ -76,5 +73,15 @@
547 map_.erase(volume_it);
548 }
549
550+std::vector<VolumeLauncherIcon::Ptr> DeviceLauncherSection::GetIcons() const
551+{
552+ std::vector<VolumeLauncherIcon::Ptr> icons;
553+
554+ for (auto const& it : map_)
555+ icons.push_back(it.second);
556+
557+ return icons;
558+}
559+
560 }
561 }
562
563=== modified file 'launcher/DeviceLauncherSection.h'
564--- launcher/DeviceLauncherSection.h 2012-08-22 09:03:25 +0000
565+++ launcher/DeviceLauncherSection.h 2012-09-18 15:51:21 +0000
566@@ -23,8 +23,6 @@
567 #include <map>
568 #include <memory>
569
570-#include <UnityCore/GLibSource.h>
571-
572 #include "AbstractVolumeMonitorWrapper.h"
573 #include "DevicesSettings.h"
574 #include "DeviceNotificationDisplay.h"
575@@ -42,7 +40,9 @@
576 DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor,
577 DevicesSettings::Ptr devices_settings);
578
579- sigc::signal<void, AbstractLauncherIcon::Ptr> IconAdded;
580+ std::vector<VolumeLauncherIcon::Ptr> GetIcons() const;
581+
582+ sigc::signal<void, AbstractLauncherIcon::Ptr> icon_added;
583
584 private:
585 void PopulateEntries();
586@@ -55,8 +55,6 @@
587 DevicesSettings::Ptr devices_settings_;
588 FileManagerOpener::Ptr file_manager_opener_;
589 DeviceNotificationDisplay::Ptr device_notification_display_;
590-
591- glib::Idle device_populate_idle_;
592 };
593
594 }
595
596=== modified file 'launcher/DndData.cpp'
597--- launcher/DndData.cpp 2012-07-09 14:11:06 +0000
598+++ launcher/DndData.cpp 2012-09-18 15:51:21 +0000
599@@ -27,12 +27,12 @@
600 #include <UnityCore/GLibWrapper.h>
601
602 namespace unity {
603-
604-void DndData::Fill(char* uris)
605-{
606+
607+void DndData::Fill(const char* uris)
608+{
609 Reset();
610-
611- char* pch = strtok (uris, "\r\n");
612+
613+ const char* pch = strtok (const_cast<char*>(uris), "\r\n");
614 while (pch)
615 {
616 glib::String content_type(g_content_type_guess(pch,
617
618=== modified file 'launcher/DndData.h'
619--- launcher/DndData.h 2012-05-07 19:52:54 +0000
620+++ launcher/DndData.h 2012-09-18 15:51:21 +0000
621@@ -32,7 +32,7 @@
622 /**
623 * Fills the object given a list of uris.
624 **/
625- void Fill(char* uris);
626+ void Fill(const char* uris);
627
628 /**
629 * Resets the object. Call this function when no longer need data
630
631=== added file 'launcher/ExpoLauncherIcon.cpp'
632--- launcher/ExpoLauncherIcon.cpp 1970-01-01 00:00:00 +0000
633+++ launcher/ExpoLauncherIcon.cpp 2012-09-18 15:51:21 +0000
634@@ -0,0 +1,64 @@
635+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
636+/*
637+ * Copyright (C) 2012 Canonical Ltd
638+ *
639+ * This program is free software: you can redistribute it and/or modify
640+ * it under the terms of the GNU General Public License version 3 as
641+ * published by the Free Software Foundation.
642+ *
643+ * This program is distributed in the hope that it will be useful,
644+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
645+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
646+ * GNU General Public License for more details.
647+ *
648+ * You should have received a copy of the GNU General Public License
649+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
650+ *
651+ * Authored by: Marco Trevisan <marco.trevisan@canonical.com>
652+ */
653+
654+#include "ExpoLauncherIcon.h"
655+#include "unity-shared/WindowManager.h"
656+#include "FavoriteStore.h"
657+
658+#include <glib/gi18n-lib.h>
659+
660+namespace unity
661+{
662+namespace launcher
663+{
664+
665+ExpoLauncherIcon::ExpoLauncherIcon()
666+ : SimpleLauncherIcon(IconType::EXPO)
667+{
668+ tooltip_text = _("Workspace Switcher");
669+ icon_name = "workspace-switcher";
670+ SetQuirk(Quirk::VISIBLE, false);
671+ SetQuirk(Quirk::RUNNING, false);
672+ SetShortcut('s');
673+}
674+
675+void ExpoLauncherIcon::ActivateLauncherIcon(ActionArg arg)
676+{
677+ SimpleLauncherIcon::ActivateLauncherIcon(arg);
678+ WindowManager::Default()->InitiateExpo();
679+}
680+
681+void ExpoLauncherIcon::Stick(bool save)
682+{
683+ SimpleLauncherIcon::Stick(save);
684+ SetQuirk(Quirk::VISIBLE, (WindowManager::Default()->WorkspaceCount() > 1));
685+}
686+
687+std::string ExpoLauncherIcon::GetName() const
688+{
689+ return "ExpoLauncherIcon";
690+}
691+
692+std::string ExpoLauncherIcon::GetRemoteUri()
693+{
694+ return FavoriteStore::URI_PREFIX_UNITY + "expo-icon";
695+}
696+
697+} // namespace launcher
698+} // namespace unity
699
700=== added file 'launcher/ExpoLauncherIcon.h'
701--- launcher/ExpoLauncherIcon.h 1970-01-01 00:00:00 +0000
702+++ launcher/ExpoLauncherIcon.h 2012-09-18 15:51:21 +0000
703@@ -0,0 +1,45 @@
704+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
705+/*
706+ * Copyright (C) 2012 Canonical Ltd
707+ *
708+ * This program is free software: you can redistribute it and/or modify
709+ * it under the terms of the GNU General Public License version 3 as
710+ * published by the Free Software Foundation.
711+ *
712+ * This program is distributed in the hope that it will be useful,
713+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
714+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
715+ * GNU General Public License for more details.
716+ *
717+ * You should have received a copy of the GNU General Public License
718+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
719+ *
720+ * Authored by: Marco Trevisan <marco.trevisan@canonical.com>
721+ */
722+
723+#ifndef EXPO_LAUNCHER_ICON_H
724+#define EXPO_LAUNCHER_ICON_H
725+
726+#include "SimpleLauncherIcon.h"
727+
728+namespace unity
729+{
730+namespace launcher
731+{
732+
733+class ExpoLauncherIcon : public SimpleLauncherIcon
734+{
735+public:
736+ ExpoLauncherIcon();
737+ void Stick(bool save);
738+
739+protected:
740+ void ActivateLauncherIcon(ActionArg arg);
741+ std::string GetName() const;
742+ std::string GetRemoteUri();
743+};
744+
745+}
746+}
747+
748+#endif // EXPO_LAUNCHER_ICON_H
749
750=== modified file 'launcher/FavoriteStore.cpp'
751--- launcher/FavoriteStore.cpp 2012-05-07 19:52:54 +0000
752+++ launcher/FavoriteStore.cpp 2012-09-18 15:51:21 +0000
753@@ -1,6 +1,6 @@
754 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
755 /*
756-* Copyright (C) 2010 Canonical Ltd
757+* Copyright (C) 2010-2012 Canonical Ltd
758 *
759 * This program is free software: you can redistribute it and/or modify
760 * it under the terms of the GNU General Public License version 3 as
761@@ -15,19 +15,29 @@
762 * along with this program. If not, see <http://www.gnu.org/licenses/>.
763 *
764 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
765+* Marco Trevisan <marco.trevisan@canonical.com>
766 */
767
768 #include <NuxCore/Logger.h>
769-#include "FavoriteStoreGSettings.h"
770+#include <glib.h>
771+
772+#include "FavoriteStore.h"
773+#include "FavoriteStorePrivate.h"
774
775 namespace unity
776 {
777 namespace
778 {
779- nux::logging::Logger logger("unity.favouritestore");
780- FavoriteStore* favoritestore_instance = nullptr;
781+nux::logging::Logger logger("unity.favorite.store");
782+FavoriteStore* favoritestore_instance = nullptr;
783+const std::string PREFIX_SEPARATOR = "://";
784 }
785
786+const std::string FavoriteStore::URI_PREFIX_APP = "application://";
787+const std::string FavoriteStore::URI_PREFIX_FILE = "file://";
788+const std::string FavoriteStore::URI_PREFIX_DEVICE = "device://";
789+const std::string FavoriteStore::URI_PREFIX_UNITY = "unity://";
790+
791 FavoriteStore::FavoriteStore()
792 {
793 if (favoritestore_instance)
794@@ -56,4 +66,83 @@
795 return *favoritestore_instance;
796 }
797
798+bool FavoriteStore::IsValidFavoriteUri(std::string const& uri)
799+{
800+ if (uri.empty())
801+ return false;
802+
803+ if (uri.find(URI_PREFIX_APP) == 0 || uri.find(URI_PREFIX_FILE) == 0)
804+ {
805+ return internal::impl::IsDesktopFilePath(uri);
806+ }
807+ else if (uri.find(URI_PREFIX_DEVICE) == 0)
808+ {
809+ return uri.length() > URI_PREFIX_DEVICE.length();
810+ }
811+ else if (uri.find(URI_PREFIX_UNITY) == 0)
812+ {
813+ return uri.length() > URI_PREFIX_UNITY.length();
814+ }
815+
816+ return false;
817+}
818+
819+std::string FavoriteStore::ParseFavoriteFromUri(std::string const& uri) const
820+{
821+ if (uri.empty())
822+ return "";
823+
824+ std::string fav = uri;
825+ auto prefix_pos = fav.find(PREFIX_SEPARATOR);
826+
827+ if (prefix_pos == std::string::npos)
828+ {
829+ // We assume that favorites with no prefix, but with a .desktop suffix are applications
830+ if (internal::impl::IsDesktopFilePath(uri))
831+ {
832+ fav = URI_PREFIX_APP + fav;
833+ prefix_pos = URI_PREFIX_APP.length();
834+ }
835+ }
836+ else
837+ {
838+ prefix_pos += PREFIX_SEPARATOR.length();
839+ }
840+
841+ // Matches application://desktop-id.desktop or application:///path/to/file.desktop
842+ if (fav.find(URI_PREFIX_APP) == 0 || fav.find(URI_PREFIX_FILE) == 0)
843+ {
844+ std::string const& fav_value = fav.substr(prefix_pos);
845+
846+ if (fav_value.empty())
847+ {
848+ LOG_WARNING(logger) << "Unable to load Favorite for uri '" << fav << "'";
849+ return "";
850+ }
851+
852+ if (fav_value[0] == '/' || fav.find(URI_PREFIX_FILE) == 0)
853+ {
854+ if (g_file_test(fav_value.c_str(), G_FILE_TEST_EXISTS))
855+ {
856+ return fav;
857+ }
858+ else
859+ {
860+ LOG_WARNING(logger) << "Unable to load desktop file: " << fav_value;
861+ }
862+ }
863+ else
864+ {
865+ return URI_PREFIX_APP + fav_value;
866+ }
867+ }
868+ else if (IsValidFavoriteUri(fav))
869+ {
870+ return fav;
871+ }
872+
873+ LOG_WARNING(logger) << "Unable to load Favorite for uri '" << fav << "'";
874+ return "";
875+}
876+
877 }
878
879=== modified file 'launcher/FavoriteStore.h'
880--- launcher/FavoriteStore.h 2012-05-07 19:52:54 +0000
881+++ launcher/FavoriteStore.h 2012-09-18 15:51:21 +0000
882@@ -1,6 +1,6 @@
883 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
884 /*
885-* Copyright (C) 2010 Canonical Ltd
886+* Copyright (C) 2010-2012 Canonical Ltd
887 *
888 * This program is free software: you can redistribute it and/or modify
889 * it under the terms of the GNU General Public License version 3 as
890@@ -15,6 +15,7 @@
891 * along with this program. If not, see <http://www.gnu.org/licenses/>.
892 *
893 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
894+* Marco Trevisan <marco.trevisan@canonical.com>
895 */
896
897 #ifndef UNITY_FAVORITE_STORE_H
898@@ -42,26 +43,38 @@
899
900 static FavoriteStore& Instance();
901
902- virtual FavoriteList const& GetFavorites() = 0;
903+ virtual FavoriteList const& GetFavorites() const = 0;
904
905 // These will NOT emit the relevant signals, so bare that in mind
906 // i.e. don't hope that you can add stuff and hook the view up to
907 // favorite_added events to update the view. The signals only emit if
908 // there has been a change on the GSettings object from an external
909 // source
910- virtual void AddFavorite(std::string const& desktop_path, int position) = 0;
911- virtual void RemoveFavorite(std::string const& desktop_path) = 0;
912- virtual void MoveFavorite(std::string const& desktop_path, int position) = 0;
913- virtual void SetFavorites(FavoriteList const& desktop_paths) = 0;
914+ virtual void AddFavorite(std::string const& icon_uri, int position) = 0;
915+ virtual void RemoveFavorite(std::string const& icon_uri) = 0;
916+ virtual void MoveFavorite(std::string const& icon_uri, int position) = 0;
917+ virtual bool IsFavorite(std::string const& icon_uri) const = 0;
918+ virtual int FavoritePosition(std::string const& icon_uri) const = 0;
919+ virtual void SetFavorites(FavoriteList const& icon_uris) = 0;
920
921 // Signals
922 // These only emit if something has changed the GSettings object externally
923
924- //desktop_path, position, before/after
925+ //icon_uri, position, before/after
926 sigc::signal<void, std::string const&, std::string const&, bool> favorite_added;
927- //desktop_path
928+ //icon_uri
929 sigc::signal<void, std::string const&> favorite_removed;
930 sigc::signal<void> reordered;
931+
932+ static const std::string URI_PREFIX_APP;
933+ static const std::string URI_PREFIX_FILE;
934+ static const std::string URI_PREFIX_DEVICE;
935+ static const std::string URI_PREFIX_UNITY;
936+
937+ static bool IsValidFavoriteUri(std::string const& uri);
938+
939+protected:
940+ std::string ParseFavoriteFromUri(std::string const& uri) const;
941 };
942
943 }
944
945=== modified file 'launcher/FavoriteStoreGSettings.cpp'
946--- launcher/FavoriteStoreGSettings.cpp 2012-08-15 17:22:33 +0000
947+++ launcher/FavoriteStoreGSettings.cpp 2012-09-18 15:51:21 +0000
948@@ -1,6 +1,6 @@
949 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
950 /*
951-* Copyright (C) 2010 Canonical Ltd
952+* Copyright (C) 2010-2012 Canonical Ltd
953 *
954 * This program is free software: you can redistribute it and/or modify
955 * it under the terms of the GNU General Public License version 3 as
956@@ -15,9 +15,9 @@
957 * along with this program. If not, see <http://www.gnu.org/licenses/>.
958 *
959 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
960+* Marco Trevisan <marco.trevisan@canonical.com>
961 */
962
963-#include <gio/gdesktopappinfo.h>
964 #include <NuxCore/Logger.h>
965 #include <UnityCore/DesktopUtilities.h>
966
967@@ -40,7 +40,7 @@
968
969 namespace
970 {
971-nux::logging::Logger logger("unity.favorites");
972+nux::logging::Logger logger("unity.favorite.store.gsettings");
973 const std::string SETTINGS_NAME = "com.canonical.Unity.Launcher";
974 const std::string SETTINGS_KEY = "favorites";
975 }
976@@ -59,117 +59,89 @@
977
978 void FavoriteStoreGSettings::Refresh()
979 {
980- FillList(favorites_);
981+ FillList();
982 }
983
984-void FavoriteStoreGSettings::FillList(FavoriteList& list)
985+void FavoriteStoreGSettings::FillList()
986 {
987- list.clear();
988-
989- gchar** favs = g_settings_get_strv(settings_, SETTINGS_KEY.c_str());
990-
991- for (int i = 0; favs[i] != NULL; ++i)
992+ favorites_.clear();
993+ std::shared_ptr<gchar*> favs(g_settings_get_strv(settings_, SETTINGS_KEY.c_str()));
994+
995+ for (int i = 0; favs.get()[i]; ++i)
996 {
997- // We will be storing either full /path/to/desktop/files or foo.desktop id's
998- if (favs[i][0] == '/')
999- {
1000- if (g_file_test(favs[i], G_FILE_TEST_EXISTS))
1001- {
1002- list.push_back(favs[i]);
1003- }
1004- else
1005- {
1006- LOG_WARNING(logger) << "Unable to load desktop file: "
1007- << favs[i];
1008- }
1009- }
1010- else
1011- {
1012- glib::Object<GDesktopAppInfo> info(g_desktop_app_info_new(favs[i]));
1013- const char* filename = 0;
1014- if (info)
1015- filename = g_desktop_app_info_get_filename(info);
1016+ std::string const& fav = ParseFavoriteFromUri(favs.get()[i]);
1017
1018- if (filename)
1019- {
1020- list.push_back(filename);
1021- }
1022- else
1023- {
1024- LOG_WARNING(logger) << "Unable to load GDesktopAppInfo for '" << favs[i] << "'";
1025- }
1026- }
1027+ if (!fav.empty())
1028+ favorites_.push_back(fav);
1029 }
1030-
1031- g_strfreev(favs);
1032 }
1033
1034-FavoriteList const& FavoriteStoreGSettings::GetFavorites()
1035+FavoriteList const& FavoriteStoreGSettings::GetFavorites() const
1036 {
1037 return favorites_;
1038 }
1039
1040-void FavoriteStoreGSettings::AddFavorite(std::string const& desktop_path, int position)
1041+void FavoriteStoreGSettings::AddFavorite(std::string const& icon_uri, int position)
1042 {
1043- int size = favorites_.size();
1044- if (desktop_path.empty() || position > size)
1045+ std::string const& fav = ParseFavoriteFromUri(icon_uri);
1046+
1047+ if (fav.empty() || position > static_cast<int>(favorites_.size()))
1048 return;
1049
1050 if (position < 0)
1051 {
1052 // It goes on the end.
1053- favorites_.push_back(desktop_path);
1054+ favorites_.push_back(fav);
1055 }
1056 else
1057 {
1058 FavoriteList::iterator pos = favorites_.begin();
1059 std::advance(pos, position);
1060- favorites_.insert(pos, desktop_path);
1061+ favorites_.insert(pos, fav);
1062 }
1063
1064 SaveFavorites(favorites_);
1065 Refresh();
1066 }
1067
1068-void FavoriteStoreGSettings::RemoveFavorite(std::string const& desktop_path)
1069+void FavoriteStoreGSettings::RemoveFavorite(std::string const& icon_uri)
1070 {
1071- if (desktop_path.empty() || desktop_path[0] != '/')
1072+ std::string const& fav = ParseFavoriteFromUri(icon_uri);
1073+
1074+ if (fav.empty())
1075 return;
1076
1077- FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), desktop_path);
1078+ FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), fav);
1079 if (pos == favorites_.end())
1080- {
1081 return;
1082- }
1083
1084 favorites_.erase(pos);
1085 SaveFavorites(favorites_);
1086 Refresh();
1087 }
1088
1089-void FavoriteStoreGSettings::MoveFavorite(std::string const& desktop_path, int position)
1090+void FavoriteStoreGSettings::MoveFavorite(std::string const& icon_uri, int position)
1091 {
1092- int size = favorites_.size();
1093- if (desktop_path.empty() || position > size)
1094+ std::string const& fav = ParseFavoriteFromUri(icon_uri);
1095+
1096+ if (fav.empty() || position > static_cast<int>(favorites_.size()))
1097 return;
1098
1099- FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), desktop_path);
1100+ FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), fav);
1101 if (pos == favorites_.end())
1102- {
1103 return;
1104- }
1105
1106 favorites_.erase(pos);
1107 if (position < 0)
1108 {
1109 // It goes on the end.
1110- favorites_.push_back(desktop_path);
1111+ favorites_.push_back(fav);
1112 }
1113 else
1114 {
1115 FavoriteList::iterator insert_pos = favorites_.begin();
1116 std::advance(insert_pos, position);
1117- favorites_.insert(insert_pos, desktop_path);
1118+ favorites_.insert(insert_pos, fav);
1119 }
1120
1121 SaveFavorites(favorites_);
1122@@ -186,26 +158,34 @@
1123 {
1124 const int size = favorites.size();
1125 const char* favs[size + 1];
1126- favs[size] = NULL;
1127
1128- int index = 0;
1129 // Since we don't always save the full path, we store the values we are
1130 // actually going to save in a different list.
1131- auto system_dirs = DesktopUtilities::GetDataDirectories();
1132 FavoriteList values;
1133- for (FavoriteList::const_iterator i = favorites.begin(), end = favorites.end();
1134- i != end; ++i, ++index)
1135+ int index = 0;
1136+
1137+ for (auto const& fav_uri : favorites)
1138 {
1139+ std::string const& fav = ParseFavoriteFromUri(fav_uri);
1140+ if (fav.empty())
1141+ {
1142+ LOG_WARNING(logger) << "Impossible to add favorite '" << fav_uri << "' to store";
1143+ continue;
1144+ }
1145+
1146 // By using insert we get the iterator to the newly inserted string value.
1147 // That way we can use the c_str() method to access the const char* for
1148 // the string that we are going to save. This way we know that the pointer
1149 // is valid for the lifetime of the favs array usage in the method call to
1150 // set the settings, and that we aren't referencing a temporary.
1151- std::string const& desktop_id = DesktopUtilities::GetDesktopID(system_dirs, *i);
1152- FavoriteList::iterator iter = values.insert(values.end(), desktop_id);
1153+ FavoriteList::iterator iter = values.insert(values.end(), fav);
1154 favs[index] = iter->c_str();
1155+ ++index;
1156 }
1157
1158+ for (int i = index; i <= size; ++i)
1159+ favs[i] = nullptr;
1160+
1161 ignore_signals_ = ignore;
1162 if (!g_settings_set_strv(settings_, SETTINGS_KEY.c_str(), favs))
1163 {
1164@@ -220,7 +200,7 @@
1165 return;
1166
1167 FavoriteList old(favorites_);
1168- FillList(favorites_);
1169+ FillList();
1170
1171 auto newbies = impl::GetNewbies(old, favorites_);
1172
1173@@ -243,7 +223,26 @@
1174
1175 if (impl::NeedToBeReordered(old, favorites_))
1176 reordered.emit();
1177-
1178+}
1179+
1180+bool FavoriteStoreGSettings::IsFavorite(std::string const& icon_uri) const
1181+{
1182+ return std::find(favorites_.begin(), favorites_.end(), icon_uri) != favorites_.end();
1183+}
1184+
1185+int FavoriteStoreGSettings::FavoritePosition(std::string const& icon_uri) const
1186+{
1187+ int index = 0;
1188+
1189+ for (auto const& fav : favorites_)
1190+ {
1191+ if (fav == icon_uri)
1192+ return index;
1193+
1194+ ++index;
1195+ }
1196+
1197+ return -1;
1198 }
1199
1200 } // namespace internal
1201
1202=== modified file 'launcher/FavoriteStoreGSettings.h'
1203--- launcher/FavoriteStoreGSettings.h 2012-08-01 18:12:10 +0000
1204+++ launcher/FavoriteStoreGSettings.h 2012-09-18 15:51:21 +0000
1205@@ -1,6 +1,6 @@
1206 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1207 /*
1208-* Copyright (C) 2010 Canonical Ltd
1209+* Copyright (C) 2010-2012 Canonical Ltd
1210 *
1211 * This program is free software: you can redistribute it and/or modify
1212 * it under the terms of the GNU General Public License version 3 as
1213@@ -15,6 +15,7 @@
1214 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1215 *
1216 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
1217+* Marco Trevisan <marco.trevisan@canonical.com>
1218 */
1219
1220 #ifndef FAVORITE_STORE_GSETTINGS_H
1221@@ -38,17 +39,19 @@
1222 public:
1223 FavoriteStoreGSettings();
1224
1225- virtual FavoriteList const& GetFavorites();
1226+ virtual FavoriteList const& GetFavorites() const;
1227 virtual void AddFavorite(std::string const& desktop_path, int position);
1228 virtual void RemoveFavorite(std::string const& desktop_path);
1229 virtual void MoveFavorite(std::string const& desktop_path, int position);
1230+ virtual bool IsFavorite(std::string const& icon_uri) const;
1231+ virtual int FavoritePosition(std::string const& icon_uri) const;
1232+ virtual void SetFavorites(FavoriteList const& desktop_paths);
1233 void SaveFavorites(FavoriteList const& favorites, bool ignore = true);
1234- virtual void SetFavorites(FavoriteList const& desktop_paths);
1235
1236 private:
1237 void Refresh();
1238 void Changed();
1239- void FillList(FavoriteList& list);
1240+ void FillList();
1241
1242 FavoriteList favorites_;
1243 bool ignore_signals_;
1244
1245=== modified file 'launcher/FavoriteStorePrivate.cpp'
1246--- launcher/FavoriteStorePrivate.cpp 2012-05-07 19:52:54 +0000
1247+++ launcher/FavoriteStorePrivate.cpp 2012-09-18 15:51:21 +0000
1248@@ -124,6 +124,20 @@
1249 return false;
1250 }
1251
1252+bool IsDesktopFilePath(std::string const& path)
1253+{
1254+ static const std::string desktop_ext = ".desktop";
1255+ auto path_len = path.length();
1256+ auto desktop_length = desktop_ext.length();
1257+
1258+ if (path_len > desktop_length)
1259+ {
1260+ return path.compare(path_len - desktop_length, desktop_length, desktop_ext) == 0;
1261+ }
1262+
1263+ return false;
1264+}
1265+
1266
1267 } // namespace impl
1268 } // namespace internal
1269
1270=== modified file 'launcher/FavoriteStorePrivate.h'
1271--- launcher/FavoriteStorePrivate.h 2012-05-07 19:52:54 +0000
1272+++ launcher/FavoriteStorePrivate.h 2012-09-18 15:51:21 +0000
1273@@ -32,13 +32,15 @@
1274
1275 std::vector<std::string> GetNewbies(std::list<std::string> const& old, std::list<std::string> const& fresh);
1276
1277-void GetSignalAddedInfo(std::list<std::string> const& favs, std::vector<std::string> const& newbies,
1278+void GetSignalAddedInfo(std::list<std::string> const& favs, std::vector<std::string> const& newbies,
1279 std::string const& path, std::string& position, bool& before);
1280
1281 std::vector<std::string> GetRemoved(std::list<std::string> const& old, std::list<std::string> const& fresh);
1282
1283 bool NeedToBeReordered(std::list<std::string> const& old, std::list<std::string> const& fresh);
1284
1285+bool IsDesktopFilePath(std::string const& path);
1286+
1287
1288 } // namespace impl
1289 } // namespace internal
1290
1291=== modified file 'launcher/HudLauncherIcon.cpp'
1292--- launcher/HudLauncherIcon.cpp 2012-08-22 08:17:33 +0000
1293+++ launcher/HudLauncherIcon.cpp 2012-09-18 15:51:21 +0000
1294@@ -45,6 +45,7 @@
1295 {
1296 tooltip_text = _("HUD");
1297 icon_name = PKGDATADIR"/launcher_bfb.png";
1298+ position = Position::BEGIN;
1299 SetQuirk(Quirk::VISIBLE, false);
1300 SetQuirk(Quirk::RUNNING, false);
1301 SetQuirk(Quirk::ACTIVE, true);
1302@@ -121,7 +122,7 @@
1303
1304 void HudLauncherIcon::ActivateLauncherIcon(ActionArg arg)
1305 {
1306- if (GetQuirk(Quirk::VISIBLE))
1307+ if (IsVisible())
1308 {
1309 ubus_manager_.SendMessage(UBUS_HUD_CLOSE_REQUEST);
1310 }
1311
1312=== modified file 'launcher/Launcher.cpp'
1313--- launcher/Launcher.cpp 2012-09-12 03:50:23 +0000
1314+++ launcher/Launcher.cpp 2012-09-18 15:51:21 +0000
1315@@ -54,6 +54,7 @@
1316 #include <UnityCore/GLibWrapper.h>
1317 #include <UnityCore/Variant.h>
1318
1319+#include <boost/algorithm/string.hpp>
1320 #include <sigc++/sigc++.h>
1321
1322 namespace unity
1323@@ -106,6 +107,7 @@
1324 nux::ObjectPtr<DNDCollectionWindow> const& collection_window,
1325 NUX_FILE_LINE_DECL)
1326 : View(NUX_FILE_LINE_PARAM)
1327+ , display(nux::GetGraphicsDisplay()->GetX11Display())
1328 , monitor(0)
1329 , _parent(parent)
1330 , _active_quicklist(nullptr)
1331@@ -463,9 +465,8 @@
1332 return true;
1333
1334 // animations happening on specific icons
1335- LauncherModel::iterator it;
1336- for (it = _model->begin(); it != _model->end(); ++it)
1337- if (IconNeedsAnimation(*it, current))
1338+ for (auto const &icon : *_model)
1339+ if (IconNeedsAnimation(icon, current))
1340 return true;
1341
1342 return false;
1343@@ -496,10 +497,10 @@
1344
1345 if (icon->GetIconType() == AbstractLauncherIcon::IconType::HUD)
1346 {
1347- return (icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE)) ? 1.0f : 0.0f;
1348+ return icon->IsVisible() ? 1.0f : 0.0f;
1349 }
1350
1351- if (icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE))
1352+ if (icon->IsVisible())
1353 {
1354 struct timespec icon_visible_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
1355 int enter_ms = unity::TimeUtil::TimeDelta(&current, &icon_visible_time);
1356@@ -892,8 +893,11 @@
1357
1358 if (GetActionState() == ACTION_DRAG_ICON ||
1359 (_drag_window && _drag_window->Animating()) ||
1360- icon->IsSpacer())
1361+ icon->GetIconType() == AbstractLauncherIcon::IconType::SPACER)
1362+ {
1363 arg.skip = true;
1364+ }
1365+
1366 size_modifier *= DragThresholdProgress(current);
1367 }
1368
1369@@ -933,11 +937,12 @@
1370
1371 icon->SetCenter(nux::Point3(roundf(center.x), roundf(center.y), roundf(center.z)), monitor, parent_abs_geo);
1372
1373- // FIXME: this is a hack, we should have a look why SetAnimationTarget is necessary in SetAnimationTarget
1374- // we should ideally just need it at start to set the target
1375+ // FIXME: this is a hack, to avoid that we set the target to the end of the icon
1376 if (!_initial_drag_animation && icon == _drag_icon && _drag_window && _drag_window->Animating())
1377- _drag_window->SetAnimationTarget(static_cast<int>(_drag_icon->GetCenter(monitor).x),
1378- static_cast<int>(_drag_icon->GetCenter(monitor).y));
1379+ {
1380+ auto const& icon_center = _drag_icon->GetCenter(monitor);
1381+ _drag_window->SetAnimationTarget(icon_center.x, icon_center.y);
1382+ }
1383
1384 center.y += (half_size * size_modifier) + spacing; // move to end
1385 }
1386@@ -954,10 +959,10 @@
1387 nux::Color FullySaturateColor (nux::Color color)
1388 {
1389 float max = std::max<float>(color.red, std::max<float>(color.green, color.blue));
1390+
1391 if (max > 0.0f)
1392- {
1393 color = color * (1.0f / max);
1394- }
1395+
1396 return color;
1397 }
1398
1399@@ -1397,8 +1402,8 @@
1400
1401 void Launcher::OnPluginStateChanged()
1402 {
1403- _hide_machine.SetQuirk (LauncherHideMachine::EXPO_ACTIVE, WindowManager::Default ()->IsExpoActive ());
1404- _hide_machine.SetQuirk (LauncherHideMachine::SCALE_ACTIVE, WindowManager::Default ()->IsScaleActive ());
1405+ _hide_machine.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, WindowManager::Default()->IsExpoActive());
1406+ _hide_machine.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, WindowManager::Default()->IsScaleActive());
1407 }
1408
1409 LauncherHideMode Launcher::GetHideMode() const
1410@@ -1670,11 +1675,6 @@
1411 return _model;
1412 }
1413
1414-void Launcher::SetDevicesSettings(DevicesSettings::Ptr devices_settings)
1415-{
1416- devices_settings_ = devices_settings;
1417-}
1418-
1419 void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr selection)
1420 {
1421 nux::Geometry const& geo = GetGeometry();
1422@@ -1682,7 +1682,7 @@
1423 int natural_y = 0;
1424 for (auto icon : *_model)
1425 {
1426- if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) || !icon->IsVisibleOnMonitor(monitor))
1427+ if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor))
1428 continue;
1429
1430 if (icon == selection)
1431@@ -1954,7 +1954,7 @@
1432 EnsureAnimation();
1433 }
1434
1435-bool Launcher::StartIconDragTimeout()
1436+bool Launcher::StartIconDragTimeout(int x, int y)
1437 {
1438 // if we are still waiting…
1439 if (GetActionState() == ACTION_NONE)
1440@@ -1965,7 +1965,7 @@
1441 _icon_under_mouse = nullptr;
1442 }
1443 _initial_drag_animation = true;
1444- StartIconDragRequest(GetMouseX(), GetMouseY());
1445+ StartIconDragRequest(x, y);
1446 }
1447
1448 return false;
1449@@ -1973,26 +1973,27 @@
1450
1451 void Launcher::StartIconDragRequest(int x, int y)
1452 {
1453- nux::Geometry geo = GetAbsoluteGeometry();
1454- AbstractLauncherIcon::Ptr drag_icon = MouseIconIntersection((int)(GetGeometry().width / 2.0f), y);
1455-
1456- x += geo.x;
1457- y += geo.y;
1458-
1459+ nux::Geometry const& abs_geo = GetAbsoluteGeometry();
1460+ AbstractLauncherIcon::Ptr drag_icon = MouseIconIntersection(abs_geo.width / 2.0f, y);
1461
1462 // FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
1463 // on an internal Launcher property then
1464- bool can_drag = (_model->IconHasSister(drag_icon) || drag_icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE);
1465- if (drag_icon && _last_button_press == 1 && can_drag)
1466+ if (drag_icon && _last_button_press == 1 && drag_icon->position() == AbstractLauncherIcon::Position::FLOATING)
1467 {
1468+ auto const& icon_center = drag_icon->GetCenter(monitor);
1469+ x += abs_geo.x;
1470+ y += abs_geo.y;
1471+
1472 SetActionState(ACTION_DRAG_ICON);
1473 StartIconDrag(drag_icon);
1474- UpdateDragWindowPosition(drag_icon->GetCenter(monitor).x, drag_icon->GetCenter(monitor).y);
1475+ UpdateDragWindowPosition(icon_center.x, icon_center.y);
1476+
1477 if (_initial_drag_animation)
1478 {
1479 _drag_window->SetAnimationTarget(x, y);
1480 _drag_window->StartAnimation();
1481 }
1482+
1483 EnsureAnimation();
1484 }
1485 else
1486@@ -2009,6 +2010,7 @@
1487
1488 _hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true);
1489 _drag_icon = icon;
1490+ _drag_icon_position = _model->IconIndex(icon);
1491
1492 HideDragWindow();
1493 _offscreen_drag_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(_icon_size, _icon_size, 1, nux::BITFMT_R8G8B8A8);
1494@@ -2032,15 +2034,20 @@
1495 {
1496 hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, true);
1497
1498- launcher_removerequest.emit(_drag_icon);
1499+ remove_request.emit(_drag_icon);
1500
1501 HideDragWindow();
1502 EnsureAnimation();
1503 }
1504 else
1505 {
1506- if (!_drag_window->Cancelled())
1507+ if (!_drag_window->Cancelled() && _model->IconIndex(_drag_icon) != _drag_icon_position)
1508+ {
1509+ if (_drag_icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
1510+ _drag_icon->Stick(false);
1511+
1512 _model->Save();
1513+ }
1514
1515 if (_drag_window->on_anim_completed.connected())
1516 _drag_window->on_anim_completed.disconnect();
1517@@ -2104,15 +2111,11 @@
1518 return;
1519
1520 auto const& launcher_geo = GetGeometry();
1521- auto hovered_icon = MouseIconIntersection((launcher_geo.x + launcher_geo.width) / 2.0, y - GetAbsoluteY());
1522+ auto const& hovered_icon = MouseIconIntersection((launcher_geo.x + launcher_geo.width) / 2.0, y - GetAbsoluteY());
1523 struct timespec current;
1524 clock_gettime(CLOCK_MONOTONIC, &current);
1525 float progress = DragThresholdProgress(current);
1526
1527- // Icons of different types can't be mixed, so let's avoid this.
1528- if (hovered_icon && hovered_icon->GetIconType() != _drag_icon->GetIconType())
1529- hovered_icon = nullptr;
1530-
1531 if (hovered_icon && _drag_icon != hovered_icon)
1532 {
1533 if (progress >= 1.0f)
1534@@ -2131,12 +2134,8 @@
1535 {
1536 auto const& icon = *it;
1537
1538- if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) ||
1539- !icon->IsVisibleOnMonitor(monitor) ||
1540- icon->GetIconType() != _drag_icon->GetIconType())
1541- {
1542+ if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor))
1543 continue;
1544- }
1545
1546 if (y >= icon->GetCenter(monitor).y)
1547 {
1548@@ -2217,7 +2216,9 @@
1549 }
1550 else
1551 {
1552- StartIconDragRequest(x, y);
1553+ // We we can safely start the icon drag, from the original mouse-down position
1554+ sources_.Remove(START_DRAGICON_DURATION);
1555+ StartIconDragRequest(x - _dnd_delta_x, y - _dnd_delta_y);
1556 }
1557 }
1558 else if (GetActionState() == ACTION_DRAG_LAUNCHER)
1559@@ -2227,7 +2228,7 @@
1560 }
1561 else if (GetActionState() == ACTION_DRAG_ICON)
1562 {
1563- nux::Geometry geo = GetAbsoluteGeometry();
1564+ nux::Geometry const& geo = GetAbsoluteGeometry();
1565 UpdateDragWindowPosition(geo.x + x, geo.y + y);
1566 }
1567
1568@@ -2406,7 +2407,7 @@
1569 {
1570 _icon_mouse_down = launcher_icon;
1571 // if MouseUp after the time ended -> it's an icon drag, otherwise, it's starting an app
1572- auto cb_func = sigc::mem_fun(this, &Launcher::StartIconDragTimeout);
1573+ auto cb_func = sigc::bind(sigc::mem_fun(this, &Launcher::StartIconDragTimeout), x, y);
1574 sources_.AddTimeout(START_DRAGICON_DURATION, cb_func, START_DRAGICON_TIMEOUT);
1575
1576 launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags), monitor, key_flags);
1577@@ -2453,7 +2454,7 @@
1578
1579 for (it = _model->begin(); it != _model->end(); ++it)
1580 {
1581- if (!(*it)->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) || !(*it)->IsVisibleOnMonitor(monitor))
1582+ if (!(*it)->IsVisible() || !(*it)->IsVisibleOnMonitor(monitor))
1583 continue;
1584
1585 nux::Point2 screen_coord [4];
1586@@ -2538,35 +2539,41 @@
1587 nux::GetWindowCompositor().RestoreRenderingSurface();
1588 }
1589
1590+bool Launcher::DndIsSpecialRequest(std::string const& uri) const
1591+{
1592+ return (boost::algorithm::ends_with(uri, ".desktop") || uri.find("device://") == 0);
1593+}
1594+
1595 void Launcher::OnDNDDataCollected(const std::list<char*>& mimes)
1596 {
1597 _dnd_data.Reset();
1598
1599- unity::glib::String uri_list_const(g_strdup("text/uri-list"));
1600+ const std::string uri_list = "text/uri-list";
1601+ auto& display = nux::GetWindowThread()->GetGraphicsDisplay();
1602
1603- for (auto it : mimes)
1604+ for (auto const& mime : mimes)
1605 {
1606- if (!g_str_equal(it, uri_list_const.Value()))
1607+ if (mime != uri_list)
1608 continue;
1609
1610- _dnd_data.Fill(nux::GetWindowThread()->GetGraphicsDisplay().GetDndData(uri_list_const.Value()));
1611+ _dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str())));
1612 break;
1613 }
1614
1615 _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true);
1616
1617- for (auto it : _dnd_data.Uris())
1618+ auto const& uris = _dnd_data.Uris();
1619+ if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
1620+ {return DndIsSpecialRequest(uri);}) != uris.end())
1621 {
1622- if (g_str_has_suffix(it.c_str(), ".desktop") || g_str_has_prefix(it.c_str(), "device://"))
1623- {
1624- _steal_drag = true;
1625- break;
1626- }
1627+ _steal_drag = true;
1628+
1629+ if (IsOverlayOpen())
1630+ SaturateIcons();
1631 }
1632-
1633- if (!_steal_drag)
1634+ else
1635 {
1636- for (auto it : *_model)
1637+ for (auto const& it : *_model)
1638 {
1639 if (it->ShouldHighlightOnDrag(_dnd_data))
1640 {
1641@@ -2580,11 +2587,6 @@
1642 }
1643 }
1644 }
1645- else
1646- {
1647- if (IsOverlayOpen())
1648- SaturateIcons();
1649- }
1650 }
1651
1652 void Launcher::ProcessDndEnter()
1653@@ -2652,32 +2654,29 @@
1654
1655 void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes)
1656 {
1657- nux::Area* parent = GetToplevel();
1658- unity::glib::String uri_list_const(g_strdup("text/uri-list"));
1659-
1660 if (!_data_checked)
1661 {
1662+ const std::string uri_list = "text/uri-list";
1663 _data_checked = true;
1664 _dnd_data.Reset();
1665+ auto& display = nux::GetWindowThread()->GetGraphicsDisplay();
1666
1667 // get the data
1668- for (auto it : mimes)
1669+ for (auto const& mime : mimes)
1670 {
1671- if (!g_str_equal(it, uri_list_const.Value()))
1672+ if (mime != uri_list)
1673 continue;
1674
1675- _dnd_data.Fill(nux::GetWindowThread()->GetGraphicsDisplay().GetDndData(uri_list_const.Value()));
1676+ _dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str())));
1677 break;
1678 }
1679
1680 // see if the launcher wants this one
1681- for (auto it : _dnd_data.Uris())
1682+ auto const& uris = _dnd_data.Uris();
1683+ if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
1684+ {return DndIsSpecialRequest(uri);}) != uris.end())
1685 {
1686- if (g_str_has_suffix(it.c_str(), ".desktop") || g_str_has_prefix(it.c_str(), "device://"))
1687- {
1688- _steal_drag = true;
1689- break;
1690- }
1691+ _steal_drag = true;
1692 }
1693
1694 // only set hover once we know our first x/y
1695@@ -2686,7 +2685,7 @@
1696
1697 if (!_steal_drag)
1698 {
1699- for (auto it : *_model)
1700+ for (auto const& it : *_model)
1701 {
1702 if (it->ShouldHighlightOnDrag(_dnd_data))
1703 it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
1704@@ -2696,7 +2695,7 @@
1705 }
1706 }
1707
1708- SetMousePosition(x - parent->GetGeometry().x, y - parent->GetGeometry().y);
1709+ SetMousePosition(x - _parent->GetGeometry().x, y - _parent->GetGeometry().y);
1710
1711 if (!IsOverlayOpen() && _mouse_position.x == 0 && _mouse_position.y <= (_parent->GetGeometry().height - _icon_size - 2 * _space_between_icons) && !_drag_edge_touching)
1712 {
1713@@ -2723,7 +2722,7 @@
1714 if (hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
1715 _steal_drag = false;
1716
1717- if (hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::APPLICATION || hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::EXPO)
1718+ if (hovered_icon->position() == AbstractLauncherIcon::Position::FLOATING)
1719 hovered_icon_is_appropriate = true;
1720 }
1721
1722@@ -2733,7 +2732,6 @@
1723 if (!_dnd_hovered_icon && hovered_icon_is_appropriate)
1724 {
1725 _dnd_hovered_icon = new SpacerLauncherIcon(monitor());
1726- _dnd_hovered_icon->SetSortPriority(G_MAXINT);
1727 _model->AddIcon(_dnd_hovered_icon);
1728 _model->ReorderBefore(_dnd_hovered_icon, hovered_icon, true);
1729 }
1730@@ -2788,34 +2786,10 @@
1731 {
1732 if (_steal_drag)
1733 {
1734- for (auto it : _dnd_data.Uris())
1735+ for (auto const& uri : _dnd_data.Uris())
1736 {
1737- if (g_str_has_suffix(it.c_str(), ".desktop"))
1738- {
1739- char* path = nullptr;
1740-
1741- if (g_str_has_prefix(it.c_str(), "application://"))
1742- {
1743- const char* tmp = it.c_str() + strlen("application://");
1744- unity::glib::String tmp2(g_strdup_printf("file:///usr/share/applications/%s", tmp));
1745- path = g_filename_from_uri(tmp2.Value(), NULL, NULL);
1746- }
1747- else if (g_str_has_prefix(it.c_str(), "file://"))
1748- {
1749- path = g_filename_from_uri(it.c_str(), NULL, NULL);
1750- }
1751-
1752- if (path)
1753- {
1754- launcher_addrequest.emit(path, _dnd_hovered_icon);
1755- g_free(path);
1756- }
1757- }
1758- else if (devices_settings_ && g_str_has_prefix(it.c_str(), "device://"))
1759- {
1760- const gchar* uuid = it.c_str() + 9;
1761- devices_settings_->TryToUnblacklist(uuid);
1762- }
1763+ if (DndIsSpecialRequest(uri))
1764+ add_request.emit(uri, _dnd_hovered_icon);
1765 }
1766 }
1767 else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)
1768
1769=== modified file 'launcher/Launcher.h'
1770--- launcher/Launcher.h 2012-09-12 03:50:23 +0000
1771+++ launcher/Launcher.h 2012-09-18 15:51:21 +0000
1772@@ -83,8 +83,6 @@
1773 void SetModel(LauncherModel::Ptr model);
1774 LauncherModel::Ptr GetModel() const;
1775
1776- void SetDevicesSettings(DevicesSettings::Ptr devices_settings);
1777-
1778 void StartKeyShowLauncher();
1779 void EndKeyShowLauncher();
1780
1781@@ -121,9 +119,8 @@
1782 int GetDragDelta() const;
1783 void SetHover(bool hovered);
1784
1785- sigc::signal<void, char*, AbstractLauncherIcon::Ptr> launcher_addrequest;
1786- sigc::signal<void, AbstractLauncherIcon::Ptr> launcher_removerequest;
1787- sigc::signal<void, AbstractLauncherIcon::Ptr> icon_animation_complete;
1788+ sigc::signal<void, std::string const&, AbstractLauncherIcon::Ptr> add_request;
1789+ sigc::signal<void, AbstractLauncherIcon::Ptr> remove_request;
1790 sigc::signal<void> selection_change;
1791 sigc::signal<void> hidden_changed;
1792 sigc::signal<void> sc_launcher_icon_animation;
1793@@ -199,7 +196,7 @@
1794 void OnSelectionChanged(AbstractLauncherIcon::Ptr selection);
1795
1796 bool StrutHack();
1797- bool StartIconDragTimeout();
1798+ bool StartIconDragTimeout(int x, int y);
1799 bool OnScrollTimeout();
1800 bool OnUpdateDragManagerTimeout();
1801
1802@@ -319,6 +316,7 @@
1803 void DndReset();
1804 void DndHoveredIconReset();
1805 void DndTimeoutSetup();
1806+ bool DndIsSpecialRequest(std::string const& uri) const;
1807
1808 LauncherModel::Ptr _model;
1809 nux::BaseWindow* _parent;
1810@@ -365,6 +363,7 @@
1811 int _launcher_drag_delta_min;
1812 int _enter_y;
1813 int _last_button_press;
1814+ int _drag_icon_position;
1815 float _drag_out_delta_x;
1816 bool _drag_gesture_ongoing;
1817 float _last_reveal_progress;
1818@@ -389,8 +388,6 @@
1819 ui::AbstractIconRenderer::Ptr icon_renderer;
1820 BackgroundEffectHelper bg_effect_helper_;
1821
1822- DevicesSettings::Ptr devices_settings_;
1823-
1824 UBusManager ubus_;
1825 glib::SourceManager sources_;
1826
1827
1828=== modified file 'launcher/LauncherController.cpp'
1829--- launcher/LauncherController.cpp 2012-09-13 10:56:42 +0000
1830+++ launcher/LauncherController.cpp 2012-09-18 15:51:21 +0000
1831@@ -1,6 +1,6 @@
1832 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1833 /*
1834- * Copyright (C) 2010, 2011 Canonical Ltd
1835+ * Copyright (C) 2010-2012 Canonical Ltd
1836 *
1837 * This program is free software: you can redistribute it and/or modify
1838 * it under the terms of the GNU General Public License version 3 as
1839@@ -16,6 +16,7 @@
1840 *
1841 * Authored by: Jason Smith <jason.smith@canonical.com>
1842 * Tim Penhey <tim.penhey@canonical.com>
1843+ * Marco Trevisan <marco.trevisan@canonical.com>
1844 */
1845
1846 #include <glib/gi18n-lib.h>
1847@@ -25,6 +26,7 @@
1848 #include <Nux/HLayout.h>
1849 #include <Nux/BaseWindow.h>
1850 #include <NuxCore/Logger.h>
1851+#include <UnityCore/DesktopUtilities.h>
1852
1853 #include "LauncherOptions.h"
1854 #include "BamfLauncherIcon.h"
1855@@ -35,6 +37,7 @@
1856 #include "LauncherController.h"
1857 #include "LauncherControllerPrivate.h"
1858 #include "SoftwareCenterLauncherIcon.h"
1859+#include "ExpoLauncherIcon.h"
1860 #include "unity-shared/WindowManager.h"
1861 #include "TrashLauncherIcon.h"
1862 #include "BFBLauncherIcon.h"
1863@@ -82,63 +85,45 @@
1864 const std::string KEYPRESS_TIMEOUT = "keypress-timeout";
1865 const std::string LABELS_TIMEOUT = "label-show-timeout";
1866 const std::string HIDE_TIMEOUT = "hide-timeout";
1867-}
1868-}
1869-
1870-
1871+
1872+ const std::string SOFTWARE_CENTER_AGENT = "software-center-agent";
1873+
1874+ const std::string RUNNING_APPS_URI = FavoriteStore::URI_PREFIX_UNITY + "running-apps";
1875+ const std::string DEVICES_URI = FavoriteStore::URI_PREFIX_UNITY + "devices";
1876+}
1877+}
1878
1879 GDBusInterfaceVTable Controller::Impl::interface_vtable =
1880 { Controller::Impl::OnDBusMethodCall, NULL, NULL};
1881
1882-Controller::Impl::Impl(Display* display, Controller* parent)
1883+
1884+Controller::Impl::Impl(Controller* parent)
1885 : parent_(parent)
1886- , model_(new LauncherModel())
1887- , sort_priority_(0)
1888- , volume_monitor_(new VolumeMonitorWrapper)
1889- , devices_settings_(new DevicesSettingsImp)
1890- , device_section_(volume_monitor_, devices_settings_)
1891- , show_desktop_icon_(false)
1892- , display_(display)
1893+ , model_(std::make_shared<LauncherModel>())
1894 , matcher_(bamf_matcher_get_default())
1895+ , device_section_(std::make_shared<VolumeMonitorWrapper>(), std::make_shared<DevicesSettingsImp>())
1896+ , expo_icon_(new ExpoLauncherIcon())
1897+ , desktop_icon_(new DesktopLauncherIcon())
1898+ , sort_priority_(AbstractLauncherIcon::DefaultPriority(AbstractLauncherIcon::IconType::APPLICATION))
1899+ , launcher_open(false)
1900+ , launcher_keynav(false)
1901+ , launcher_grabbed(false)
1902+ , reactivate_keynav(false)
1903+ , keynav_restore_window_(true)
1904+ , launcher_key_press_time_(0)
1905+ , dbus_owner_(g_bus_own_name(G_BUS_TYPE_SESSION, DBUS_NAME.c_str(), G_BUS_NAME_OWNER_FLAGS_NONE,
1906+ OnBusAcquired, nullptr, nullptr, this, nullptr))
1907 {
1908 edge_barriers_.options = parent_->options();
1909
1910 UScreen* uscreen = UScreen::GetDefault();
1911- auto monitors = uscreen->GetMonitors();
1912- int primary = uscreen->GetPrimaryMonitor();
1913-
1914- launcher_open = false;
1915- launcher_keynav = false;
1916- launcher_grabbed = false;
1917- reactivate_keynav = false;
1918- keynav_restore_window_ = true;
1919-
1920- EnsureLaunchers(primary, monitors);
1921-
1922- launcher_ = launchers[0];
1923- device_section_.IconAdded.connect(sigc::mem_fun(this, &Impl::OnIconAdded));
1924-
1925- num_workspaces_ = WindowManager::Default()->WorkspaceCount();
1926- if (num_workspaces_ > 1)
1927- {
1928- InsertExpoAction();
1929- }
1930-
1931- // Insert the "Show Desktop" launcher icon in the launcher...
1932- if (show_desktop_icon_)
1933- InsertDesktopIcon();
1934-
1935- InsertTrash();
1936-
1937- sources_.AddTimeout(500, [&] { SetupBamf(); return false; });
1938+ EnsureLaunchers(uscreen->GetPrimaryMonitor(), uscreen->GetMonitors());
1939+
1940+ SetupIcons();
1941
1942 remote_model_.entry_added.connect(sigc::mem_fun(this, &Impl::OnLauncherEntryRemoteAdded));
1943 remote_model_.entry_removed.connect(sigc::mem_fun(this, &Impl::OnLauncherEntryRemoteRemoved));
1944
1945- FavoriteStore::Instance().favorite_added.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteAdded));
1946- FavoriteStore::Instance().favorite_removed.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteRemoved));
1947- FavoriteStore::Instance().reordered.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreReordered));
1948-
1949 LauncherHideMode hide_mode = parent_->options()->hide_mode;
1950 BFBLauncherIcon* bfb = new BFBLauncherIcon(hide_mode);
1951 RegisterIcon(AbstractLauncherIcon::Ptr(bfb));
1952@@ -146,35 +131,27 @@
1953 HudLauncherIcon* hud = new HudLauncherIcon(hide_mode);
1954 RegisterIcon(AbstractLauncherIcon::Ptr(hud));
1955
1956- parent_->options()->hide_mode.changed.connect([bfb,hud](LauncherHideMode mode) {
1957+ TrashLauncherIcon* trash = new TrashLauncherIcon();
1958+ RegisterIcon(AbstractLauncherIcon::Ptr(trash));
1959+
1960+ parent_->options()->hide_mode.changed.connect([bfb, hud](LauncherHideMode mode) {
1961 bfb->SetHideMode(mode);
1962 hud->SetHideMode(mode);
1963 });
1964
1965- desktop_icon_ = AbstractLauncherIcon::Ptr(new DesktopLauncherIcon());
1966-
1967 uscreen->changed.connect(sigc::mem_fun(this, &Controller::Impl::OnScreenChanged));
1968
1969 WindowManager& plugin_adapter = *(WindowManager::Default());
1970- plugin_adapter.window_focus_changed.connect (sigc::mem_fun (this, &Controller::Impl::OnWindowFocusChanged));
1971-
1972- launcher_key_press_time_ = 0;
1973+ plugin_adapter.window_focus_changed.connect(sigc::mem_fun(this, &Controller::Impl::OnWindowFocusChanged));
1974
1975 ubus.RegisterInterest(UBUS_QUICKLIST_END_KEY_NAV, [&](GVariant * args) {
1976 if (reactivate_keynav)
1977 parent_->KeyNavGrab();
1978- model_->SetSelection(reactivate_index);
1979+
1980+ model_->SetSelection(reactivate_index);
1981 });
1982
1983 parent_->AddChild(model_.get());
1984-
1985- uscreen->resuming.connect([&]() -> void {
1986- for (auto launcher : launchers)
1987- launcher->QueueDraw();
1988- });
1989-
1990- dbus_owner_ = g_bus_own_name(G_BUS_TYPE_SESSION, DBUS_NAME.c_str(), G_BUS_NAME_OWNER_FLAGS_NONE,
1991- OnBusAcquired, nullptr, nullptr, this, nullptr);
1992 }
1993
1994 Controller::Impl::~Impl()
1995@@ -182,9 +159,9 @@
1996 // Since the launchers are in a window which adds a reference to the
1997 // launcher, we need to make sure the base windows are unreferenced
1998 // otherwise the launchers never die.
1999- for (auto launcher_ptr : launchers)
2000+ for (auto const& launcher_ptr : launchers)
2001 {
2002- if (launcher_ptr.IsValid())
2003+ if (launcher_ptr)
2004 launcher_ptr->GetParent()->UnReference();
2005 }
2006
2007@@ -198,7 +175,7 @@
2008 unsigned int launchers_size = launchers.size();
2009 unsigned int last_launcher = 0;
2010
2011- for (unsigned int i = 0; i < num_launchers; i++, last_launcher++)
2012+ for (unsigned int i = 0; i < num_launchers; ++i, ++last_launcher)
2013 {
2014 if (i >= launchers_size)
2015 {
2016@@ -232,6 +209,7 @@
2017 }
2018 }
2019
2020+ launcher_ = launchers[0];
2021 launchers.resize(num_launchers);
2022 }
2023
2024@@ -240,7 +218,7 @@
2025 EnsureLaunchers(primary_monitor, monitors);
2026 }
2027
2028-void Controller::Impl::OnWindowFocusChanged (guint32 xid)
2029+void Controller::Impl::OnWindowFocusChanged(guint32 xid)
2030 {
2031 static bool keynav_first_focus = false;
2032
2033@@ -264,11 +242,9 @@
2034 nux::BaseWindow* launcher_window = new nux::BaseWindow(TEXT("LauncherWindow"));
2035
2036 Launcher* launcher = new Launcher(launcher_window, nux::ObjectPtr<DNDCollectionWindow>(new DNDCollectionWindow));
2037- launcher->display = display_;
2038 launcher->monitor = monitor;
2039 launcher->options = parent_->options();
2040 launcher->SetModel(model_);
2041- launcher->SetDevicesSettings(devices_settings_);
2042
2043 nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
2044 layout->AddView(launcher, 1);
2045@@ -283,58 +259,103 @@
2046 launcher_window->InputWindowEnableStruts(parent_->options()->hide_mode == LAUNCHER_HIDE_NEVER);
2047 launcher_window->SetEnterFocusInputArea(launcher);
2048
2049- launcher->launcher_addrequest.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest));
2050- launcher->launcher_removerequest.connect(sigc::mem_fun(this, &Impl::OnLauncherRemoveRequest));
2051-
2052- launcher->icon_animation_complete.connect(sigc::mem_fun(this, &Impl::OnSCIconAnimationComplete));
2053+ launcher->add_request.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest));
2054+ launcher->remove_request.connect(sigc::mem_fun(this, &Impl::OnLauncherRemoveRequest));
2055
2056 parent_->AddChild(launcher);
2057
2058 return launcher;
2059 }
2060
2061-void Controller::Impl::OnLauncherAddRequest(char* path, AbstractLauncherIcon::Ptr before)
2062-{
2063- for (auto it : model_->GetSublist<BamfLauncherIcon> ())
2064- {
2065- if (path && path == it->DesktopFile())
2066- {
2067- it->Stick();
2068- model_->ReorderBefore(it, before, false);
2069- Save();
2070- return;
2071- }
2072- }
2073-
2074- AbstractLauncherIcon::Ptr result = CreateFavorite(path);
2075- if (result)
2076- {
2077- RegisterIcon(result);
2078- if (before)
2079- model_->ReorderBefore(result, before, false);
2080- }
2081-
2082- Save();
2083-}
2084-
2085-void Controller::Impl::Save()
2086-{
2087- unity::FavoriteList desktop_paths;
2088-
2089- // Updates gsettings favorites.
2090- auto launchers = model_->GetSublist<BamfLauncherIcon> ();
2091- for (auto icon : launchers)
2092+void Controller::Impl::OnLauncherAddRequest(std::string const& icon_uri, AbstractLauncherIcon::Ptr icon_before)
2093+{
2094+ std::string app_uri;
2095+
2096+ if (icon_uri.find(FavoriteStore::URI_PREFIX_FILE) == 0)
2097+ {
2098+ auto const& desktop_path = icon_uri.substr(FavoriteStore::URI_PREFIX_FILE.length());
2099+ app_uri = FavoriteStore::URI_PREFIX_APP + DesktopUtilities::GetDesktopID(desktop_path);
2100+ }
2101+
2102+ auto const& icon = GetIconByUri(app_uri.empty() ? icon_uri : app_uri);
2103+
2104+ if (icon)
2105+ {
2106+ icon->Stick(false);
2107+ model_->ReorderAfter(icon, icon_before);
2108+ }
2109+ else
2110+ {
2111+ if (icon_before)
2112+ RegisterIcon(CreateFavoriteIcon(icon_uri), icon_before->SortPriority());
2113+ else
2114+ RegisterIcon(CreateFavoriteIcon(icon_uri));
2115+ }
2116+
2117+ SaveIconsOrder();
2118+}
2119+
2120+void Controller::Impl::AddFavoriteKeepingOldPosition(FavoriteList& icons, std::string const& icon_uri) const
2121+{
2122+ auto const& favorites = FavoriteStore::Instance().GetFavorites();
2123+ auto it = std::find(favorites.rbegin(), favorites.rend(), icon_uri);
2124+
2125+ FavoriteList::reverse_iterator icons_it = icons.rbegin();
2126+
2127+ while (it != favorites.rend())
2128+ {
2129+ icons_it = std::find(icons.rbegin(), icons.rend(), *it);
2130+
2131+ if (icons_it != icons.rend())
2132+ break;
2133+
2134+ ++it;
2135+ }
2136+
2137+ icons.insert(icons_it.base(), icon_uri);
2138+}
2139+
2140+void Controller::Impl::SaveIconsOrder()
2141+{
2142+ FavoriteList icons;
2143+ bool found_first_running_app = false;
2144+ bool found_first_device = false;
2145+
2146+ for (auto const& icon : *model_)
2147 {
2148 if (!icon->IsSticky())
2149+ {
2150+ if (!icon->IsVisible())
2151+ continue;
2152+
2153+ if (!found_first_running_app && icon->GetIconType() == AbstractLauncherIcon::IconType::APPLICATION)
2154+ {
2155+ found_first_running_app = true;
2156+ icons.push_back(local::RUNNING_APPS_URI);
2157+ }
2158+
2159+ if (!found_first_device && icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
2160+ {
2161+ found_first_device = true;
2162+ icons.push_back(local::DEVICES_URI);
2163+ }
2164+
2165 continue;
2166-
2167- std::string const& desktop_file = icon->DesktopFile();
2168-
2169- if (!desktop_file.empty())
2170- desktop_paths.push_back(desktop_file);
2171+ }
2172+
2173+ std::string const& remote_uri = icon->RemoteUri();
2174+
2175+ if (!remote_uri.empty())
2176+ icons.push_back(remote_uri);
2177 }
2178
2179- unity::FavoriteStore::Instance().SetFavorites(desktop_paths);
2180+ if (!found_first_running_app)
2181+ AddFavoriteKeepingOldPosition(icons, local::RUNNING_APPS_URI);
2182+
2183+ if (!found_first_device)
2184+ AddFavoriteKeepingOldPosition(icons, local::DEVICES_URI);
2185+
2186+ FavoriteStore::Instance().SetFavorites(icons);
2187 }
2188
2189 void
2190@@ -345,64 +366,53 @@
2191 int icon_y,
2192 int icon_size)
2193 {
2194- auto bamf_icons = model_->GetSublist<BamfLauncherIcon>();
2195- for (auto icon : bamf_icons)
2196- {
2197- if (icon->DesktopFile() == path)
2198- return;
2199- }
2200-
2201 // Check if desktop file was supplied, or if it's set to SC's agent
2202 // See https://bugs.launchpad.net/unity/+bug/1002440
2203- if (path.empty() || path == "software-center-agent")
2204- return;
2205-
2206- SoftwareCenterLauncherIcon::Ptr result = CreateSCLauncherIcon(path, aptdaemon_trans_id, icon_path);
2207-
2208- CurrentLauncher()->ForceReveal(true);
2209+ if (path.empty() || path == local::SOFTWARE_CENTER_AGENT)
2210+ return;
2211+
2212+ auto const& icon = std::find_if(model_->begin(), model_->end(),
2213+ [&path](AbstractLauncherIcon::Ptr const& i) { return (i->DesktopFile() == path); });
2214+
2215+ if (icon != model_->end())
2216+ return;
2217+
2218+ auto const& result = CreateSCLauncherIcon(path, aptdaemon_trans_id, icon_path);
2219
2220 if (result)
2221 {
2222- result->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
2223- result->Animate(CurrentLauncher(), icon_x, icon_y, icon_size);
2224- RegisterIcon(result);
2225- Save();
2226+ // Setting the icon position and adding it to the model, makes the launcher
2227+ // to compute its center
2228+ RegisterIcon(result, GetLastIconPriority<BamfLauncherIcon>("", true));
2229+
2230+ // This will ensure that the center of the new icon is set, so that
2231+ // the animation could be done properly.
2232+ sources_.AddIdle([this, icon_x, icon_y, result] {
2233+ result->Animate(CurrentLauncher(), icon_x, icon_y);
2234+ return false;
2235+ });
2236 }
2237 }
2238
2239-void Controller::Impl::OnSCIconAnimationComplete(AbstractLauncherIcon::Ptr icon)
2240-{
2241- icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true);
2242- launcher_->ForceReveal(false);
2243-}
2244-
2245 void Controller::Impl::SortAndUpdate()
2246 {
2247- gint shortcut = 1;
2248+ unsigned shortcut = 1;
2249
2250- auto launchers = model_->GetSublist<BamfLauncherIcon> ();
2251- for (auto icon : launchers)
2252+ for (auto const& icon : model_->GetSublist<BamfLauncherIcon>())
2253 {
2254 if (shortcut <= 10 && icon->IsVisible())
2255 {
2256- std::stringstream shortcut_string;
2257- shortcut_string << (shortcut % 10);
2258- icon->SetShortcut(shortcut_string.str()[0]);
2259+ icon->SetShortcut(std::to_string(shortcut % 10)[0]);
2260 ++shortcut;
2261 }
2262- // reset shortcut
2263 else
2264 {
2265+ // reset shortcut
2266 icon->SetShortcut(0);
2267 }
2268 }
2269 }
2270
2271-void Controller::Impl::OnIconAdded(AbstractLauncherIcon::Ptr icon)
2272-{
2273- this->RegisterIcon(icon);
2274-}
2275-
2276 void Controller::Impl::OnIconRemoved(AbstractLauncherIcon::Ptr icon)
2277 {
2278 SortAndUpdate();
2279@@ -428,10 +438,13 @@
2280 {
2281 auto device_icon = dynamic_cast<VolumeLauncherIcon*>(icon.GetPointer());
2282
2283- if (device_icon && device_icon->CanEject())
2284- device_icon->EjectAndShowNotification();
2285- else if (device_icon && device_icon->CanStop())
2286- device_icon->StopDrive();
2287+ if (device_icon)
2288+ {
2289+ if (device_icon->CanEject())
2290+ device_icon->EjectAndShowNotification();
2291+ else if (device_icon->CanStop())
2292+ device_icon->StopDrive();
2293+ }
2294
2295 break;
2296 }
2297@@ -442,63 +455,63 @@
2298
2299 void Controller::Impl::OnLauncherEntryRemoteAdded(LauncherEntryRemote::Ptr const& entry)
2300 {
2301- for (auto icon : *model_)
2302- {
2303- if (!icon || icon->RemoteUri().empty())
2304- continue;
2305-
2306- if (entry->AppUri() == icon->RemoteUri())
2307- {
2308- icon->InsertEntryRemote(entry);
2309- }
2310- }
2311+ if (entry->AppUri().empty())
2312+ return;
2313+
2314+ auto const& apps_icons = model_->GetSublist<BamfLauncherIcon>();
2315+ auto const& icon = std::find_if(apps_icons.begin(), apps_icons.end(),
2316+ [&entry](AbstractLauncherIcon::Ptr const& i) { return (i->RemoteUri() == entry->AppUri()); });
2317+
2318+ if (icon != apps_icons.end())
2319+ (*icon)->InsertEntryRemote(entry);
2320 }
2321
2322 void Controller::Impl::OnLauncherEntryRemoteRemoved(LauncherEntryRemote::Ptr const& entry)
2323 {
2324- for (auto icon : *model_)
2325- {
2326+ for (auto const& icon : *model_)
2327 icon->RemoveEntryRemote(entry);
2328- }
2329 }
2330
2331 void Controller::Impl::OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before)
2332 {
2333- auto bamf_list = model_->GetSublist<BamfLauncherIcon>();
2334- AbstractLauncherIcon::Ptr other;
2335- if (bamf_list.size() > 0)
2336- other = *(bamf_list.begin());
2337+ if (entry == local::RUNNING_APPS_URI || entry == local::DEVICES_URI)
2338+ {
2339+ // Since the running apps and the devices are always shown, when added to
2340+ // the model, we only have to re-order them
2341+ ResetIconPriorities();
2342+ return;
2343+ }
2344+
2345+ AbstractLauncherIcon::Ptr other = *(model_->begin());
2346
2347 if (!pos.empty())
2348 {
2349- for (auto it : bamf_list)
2350+ for (auto const& it : *model_)
2351 {
2352- if (it->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) && pos == it->DesktopFile())
2353+ if (it->IsVisible() && pos == it->RemoteUri())
2354 other = it;
2355 }
2356 }
2357
2358- for (auto it : bamf_list)
2359+ AbstractLauncherIcon::Ptr const& fav = GetIconByUri(entry);
2360+ if (fav)
2361 {
2362- if (entry == it->DesktopFile())
2363- {
2364- it->Stick(false);
2365- if (!before)
2366- model_->ReorderAfter(it, other);
2367- else
2368- model_->ReorderBefore(it, other, false);
2369- return;
2370- }
2371+ fav->Stick(false);
2372+
2373+ if (before)
2374+ model_->ReorderBefore(fav, other, false);
2375+ else
2376+ model_->ReorderAfter(fav, other);
2377 }
2378-
2379- AbstractLauncherIcon::Ptr result = CreateFavorite(entry.c_str());
2380- if (result)
2381+ else
2382 {
2383+ AbstractLauncherIcon::Ptr const& result = CreateFavoriteIcon(entry);
2384 RegisterIcon(result);
2385- if (!before)
2386+
2387+ if (before)
2388+ model_->ReorderBefore(result, other, false);
2389+ else
2390 model_->ReorderAfter(result, other);
2391- else
2392- model_->ReorderBefore(result, other, false);
2393 }
2394
2395 SortAndUpdate();
2396@@ -506,104 +519,132 @@
2397
2398 void Controller::Impl::OnFavoriteStoreFavoriteRemoved(std::string const& entry)
2399 {
2400- for (auto icon : model_->GetSublist<BamfLauncherIcon> ())
2401- {
2402- if (icon->DesktopFile() == entry)
2403- {
2404- icon->UnStick();
2405- break;
2406- }
2407+ if (entry == local::RUNNING_APPS_URI || entry == local::DEVICES_URI)
2408+ {
2409+ // Since the running apps and the devices are always shown, when added to
2410+ // the model, we only have to re-order them
2411+ ResetIconPriorities();
2412+ return;
2413+ }
2414+
2415+ auto const& icon = GetIconByUri(entry);
2416+ if (icon)
2417+ {
2418+ icon->UnStick();
2419+
2420+ // When devices are removed from favorites, they should be re-ordered (not removed)
2421+ if (icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
2422+ ResetIconPriorities();
2423 }
2424 }
2425
2426-void Controller::Impl::OnFavoriteStoreReordered()
2427+void Controller::Impl::ResetIconPriorities()
2428 {
2429 FavoriteList const& favs = FavoriteStore::Instance().GetFavorites();
2430- auto bamf_list = model_->GetSublist<BamfLauncherIcon>();
2431-
2432- int i = 0;
2433- for (auto it : favs)
2434- {
2435- auto icon = std::find_if(bamf_list.begin(), bamf_list.end(),
2436- [&it](AbstractLauncherIcon::Ptr x) { return (x->DesktopFile() == it); });
2437-
2438- if (icon != bamf_list.end())
2439- {
2440- (*icon)->SetSortPriority(i++);
2441- }
2442- }
2443-
2444- for (auto it : bamf_list)
2445- {
2446- if (!it->IsSticky())
2447- it->SetSortPriority(i++);
2448+ auto const& apps_icons = model_->GetSublist<BamfLauncherIcon>();
2449+ auto const& volumes_icons = model_->GetSublist<VolumeLauncherIcon>();
2450+ bool running_apps_found = false;
2451+ bool volumes_found = false;
2452+
2453+ for (auto const& fav : favs)
2454+ {
2455+ if (fav == local::RUNNING_APPS_URI)
2456+ {
2457+ for (auto const& ico : apps_icons)
2458+ {
2459+ if (!ico->IsSticky())
2460+ ico->SetSortPriority(++sort_priority_);
2461+ }
2462+
2463+ running_apps_found = true;
2464+ continue;
2465+ }
2466+ else if (fav == local::DEVICES_URI)
2467+ {
2468+ for (auto const& ico : volumes_icons)
2469+ {
2470+ if (!ico->IsSticky())
2471+ ico->SetSortPriority(++sort_priority_);
2472+ }
2473+
2474+ volumes_found = true;
2475+ continue;
2476+ }
2477+
2478+ auto const& icon = GetIconByUri(fav);
2479+
2480+ if (icon)
2481+ icon->SetSortPriority(++sort_priority_);
2482+ }
2483+
2484+ if (!running_apps_found)
2485+ {
2486+ for (auto const& ico : apps_icons)
2487+ {
2488+ if (!ico->IsSticky())
2489+ ico->SetSortPriority(++sort_priority_);
2490+ }
2491+ }
2492+
2493+ if (!volumes_found)
2494+ {
2495+ for (auto const& ico : volumes_icons)
2496+ {
2497+ if (!ico->IsSticky())
2498+ ico->SetSortPriority(++sort_priority_);
2499+ }
2500 }
2501
2502 model_->Sort();
2503 }
2504
2505-void Controller::Impl::OnExpoActivated()
2506-{
2507- WindowManager::Default()->InitiateExpo();
2508-}
2509-
2510-void Controller::Impl::InsertTrash()
2511-{
2512- AbstractLauncherIcon::Ptr icon(new TrashLauncherIcon());
2513- RegisterIcon(icon);
2514-}
2515-
2516 void Controller::Impl::UpdateNumWorkspaces(int workspaces)
2517 {
2518- if ((num_workspaces_ == 0) && (workspaces > 0))
2519- {
2520- InsertExpoAction();
2521- }
2522- else if ((num_workspaces_ > 0) && (workspaces == 0))
2523- {
2524- RemoveExpoAction();
2525- }
2526-
2527- num_workspaces_ = workspaces;
2528-}
2529-
2530-void Controller::Impl::InsertExpoAction()
2531-{
2532- expo_icon_ = AbstractLauncherIcon::Ptr(new SimpleLauncherIcon(AbstractLauncherIcon::IconType::EXPO));
2533-
2534- SimpleLauncherIcon* icon = static_cast<SimpleLauncherIcon*>(expo_icon_.GetPointer());
2535- icon->tooltip_text = _("Workspace Switcher");
2536- icon->icon_name = "workspace-switcher";
2537- icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true);
2538- icon->SetQuirk(AbstractLauncherIcon::Quirk::RUNNING, false);
2539- icon->SetShortcut('s');
2540-
2541- on_expoicon_activate_connection_ = icon->activate.connect(sigc::mem_fun(this, &Impl::OnExpoActivated));
2542-
2543-
2544- RegisterIcon(expo_icon_);
2545-}
2546-
2547-void Controller::Impl::RemoveExpoAction()
2548-{
2549- if (on_expoicon_activate_connection_)
2550- on_expoicon_activate_connection_.disconnect();
2551- model_->RemoveIcon(expo_icon_);
2552-}
2553-
2554-void Controller::Impl::InsertDesktopIcon()
2555-{
2556- RegisterIcon(desktop_icon_);
2557-}
2558-
2559-void Controller::Impl::RemoveDesktopIcon()
2560-{
2561- model_->RemoveIcon(desktop_icon_);
2562-}
2563-
2564-void Controller::Impl::RegisterIcon(AbstractLauncherIcon::Ptr icon)
2565-{
2566+ bool visible = expo_icon_->IsVisible();
2567+ bool wp_enabled = (workspaces > 1);
2568+
2569+ if (wp_enabled && !visible)
2570+ {
2571+ if (FavoriteStore::Instance().IsFavorite(expo_icon_->RemoteUri()))
2572+ {
2573+ expo_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true);
2574+ }
2575+ }
2576+ else if (!wp_enabled && visible)
2577+ {
2578+ expo_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
2579+ }
2580+}
2581+
2582+void Controller::Impl::RegisterIcon(AbstractLauncherIcon::Ptr icon, int priority)
2583+{
2584+ if (!icon || model_->IconIndex(icon) >= 0)
2585+ return;
2586+
2587+ if (priority != std::numeric_limits<int>::min())
2588+ icon->SetSortPriority(priority);
2589+
2590+ icon->position_saved.connect([this] {
2591+ // These calls must be done in order: first we save the new sticky icons
2592+ // then we re-order the model so that there won't be two icons with the same
2593+ // priority
2594+ SaveIconsOrder();
2595+ ResetIconPriorities();
2596+ });
2597+
2598+ std::string const& icon_uri = icon->RemoteUri();
2599+ icon->position_forgot.connect([this, icon_uri] {
2600+ FavoriteStore::Instance().RemoveFavorite(icon_uri);
2601+ });
2602+
2603+ if (icon->GetIconType() == AbstractLauncherIcon::IconType::APPLICATION)
2604+ {
2605+ icon->visibility_changed.connect(sigc::mem_fun(this, &Impl::SortAndUpdate));
2606+ SortAndUpdate();
2607+ }
2608+
2609 model_->AddIcon(icon);
2610+
2611 std::string const& path = icon->DesktopFile();
2612
2613 if (!path.empty())
2614@@ -615,7 +656,59 @@
2615 }
2616 }
2617
2618-/* static private */
2619+template<typename IconType>
2620+int Controller::Impl::GetLastIconPriority(std::string const& favorite_uri, bool sticky)
2621+{
2622+ auto const& icons = model_->GetSublist<IconType>();
2623+ int icon_prio = std::numeric_limits<int>::min();
2624+
2625+ AbstractLauncherIcon::Ptr last_icon;
2626+
2627+ // Get the last (non)-sticky icon position (if available)
2628+ for (auto it = icons.rbegin(); it != icons.rend(); ++it)
2629+ {
2630+ auto const& icon = *it;
2631+ bool update_last_icon = ((!last_icon && !sticky) || sticky);
2632+
2633+ if (update_last_icon || icon->IsSticky() == sticky)
2634+ {
2635+ last_icon = icon;
2636+
2637+ if (icon->IsSticky() == sticky)
2638+ break;
2639+ }
2640+ }
2641+
2642+ if (last_icon)
2643+ {
2644+ icon_prio = last_icon->SortPriority();
2645+
2646+ if (sticky && last_icon->IsSticky() != sticky)
2647+ icon_prio -= 1;
2648+ }
2649+ else if (!favorite_uri.empty())
2650+ {
2651+ // If we have no applications opened, we must guess it position by favorites
2652+ for (auto const& fav : FavoriteStore::Instance().GetFavorites())
2653+ {
2654+ if (fav == favorite_uri)
2655+ {
2656+ if (icon_prio == std::numeric_limits<int>::min())
2657+ icon_prio = (*model_->begin())->SortPriority() - 1;
2658+
2659+ break;
2660+ }
2661+
2662+ auto const& icon = GetIconByUri(fav);
2663+
2664+ if (icon)
2665+ icon_prio = icon->SortPriority();
2666+ }
2667+ }
2668+
2669+ return icon_prio;
2670+}
2671+
2672 void Controller::Impl::OnViewOpened(BamfMatcher* matcher, BamfView* view)
2673 {
2674 if (!BAMF_IS_APPLICATION(view))
2675@@ -630,35 +723,111 @@
2676 }
2677
2678 AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
2679- icon->visibility_changed.connect(sigc::mem_fun(this, &Impl::SortAndUpdate));
2680- icon->SetSortPriority(sort_priority_++);
2681- RegisterIcon(icon);
2682- SortAndUpdate();
2683-}
2684-
2685-AbstractLauncherIcon::Ptr Controller::Impl::CreateFavorite(const char* file_path)
2686-{
2687- BamfApplication* app;
2688+ RegisterIcon(icon, GetLastIconPriority<BamfLauncherIcon>(local::RUNNING_APPS_URI));
2689+}
2690+
2691+void Controller::Impl::OnDeviceIconAdded(AbstractLauncherIcon::Ptr icon)
2692+{
2693+ RegisterIcon(icon, GetLastIconPriority<VolumeLauncherIcon>(local::DEVICES_URI));
2694+}
2695+
2696+AbstractLauncherIcon::Ptr Controller::Impl::CreateFavoriteIcon(std::string const& icon_uri)
2697+{
2698 AbstractLauncherIcon::Ptr result;
2699
2700- app = bamf_matcher_get_application_for_desktop_file(matcher_, file_path, true);
2701- if (!app)
2702- return result;
2703-
2704- if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
2705- {
2706- bamf_view_set_sticky(BAMF_VIEW(app), true);
2707- return result;
2708- }
2709-
2710- bamf_view_set_sticky(BAMF_VIEW(app), true);
2711- AbstractLauncherIcon::Ptr icon (new BamfLauncherIcon(app));
2712- icon->SetSortPriority(sort_priority_++);
2713- result = icon;
2714+ if (!FavoriteStore::IsValidFavoriteUri(icon_uri))
2715+ {
2716+ LOG_WARNING(logger) << "Ignoring favorite '" << icon_uri << "'.";
2717+ return result;
2718+ }
2719+
2720+ std::string desktop_id;
2721+
2722+ if (icon_uri.find(FavoriteStore::URI_PREFIX_APP) == 0)
2723+ {
2724+ desktop_id = icon_uri.substr(FavoriteStore::URI_PREFIX_APP.size());
2725+ }
2726+ else if (icon_uri.find(FavoriteStore::URI_PREFIX_FILE) == 0)
2727+ {
2728+ desktop_id = icon_uri.substr(FavoriteStore::URI_PREFIX_FILE.size());
2729+ }
2730+
2731+ if (!desktop_id.empty())
2732+ {
2733+ BamfApplication* app;
2734+ std::string const& desktop_path = DesktopUtilities::GetDesktopPathById(desktop_id);
2735+
2736+ app = bamf_matcher_get_application_for_desktop_file(matcher_, desktop_path.c_str(), true);
2737+
2738+ if (!app)
2739+ return result;
2740+
2741+ if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
2742+ {
2743+ bamf_view_set_sticky(BAMF_VIEW(app), true);
2744+ return result;
2745+ }
2746+
2747+ result = AbstractLauncherIcon::Ptr(new BamfLauncherIcon(app));
2748+ }
2749+ else if (icon_uri.find(FavoriteStore::URI_PREFIX_DEVICE) == 0)
2750+ {
2751+ auto const& devices = device_section_.GetIcons();
2752+ auto const& icon = std::find_if(devices.begin(), devices.end(),
2753+ [&icon_uri](AbstractLauncherIcon::Ptr const& i) { return (i->RemoteUri() == icon_uri); });
2754+
2755+ if (icon == devices.end())
2756+ {
2757+ // Using an idle to remove the favorite, not to erase while iterating
2758+ sources_.AddIdle([this, icon_uri] {
2759+ FavoriteStore::Instance().RemoveFavorite(icon_uri);
2760+ return false;
2761+ });
2762+
2763+ return result;
2764+ }
2765+
2766+ result = *icon;
2767+ }
2768+ else if (desktop_icon_->RemoteUri() == icon_uri)
2769+ {
2770+ result = desktop_icon_;
2771+ }
2772+ else if (expo_icon_->RemoteUri() == icon_uri)
2773+ {
2774+ result = expo_icon_;
2775+ }
2776+
2777+ if (result)
2778+ {
2779+ if (!result->IsSticky())
2780+ result->Stick(false);
2781+ else
2782+ {
2783+ LOG_ERROR(logger) << "Ignoring favorite '" << icon_uri << "': it's already on the launcher!";
2784+ result = nullptr;
2785+ }
2786+ }
2787
2788 return result;
2789 }
2790
2791+AbstractLauncherIcon::Ptr Controller::Impl::GetIconByUri(std::string const& icon_uri)
2792+{
2793+ if (icon_uri.empty())
2794+ return AbstractLauncherIcon::Ptr();
2795+
2796+ auto const& icon = std::find_if(model_->begin(), model_->end(),
2797+ [&icon_uri](AbstractLauncherIcon::Ptr const& i) { return (i->RemoteUri() == icon_uri); });
2798+
2799+ if (icon != model_->end())
2800+ {
2801+ return *icon;
2802+ }
2803+
2804+ return AbstractLauncherIcon::Ptr();
2805+}
2806+
2807 SoftwareCenterLauncherIcon::Ptr Controller::Impl::CreateSCLauncherIcon(std::string const& file_path,
2808 std::string const& aptdaemon_trans_id,
2809 std::string const& icon_path)
2810@@ -678,50 +847,79 @@
2811
2812 bamf_view_set_sticky(BAMF_VIEW(app), true);
2813 result = new SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path);
2814- result->SetSortPriority(sort_priority_++);
2815
2816 return result;
2817 }
2818
2819-void Controller::Impl::SetupBamf()
2820-{
2821- GList* apps, *l;
2822- BamfApplication* app;
2823-
2824- FavoriteList const& favs = FavoriteStore::Instance().GetFavorites();
2825-
2826- for (FavoriteList::const_iterator i = favs.begin(), end = favs.end();
2827- i != end; ++i)
2828- {
2829- AbstractLauncherIcon::Ptr fav = CreateFavorite(i->c_str());
2830-
2831- if (fav)
2832- {
2833- fav->SetSortPriority(sort_priority_++);
2834- RegisterIcon(fav);
2835- }
2836- }
2837-
2838- apps = bamf_matcher_get_applications(matcher_);
2839+void Controller::Impl::AddRunningApps()
2840+{
2841+ std::shared_ptr<GList> apps(bamf_matcher_get_applications(matcher_), g_list_free);
2842+
2843+ for (GList *l = apps.get(); l; l = l->next)
2844+ {
2845+ if (!BAMF_IS_APPLICATION(l->data))
2846+ continue;
2847+
2848+ BamfApplication* app = BAMF_APPLICATION(l->data);
2849+
2850+ if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
2851+ continue;
2852+
2853+ AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
2854+ RegisterIcon(icon, ++sort_priority_);
2855+ }
2856+}
2857+
2858+void Controller::Impl::AddDevices()
2859+{
2860+ auto& fav_store = FavoriteStore::Instance();
2861+ for (auto const& icon : device_section_.GetIcons())
2862+ {
2863+ if (!icon->IsSticky() && !fav_store.IsFavorite(icon->RemoteUri()))
2864+ RegisterIcon(icon, ++sort_priority_);
2865+ }
2866+}
2867+
2868+void Controller::Impl::SetupIcons()
2869+{
2870+ auto& favorite_store = FavoriteStore::Instance();
2871+ FavoriteList const& favs = favorite_store.GetFavorites();
2872+ bool running_apps_added = false;
2873+ bool devices_added = false;
2874+
2875+ for (auto const& fav_uri : favs)
2876+ {
2877+ if (fav_uri == local::RUNNING_APPS_URI)
2878+ {
2879+ AddRunningApps();
2880+ running_apps_added = true;
2881+ continue;
2882+ }
2883+ else if (fav_uri == local::DEVICES_URI)
2884+ {
2885+ AddDevices();
2886+ devices_added = true;
2887+ continue;
2888+ }
2889+
2890+ RegisterIcon(CreateFavoriteIcon(fav_uri), ++sort_priority_);
2891+ }
2892+
2893+ if (!running_apps_added)
2894+ AddRunningApps();
2895+
2896+ if (!devices_added)
2897+ AddDevices();
2898+
2899 view_opened_signal_.Connect(matcher_, "view-opened", sigc::mem_fun(this, &Impl::OnViewOpened));
2900-
2901- for (l = apps; l; l = l->next)
2902- {
2903- app = BAMF_APPLICATION(l->data);
2904-
2905- if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
2906- continue;
2907-
2908- AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
2909- icon->SetSortPriority(sort_priority_++);
2910- RegisterIcon(icon);
2911- }
2912- g_list_free(apps);
2913- SortAndUpdate();
2914+ device_section_.icon_added.connect(sigc::mem_fun(this, &Impl::OnDeviceIconAdded));
2915+ favorite_store.favorite_added.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteAdded));
2916+ favorite_store.favorite_removed.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteRemoved));
2917+ favorite_store.reordered.connect(sigc::mem_fun(this, &Impl::ResetIconPriorities));
2918
2919 model_->order_changed.connect(sigc::mem_fun(this, &Impl::SortAndUpdate));
2920 model_->icon_removed.connect(sigc::mem_fun(this, &Impl::OnIconRemoved));
2921- model_->saved.connect(sigc::mem_fun(this, &Impl::Save));
2922+ model_->saved.connect(sigc::mem_fun(this, &Impl::SaveIconsOrder));
2923 }
2924
2925 void Controller::Impl::SendHomeActivationRequest()
2926@@ -729,10 +927,10 @@
2927 ubus.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST, g_variant_new("(sus)", "home.lens", dash::NOT_HANDLED, ""));
2928 }
2929
2930-Controller::Controller(Display* display)
2931+Controller::Controller()
2932 : options(Options::Ptr(new Options()))
2933 , multiple_launchers(true)
2934- , pimpl(new Impl(display, this))
2935+ , pimpl(new Impl(this))
2936 {
2937 multiple_launchers.changed.connect([&](bool value) -> void {
2938 UScreen* uscreen = UScreen::GetDefault();
2939@@ -814,19 +1012,6 @@
2940 pimpl->launcher_->GetParent()->PushToFront();
2941 }
2942
2943-void Controller::SetShowDesktopIcon(bool show_desktop_icon)
2944-{
2945- if (pimpl->show_desktop_icon_ == show_desktop_icon)
2946- return;
2947-
2948- pimpl->show_desktop_icon_ = show_desktop_icon;
2949-
2950- if (pimpl->show_desktop_icon_)
2951- pimpl->InsertDesktopIcon();
2952- else
2953- pimpl->RemoveDesktopIcon();
2954-}
2955-
2956 int Controller::Impl::MonitorWithMouse()
2957 {
2958 UScreen* uscreen = UScreen::GetDefault();
2959@@ -1110,7 +1295,7 @@
2960 timespec current;
2961 clock_gettime(CLOCK_MONOTONIC, &current);
2962
2963- unity::variant::BuilderWrapper(builder)
2964+ variant::BuilderWrapper(builder)
2965 .add("key_nav_is_active", KeyNavIsActive())
2966 .add("key_nav_launcher_monitor", pimpl->keyboard_launcher_.IsValid() ? pimpl->keyboard_launcher_->monitor : -1)
2967 .add("key_nav_selection", pimpl->model_->SelectionIndex())
2968
2969=== modified file 'launcher/LauncherController.h'
2970--- launcher/LauncherController.h 2012-08-11 09:16:21 +0000
2971+++ launcher/LauncherController.h 2012-09-18 15:51:21 +0000
2972@@ -47,7 +47,7 @@
2973 nux::Property<Options::Ptr> options;
2974 nux::Property<bool> multiple_launchers;
2975
2976- Controller(Display* display);
2977+ Controller();
2978 ~Controller();
2979
2980 Launcher& launcher() const;
2981@@ -61,8 +61,6 @@
2982
2983 void PushToFront();
2984
2985- void SetShowDesktopIcon(bool show_desktop_icon);
2986-
2987 bool AboutToShowDash(int was_tap, int when) const;
2988
2989 void HandleLauncherKeyPress(int when);
2990
2991=== modified file 'launcher/LauncherControllerPrivate.h'
2992--- launcher/LauncherControllerPrivate.h 2012-08-17 13:07:53 +0000
2993+++ launcher/LauncherControllerPrivate.h 2012-09-18 15:51:21 +0000
2994@@ -46,59 +46,53 @@
2995 class Controller::Impl
2996 {
2997 public:
2998- Impl(Display* display, Controller* parent);
2999+ Impl(Controller* parent);
3000 ~Impl();
3001
3002 void UpdateNumWorkspaces(int workspaces);
3003
3004 Launcher* CreateLauncher(int monitor);
3005
3006- void Save();
3007+ void SaveIconsOrder();
3008 void SortAndUpdate();
3009
3010 nux::ObjectPtr<Launcher> CurrentLauncher();
3011
3012- void OnIconAdded(AbstractLauncherIcon::Ptr icon);
3013+ template<typename IconType>
3014+ int GetLastIconPriority(std::string const& favorite_uri = "", bool sticky = false);
3015+ void AddFavoriteKeepingOldPosition(FavoriteList& icons, std::string const& icon_uri) const;
3016+
3017 void OnIconRemoved(AbstractLauncherIcon::Ptr icon);
3018+ void OnDeviceIconAdded(AbstractLauncherIcon::Ptr icon);
3019
3020- void OnLauncherAddRequest(char* path, AbstractLauncherIcon::Ptr before);
3021+ void OnLauncherAddRequest(std::string const& icon_uri, AbstractLauncherIcon::Ptr before);
3022 void OnLauncherAddRequestSpecial(std::string const& path, std::string const& aptdaemon_trans_id,
3023 std::string const& icon_path, int icon_x, int icon_y, int icon_size);
3024 void OnLauncherRemoveRequest(AbstractLauncherIcon::Ptr icon);
3025- void OnSCIconAnimationComplete(AbstractLauncherIcon::Ptr icon);
3026
3027 void OnLauncherEntryRemoteAdded(LauncherEntryRemote::Ptr const& entry);
3028 void OnLauncherEntryRemoteRemoved(LauncherEntryRemote::Ptr const& entry);
3029
3030 void OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before);
3031 void OnFavoriteStoreFavoriteRemoved(std::string const& entry);
3032- void OnFavoriteStoreReordered();
3033-
3034-
3035- void InsertExpoAction();
3036- void RemoveExpoAction();
3037-
3038- void InsertDesktopIcon();
3039- void RemoveDesktopIcon();
3040+ void ResetIconPriorities();
3041
3042 void SendHomeActivationRequest();
3043
3044 int MonitorWithMouse();
3045
3046- void InsertTrash();
3047-
3048- void RegisterIcon(AbstractLauncherIcon::Ptr icon);
3049-
3050- AbstractLauncherIcon::Ptr CreateFavorite(const char* file_path);
3051-
3052+ void RegisterIcon(AbstractLauncherIcon::Ptr icon, int priority = std::numeric_limits<int>::min());
3053+
3054+ AbstractLauncherIcon::Ptr CreateFavoriteIcon(std::string const& icon_uri);
3055+ AbstractLauncherIcon::Ptr GetIconByUri(std::string const& icon_uri);
3056 SoftwareCenterLauncherIcon::Ptr CreateSCLauncherIcon(std::string const& file_path, std::string const& aptdaemon_trans_id, std::string const& icon_path);
3057
3058- void SetupBamf();
3059+ void SetupIcons();
3060+ void AddRunningApps();
3061+ void AddDevices();
3062
3063 void EnsureLaunchers(int primary, std::vector<nux::Geometry> const& monitors);
3064
3065- void OnExpoActivated();
3066-
3067 void OnScreenChanged(int primary_monitor, std::vector<nux::Geometry>& monitors);
3068
3069 void OnWindowFocusChanged (guint32 xid);
3070@@ -123,38 +117,31 @@
3071
3072 Controller* parent_;
3073 LauncherModel::Ptr model_;
3074+ glib::Object<BamfMatcher> matcher_;
3075 nux::ObjectPtr<Launcher> launcher_;
3076 nux::ObjectPtr<Launcher> keyboard_launcher_;
3077- int sort_priority_;
3078- AbstractVolumeMonitorWrapper::Ptr volume_monitor_;
3079- DevicesSettingsImp::Ptr devices_settings_;
3080 DeviceLauncherSection device_section_;
3081 LauncherEntryRemoteModel remote_model_;
3082 AbstractLauncherIcon::Ptr expo_icon_;
3083 AbstractLauncherIcon::Ptr desktop_icon_;
3084- int num_workspaces_;
3085- bool show_desktop_icon_;
3086- Display* display_;
3087-
3088- bool launcher_open;
3089- bool launcher_keynav;
3090- bool launcher_grabbed;
3091- bool reactivate_keynav;
3092- int reactivate_index;
3093- bool keynav_restore_window_;
3094- int launcher_key_press_time_;
3095- unsigned int dbus_owner_;
3096-
3097 ui::EdgeBarrierController edge_barriers_;
3098-
3099 LauncherList launchers;
3100
3101- glib::Object<BamfMatcher> matcher_;
3102+ unsigned sort_priority_;
3103+ bool launcher_open;
3104+ bool launcher_keynav;
3105+ bool launcher_grabbed;
3106+ bool reactivate_keynav;
3107+ int reactivate_index;
3108+ bool keynav_restore_window_;
3109+ int launcher_key_press_time_;
3110+ unsigned dbus_owner_;
3111+
3112+
3113 glib::Signal<void, BamfMatcher*, BamfView*> view_opened_signal_;
3114 glib::SourceManager sources_;
3115 UBusManager ubus;
3116
3117- sigc::connection on_expoicon_activate_connection_;
3118 sigc::connection launcher_key_press_connection_;
3119 sigc::connection launcher_event_outside_connection_;
3120 };
3121
3122=== modified file 'launcher/LauncherIcon.cpp'
3123--- launcher/LauncherIcon.cpp 2012-08-15 02:51:33 +0000
3124+++ launcher/LauncherIcon.cpp 2012-09-18 15:51:21 +0000
3125@@ -74,10 +74,11 @@
3126
3127 LauncherIcon::LauncherIcon(IconType type)
3128 : _icon_type(type)
3129+ , _sticky(false)
3130 , _remote_urgent(false)
3131 , _present_urgency(0)
3132 , _progress(0)
3133- , _sort_priority(0)
3134+ , _sort_priority(DefaultPriority(type))
3135 , _last_monitor(0)
3136 , _background_color(nux::color::White)
3137 , _glow_color(nux::color::White)
3138@@ -89,7 +90,7 @@
3139 , _saved_center(max_num_monitors)
3140 , _allow_quicklist_to_show(true)
3141 {
3142- for (unsigned i = 0; i < unsigned(Quirk::LAST); i++)
3143+ for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i)
3144 {
3145 _quirks[i] = false;
3146 _quirk_times[i].tv_sec = 0;
3147@@ -107,10 +108,10 @@
3148 tooltip_text.SetSetterFunction(sigc::mem_fun(this, &LauncherIcon::SetTooltipText));
3149 tooltip_text = "blank";
3150
3151+ position = Position::FLOATING;
3152+
3153 // FIXME: the abstraction is already broken, should be fixed for O
3154 // right now, hooking the dynamic quicklist the less ugly possible way
3155-
3156-
3157 mouse_enter.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseEnter));
3158 mouse_leave.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseLeave));
3159 mouse_down.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseDown));
3160@@ -517,6 +518,7 @@
3161
3162 if (!_tooltip)
3163 LoadTooltip();
3164+ _tooltip->SetText(tooltip_text());
3165 _tooltip->ShowTooltipWithTipAt(tip_x, tip_y);
3166 _tooltip->ShowWindow(!tooltip_text().empty());
3167 tooltip_visible.emit(_tooltip);
3168@@ -1179,6 +1181,31 @@
3169 remove.emit(AbstractLauncherIcon::Ptr(this));
3170 }
3171
3172+void LauncherIcon::Stick(bool save)
3173+{
3174+ if (_sticky)
3175+ return;
3176+
3177+ _sticky = true;
3178+
3179+ if (save)
3180+ position_saved.emit();
3181+
3182+ SetQuirk(Quirk::VISIBLE, true);
3183+}
3184+
3185+void LauncherIcon::UnStick()
3186+{
3187+ if (!_sticky)
3188+ return;
3189+
3190+ _sticky = false;
3191+
3192+ position_forgot.emit();
3193+
3194+ SetQuirk(Quirk::VISIBLE, false);
3195+}
3196+
3197
3198 } // namespace launcher
3199 } // namespace unity
3200
3201=== modified file 'launcher/LauncherIcon.h'
3202--- launcher/LauncherIcon.h 2012-08-15 02:51:33 +0000
3203+++ launcher/LauncherIcon.h 2012-09-18 15:51:21 +0000
3204@@ -108,11 +108,6 @@
3205
3206 const bool WindowVisibleOnViewport();
3207
3208- virtual bool IsSpacer()
3209- {
3210- return false;
3211- };
3212-
3213 float PresentUrgency();
3214
3215 float GetProgress();
3216@@ -188,9 +183,9 @@
3217
3218 virtual std::string DesktopFile() { return std::string(""); }
3219
3220- virtual bool IsSticky() const { return false; }
3221+ virtual bool IsSticky() const { return _sticky; }
3222
3223- virtual bool IsVisible() const { return false; }
3224+ virtual bool IsVisible() const { return GetQuirk(Quirk::VISIBLE); }
3225
3226 virtual bool IsVisibleOnMonitor(int monitor) const;
3227
3228@@ -198,9 +193,9 @@
3229
3230 virtual void AboutToRemove() {}
3231
3232- virtual void Stick(bool save = true) {}
3233+ virtual void Stick(bool save = true);
3234
3235- virtual void UnStick() {}
3236+ virtual void UnStick();
3237
3238 protected:
3239 std::vector<nux::Point3> GetCenters();
3240@@ -313,6 +308,7 @@
3241
3242 void OnTooltipEnabledChanged(bool value);
3243
3244+ bool _sticky;
3245 bool _remote_urgent;
3246 float _present_urgency;
3247 float _progress;
3248
3249=== modified file 'launcher/LauncherModel.cpp'
3250--- launcher/LauncherModel.cpp 2012-09-04 15:51:31 +0000
3251+++ launcher/LauncherModel.cpp 2012-09-18 15:51:21 +0000
3252@@ -56,14 +56,14 @@
3253
3254 bool LauncherModel::IconShouldShelf(AbstractLauncherIcon::Ptr const& icon) const
3255 {
3256- return icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH;
3257+ return icon->position() == AbstractLauncherIcon::Position::END;
3258 }
3259
3260 bool LauncherModel::CompareIcons(AbstractLauncherIcon::Ptr const& first, AbstractLauncherIcon::Ptr const& second)
3261 {
3262- if (first->GetIconType() < second->GetIconType())
3263+ if (first->position() < second->position())
3264 return true;
3265- else if (first->GetIconType() > second->GetIconType())
3266+ else if (first->position() > second->position())
3267 return false;
3268
3269 return first->SortPriority() < second->SortPriority();
3270@@ -163,25 +163,11 @@
3271 if (!icon)
3272 return false;
3273
3274- const_iterator it;
3275- const_iterator end;
3276-
3277- if (IconShouldShelf(icon))
3278- {
3279- it = _inner_shelf.begin();
3280- end = _inner_shelf.end();
3281- }
3282- else
3283- {
3284- it = _inner_main.begin();
3285- end = _inner_main.end();
3286- }
3287-
3288- for (; it != end; ++it)
3289- {
3290- AbstractLauncherIcon::Ptr const& iter_icon = *it;
3291-
3292- if (iter_icon != icon && iter_icon->GetIconType() == icon->GetIconType())
3293+ auto const& container = IconShouldShelf(icon) ? _inner_shelf : _inner_main;
3294+
3295+ for (auto const& icon_it : container)
3296+ {
3297+ if (icon_it != icon && icon_it->GetIconType() == icon->GetIconType())
3298 return true;
3299 }
3300
3301@@ -193,16 +179,20 @@
3302 if (icon == other || icon.IsNull() || other.IsNull())
3303 return;
3304
3305- if (icon->GetIconType() != other->GetIconType())
3306+ if (icon->position() != other->position())
3307 return;
3308
3309 icon->SetSortPriority(other->SortPriority() + 1);
3310
3311 for (auto it = std::next(std::find(begin(), end(), other)); it != end(); ++it)
3312 {
3313+ auto const& icon_it = *it;
3314+
3315+ if (icon_it == icon)
3316+ continue;
3317+
3318 // Increasing the priority of the icons next to the other one
3319- auto const& icon_it = *it;
3320- int new_priority = icon_it->SortPriority() + 1;
3321+ int new_priority = icon_it->SortPriority() + 2;
3322 icon_it->SetSortPriority(new_priority);
3323 }
3324
3325@@ -214,7 +204,7 @@
3326 if (icon == other || icon.IsNull() || other.IsNull())
3327 return;
3328
3329- if (icon->GetIconType() != other->GetIconType())
3330+ if (icon->position() != other->position())
3331 return;
3332
3333 bool found_target = false;
3334@@ -228,7 +218,13 @@
3335 continue;
3336 }
3337
3338- int new_priority = icon_it->SortPriority() + (found_target ? 1 : -1);
3339+ int old_priority = icon_it->SortPriority();
3340+ int new_priority = old_priority + (found_target ? 1 : -1);
3341+
3342+ // We need to reduce the priority of all the icons previous to 'other'
3343+ if (icon_it != other && !found_target && other->SortPriority() == old_priority)
3344+ new_priority -= 1;
3345+
3346 icon_it->SetSortPriority(new_priority);
3347
3348 if (icon_it == other)
3349@@ -237,7 +233,7 @@
3350 icon_it->SaveCenter();
3351
3352 center = !center;
3353- new_priority = new_priority - 1;
3354+ new_priority += -1;
3355 icon->SetSortPriority(new_priority);
3356
3357 if (animate && center)
3358@@ -260,7 +256,7 @@
3359 if (icon == other || icon.IsNull() || other.IsNull())
3360 return;
3361
3362- if (icon->GetIconType() != other->GetIconType())
3363+ if (icon->position() != other->position())
3364 return;
3365
3366 bool found_icon = false;
3367@@ -276,7 +272,13 @@
3368 continue;
3369 }
3370
3371- int new_priority = icon_it->SortPriority() + (found_target ? 1 : -1);
3372+ int old_priority = icon_it->SortPriority();
3373+ int new_priority = old_priority + (found_target ? 1 : -1);
3374+
3375+ // We need to reduce the priority of all the icons previous to 'other'
3376+ if (icon_it != other && !found_target && other->SortPriority() == old_priority)
3377+ new_priority -= 1;
3378+
3379 icon_it->SetSortPriority(new_priority);
3380
3381 if (icon_it == other)
3382@@ -285,7 +287,7 @@
3383 icon_it->SaveCenter();
3384
3385 center = !center;
3386- new_priority = new_priority + (found_icon ? 1 : -1);
3387+ new_priority += found_icon ? 1 : -1;
3388 icon->SetSortPriority(new_priority);
3389
3390 if (animate && center)
3391@@ -377,7 +379,7 @@
3392
3393 for (auto const& current : _inner)
3394 {
3395- if (current->GetIconType() != icon->GetIconType())
3396+ if (current->position() != icon->position())
3397 continue;
3398
3399 if (!found_target)
3400
3401=== modified file 'launcher/MockLauncherIcon.h'
3402--- launcher/MockLauncherIcon.h 2012-09-04 14:13:16 +0000
3403+++ launcher/MockLauncherIcon.h 2012-09-18 15:51:21 +0000
3404@@ -45,20 +45,20 @@
3405 NUX_DECLARE_OBJECT_TYPE(MockLauncherIcon, AbstractLauncherIcon);
3406 public:
3407 MockLauncherIcon(IconType type = IconType::APPLICATION)
3408- : type_(type)
3409- , sort_priority_(0)
3410- , icon_(0)
3411+ : icon_(0)
3412+ , type_(type)
3413+ , sort_priority_(DefaultPriority(type))
3414+ , remote_uri_("fake")
3415 {
3416 tooltip_text = "Mock Icon";
3417+ position = Position::FLOATING;
3418
3419 for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i)
3420- {
3421 quirks_[i] = false;
3422- }
3423 }
3424
3425 std::string GetName() const { return "MockLauncherIcon"; }
3426-
3427+
3428 void AddProperties(GVariantBuilder* builder) {}
3429
3430 void HideTooltip() {}
3431@@ -180,11 +180,6 @@
3432 return true;
3433 }
3434
3435- bool IsSpacer()
3436- {
3437- return false;
3438- }
3439-
3440 float PresentUrgency()
3441 {
3442 return 0.0f;
3443@@ -244,7 +239,7 @@
3444
3445 std::string RemoteUri()
3446 {
3447- return "fake";
3448+ return remote_uri_;
3449 }
3450
3451 nux::BaseTexture* TextureForSize(int size)
3452@@ -293,9 +288,9 @@
3453 bool IsVisible() const { return false; }
3454
3455 void AboutToRemove() {}
3456-
3457+
3458 void Stick(bool save = true) {}
3459-
3460+
3461 void UnStick() {}
3462
3463 private:
3464@@ -346,12 +341,13 @@
3465 return result;
3466 }
3467
3468+ nux::BaseTexture* icon_;
3469 IconType type_;
3470 int sort_priority_;
3471- nux::BaseTexture* icon_;
3472 bool quirks_[unsigned(Quirk::LAST)];
3473 timespec quirk_times_[unsigned(Quirk::LAST)];
3474 std::map<int, nux::Point3> center_;
3475+ std::string remote_uri_;
3476 };
3477
3478 }
3479
3480=== modified file 'launcher/SoftwareCenterLauncherIcon.cpp'
3481--- launcher/SoftwareCenterLauncherIcon.cpp 2012-08-02 13:16:06 +0000
3482+++ launcher/SoftwareCenterLauncherIcon.cpp 2012-09-18 15:51:21 +0000
3483@@ -45,23 +45,19 @@
3484 , needs_urgent_(false)
3485 , aptdaemon_trans_id_(aptdaemon_trans_id)
3486 {
3487-
3488+ SetQuirk(Quirk::VISIBLE, false);
3489 aptdaemon_trans_.Connect("PropertyChanged", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnPropertyChanged));
3490 aptdaemon_trans_.Connect("Finished", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnFinished));
3491
3492- icon_name = icon_path;
3493+ if (!icon_path.empty())
3494+ icon_name = icon_path;
3495+
3496 if (!aptdaemon_trans_id_.empty()) // Application is being installed, or hasn't been installed yet
3497 tooltip_text = _("Waiting to install");
3498 }
3499
3500-void SoftwareCenterLauncherIcon::Animate(nux::ObjectPtr<Launcher> launcher,
3501- int icon_x,
3502- int icon_y,
3503- int icon_size)
3504+void SoftwareCenterLauncherIcon::Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y)
3505 {
3506- int target_x = 0;
3507- int target_y = 0;
3508-
3509 launcher_ = launcher;
3510
3511 icon_texture_ = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(
3512@@ -72,30 +68,15 @@
3513
3514 drag_window_ = new LauncherDragWindow(icon_texture_);
3515
3516+ launcher->ForceReveal(true);
3517 launcher->RenderIconToTexture(nux::GetWindowThread()->GetGraphicsEngine(),
3518 AbstractLauncherIcon::Ptr(this),
3519 icon_texture_);
3520
3521- drag_window_->SetBaseXY(icon_x, icon_y);
3522+ auto const& icon_center = GetCenter(launcher->monitor());
3523+ drag_window_->SetBaseXY(start_x, start_y);
3524 drag_window_->ShowWindow(true);
3525-
3526- // Find out the center of last BamfLauncherIcon with non-zero co-ordinates
3527- auto bamf_icons = launcher->GetModel()->GetSublist<BamfLauncherIcon>();
3528- //TODO: don't iterate through them and pick the last one, just use back() to get the last one.
3529- for (auto current_bamf_icon : bamf_icons)
3530- {
3531- auto icon_center = current_bamf_icon->GetCenter(launcher->monitor);
3532-
3533- if (icon_center.x != 0 && icon_center.y != 0)
3534- {
3535- target_x = icon_center.x;
3536- target_y = icon_center.y;
3537- }
3538- }
3539-
3540- target_y = target_y + (launcher->GetIconSize() / 2);
3541- drag_window_->SetAnimationTarget(target_x, target_y);
3542-
3543+ drag_window_->SetAnimationTarget(icon_center.x, icon_center.y + (launcher->GetIconSize() / 2));
3544 drag_window_->on_anim_completed = drag_window_->anim_completed.connect(sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnDragAnimationFinished));
3545 drag_window_->StartAnimation();
3546 }
3547@@ -103,23 +84,29 @@
3548 void SoftwareCenterLauncherIcon::OnDragAnimationFinished()
3549 {
3550 drag_window_->ShowWindow(false);
3551- launcher_->icon_animation_complete.emit(AbstractLauncherIcon::Ptr(this));
3552 drag_window_ = nullptr;
3553+ launcher_->ForceReveal(false);
3554+ launcher_ = nullptr;
3555+ icon_texture_ = nullptr;
3556+ SetQuirk(Quirk::VISIBLE, true);
3557 }
3558
3559 void SoftwareCenterLauncherIcon::ActivateLauncherIcon(ActionArg arg)
3560 {
3561 if (finished_)
3562 {
3563- if (needs_urgent_)
3564- {
3565- SetQuirk(Quirk::URGENT, false);
3566- needs_urgent_ = false;
3567- }
3568- BamfLauncherIcon::ActivateLauncherIcon(arg);
3569+ if (needs_urgent_)
3570+ {
3571+ SetQuirk(Quirk::URGENT, false);
3572+ needs_urgent_ = false;
3573+ }
3574+
3575+ BamfLauncherIcon::ActivateLauncherIcon(arg);
3576 }
3577 else
3578- SetQuirk(Quirk::STARTING, false);
3579+ {
3580+ SetQuirk(Quirk::STARTING, false);
3581+ }
3582 }
3583
3584 void SoftwareCenterLauncherIcon::OnFinished(GVariant *params)
3585@@ -135,7 +122,9 @@
3586 SetProgress(0.0f);
3587 finished_ = true;
3588 needs_urgent_ = true;
3589- } else {
3590+ }
3591+ else
3592+ {
3593 // failure condition, remove icon again
3594 UnStick();
3595 }
3596@@ -167,7 +156,7 @@
3597
3598 std::string SoftwareCenterLauncherIcon::GetName() const
3599 {
3600- return "SoftwareCenterLauncherIcon";
3601+ return "SoftwareCenterLauncherIcon";
3602 }
3603
3604 }
3605
3606=== modified file 'launcher/SoftwareCenterLauncherIcon.h'
3607--- launcher/SoftwareCenterLauncherIcon.h 2012-07-25 03:11:05 +0000
3608+++ launcher/SoftwareCenterLauncherIcon.h 2012-09-18 15:51:21 +0000
3609@@ -42,7 +42,7 @@
3610 std::string const& aptdaemon_trans_id,
3611 std::string const& icon_path);
3612
3613- void Animate(nux::ObjectPtr<Launcher> launcher, int icon_x, int icon_y, int icon_size);
3614+ void Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y);
3615
3616 std::string GetName() const;
3617
3618
3619=== modified file 'launcher/SpacerLauncherIcon.cpp'
3620--- launcher/SpacerLauncherIcon.cpp 2012-08-02 13:16:06 +0000
3621+++ launcher/SpacerLauncherIcon.cpp 2012-09-18 15:51:21 +0000
3622@@ -28,7 +28,7 @@
3623 {
3624
3625 SpacerLauncherIcon::SpacerLauncherIcon(int monitor)
3626- : SingleMonitorLauncherIcon(IconType::APPLICATION, monitor)
3627+ : SingleMonitorLauncherIcon(IconType::SPACER, monitor)
3628 {
3629 SetQuirk(Quirk::VISIBLE, true);
3630 SetQuirk(Quirk::RUNNING, false);
3631
3632=== modified file 'launcher/SpacerLauncherIcon.h'
3633--- launcher/SpacerLauncherIcon.h 2012-05-07 19:52:54 +0000
3634+++ launcher/SpacerLauncherIcon.h 2012-09-18 15:51:21 +0000
3635@@ -32,10 +32,6 @@
3636 public:
3637 SpacerLauncherIcon(int monitor);
3638
3639- bool IsSpacer()
3640- {
3641- return true;
3642- }
3643 protected:
3644 std::string GetName() const;
3645 };
3646
3647=== modified file 'launcher/StandaloneLauncher.cpp'
3648--- launcher/StandaloneLauncher.cpp 2012-09-11 22:58:48 +0000
3649+++ launcher/StandaloneLauncher.cpp 2012-09-18 15:51:21 +0000
3650@@ -46,7 +46,7 @@
3651 void ThreadWidgetInit(nux::NThread* thread, void* InitData)
3652 {
3653 // launcherWindow->SetGeometry (nux::Geometry(0, 0, 300, 800));
3654- controller.reset(new launcher::Controller(0));
3655+ controller.reset(new launcher::Controller());
3656 }
3657
3658 int main(int argc, char** argv)
3659
3660=== modified file 'launcher/TrashLauncherIcon.cpp'
3661--- launcher/TrashLauncherIcon.cpp 2012-09-14 17:13:33 +0000
3662+++ launcher/TrashLauncherIcon.cpp 2012-09-18 15:51:21 +0000
3663@@ -46,6 +46,7 @@
3664 {
3665 tooltip_text = _("Trash");
3666 icon_name = "user-trash";
3667+ position = Position::END;
3668 SetQuirk(Quirk::VISIBLE, true);
3669 SetQuirk(Quirk::RUNNING, false);
3670 SetShortcut('t');
3671
3672=== modified file 'launcher/VolumeLauncherIcon.cpp'
3673--- launcher/VolumeLauncherIcon.cpp 2012-08-28 17:42:25 +0000
3674+++ launcher/VolumeLauncherIcon.cpp 2012-09-18 15:51:21 +0000
3675@@ -26,6 +26,7 @@
3676 #include "DevicesSettings.h"
3677 #include "Volume.h"
3678 #include "VolumeLauncherIcon.h"
3679+#include "FavoriteStore.h"
3680
3681 namespace unity
3682 {
3683@@ -36,7 +37,7 @@
3684
3685 nux::logging::Logger logger("unity.launcher");
3686
3687-const unsigned int volume_changed_timeout = 500;
3688+const unsigned int volume_changed_timeout = 500;
3689
3690 }
3691
3692@@ -61,7 +62,7 @@
3693 }
3694
3695 ~Impl()
3696- {
3697+ {
3698 volume_changed_conn_.disconnect();
3699 volume_removed_conn_.disconnect();
3700 settings_changed_conn_.disconnect();
3701@@ -83,7 +84,7 @@
3702
3703 void UpdateKeepInLauncher()
3704 {
3705- auto identifier = volume_->GetIdentifier();
3706+ auto const& identifier = volume_->GetIdentifier();
3707 keep_in_launcher_ = !devices_settings_->IsABlacklistedDevice(identifier);
3708 }
3709
3710@@ -104,6 +105,7 @@
3711 if (devices_settings_->IsABlacklistedDevice(volume_->GetIdentifier()))
3712 devices_settings_->TryToUnblacklist(volume_->GetIdentifier());
3713
3714+ parent_->UnStick();
3715 parent_->Remove();
3716 }
3717
3718@@ -163,7 +165,8 @@
3719 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
3720
3721 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
3722- auto identifier = volume_->GetIdentifier();
3723+ auto const& identifier = volume_->GetIdentifier();
3724+ parent_->UnStick();
3725 devices_settings_->TryToBlacklist(identifier);
3726 }));
3727
3728@@ -239,6 +242,16 @@
3729 menu.push_back(menu_item);
3730 }
3731
3732+ std::string GetRemoteUri()
3733+ {
3734+ auto const& identifier = volume_->GetIdentifier();
3735+
3736+ if (identifier.empty())
3737+ return "";
3738+
3739+ return FavoriteStore::URI_PREFIX_DEVICE + identifier;
3740+ }
3741+
3742 VolumeLauncherIcon* parent_;
3743 bool keep_in_launcher_;
3744 Volume::Ptr volume_;
3745@@ -293,6 +306,23 @@
3746 return pimpl_->GetMenus();
3747 }
3748
3749+std::string VolumeLauncherIcon::GetRemoteUri()
3750+{
3751+ return pimpl_->GetRemoteUri();
3752+}
3753+
3754+void VolumeLauncherIcon::Stick(bool save)
3755+{
3756+ SimpleLauncherIcon::Stick(save);
3757+ pimpl_->devices_settings_->TryToUnblacklist(pimpl_->volume_->GetIdentifier());
3758+}
3759+
3760+void VolumeLauncherIcon::UnStick()
3761+{
3762+ SimpleLauncherIcon::UnStick();
3763+ SetQuirk(Quirk::VISIBLE, true);
3764+}
3765+
3766 //
3767 // Introspection
3768 //
3769
3770=== modified file 'launcher/VolumeLauncherIcon.h'
3771--- launcher/VolumeLauncherIcon.h 2012-08-28 17:28:02 +0000
3772+++ launcher/VolumeLauncherIcon.h 2012-09-18 15:51:21 +0000
3773@@ -43,7 +43,10 @@
3774 void EjectAndShowNotification(); // TODO: rename to private virtual void DoDropToTrash();
3775 bool CanStop() const;
3776 void StopDrive();
3777+ void Stick(bool save = true);
3778+ void UnStick();
3779 MenuItemsVector GetMenus();
3780+ std::string GetRemoteUri();
3781
3782 protected:
3783 virtual void ActivateLauncherIcon(ActionArg arg);
3784
3785=== modified file 'manual-tests/Launcher.txt'
3786--- manual-tests/Launcher.txt 2012-09-18 01:41:46 +0000
3787+++ manual-tests/Launcher.txt 2012-09-18 15:51:21 +0000
3788@@ -191,6 +191,21 @@
3789 it, and the any pips for running apps show again.
3790
3791
3792+Dragging fixed icons does not reorder an icon above or below
3793+------------------------------------------------------------
3794+This test is about not reordering when dragging fixed icons.
3795+
3796+#. Move the mouse so it is over the BFB launcher icon
3797+#. Press and hold the mouse button
3798+#. Try to drag the icon to the right of the launcher.
3799+#. Move the mouse down at least to the height of the second launcher icon
3800+ keeping the mouse pressed.
3801+#. Release
3802+
3803+Outcome:
3804+ * No icon should be dragged.
3805+
3806+
3807 Dragged launcher icons out of the launcher are properly drawn
3808 -------------------------------------------------------------
3809 This test ensures that the launcher icons out of the launcher are properly drawn
3810
3811=== modified file 'panel/PanelMenuView.h'
3812--- panel/PanelMenuView.h 2012-08-22 04:30:28 +0000
3813+++ panel/PanelMenuView.h 2012-09-18 15:51:21 +0000
3814@@ -136,7 +136,6 @@
3815 glib::Object<BamfMatcher> _matcher;
3816
3817 nux::TextureLayer* _title_layer;
3818- nux::HLayout* _menu_layout;
3819 nux::ObjectPtr<WindowButtons> _window_buttons;
3820 nux::ObjectPtr<PanelTitlebarGrabArea> _titlebar_grab_area;
3821 nux::ObjectPtr<nux::BaseTexture> _title_texture;
3822
3823=== modified file 'plugins/unityshell/src/unityshell.cpp'
3824--- plugins/unityshell/src/unityshell.cpp 2012-09-18 01:41:46 +0000
3825+++ plugins/unityshell/src/unityshell.cpp 2012-09-18 15:51:21 +0000
3826@@ -267,7 +267,6 @@
3827 optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
3828 optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
3829 optionSetShortcutOverlayNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
3830- optionSetShowDesktopIconNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
3831 optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
3832 optionSetShowLauncherTerminate(boost::bind(&UnityScreen::showLauncherKeyTerminate, this, _1, _2, _3));
3833 optionSetKeyboardFocusInitiate(boost::bind(&UnityScreen::setKeyboardFocusKeyInitiate, this, _1, _2, _3));
3834@@ -2845,9 +2844,6 @@
3835 enable_shortcut_overlay_ = optionGetShortcutOverlay();
3836 shortcut_controller_->SetEnabled(enable_shortcut_overlay_);
3837 break;
3838- case UnityshellOptions::ShowDesktopIcon:
3839- launcher_controller_->SetShowDesktopIcon(optionGetShowDesktopIcon());
3840- break;
3841 case UnityshellOptions::DecayRate:
3842 launcher_options->edge_decay_rate = optionGetDecayRate() * 100;
3843 break;
3844@@ -2920,11 +2916,13 @@
3845 CompOption::Value& v)
3846 {
3847 bool status = screen->setOptionForPlugin(plugin, name, v);
3848+
3849 if (status)
3850 {
3851- if (strcmp(plugin, "core") == 0 && strcmp(name, "hsize") == 0)
3852+ if (strcmp(plugin, "core") == 0)
3853 {
3854- launcher_controller_->UpdateNumWorkspaces(screen->vpSize().width() * screen->vpSize().height());
3855+ if (strcmp(name, "hsize") == 0 || strcmp(name, "vsize") == 0)
3856+ launcher_controller_->UpdateNumWorkspaces(screen->vpSize().width() * screen->vpSize().height());
3857 }
3858 }
3859 return status;
3860@@ -2955,7 +2953,7 @@
3861 void UnityScreen::initLauncher()
3862 {
3863 Timer timer;
3864- launcher_controller_ = std::make_shared<launcher::Controller>(screen->dpy());
3865+ launcher_controller_ = std::make_shared<launcher::Controller>();
3866 AddChild(launcher_controller_.get());
3867
3868 switcher_controller_ = std::make_shared<switcher::Controller>();
3869
3870=== modified file 'plugins/unityshell/unityshell.xml.in'
3871--- plugins/unityshell/unityshell.xml.in 2012-08-17 14:44:05 +0000
3872+++ plugins/unityshell/unityshell.xml.in 2012-09-18 15:51:21 +0000
3873@@ -400,12 +400,6 @@
3874 <default>true</default>
3875 </option>
3876
3877- <option name="show_desktop_icon" type="bool">
3878- <_short>Show "Desktop Icon" in the launcher</_short>
3879- <_long>Enable/Disable "Show Desktop Icon" in the launcher.</_long>
3880- <default>false</default>
3881- </option>
3882-
3883 <option name="menus_fadein" type="int">
3884 <_short>Menus Fade-in duration</_short>
3885 <_long>Duration (in milliseconds) of the menus fade-in animation, used when the mouse goes over the top-panel.</_long>
3886
3887=== modified file 'tests/CMakeLists.txt'
3888--- tests/CMakeLists.txt 2012-09-17 14:07:30 +0000
3889+++ tests/CMakeLists.txt 2012-09-18 15:51:21 +0000
3890@@ -3,16 +3,16 @@
3891 #
3892 # Data
3893 #
3894-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/ubuntuone-installer.desktop
3895- ${CMAKE_BINARY_DIR}/tests/data/ubuntuone-installer.desktop)
3896-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/ubuntu-software-center.desktop
3897- ${CMAKE_BINARY_DIR}/tests/data/ubuntu-software-center.desktop)
3898-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/update-manager.desktop
3899- ${CMAKE_BINARY_DIR}/tests/data/update-manager.desktop)
3900-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/bzr-handle-patch.desktop
3901- ${CMAKE_BINARY_DIR}/tests/data/bzr-handle-patch.desktop)
3902-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/no-icon.desktop
3903- ${CMAKE_BINARY_DIR}/tests/data/no-icon.desktop)
3904+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/ubuntuone-installer.desktop
3905+ ${CMAKE_BINARY_DIR}/tests/data/applications/ubuntuone-installer.desktop)
3906+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/ubuntu-software-center.desktop
3907+ ${CMAKE_BINARY_DIR}/tests/data/applications/ubuntu-software-center.desktop)
3908+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/update-manager.desktop
3909+ ${CMAKE_BINARY_DIR}/tests/data/applications/update-manager.desktop)
3910+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/bzr-handle-patch.desktop
3911+ ${CMAKE_BINARY_DIR}/tests/data/applications/bzr-handle-patch.desktop)
3912+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/no-icon.desktop
3913+ ${CMAKE_BINARY_DIR}/tests/data/applications/no-icon.desktop)
3914 #
3915 # Unit tests
3916 #
3917@@ -136,6 +136,7 @@
3918 test_indicator_entry.cpp
3919 test_indicators.cpp
3920 test_introspection.cpp
3921+ test_favorite_store.cpp
3922 test_favorite_store_gsettings.cpp
3923 test_favorite_store_private.cpp
3924 test_home_lens.cpp
3925@@ -200,20 +201,23 @@
3926 # Tests that require X
3927 add_executable(test-gtest
3928 test_main.cpp
3929- test_bamflaunchericon.cpp
3930+ test_bamf_launcher_icon.cpp
3931 test_bfb_launcher_icon.cpp
3932 test_dashview_impl.cpp
3933+ test_desktop_launcher_icon.cpp
3934 test_edge_barrier_controller.cpp
3935 test_launcher.cpp
3936 test_device_launcher_section.cpp
3937 test_lensview_impl.cpp
3938 test_hud_button.cpp
3939 test_hud_controller.cpp
3940+ test_hud_launcher_icon.cpp
3941 test_hud_view.cpp
3942 test_icon_loader.cpp
3943 test_im_text_entry.cpp
3944 test_launcher_controller.cpp
3945 test_launcher_drag_window.cpp
3946+ test_launcher_icon.cpp
3947 test_keyboard_util.cpp
3948 test_panel_style.cpp
3949 test_previews_application.cpp
3950@@ -226,10 +230,13 @@
3951 test_resultviewgrid.cpp
3952 test_shortcut_controller.cpp
3953 test_single_monitor_launcher_icon.cpp
3954+ test_software_center_launcher_icon.cpp
3955+ test_expo_launcher_icon.cpp
3956 test_switcher_controller.cpp
3957 test_switcher_model.cpp
3958 test_texture_cache.cpp
3959 test_thumbnail_generator.cpp
3960+ test_trash_launcher_icon.cpp
3961 test_launcher_minimize_speed.cpp
3962 test_volume_imp.cpp
3963 test_volume_launcher_icon.cpp
3964@@ -273,6 +280,7 @@
3965 ${CMAKE_SOURCE_DIR}/launcher/DevicesSettingsImp.cpp
3966 ${CMAKE_SOURCE_DIR}/launcher/DndData.cpp
3967 ${CMAKE_SOURCE_DIR}/launcher/EdgeBarrierController.cpp
3968+ ${CMAKE_SOURCE_DIR}/launcher/ExpoLauncherIcon.cpp
3969 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStore.cpp
3970 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStoreGSettings.cpp
3971 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp
3972
3973=== added directory 'tests/data/applications'
3974=== renamed file 'tests/data/bzr-handle-patch.desktop' => 'tests/data/applications/bzr-handle-patch.desktop'
3975=== renamed file 'tests/data/no-icon.desktop' => 'tests/data/applications/no-icon.desktop'
3976=== renamed file 'tests/data/ubuntu-software-center.desktop' => 'tests/data/applications/ubuntu-software-center.desktop'
3977=== renamed file 'tests/data/ubuntuone-installer.desktop' => 'tests/data/applications/ubuntuone-installer.desktop'
3978=== renamed file 'tests/data/update-manager.desktop' => 'tests/data/applications/update-manager.desktop'
3979=== modified file 'tests/gmockvolume.c'
3980--- tests/gmockvolume.c 2012-08-22 09:55:18 +0000
3981+++ tests/gmockvolume.c 2012-09-18 15:51:21 +0000
3982@@ -83,9 +83,10 @@
3983 static void
3984 g_mock_volume_init (GMockVolume *mock_volume)
3985 {
3986- mock_volume->name = g_strdup("");
3987+ guint32 uuid = g_random_int();
3988+ mock_volume->name = g_strdup_printf("MockVolume %u", uuid);
3989 mock_volume->icon = g_icon_new_for_string("", NULL);
3990- mock_volume->uuid = g_strdup("");
3991+ mock_volume->uuid = g_strdup_printf("%u", uuid);
3992 mock_volume->mount = NULL;
3993 }
3994
3995
3996=== renamed file 'tests/test_bamflaunchericon.cpp' => 'tests/test_bamf_launcher_icon.cpp'
3997--- tests/test_bamflaunchericon.cpp 2012-07-16 20:05:59 +0000
3998+++ tests/test_bamf_launcher_icon.cpp 2012-09-18 15:51:21 +0000
3999@@ -23,16 +23,19 @@
4000 #include <gmock/gmock.h>
4001
4002 #include <UnityCore/GLibWrapper.h>
4003+#include <UnityCore/DesktopUtilities.h>
4004
4005 #include "BamfLauncherIcon.h"
4006+#include "FavoriteStore.h"
4007
4008 using namespace unity;
4009+using namespace unity::launcher;
4010
4011 namespace
4012 {
4013
4014-const std::string USC_DESKTOP = BUILDDIR"/tests/data/ubuntu-software-center.desktop";
4015-const std::string NO_ICON_DESKTOP = BUILDDIR"/tests/data/no-icon.desktop";
4016+const std::string USC_DESKTOP = BUILDDIR"/tests/data/applications/ubuntu-software-center.desktop";
4017+const std::string NO_ICON_DESKTOP = BUILDDIR"/tests/data/applications/no-icon.desktop";
4018
4019 class TestBamfLauncherIcon : public testing::Test
4020 {
4021@@ -61,6 +64,11 @@
4022 nux::ObjectPtr<launcher::BamfLauncherIcon> empty_app;
4023 };
4024
4025+TEST_F(TestBamfLauncherIcon, Position)
4026+{
4027+ EXPECT_EQ(usc_icon->position(), AbstractLauncherIcon::Position::FLOATING);
4028+}
4029+
4030 TEST_F(TestBamfLauncherIcon, TestCustomBackgroundColor)
4031 {
4032 nux::Color const& color = usc_icon->BackgroundColor();
4033@@ -78,4 +86,64 @@
4034 EXPECT_EQ(empty_app->icon_name.Get(), "application-default-icon");
4035 }
4036
4037+TEST_F(TestBamfLauncherIcon, Stick)
4038+{
4039+ BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
4040+ ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
4041+
4042+ bool saved = false;
4043+ usc_icon->position_saved.connect([&saved] {saved = true;});
4044+
4045+ usc_icon->Stick(false);
4046+ EXPECT_TRUE(bamf_view_is_sticky(bamf_app));
4047+ EXPECT_TRUE(usc_icon->IsSticky());
4048+ EXPECT_TRUE(usc_icon->IsVisible());
4049+ EXPECT_FALSE(saved);
4050+
4051+ usc_icon->Stick(true);
4052+ EXPECT_FALSE(saved);
4053+ bamf_view_set_sticky(bamf_app, FALSE);
4054+}
4055+
4056+TEST_F(TestBamfLauncherIcon, StickAndSave)
4057+{
4058+ BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
4059+ ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
4060+
4061+ bool saved = false;
4062+ usc_icon->position_saved.connect([&saved] {saved = true;});
4063+
4064+ usc_icon->Stick(true);
4065+ EXPECT_TRUE(bamf_view_is_sticky(bamf_app));
4066+ EXPECT_TRUE(usc_icon->IsSticky());
4067+ EXPECT_TRUE(usc_icon->IsVisible());
4068+ EXPECT_TRUE(saved);
4069+ bamf_view_set_sticky(bamf_app, FALSE);
4070+}
4071+
4072+TEST_F(TestBamfLauncherIcon, Unstick)
4073+{
4074+ BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
4075+ ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
4076+
4077+ bool forgot = false;
4078+ usc_icon->position_forgot.connect([&forgot] {forgot = true;});
4079+
4080+ usc_icon->Stick(false);
4081+ ASSERT_TRUE(bamf_view_is_sticky(bamf_app));
4082+ ASSERT_TRUE(usc_icon->IsSticky());
4083+
4084+ usc_icon->UnStick();
4085+ EXPECT_FALSE(bamf_view_is_sticky(bamf_app));
4086+ EXPECT_FALSE(usc_icon->IsSticky());
4087+ EXPECT_FALSE(usc_icon->IsVisible());
4088+ EXPECT_TRUE(forgot);
4089+}
4090+
4091+TEST_F(TestBamfLauncherIcon, RemoteUri)
4092+{
4093+ EXPECT_EQ(usc_icon->RemoteUri(), FavoriteStore::URI_PREFIX_APP + DesktopUtilities::GetDesktopID(USC_DESKTOP));
4094+ EXPECT_TRUE(empty_app->RemoteUri().empty());
4095+}
4096+
4097 }
4098
4099=== modified file 'tests/test_bfb_launcher_icon.cpp'
4100--- tests/test_bfb_launcher_icon.cpp 2012-08-14 15:13:19 +0000
4101+++ tests/test_bfb_launcher_icon.cpp 2012-09-18 15:51:21 +0000
4102@@ -33,18 +33,21 @@
4103 MockBFBLauncherIcon()
4104 : BFBLauncherIcon(LauncherHideMode::LAUNCHER_HIDE_NEVER)
4105 {}
4106-
4107- AbstractLauncherIcon::MenuItemsVector GetMenus()
4108- {
4109- return BFBLauncherIcon::GetMenus();
4110- }
4111 };
4112
4113-TEST(TestBFBLauncherIcon, OverlayMenus)
4114+struct TestBFBLauncherIcon : testing::Test
4115 {
4116 MockBFBLauncherIcon bfb;
4117-
4118- for (auto menu_item : bfb.GetMenus())
4119+};
4120+
4121+TEST_F(TestBFBLauncherIcon, Position)
4122+{
4123+ EXPECT_EQ(bfb.position, AbstractLauncherIcon::Position::BEGIN);
4124+}
4125+
4126+TEST_F(TestBFBLauncherIcon, OverlayMenus)
4127+{
4128+ for (auto menu_item : bfb.Menus())
4129 {
4130 bool overlay_item = dbusmenu_menuitem_property_get_bool(menu_item, QuicklistMenuItem::OVERLAY_MENU_ITEM_PROPERTY);
4131 ASSERT_TRUE(overlay_item);
4132
4133=== added file 'tests/test_desktop_launcher_icon.cpp'
4134--- tests/test_desktop_launcher_icon.cpp 1970-01-01 00:00:00 +0000
4135+++ tests/test_desktop_launcher_icon.cpp 2012-09-18 15:51:21 +0000
4136@@ -0,0 +1,80 @@
4137+/*
4138+ * Copyright 2012 Canonical Ltd.
4139+ *
4140+ * This program is free software: you can redistribute it and/or modify it
4141+ * under the terms of the GNU General Public License version 3, as published
4142+ * by the Free Software Foundation.
4143+ *
4144+ * This program is distributed in the hope that it will be useful, but
4145+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4146+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4147+ * PURPOSE. See the GNU General Public License for more details.
4148+ *
4149+ * You should have received a copy of the GNU General Public License
4150+ * version 3 along with this program. If not, see
4151+ * <http://www.gnu.org/licenses/>
4152+ *
4153+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
4154+ */
4155+
4156+#include <gmock/gmock.h>
4157+
4158+#include "PluginAdapter.h"
4159+#include "DesktopLauncherIcon.h"
4160+
4161+using namespace unity;
4162+using namespace unity::launcher;
4163+
4164+namespace
4165+{
4166+
4167+struct TestDesktopLauncherIcon : testing::Test
4168+{
4169+ DesktopLauncherIcon icon;
4170+};
4171+
4172+TEST_F(TestDesktopLauncherIcon, Type)
4173+{
4174+ EXPECT_EQ(icon.GetIconType(), AbstractLauncherIcon::IconType::DESKTOP);
4175+}
4176+
4177+TEST_F(TestDesktopLauncherIcon, Shortcut)
4178+{
4179+ EXPECT_EQ(icon.GetShortcut(), 'd');
4180+}
4181+
4182+TEST_F(TestDesktopLauncherIcon, Position)
4183+{
4184+ EXPECT_EQ(icon.position(), AbstractLauncherIcon::Position::FLOATING);
4185+}
4186+
4187+TEST_F(TestDesktopLauncherIcon, ActivateToggleShowDesktop)
4188+{
4189+ auto plugin_adapter = PluginAdapter::Default();
4190+
4191+ ASSERT_FALSE(plugin_adapter->InShowDesktop());
4192+
4193+ icon.Activate(ActionArg());
4194+ ASSERT_TRUE(plugin_adapter->InShowDesktop());
4195+
4196+ icon.Activate(ActionArg());
4197+ EXPECT_FALSE(plugin_adapter->InShowDesktop());
4198+}
4199+
4200+TEST_F(TestDesktopLauncherIcon, ShowInSwitcher)
4201+{
4202+ EXPECT_TRUE(icon.ShowInSwitcher(false));
4203+ EXPECT_TRUE(icon.ShowInSwitcher(true));
4204+
4205+ icon.SetShowInSwitcher(false);
4206+
4207+ EXPECT_FALSE(icon.ShowInSwitcher(false));
4208+ EXPECT_FALSE(icon.ShowInSwitcher(true));
4209+}
4210+
4211+TEST_F(TestDesktopLauncherIcon, RemoteUri)
4212+{
4213+ EXPECT_EQ(icon.RemoteUri(), "unity://desktop-icon");
4214+}
4215+
4216+}
4217
4218=== modified file 'tests/test_desktop_utilities.cpp'
4219--- tests/test_desktop_utilities.cpp 2012-06-01 09:33:15 +0000
4220+++ tests/test_desktop_utilities.cpp 2012-09-18 15:51:21 +0000
4221@@ -30,7 +30,9 @@
4222 using testing::Eq;
4223
4224 namespace {
4225-
4226+
4227+const std::string LOCAL_DATA_DIR = BUILDDIR"/tests/data";
4228+
4229 TEST(TestDesktopUtilitiesDesktopID, TestEmptyValues)
4230 {
4231 std::vector<std::string> empty_list;
4232@@ -88,71 +90,99 @@
4233 Eq("subdir-to.desktop"));
4234 EXPECT_THAT(DesktopUtilities::GetDesktopID(dirs, "/this/path/applications/subdir1/subdir2/to.desktop"),
4235 Eq("subdir1-subdir2-to.desktop"));
4236+ EXPECT_THAT(DesktopUtilities::GetDesktopID(dirs, "/this/path/applications/subdir1/subdir2-to.desktop"),
4237+ Eq("subdir1-subdir2-to.desktop"));
4238 }
4239
4240 TEST(TestDesktopUtilitiesDataDirectories, TestGetUserDataDirectory)
4241 {
4242- const gchar* old_home = g_getenv("XDG_DATA_HOME");
4243+ const gchar* env = g_getenv("XDG_DATA_HOME");
4244+ std::string old_home = env ? env : "";
4245+
4246 g_setenv("XDG_DATA_HOME", "UnityUserConfig", TRUE);
4247
4248 std::string const& user_data_dir = DesktopUtilities::GetUserDataDirectory();
4249
4250- g_setenv("XDG_DATA_HOME", old_home, TRUE);
4251+ g_setenv("XDG_DATA_HOME", old_home.c_str(), TRUE);
4252
4253 EXPECT_THAT(user_data_dir, Eq("UnityUserConfig"));
4254 }
4255
4256 TEST(TestDesktopUtilitiesDataDirectories, TestGetSystemDataDirectory)
4257 {
4258- const gchar* old_dirs = g_getenv("XDG_DATA_DIRS");
4259- g_setenv("XDG_DATA_DIRS", "dir1:dir2::dir3:dir4", TRUE);
4260+ const gchar* env = g_getenv("XDG_DATA_DIRS");
4261+ std::string old_dirs = env ? env : "";
4262+ g_setenv("XDG_DATA_DIRS", ("dir1:dir2::dir3:dir4:"+LOCAL_DATA_DIR).c_str(), TRUE);
4263
4264 std::vector<std::string> const& system_dirs = DesktopUtilities::GetSystemDataDirectories();
4265
4266- g_setenv("XDG_DATA_DIRS", old_dirs, TRUE);
4267+ g_setenv("XDG_DATA_DIRS", old_dirs.c_str(), TRUE);
4268
4269- ASSERT_THAT(system_dirs.size(), Eq(4));
4270+ ASSERT_THAT(system_dirs.size(), Eq(5));
4271 EXPECT_THAT(system_dirs[0], Eq("dir1"));
4272 EXPECT_THAT(system_dirs[1], Eq("dir2"));
4273 EXPECT_THAT(system_dirs[2], Eq("dir3"));
4274 EXPECT_THAT(system_dirs[3], Eq("dir4"));
4275+ EXPECT_THAT(system_dirs[4], Eq(LOCAL_DATA_DIR));
4276 }
4277
4278 TEST(TestDesktopUtilitiesDataDirectories, TestGetDataDirectory)
4279 {
4280- const gchar* old_dirs = g_getenv("XDG_DATA_DIRS");
4281- g_setenv("XDG_DATA_DIRS", "dir1:dir2::dir3:dir4", TRUE);
4282- const gchar* old_home = g_getenv("XDG_DATA_HOME");
4283+ const gchar* env = g_getenv("XDG_DATA_DIRS");
4284+ std::string old_dirs = env ? env : "";
4285+ env = g_getenv("XDG_DATA_HOME");
4286+ std::string old_home = env ? env : "";
4287+
4288+ g_setenv("XDG_DATA_DIRS", ("dir1:dir2::dir3:dir4:"+LOCAL_DATA_DIR).c_str(), TRUE);
4289 g_setenv("XDG_DATA_HOME", "UnityUserConfig", TRUE);
4290
4291 std::vector<std::string> const& data_dirs = DesktopUtilities::GetDataDirectories();
4292
4293- g_setenv("XDG_DATA_DIRS", old_dirs, TRUE);
4294- g_setenv("XDG_DATA_HOME", old_home, TRUE);
4295+ g_setenv("XDG_DATA_DIRS", old_dirs.c_str(), TRUE);
4296+ g_setenv("XDG_DATA_HOME", old_home.c_str(), TRUE);
4297
4298- ASSERT_THAT(data_dirs.size(), Eq(5));
4299+ ASSERT_THAT(data_dirs.size(), Eq(6));
4300 EXPECT_THAT(data_dirs[0], Eq("dir1"));
4301 EXPECT_THAT(data_dirs[1], Eq("dir2"));
4302 EXPECT_THAT(data_dirs[2], Eq("dir3"));
4303 EXPECT_THAT(data_dirs[3], Eq("dir4"));
4304- EXPECT_THAT(data_dirs[4], Eq("UnityUserConfig"));
4305-}
4306-
4307-TEST(TestDesktopUtilitiesDataDirectories, TestGetBackgroundColor)
4308-{
4309- std::string const& color = DesktopUtilities::GetBackgroundColor(BUILDDIR"/tests/data/ubuntu-software-center.desktop");
4310+ EXPECT_THAT(data_dirs[4], Eq(LOCAL_DATA_DIR));
4311+ EXPECT_THAT(data_dirs[5], Eq("UnityUserConfig"));
4312+}
4313+
4314+TEST(TestDesktopUtilities, TestGetDesktopPathById)
4315+{
4316+ const gchar* env = g_getenv("XDG_DATA_DIRS");
4317+ std::string old_dirs = env ? env : "";
4318+ env = g_getenv("XDG_DATA_HOME");
4319+ std::string old_home = env ? env : "";
4320+
4321+ g_setenv("XDG_DATA_DIRS", LOCAL_DATA_DIR.c_str(), TRUE);
4322+ g_setenv("XDG_DATA_HOME", "UnityUserConfig", TRUE);
4323+
4324+ std::string const& file = DesktopUtilities::GetDesktopPathById("ubuntu-software-center.desktop");
4325+
4326+ g_setenv("XDG_DATA_DIRS", old_dirs.c_str(), TRUE);
4327+ g_setenv("XDG_DATA_HOME", old_dirs.c_str(), TRUE);
4328+
4329+ EXPECT_EQ(file, LOCAL_DATA_DIR + "/applications/ubuntu-software-center.desktop");
4330+}
4331+
4332+TEST(TestDesktopUtilities, TestGetBackgroundColor)
4333+{
4334+ std::string const& color = DesktopUtilities::GetBackgroundColor(LOCAL_DATA_DIR+"/applications/ubuntu-software-center.desktop");
4335
4336 EXPECT_EQ(color, "#aabbcc");
4337 }
4338
4339-TEST(TestDesktopUtilitiesDataDirectories, TestGetBackgroundColorNoKey)
4340+TEST(TestDesktopUtilities, TestGetBackgroundColorNoKey)
4341 {
4342- std::string const& color = DesktopUtilities::GetBackgroundColor(BUILDDIR"/tests/data/update-manager.desktop");
4343+ std::string const& color = DesktopUtilities::GetBackgroundColor(LOCAL_DATA_DIR+"/applications/update-manager.desktop");
4344
4345 EXPECT_TRUE(color.empty());
4346 }
4347
4348-TEST(TestDesktopUtilitiesDataDirectories, TestGetBackgroundColorNoFile)
4349+TEST(TestDesktopUtilities, TestGetBackgroundColorNoFile)
4350 {
4351 std::string const& color = DesktopUtilities::GetBackgroundColor("hello-world.desktop");
4352
4353
4354=== modified file 'tests/test_device_launcher_section.cpp'
4355--- tests/test_device_launcher_section.cpp 2012-08-17 15:53:06 +0000
4356+++ tests/test_device_launcher_section.cpp 2012-09-18 15:51:21 +0000
4357@@ -21,17 +21,16 @@
4358 */
4359
4360 #include <gmock/gmock.h>
4361+
4362+#include "DevicesSettings.h"
4363+#include "test_mock_devices.h"
4364+#include "test_utils.h"
4365+
4366 using namespace testing;
4367-
4368-#include "DeviceLauncherSection.h"
4369-#include "DevicesSettings.h"
4370-#include "AbstractVolumeMonitorWrapper.h"
4371-using namespace unity;
4372 using namespace unity::launcher;
4373
4374-#include "gmockvolume.h"
4375-#include "test_utils.h"
4376-
4377+namespace unity
4378+{
4379 namespace
4380 {
4381
4382@@ -50,72 +49,38 @@
4383 bool icon_added;
4384 };
4385
4386-class MockVolumeMonitorWrapper : public AbstractVolumeMonitorWrapper
4387-{
4388-public:
4389- typedef std::shared_ptr<MockVolumeMonitorWrapper> Ptr;
4390-
4391- MockVolumeMonitorWrapper()
4392- : volume1(G_VOLUME(g_mock_volume_new()))
4393- , volume2(G_VOLUME(g_mock_volume_new()))
4394- {
4395- }
4396-
4397- VolumeList GetVolumes()
4398- {
4399- VolumeList ret;
4400-
4401- ret.push_back(volume1);
4402- ret.push_back(volume2);
4403-
4404- return ret;
4405- }
4406-
4407- glib::Object<GVolume> volume1;
4408- glib::Object<GVolume> volume2;
4409-};
4410-
4411-class MockDevicesSettings : public DevicesSettings
4412-{
4413- MOCK_CONST_METHOD1(IsABlacklistedDevice, bool(std::string const& uuid));
4414- MOCK_METHOD1(TryToBlacklist, void(std::string const& uuid));
4415- MOCK_METHOD1(TryToUnblacklist, void(std::string const& uuid));
4416-};
4417-
4418-class TestDeviceLauncherSection : public Test
4419-{
4420-public:
4421+struct TestDeviceLauncherSection : Test
4422+{
4423 TestDeviceLauncherSection()
4424 : monitor_(new MockVolumeMonitorWrapper)
4425 , devices_settings_(new MockDevicesSettings)
4426 , section_(monitor_, devices_settings_)
4427 {}
4428
4429- void SetUp()
4430- {
4431- // Make sure PopulateEntries is called.
4432- Utils::WaitForTimeoutMSec(1500);
4433- }
4434-
4435 MockVolumeMonitorWrapper::Ptr monitor_;
4436 DevicesSettings::Ptr devices_settings_;
4437 DeviceLauncherSection section_;
4438 };
4439
4440-
4441-TEST_F(TestDeviceLauncherSection, TestNoDuplicates)
4442+TEST_F(TestDeviceLauncherSection, NoDuplicates)
4443 {
4444 std::shared_ptr<EventListener> listener(new EventListener);
4445- section_.IconAdded.connect(sigc::mem_fun(*listener, &EventListener::OnIconAdded));
4446+ section_.icon_added.connect(sigc::mem_fun(*listener, &EventListener::OnIconAdded));
4447
4448 // Emit the signal volume_added for each volume.
4449- monitor_->volume_added.emit(monitor_->volume1);
4450- monitor_->volume_added.emit(monitor_->volume2);
4451+ monitor_->volume_added.emit(*(std::next(monitor_->volumes_.begin(), 0)));
4452+ monitor_->volume_added.emit(*(std::next(monitor_->volumes_.begin(), 1)));
4453
4454 Utils::WaitForTimeoutMSec(500);
4455
4456 EXPECT_EQ(listener->icon_added, false);
4457 }
4458
4459+TEST_F(TestDeviceLauncherSection, GetIcons)
4460+{
4461+ EXPECT_EQ(section_.GetIcons().size(), 2);
4462+}
4463+
4464+}
4465 }
4466
4467
4468=== added file 'tests/test_expo_launcher_icon.cpp'
4469--- tests/test_expo_launcher_icon.cpp 1970-01-01 00:00:00 +0000
4470+++ tests/test_expo_launcher_icon.cpp 2012-09-18 15:51:21 +0000
4471@@ -0,0 +1,58 @@
4472+/*
4473+ * Copyright 2012 Canonical Ltd.
4474+ *
4475+ * This program is free software: you can redistribute it and/or modify it
4476+ * under the terms of the GNU General Public License version 3, as published
4477+ * by the Free Software Foundation.
4478+ *
4479+ * This program is distributed in the hope that it will be useful, but
4480+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4481+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4482+ * PURPOSE. See the GNU General Public License for more details.
4483+ *
4484+ * You should have received a copy of the GNU General Public License
4485+ * version 3 along with this program. If not, see
4486+ * <http://www.gnu.org/licenses/>
4487+ *
4488+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
4489+ */
4490+
4491+#include <gmock/gmock.h>
4492+
4493+#include "ExpoLauncherIcon.h"
4494+#include "PluginAdapter.h"
4495+
4496+using namespace unity;
4497+using namespace unity::launcher;
4498+
4499+namespace
4500+{
4501+struct TestExpoLauncherIcon : testing::Test
4502+{
4503+ ExpoLauncherIcon icon;
4504+};
4505+
4506+TEST_F(TestExpoLauncherIcon, ActivateToggleExpo)
4507+{
4508+ auto plugin_adapter = PluginAdapter::Default();
4509+
4510+ ASSERT_FALSE(plugin_adapter->IsExpoActive());
4511+
4512+ icon.Activate(ActionArg());
4513+ ASSERT_TRUE(plugin_adapter->IsExpoActive());
4514+
4515+ icon.Activate(ActionArg());
4516+ EXPECT_FALSE(plugin_adapter->IsExpoActive());
4517+}
4518+
4519+TEST_F(TestExpoLauncherIcon, Position)
4520+{
4521+ EXPECT_EQ(icon.position(), AbstractLauncherIcon::Position::FLOATING);
4522+}
4523+
4524+TEST_F(TestExpoLauncherIcon, RemoteUri)
4525+{
4526+ EXPECT_EQ(icon.RemoteUri(), "unity://expo-icon");
4527+}
4528+
4529+}
4530
4531=== added file 'tests/test_favorite_store.cpp'
4532--- tests/test_favorite_store.cpp 1970-01-01 00:00:00 +0000
4533+++ tests/test_favorite_store.cpp 2012-09-18 15:51:21 +0000
4534@@ -0,0 +1,111 @@
4535+/*
4536+ * Copyright 2012 Canonical Ltd.
4537+ *
4538+ * This program is free software: you can redistribute it and/or modify it
4539+ * under the terms of the GNU General Public License version 3, as published
4540+ * by the Free Software Foundation.
4541+ *
4542+ * This program is distributed in the hope that it will be useful, but
4543+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4544+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4545+ * PURPOSE. See the GNU General Public License for more details.
4546+ *
4547+ * You should have received a copy of the GNU General Public License
4548+ * version 3 along with this program. If not, see
4549+ * <http://www.gnu.org/licenses/>
4550+ *
4551+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
4552+ */
4553+
4554+#include <gmock/gmock.h>
4555+#include <config.h>
4556+
4557+#include "FavoriteStore.h"
4558+
4559+using namespace unity;
4560+
4561+namespace
4562+{
4563+class MockFavoriteStore : public FavoriteStore
4564+{
4565+public:
4566+ FavoriteList const& GetFavorites() const { return fav_list_; }
4567+ void AddFavorite(std::string const& icon_uri, int position) {}
4568+ void RemoveFavorite(std::string const& icon_uri) {}
4569+ void MoveFavorite(std::string const& icon_uri, int position) {}
4570+ bool IsFavorite(std::string const& icon_uri) const { return false; }
4571+ int FavoritePosition(std::string const& icon_uri) const { return -1; }
4572+ void SetFavorites(FavoriteList const& icon_uris) {}
4573+
4574+ std::string ParseFavoriteFromUri(std::string const& uri) const
4575+ {
4576+ return FavoriteStore::ParseFavoriteFromUri(uri);
4577+ }
4578+
4579+private:
4580+ FavoriteList fav_list_;
4581+};
4582+
4583+struct TestFavoriteStore : public testing::Test
4584+{
4585+ MockFavoriteStore favorite_store;
4586+};
4587+
4588+TEST_F(TestFavoriteStore, Construction)
4589+{
4590+ FavoriteStore& instance = FavoriteStore::Instance();
4591+ EXPECT_EQ(&instance, &favorite_store);
4592+}
4593+
4594+TEST_F(TestFavoriteStore, UriPrefixes)
4595+{
4596+ EXPECT_EQ(FavoriteStore::URI_PREFIX_APP, "application://");
4597+ EXPECT_EQ(FavoriteStore::URI_PREFIX_FILE, "file://");
4598+ EXPECT_EQ(FavoriteStore::URI_PREFIX_DEVICE, "device://");
4599+ EXPECT_EQ(FavoriteStore::URI_PREFIX_UNITY, "unity://");
4600+}
4601+
4602+TEST_F(TestFavoriteStore, IsValidFavoriteUri)
4603+{
4604+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri(""));
4605+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("invalid-favorite"));
4606+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("/path/to/desktop_file"));
4607+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("desktop_file"));
4608+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("file:///path/to/desktop_file"));
4609+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("application://desktop_file"));
4610+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("application://"));
4611+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("device://"));
4612+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("unity://"));
4613+
4614+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("device://uuid"));
4615+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("file:///path/to/desktop_file.desktop"));
4616+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("application://desktop_file.desktop"));
4617+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("device://a"));
4618+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("unity://b"));
4619+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("application://c.desktop"));
4620+}
4621+
4622+TEST_F(TestFavoriteStore, ParseFavoriteFromUri)
4623+{
4624+ const std::string VALID_DESKTOP_PATH = BUILDDIR"/tests/data/applications/ubuntu-software-center.desktop";
4625+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("file.desktop"), "application://file.desktop");
4626+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri(VALID_DESKTOP_PATH), "application://"+VALID_DESKTOP_PATH);
4627+
4628+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("application://file.desktop"), "application://file.desktop");
4629+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("application://"+VALID_DESKTOP_PATH), "application://"+VALID_DESKTOP_PATH);
4630+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("file://"+VALID_DESKTOP_PATH), "file://"+VALID_DESKTOP_PATH);
4631+
4632+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("unity://uri"), "unity://uri");
4633+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("device://uuid"), "device://uuid");
4634+
4635+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("file").empty());
4636+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("/path/to/file").empty());
4637+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("/path/to/file.desktop").empty());
4638+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("application:///path/to/file.desktop").empty());
4639+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("file:///path/to/file.desktop").empty());
4640+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("file://file.desktop").empty());
4641+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("unity://").empty());
4642+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("device://").empty());
4643+}
4644+
4645+}
4646
4647=== modified file 'tests/test_favorite_store_gsettings.cpp'
4648--- tests/test_favorite_store_gsettings.cpp 2012-08-02 12:13:38 +0000
4649+++ tests/test_favorite_store_gsettings.cpp 2012-09-18 15:51:21 +0000
4650@@ -21,18 +21,12 @@
4651
4652 #include <config.h>
4653
4654-#include <algorithm>
4655-#include <memory>
4656-#include <string>
4657-
4658-#define G_SETTINGS_ENABLE_BACKEND
4659-#include <gio/gsettingsbackend.h>
4660 #include <gmock/gmock.h>
4661 #include <glib.h>
4662
4663 #include "FavoriteStore.h"
4664 #include "FavoriteStoreGSettings.h"
4665-#include "FavoriteStorePrivate.h"
4666+
4667 #include <UnityCore/GLibWrapper.h>
4668
4669 using namespace unity;
4670@@ -45,14 +39,16 @@
4671 const gchar* SETTINGS_KEY = "favorites";
4672 const gchar* SCHEMA_DIRECTORY = BUILDDIR"/settings";
4673
4674-const char* base_store_favs[] = { BUILDDIR"/tests/data/ubuntuone-installer.desktop",
4675- BUILDDIR"/tests/data/ubuntu-software-center.desktop",
4676- BUILDDIR"/tests/data/update-manager.desktop",
4677+const char* base_store_favs[] = { BUILDDIR"/tests/data/applications/ubuntuone-installer.desktop",
4678+ "file://" BUILDDIR "/tests/data/applications/ubuntu-software-center.desktop",
4679+ "application://" BUILDDIR "/tests/data/applications/update-manager.desktop",
4680+ "unity://test-icon",
4681+ "device://uuid",
4682 NULL
4683 };
4684 const int n_base_store_favs = G_N_ELEMENTS(base_store_favs) - 1; /* NULL */
4685
4686-const std::string other_desktop = BUILDDIR"/tests/data/bzr-handle-patch.desktop";
4687+const std::string other_desktop = "application://" BUILDDIR "/tests/data/applications/bzr-handle-patch.desktop";
4688
4689 // Utilities
4690 std::string const& at(FavoriteList const& favs, int index)
4691@@ -110,9 +106,9 @@
4692 FavoriteList const& favs = settings.GetFavorites();
4693
4694 ASSERT_EQ(favs.size(), n_base_store_favs);
4695- EXPECT_TRUE(ends_with(at(favs, 0), base_store_favs[0]));
4696+ EXPECT_TRUE(ends_with(at(favs, 0), FavoriteStore::URI_PREFIX_APP+base_store_favs[0]));
4697 EXPECT_TRUE(ends_with(at(favs, 1), base_store_favs[1]));
4698- EXPECT_TRUE(at(favs, 2) == base_store_favs[2]);
4699+ EXPECT_EQ(at(favs, 2), base_store_favs[2]);
4700 }
4701
4702 TEST_F(TestFavoriteStoreGSettings, TestAddFavorite)
4703@@ -122,7 +118,7 @@
4704 settings.AddFavorite(other_desktop, 0);
4705 FavoriteList const& favs = settings.GetFavorites();
4706 ASSERT_EQ(favs.size(), n_base_store_favs + 1);
4707- EXPECT_TRUE(other_desktop == at(favs, 0));
4708+ EXPECT_EQ(other_desktop, at(favs, 0));
4709 }
4710
4711 TEST_F(TestFavoriteStoreGSettings, TestAddFavoritePosition)
4712@@ -132,7 +128,7 @@
4713 settings.AddFavorite(other_desktop, 2);
4714 FavoriteList const& favs = settings.GetFavorites();
4715 ASSERT_EQ(favs.size(), n_base_store_favs + 1);
4716- EXPECT_TRUE(other_desktop == at(favs, 2));
4717+ EXPECT_EQ(other_desktop, at(favs, 2));
4718 }
4719
4720 TEST_F(TestFavoriteStoreGSettings,TestAddFavoriteLast)
4721@@ -142,7 +138,7 @@
4722 settings.AddFavorite(other_desktop, -1);
4723 FavoriteList const& favs = settings.GetFavorites();
4724 ASSERT_EQ(favs.size(), n_base_store_favs + 1);
4725- EXPECT_TRUE(other_desktop == favs.back());
4726+ EXPECT_EQ(other_desktop, favs.back());
4727 }
4728
4729 TEST_F(TestFavoriteStoreGSettings,TestAddFavoriteOutOfRange)
4730@@ -178,13 +174,13 @@
4731 FavoriteStore &settings = FavoriteStore::Instance();
4732
4733 FavoriteList const& favs = settings.GetFavorites();
4734- settings.RemoveFavorite("");
4735- EXPECT_EQ(favs.size(), n_base_store_favs);
4736-
4737- settings.RemoveFavorite("foo.desktop");
4738- EXPECT_EQ(favs.size(), n_base_store_favs);
4739-
4740- settings.RemoveFavorite("/this/desktop/doesnt/exist/hopefully.desktop");
4741+ settings.RemoveFavorite(" ");
4742+ EXPECT_EQ(favs.size(), n_base_store_favs);
4743+
4744+ settings.RemoveFavorite("application://foo.desktop");
4745+ EXPECT_EQ(favs.size(), n_base_store_favs);
4746+
4747+ settings.RemoveFavorite("application:///this/desktop/doesnt/exist/hopefully.desktop");
4748 EXPECT_EQ(favs.size(), n_base_store_favs);
4749 }
4750
4751@@ -198,7 +194,7 @@
4752
4753 ASSERT_EQ(favs.size(), n_base_store_favs);
4754 EXPECT_EQ(at(favs, 0), base_store_favs[2]);
4755- EXPECT_TRUE(ends_with(at(favs, 1), base_store_favs[0]));
4756+ EXPECT_TRUE(ends_with(at(favs, 1), FavoriteStore::URI_PREFIX_APP+base_store_favs[0]));
4757 EXPECT_TRUE(ends_with(at(favs, 2), base_store_favs[1]));
4758 }
4759
4760@@ -212,7 +208,7 @@
4761 settings.MoveFavorite(at(favs, 0), 100);
4762
4763 ASSERT_EQ(favs.size(), n_base_store_favs);
4764- EXPECT_TRUE(ends_with(at(favs, 0), base_store_favs[0]));
4765+ EXPECT_TRUE(ends_with(at(favs, 0), FavoriteStore::URI_PREFIX_APP+base_store_favs[0]));
4766 EXPECT_TRUE(ends_with(at(favs, 1), base_store_favs[1]));
4767 EXPECT_EQ(at(favs, 2), base_store_favs[2]);
4768 }
4769@@ -239,7 +235,7 @@
4770 favorite_store->SaveFavorites(favs, false);
4771
4772 ASSERT_TRUE(signal_received);
4773- EXPECT_EQ(position, base_store_favs[0]);
4774+ EXPECT_EQ(position, FavoriteStore::URI_PREFIX_APP+base_store_favs[0]);
4775 EXPECT_TRUE(before);
4776 }
4777
4778@@ -322,12 +318,12 @@
4779 {
4780 FavoriteStore &settings = FavoriteStore::Instance();
4781 bool signal_received = false;
4782- std::string path_removed;
4783+ std::vector<std::string> paths_removed;
4784
4785 settings.favorite_removed.connect([&](std::string const& path)
4786 {
4787 signal_received = true;
4788- path_removed = path;
4789+ paths_removed.push_back(path);
4790 });
4791
4792 FavoriteList favs;
4793@@ -336,7 +332,10 @@
4794 favorite_store->SaveFavorites(favs, false);
4795
4796 ASSERT_TRUE(signal_received);
4797- EXPECT_EQ(path_removed, base_store_favs[1]);
4798+ ASSERT_EQ(paths_removed.size(), 3);
4799+ EXPECT_EQ(paths_removed[0], base_store_favs[4]);
4800+ EXPECT_EQ(paths_removed[1], base_store_favs[1]);
4801+ EXPECT_EQ(paths_removed[2], base_store_favs[3]);
4802 }
4803
4804 TEST_F(TestFavoriteStoreGSettings, TestFavoriteReordered)
4805@@ -464,4 +463,28 @@
4806 EXPECT_TRUE(reordered_received);
4807 }
4808
4809+TEST_F(TestFavoriteStoreGSettings, TestIsFavorite)
4810+{
4811+ EXPECT_TRUE(favorite_store->IsFavorite(FavoriteStore::URI_PREFIX_APP+base_store_favs[0]));
4812+
4813+ for (int i = 1; i < n_base_store_favs; i++)
4814+ {
4815+ ASSERT_TRUE(favorite_store->IsFavorite(base_store_favs[i]));
4816+ }
4817+
4818+ EXPECT_FALSE(favorite_store->IsFavorite("unity://invalid-favorite"));
4819+}
4820+
4821+TEST_F(TestFavoriteStoreGSettings, TestFavoritePosition)
4822+{
4823+ EXPECT_EQ(favorite_store->FavoritePosition(FavoriteStore::URI_PREFIX_APP+base_store_favs[0]), 0);
4824+
4825+ for (int i = 1; i < n_base_store_favs; i++)
4826+ {
4827+ ASSERT_EQ(favorite_store->FavoritePosition(base_store_favs[i]), i);
4828+ }
4829+
4830+ EXPECT_EQ(favorite_store->FavoritePosition("unity://invalid-favorite"), -1);
4831+}
4832+
4833 } // anonymous namespace
4834
4835=== added file 'tests/test_hud_launcher_icon.cpp'
4836--- tests/test_hud_launcher_icon.cpp 1970-01-01 00:00:00 +0000
4837+++ tests/test_hud_launcher_icon.cpp 2012-09-18 15:51:21 +0000
4838@@ -0,0 +1,53 @@
4839+/*
4840+ * Copyright 2012 Canonical Ltd.
4841+ *
4842+ * This program is free software: you can redistribute it and/or modify it
4843+ * under the terms of the GNU General Public License version 3, as published
4844+ * by the Free Software Foundation.
4845+ *
4846+ * This program is distributed in the hope that it will be useful, but
4847+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4848+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4849+ * PURPOSE. See the GNU General Public License for more details.
4850+ *
4851+ * You should have received a copy of the GNU General Public License
4852+ * version 3 along with this program. If not, see
4853+ * <http://www.gnu.org/licenses/>
4854+ *
4855+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
4856+ */
4857+
4858+#include <gmock/gmock.h>
4859+
4860+#include "HudLauncherIcon.h"
4861+
4862+using namespace unity;
4863+using namespace unity::launcher;
4864+
4865+namespace
4866+{
4867+
4868+class MockHudLauncherIcon : public HudLauncherIcon
4869+{
4870+public:
4871+ MockHudLauncherIcon()
4872+ : HudLauncherIcon(LauncherHideMode::LAUNCHER_HIDE_NEVER)
4873+ {}
4874+};
4875+
4876+struct TestHudLauncherIcon : testing::Test
4877+{
4878+ MockHudLauncherIcon hud;
4879+};
4880+
4881+TEST_F(TestHudLauncherIcon, Type)
4882+{
4883+ EXPECT_EQ(hud.GetIconType(), AbstractLauncherIcon::IconType::HUD);
4884+}
4885+
4886+TEST_F(TestHudLauncherIcon, Position)
4887+{
4888+ EXPECT_EQ(hud.position(), AbstractLauncherIcon::Position::BEGIN);
4889+}
4890+
4891+}
4892
4893=== modified file 'tests/test_launcher.cpp'
4894--- tests/test_launcher.cpp 2012-09-04 14:26:23 +0000
4895+++ tests/test_launcher.cpp 2012-09-18 15:51:21 +0000
4896@@ -48,8 +48,12 @@
4897 {
4898 public:
4899 typedef nux::ObjectPtr<MockMockLauncherIcon> Ptr;
4900+ MockMockLauncherIcon(IconType type = IconType::APPLICATION)
4901+ : MockLauncherIcon(type)
4902+ {}
4903
4904 MOCK_METHOD1(ShouldHighlightOnDrag, bool(DndData const&));
4905+ MOCK_METHOD1(Stick, void(bool));
4906 };
4907
4908 }
4909@@ -57,7 +61,7 @@
4910 class TestLauncher : public Test
4911 {
4912 public:
4913- class MockLauncher : public launcher::Launcher
4914+ class MockLauncher : public Launcher
4915 {
4916 public:
4917 MockLauncher(nux::BaseWindow* parent, nux::ObjectPtr<DNDCollectionWindow> const& collection_window)
4918@@ -92,6 +96,11 @@
4919 Launcher::ShowDragWindow();
4920 }
4921
4922+ void EndIconDrag()
4923+ {
4924+ Launcher::EndIconDrag();
4925+ }
4926+
4927 void UpdateDragWindowPosition(int x, int y)
4928 {
4929 Launcher::UpdateDragWindowPosition(x, y);
4930@@ -106,6 +115,55 @@
4931 {
4932 Launcher::ResetMouseDragState();
4933 }
4934+
4935+ bool DndIsSpecialRequest(std::string const& uri) const
4936+ {
4937+ return Launcher::DndIsSpecialRequest(uri);
4938+ }
4939+
4940+ int GetDragIconPosition() const
4941+ {
4942+ return _drag_icon_position;
4943+ }
4944+
4945+ void ProcessDndEnter()
4946+ {
4947+ Launcher::ProcessDndEnter();
4948+ }
4949+
4950+ void ProcessDndLeave()
4951+ {
4952+ Launcher::ProcessDndLeave();
4953+ }
4954+
4955+ void ProcessDndMove(int x, int y, std::list<char*> mimes)
4956+ {
4957+ Launcher::ProcessDndMove(x, y, mimes);
4958+ }
4959+
4960+ void FakeProcessDndMove(int x, int y, std::list<std::string> uris)
4961+ {
4962+ _dnd_data.Reset();
4963+
4964+ std::string data_uri;
4965+ for (std::string const& uri : uris)
4966+ data_uri += uri+"\r\n";
4967+
4968+ _dnd_data.Fill(data_uri.c_str());
4969+
4970+ if (std::find_if(_dnd_data.Uris().begin(), _dnd_data.Uris().end(), [this] (std::string const& uri)
4971+ {return DndIsSpecialRequest(uri);}) != _dnd_data.Uris().end())
4972+ {
4973+ _steal_drag = true;
4974+ }
4975+
4976+ _dnd_hovered_icon = MouseIconIntersection(x, y);
4977+ }
4978+
4979+ void ProcessDndDrop(int x, int y)
4980+ {
4981+ Launcher::ProcessDndDrop(x, y);
4982+ }
4983 };
4984
4985 TestLauncher()
4986@@ -119,6 +177,29 @@
4987 launcher_->SetModel(model_);
4988 }
4989
4990+ std::vector<MockMockLauncherIcon::Ptr> AddMockIcons(unsigned number)
4991+ {
4992+ std::vector<MockMockLauncherIcon::Ptr> icons;
4993+ int icon_size = launcher_->GetIconSize();
4994+ int monitor = launcher_->monitor();
4995+ auto const& launcher_geo = launcher_->GetGeometry();
4996+ int model_pre_size = model_->Size();
4997+
4998+ for (unsigned i = 0; i < number; ++i)
4999+ {
5000+ MockMockLauncherIcon::Ptr icon(new MockMockLauncherIcon);
The diff has been truncated for viewing.