Merge lp:~azzar1/unity/fix-1035301 into lp:unity

Proposed by Andrea Azzarone
Status: Merged
Approved by: Andrea Azzarone
Approved revision: no longer in the source branch.
Merged at revision: 2929
Proposed branch: lp:~azzar1/unity/fix-1035301
Merge into: lp:unity
Diff against target: 1934 lines (+1075/-316)
31 files modified
launcher/AbstractLauncherIcon.h (+1/-0)
launcher/CMakeLists.txt (+4/-1)
launcher/DNDCollectionWindow.cpp (+0/-99)
launcher/DNDCollectionWindow.h (+0/-63)
launcher/Launcher.cpp (+86/-121)
launcher/Launcher.h (+7/-8)
launcher/LauncherController.cpp (+45/-4)
launcher/LauncherController.h (+2/-1)
launcher/LauncherControllerPrivate.h (+8/-1)
launcher/LauncherIcon.cpp (+2/-0)
launcher/StandaloneLauncher.cpp (+2/-2)
launcher/XdndCollectionWindow.h (+51/-0)
launcher/XdndCollectionWindowImp.cpp (+112/-0)
launcher/XdndCollectionWindowImp.h (+44/-0)
launcher/XdndManager.h (+43/-0)
launcher/XdndManagerImp.cpp (+98/-0)
launcher/XdndManagerImp.h (+54/-0)
launcher/XdndStartStopNotifier.cpp (+27/-0)
launcher/XdndStartStopNotifier.h (+41/-0)
launcher/XdndStartStopNotifierImp.cpp (+77/-0)
launcher/XdndStartStopNotifierImp.h (+47/-0)
plugins/unityshell/src/unitya11ytests.cpp (+1/-1)
plugins/unityshell/src/unityshell.cpp (+9/-1)
tests/CMakeLists.txt (+2/-0)
tests/test_launcher.cpp (+4/-9)
tests/test_launcher_controller.cpp (+56/-0)
tests/test_xdnd_manager_imp.cpp (+130/-0)
tests/test_xdnd_start_stop_notifier_imp.cpp (+107/-0)
unity-shared/UScreen.cpp (+7/-0)
unity-shared/UScreen.h (+1/-0)
unity-standalone/StandaloneUnity.cpp (+7/-5)
To merge this branch: bzr merge lp:~azzar1/unity/fix-1035301
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Brandon Schaefer (community) Approve
Review via email: mp+134533@code.launchpad.net

Commit message

Refactor xdnd launcher code.

Description of the change

== Problem ==
Dash, Multi-monitor - When Launcher is set to auto-hide, and the user starts dragging a item, only the Launcher on the monitor which currently contains the dragged item should reveal.

== Fix ==
Move xdnd launcher code from Launcher.cpp to different classes/files:
# XdndStartStopNotifier*
# XdndCollectionWindow*
# XdndManager*

== Test ==
Unit test added.

To post a comment you must log in.
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Overall I'm up for this new implementation... Few comments though:

603+Controller::Impl::Impl(Controller* parent, XdndManager::Ptr xdnd_manager)

 const& ? :)

xdnd_manager_->dnd_started.connect([this](std::string const& data, int monitor)

And other lambdas... Since they're quite long, mabye it's better to put them into methods.

806 +class XdndCollectionWindow : boost::noncopyable {

new line for {

820 +#endif
821 \ No newline at end of file

Add \n ;)

864 + SetGeometry(wm.GetScreenGeometry());

Shouldn't you update this value when the screen geometry changes?

971 + void Collect() /*override*/;
972 + void Deactivate() /*override*/;

I think you can re-enable them since now we use gcc-4.7 in jenkins too.

884 + auto display = nux::GetGraphicsDisplay()->GetX11Display();

You can check for this value only if window_id is the target one, isn't it?

900 + std::vector<std::string> data;
901 + for (auto mime : mimes)
902 + data.push_back(mime);

Can't be happen that std::list<char>

1082 + if (valid_dnd_in_progress_) {

Fix indentation

1096 + char target[] = "text/uri-list";

Adding a global const for this?

There's some commented code in TestXdndManager.SignalDndStarted, do you want to clean it up?

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

Ok thank you for the review :) Just one comment:

> 900 + std::vector<std::string> data;
> 901 + for (auto mime : mimes)
> 902 + data.push_back(mime);

> Can't be happen that std::list<char>

What? :)

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

>
> 1096 + char target[] = "text/uri-list";
>

No we can't. Because nux::...::GetDndData accept a char* not a const char*.

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

> > Can't be happen that std::list<char>
>
> What? :)

Contains a nullptr?

> No we can't. Because nux::...::GetDndData accept a char* not a const char*.

Ok, we need to fix the API then.

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

> > > Can't be happen that std::list<char>
> >
> > What? :)
>
> Contains a nullptr?

Hmmm, it should not happen but it's better to check for null.

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

784 + controller.reset(new launcher::Controller(xdnd_manager));

Could we do a make_shared?

883 + SetBackgroundColor(nux::Color(0x00000000));

Could you make that nux::color::Transparent?

884 + SetOpacity(0.0f);

Do we need to set this if it is already transparent?

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

>
> 884 + SetOpacity(0.0f);
>
> Do we need to set this if it is already transparent?

Yeah there was a nvidia bug few month ago. Can't remember the bug number.

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

Test pass now :). Looks good code wise, and works! +1

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'launcher/AbstractLauncherIcon.h'
--- launcher/AbstractLauncherIcon.h 2012-11-15 17:56:23 +0000
+++ launcher/AbstractLauncherIcon.h 2012-11-24 14:30:27 +0000
@@ -103,6 +103,7 @@
103 RUNNING,103 RUNNING,
104 URGENT,104 URGENT,
105 PRESENTED,105 PRESENTED,
106 UNFOLDED,
106 STARTING,107 STARTING,
107 SHIMMER,108 SHIMMER,
108 CENTER_SAVED,109 CENTER_SAVED,
109110
=== modified file 'launcher/CMakeLists.txt'
--- launcher/CMakeLists.txt 2012-11-15 18:44:55 +0000
+++ launcher/CMakeLists.txt 2012-11-24 14:30:27 +0000
@@ -33,7 +33,6 @@
33 ApplicationLauncherIcon.cpp33 ApplicationLauncherIcon.cpp
34 BFBLauncherIcon.cpp34 BFBLauncherIcon.cpp
35 CairoBaseWindow.cpp35 CairoBaseWindow.cpp
36 DNDCollectionWindow.cpp
37 Decaymulator.cpp36 Decaymulator.cpp
38 DesktopLauncherIcon.cpp37 DesktopLauncherIcon.cpp
39 DeviceLauncherSection.cpp38 DeviceLauncherSection.cpp
@@ -73,6 +72,10 @@
73 VolumeImp.cpp72 VolumeImp.cpp
74 VolumeLauncherIcon.cpp73 VolumeLauncherIcon.cpp
75 VolumeMonitorWrapper.cpp74 VolumeMonitorWrapper.cpp
75 XdndCollectionWindowImp.cpp
76 XdndManagerImp.cpp
77 XdndStartStopNotifier.cpp
78 XdndStartStopNotifierImp.cpp
76 )79 )
7780
78if (ENABLE_X_SUPPORT)81if (ENABLE_X_SUPPORT)
7982
=== removed file 'launcher/DNDCollectionWindow.cpp'
--- launcher/DNDCollectionWindow.cpp 2012-10-11 01:44:15 +0000
+++ launcher/DNDCollectionWindow.cpp 1970-01-01 00:00:00 +0000
@@ -1,99 +0,0 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2011 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <azzaronea@gmail.com>
18*/
19
20#include "DNDCollectionWindow.h"
21
22#include "unity-shared/WindowManager.h"
23
24namespace unity {
25
26NUX_IMPLEMENT_OBJECT_TYPE(DNDCollectionWindow);
27
28DNDCollectionWindow::DNDCollectionWindow()
29 : nux::BaseWindow("")
30 , display(NULL)
31{
32 // Make it invisible...
33 SetBackgroundColor(nux::Color(0x00000000));
34 SetOpacity(0.0f);
35 // ... and as big as the whole screen.
36 WindowManager& wm = WindowManager::Default();
37 SetGeometry(wm.GetScreenGeometry());
38
39 ShowWindow(true);
40 PushToBack();
41 // Hack to create the X Window as soon as possible.
42 EnableInputWindow(true, "DNDCollectionWindow");
43 EnableInputWindow(false, "DNDCollectionWindow");
44 SetDndEnabled(false, true);
45
46 wm.window_moved.connect(sigc::mem_fun(this, &DNDCollectionWindow::OnWindowMoved));
47}
48
49DNDCollectionWindow::~DNDCollectionWindow()
50{
51 for (auto it : mimes_)
52 g_free(it);
53}
54
55/**
56 * EnableInputWindow doesn't show the window immediately.
57 * Since nux::EnableInputWindow uses XMoveResizeWindow the best way to know if
58 * the X Window is really on/off screen is receiving WindowManager::window_moved
59 * signal. Please don't hate me!
60 **/
61void DNDCollectionWindow::OnWindowMoved(Window window_id)
62{
63 if (window_id == GetInputWindowId() && display() != NULL)
64 {
65 // Create a fake mouse move because sometimes an extra one is required.
66 XWarpPointer(display(), None, None, 0, 0, 0, 0, 0, 0);
67 XFlush(display());
68 }
69}
70
71void DNDCollectionWindow::Collect()
72{
73 // Using PushToFront we're sure that the window is shown over the panel window,
74 // the launcher window and the dash window. Don't forget to call PushToBack as
75 // soon as possible.
76 PushToFront();
77 EnableInputWindow(true, "DndCollectionWindow");
78}
79
80void DNDCollectionWindow::ProcessDndMove(int x, int y, std::list<char*> mimes)
81{
82 // Hide the window as soon as possible.
83 PushToBack();
84 EnableInputWindow(false, "DNDCollectionWindow");
85
86 // Free mimes_ before fill it again.
87 for (auto it : mimes_)
88 g_free(it);
89 mimes_.clear();
90
91 // Duplicate the list.
92 for (auto it : mimes)
93 mimes_.push_back(g_strdup(it));
94
95 // Emit the collected signal.
96 collected.emit(mimes_);
97}
98
99} // namespace unity
1000
=== removed file 'launcher/DNDCollectionWindow.h'
--- launcher/DNDCollectionWindow.h 2012-10-11 01:44:15 +0000
+++ launcher/DNDCollectionWindow.h 1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2011 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <azzaronea@gmail.com>
18*/
19
20#ifndef DNDCOLLECTIONWINDOW_H
21#define DNDCOLLECTIONWINDOW_H
22
23#include <list>
24
25#include <Nux/Nux.h>
26#include <Nux/BaseWindow.h>
27#include <sigc++/sigc++.h>
28
29namespace unity {
30
31/**
32 * DNDCollectionWindow makes it possible to collect drag and drop (dnd) data as
33 * soon as dnd starts and not when the mouse pointer enter the x window.
34 **/
35
36class DNDCollectionWindow : public nux::BaseWindow
37{
38NUX_DECLARE_OBJECT_TYPE(DNDCollectionWindow, nux::BaseWindow);
39
40// Methods
41public:
42 DNDCollectionWindow();
43 ~DNDCollectionWindow();
44
45 void Collect();
46
47private:
48 void ProcessDndMove(int x, int y, std::list<char*> mimes);
49 void OnWindowMoved(Window window_id);
50
51// Members
52public:
53 nux::Property<Display*> display;
54
55 sigc::signal<void, const std::list<char*>&> collected;
56
57private:
58 std::list<char*> mimes_;
59};
60
61} // namespace unity
62
63#endif // DNDCOLLECTIONWINDOW_H
640
=== modified file 'launcher/Launcher.cpp'
--- launcher/Launcher.cpp 2012-11-16 15:58:49 +0000
+++ launcher/Launcher.cpp 2012-11-24 14:30:27 +0000
@@ -91,7 +91,6 @@
91const int MOUSE_DEADZONE = 15;91const int MOUSE_DEADZONE = 15;
92const float DRAG_OUT_PIXELS = 300.0f;92const float DRAG_OUT_PIXELS = 300.0f;
9393
94const std::string DND_CHECK_TIMEOUT = "dnd-check-timeout";
95const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout";94const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout";
96const std::string SCROLL_TIMEOUT = "scroll-timeout";95const std::string SCROLL_TIMEOUT = "scroll-timeout";
97const std::string ANIMATION_IDLE = "animation-idle";96const std::string ANIMATION_IDLE = "animation-idle";
@@ -103,7 +102,6 @@
103const int Launcher::Launcher::ANIM_DURATION_SHORT = 125;102const int Launcher::Launcher::ANIM_DURATION_SHORT = 125;
104103
105Launcher::Launcher(nux::BaseWindow* parent,104Launcher::Launcher(nux::BaseWindow* parent,
106 nux::ObjectPtr<DNDCollectionWindow> const& collection_window,
107 NUX_FILE_LINE_DECL)105 NUX_FILE_LINE_DECL)
108 : View(NUX_FILE_LINE_PARAM)106 : View(NUX_FILE_LINE_PARAM)
109#ifdef USE_X11107#ifdef USE_X11
@@ -145,14 +143,11 @@
145 , _drag_out_delta_x(0.0f)143 , _drag_out_delta_x(0.0f)
146 , _drag_gesture_ongoing(false)144 , _drag_gesture_ongoing(false)
147 , _last_reveal_progress(0.0f)145 , _last_reveal_progress(0.0f)
148 , _collection_window(collection_window)
149 , _selection_atom(0)146 , _selection_atom(0)
150 , _background_color(nux::color::DimGray)147 , _background_color(nux::color::DimGray)
151{148{
152 m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);149 m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);
153150
154 _collection_window->collected.connect(sigc::mem_fun(this, &Launcher::OnDNDDataCollected));
155
156 bg_effect_helper_.owner = this;151 bg_effect_helper_.owner = this;
157 bg_effect_helper_.enabled = false;152 bg_effect_helper_.enabled = false;
158153
@@ -180,18 +175,12 @@
180 ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed));175 ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed));
181176
182 WindowManager& wm = WindowManager::Default();177 WindowManager& wm = WindowManager::Default();
183 wm.window_mapped.connect(sigc::hide(sigc::mem_fun(this, &Launcher::DndTimeoutSetup)));
184 wm.window_unmapped.connect(sigc::hide(sigc::mem_fun(this, &Launcher::DndTimeoutSetup)));
185 wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));178 wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
186 wm.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));179 wm.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
187 wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));180 wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
188 wm.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));181 wm.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged));
189 wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::EnsureAnimation));182 wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::EnsureAnimation));
190183
191#ifdef USE_X11
192 display.changed.connect(sigc::mem_fun(this, &Launcher::OnDisplayChanged));
193#endif
194
195 // 0 out timers to avoid wonky startups184 // 0 out timers to avoid wonky startups
196 for (int i = 0; i < TIME_LAST; ++i)185 for (int i = 0; i < TIME_LAST; ++i)
197 {186 {
@@ -227,11 +216,6 @@
227 return "Launcher";216 return "Launcher";
228}217}
229218
230void Launcher::OnDisplayChanged(Display* display)
231{
232 _collection_window->display = display;
233}
234
235#ifdef NUX_GESTURES_SUPPORT219#ifdef NUX_GESTURES_SUPPORT
236void Launcher::OnDragStart(const nux::GestureEvent &event)220void Launcher::OnDragStart(const nux::GestureEvent &event)
237{221{
@@ -399,6 +383,10 @@
399 if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)383 if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)
400 return true;384 return true;
401385
386 time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED);
387 if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION)
388 return true;
389
402 time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER);390 time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER);
403 if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION_LONG)391 if (unity::TimeUtil::TimeDelta(&current, &time) < ANIM_DURATION_LONG)
404 return true;392 return true;
@@ -552,6 +540,18 @@
552 return 1.0f - result;540 return 1.0f - result;
553}541}
554542
543float Launcher::IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
544{
545 struct timespec icon_unfold_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED);
546 int ms = unity::TimeUtil::TimeDelta(&current, &icon_unfold_time);
547 float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f);
548
549 if (icon->GetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED))
550 return result;
551 else
552 return 1.0f - result;
553}
554
555float Launcher::IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const555float Launcher::IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const
556{556{
557 struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT);557 struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT);
@@ -919,13 +919,14 @@
919919
920 // goes for 0.0f when fully unfolded, to 1.0f folded920 // goes for 0.0f when fully unfolded, to 1.0f folded
921 float folding_progress = CLAMP((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);921 float folding_progress = CLAMP((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f);
922 float present_progress = IconPresentProgress(icon, current);922 float unfold_progress = IconUnfoldProgress(icon, current);
923923
924 folding_progress *= 1.0f - present_progress;924 folding_progress *= 1.0f - unfold_progress;
925925
926 float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress);926 float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress);
927 float icon_hide_offset = autohide_offset;927 float icon_hide_offset = autohide_offset;
928928
929 float present_progress = IconPresentProgress(icon, current);
929 icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency());930 icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency());
930931
931 // icon is crossing threshold, start folding932 // icon is crossing threshold, start folding
@@ -1017,8 +1018,8 @@
1017 // magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching";1018 // magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching";
1018 float magic_constant = 1.3f;1019 float magic_constant = 1.3f;
10191020
1020 float present_progress = IconPresentProgress(*it, current);1021 float unfold_progress = IconUnfoldProgress(*it, current);
1021 folding_threshold -= CLAMP(sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * present_progress);1022 folding_threshold -= CLAMP(sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * unfold_progress);
1022 }1023 }
10231024
1024 if (sum - _space_between_icons <= launcher_height)1025 if (sum - _space_between_icons <= launcher_height)
@@ -1366,59 +1367,6 @@
1366 return _mouse_position.y;1367 return _mouse_position.y;
1367}1368}
13681369
1369bool Launcher::OnUpdateDragManagerTimeout()
1370{
1371#ifdef USE_X11
1372 if (!display())
1373 return false;
1374
1375 if (!_selection_atom)
1376 _selection_atom = XInternAtom(display(), "XdndSelection", false);
1377
1378 Window drag_owner = XGetSelectionOwner(display(), _selection_atom);
1379
1380 // evil hack because Qt does not release the seelction owner on drag finished
1381 Window root_r, child_r;
1382 int root_x_r, root_y_r, win_x_r, win_y_r;
1383 unsigned int mask;
1384 XQueryPointer(display(), DefaultRootWindow(display()), &root_r, &child_r, &root_x_r, &root_y_r, &win_x_r, &win_y_r, &mask);
1385
1386 if (drag_owner && (mask & (Button1Mask | Button2Mask | Button3Mask)))
1387 {
1388 if (_data_checked == false)
1389 {
1390 _data_checked = true;
1391 _collection_window->Collect();
1392 }
1393
1394 return true;
1395 }
1396
1397 _data_checked = false;
1398 _collection_window->PushToBack();
1399 _collection_window->EnableInputWindow(false, "DNDCollectionWindow");
1400
1401 if (IsOverlayOpen() && !_hovered)
1402 DesaturateIcons();
1403
1404 DndReset();
1405 _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
1406 _hide_machine.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, false);
1407#endif
1408 return false;
1409}
1410
1411void Launcher::DndTimeoutSetup()
1412{
1413#ifdef USE_X11
1414 if (sources_.GetSource(DND_CHECK_TIMEOUT))
1415 return;
1416
1417 auto cb_func = sigc::mem_fun(this, &Launcher::OnUpdateDragManagerTimeout);
1418 sources_.AddTimeout(200, cb_func, DND_CHECK_TIMEOUT);
1419#endif
1420}
1421
1422void Launcher::OnPluginStateChanged()1370void Launcher::OnPluginStateChanged()
1423{1371{
1424 WindowManager& wm = WindowManager::Default();1372 WindowManager& wm = WindowManager::Default();
@@ -2566,53 +2514,6 @@
2566 return (boost::algorithm::ends_with(uri, ".desktop") || uri.find("device://") == 0);2514 return (boost::algorithm::ends_with(uri, ".desktop") || uri.find("device://") == 0);
2567}2515}
25682516
2569void Launcher::OnDNDDataCollected(const std::list<char*>& mimes)
2570{
2571#ifdef USE_X11
2572 _dnd_data.Reset();
2573
2574 const std::string uri_list = "text/uri-list";
2575 auto& display = nux::GetWindowThread()->GetGraphicsDisplay();
2576
2577 for (auto const& mime : mimes)
2578 {
2579 if (mime != uri_list)
2580 continue;
2581
2582 _dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str())));
2583 break;
2584 }
2585
2586 _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true);
2587
2588 auto const& uris = _dnd_data.Uris();
2589 if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
2590 {return DndIsSpecialRequest(uri);}) != uris.end())
2591 {
2592 _steal_drag = true;
2593
2594 if (IsOverlayOpen())
2595 SaturateIcons();
2596 }
2597 else
2598 {
2599 for (auto const& it : *_model)
2600 {
2601 if (it->ShouldHighlightOnDrag(_dnd_data))
2602 {
2603 it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
2604 it->SetQuirk(AbstractLauncherIcon::Quirk::PRESENTED, true);
2605 }
2606 else
2607 {
2608 it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
2609 it->SetQuirk(AbstractLauncherIcon::Quirk::PRESENTED, false);
2610 }
2611 }
2612 }
2613#endif
2614}
2615
2616void Launcher::ProcessDndEnter()2517void Launcher::ProcessDndEnter()
2617{2518{
2618#ifdef USE_X112519#ifdef USE_X11
@@ -2648,7 +2549,7 @@
2648 it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, is_overlay_open && !_hovered);2549 it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, is_overlay_open && !_hovered);
2649 }2550 }
26502551
2651 it->SetQuirk(AbstractLauncherIcon::Quirk::PRESENTED, false);2552 it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false);
2652 }2553 }
26532554
2654 DndHoveredIconReset();2555 DndHoveredIconReset();
@@ -2873,5 +2774,69 @@
2873 return _launcher_drag_delta;2774 return _launcher_drag_delta;
2874}2775}
28752776
2777void Launcher::DndStarted(std::string const& data)
2778{
2779#ifdef USE_X11
2780 SetDndQuirk();
2781
2782 _dnd_data.Fill(data.c_str());
2783
2784 auto const& uris = _dnd_data.Uris();
2785 if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
2786 {return DndIsSpecialRequest(uri);}) != uris.end())
2787 {
2788 _steal_drag = true;
2789
2790 if (IsOverlayOpen())
2791 SaturateIcons();
2792 }
2793 else
2794 {
2795 for (auto const& it : *_model)
2796 {
2797 if (it->ShouldHighlightOnDrag(_dnd_data))
2798 {
2799 it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
2800 it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, true);
2801 }
2802 else
2803 {
2804 it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true);
2805 it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false);
2806 }
2807 }
2808 }
2809#endif
2810}
2811
2812void Launcher::DndFinished()
2813{
2814#ifdef USE_X11
2815 UnsetDndQuirk();
2816
2817 _data_checked = false;
2818
2819 if (IsOverlayOpen() && !_hovered)
2820 DesaturateIcons();
2821
2822 DndReset();
2823#endif
2824}
2825
2826void Launcher::SetDndQuirk()
2827{
2828#ifdef USE_X11
2829 _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true);
2830#endif
2831}
2832
2833void Launcher::UnsetDndQuirk()
2834{
2835#ifdef USE_X11
2836 _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
2837 _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
2838#endif
2839}
2840
2876} // namespace launcher2841} // namespace launcher
2877} // namespace unity2842} // namespace unity
28782843
=== modified file 'launcher/Launcher.h'
--- launcher/Launcher.h 2012-11-13 22:39:49 +0000
+++ launcher/Launcher.h 2012-11-24 14:30:27 +0000
@@ -32,7 +32,6 @@
32#include "unity-shared/AbstractIconRenderer.h"32#include "unity-shared/AbstractIconRenderer.h"
33#include "unity-shared/BackgroundEffectHelper.h"33#include "unity-shared/BackgroundEffectHelper.h"
34#include "DevicesSettings.h"34#include "DevicesSettings.h"
35#include "DNDCollectionWindow.h"
36#include "DndData.h"35#include "DndData.h"
37#include "unity-shared/Introspectable.h"36#include "unity-shared/Introspectable.h"
38#include "LauncherModel.h"37#include "LauncherModel.h"
@@ -66,7 +65,7 @@
66 NUX_DECLARE_OBJECT_TYPE(Launcher, nux::View);65 NUX_DECLARE_OBJECT_TYPE(Launcher, nux::View);
67public:66public:
6867
69 Launcher(nux::BaseWindow* parent, nux::ObjectPtr<DNDCollectionWindow> const& collection_window, NUX_FILE_LINE_PROTO);68 Launcher(nux::BaseWindow* parent, NUX_FILE_LINE_PROTO);
7069
71 nux::Property<Display*> display;70 nux::Property<Display*> display;
72 nux::Property<int> monitor;71 nux::Property<int> monitor;
@@ -127,6 +126,11 @@
127 int GetDragDelta() const;126 int GetDragDelta() const;
128 void SetHover(bool hovered);127 void SetHover(bool hovered);
129128
129 void DndStarted(std::string const& mimes);
130 void DndFinished();
131 void SetDndQuirk();
132 void UnsetDndQuirk();
133
130 sigc::signal<void, std::string const&, AbstractLauncherIcon::Ptr const&> add_request;134 sigc::signal<void, std::string const&, AbstractLauncherIcon::Ptr const&> add_request;
131 sigc::signal<void, AbstractLauncherIcon::Ptr const&> remove_request;135 sigc::signal<void, AbstractLauncherIcon::Ptr const&> remove_request;
132 sigc::signal<void> selection_change;136 sigc::signal<void> selection_change;
@@ -213,7 +217,6 @@
213 bool StrutHack();217 bool StrutHack();
214 bool StartIconDragTimeout(int x, int y);218 bool StartIconDragTimeout(int x, int y);
215 bool OnScrollTimeout();219 bool OnScrollTimeout();
216 bool OnUpdateDragManagerTimeout();
217220
218 void SetMousePosition(int x, int y);221 void SetMousePosition(int x, int y);
219222
@@ -248,6 +251,7 @@
248 float DragOutProgress(struct timespec const& current) const;251 float DragOutProgress(struct timespec const& current) const;
249 float IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;252 float IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;
250 float IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;253 float IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;
254 float IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;
251 float IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;255 float IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;
252 float IconShimmerProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;256 float IconShimmerProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;
253 float IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;257 float IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const;
@@ -322,12 +326,8 @@
322326
323 virtual long PostLayoutManagement(long LayoutResult);327 virtual long PostLayoutManagement(long LayoutResult);
324328
325 void OnDisplayChanged(Display* display);
326 void OnDNDDataCollected(const std::list<char*>& mimes);
327
328 void DndReset();329 void DndReset();
329 void DndHoveredIconReset();330 void DndHoveredIconReset();
330 void DndTimeoutSetup();
331 bool DndIsSpecialRequest(std::string const& uri) const;331 bool DndIsSpecialRequest(std::string const& uri) const;
332332
333 LauncherModel::Ptr _model;333 LauncherModel::Ptr _model;
@@ -383,7 +383,6 @@
383 nux::Point2 _mouse_position;383 nux::Point2 _mouse_position;
384 nux::ObjectPtr<nux::IOpenGLBaseTexture> _offscreen_drag_texture;384 nux::ObjectPtr<nux::IOpenGLBaseTexture> _offscreen_drag_texture;
385 nux::ObjectPtr<LauncherDragWindow> _drag_window;385 nux::ObjectPtr<LauncherDragWindow> _drag_window;
386 nux::ObjectPtr<unity::DNDCollectionWindow> _collection_window;
387 LauncherHideMachine _hide_machine;386 LauncherHideMachine _hide_machine;
388 LauncherHoverMachine _hover_machine;387 LauncherHoverMachine _hover_machine;
389388
390389
=== modified file 'launcher/LauncherController.cpp'
--- launcher/LauncherController.cpp 2012-11-15 17:56:23 +0000
+++ launcher/LauncherController.cpp 2012-11-24 14:30:27 +0000
@@ -95,10 +95,11 @@
95 { Controller::Impl::OnDBusMethodCall, NULL, NULL};95 { Controller::Impl::OnDBusMethodCall, NULL, NULL};
9696
9797
98Controller::Impl::Impl(Controller* parent)98Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager)
99 : parent_(parent)99 : parent_(parent)
100 , model_(std::make_shared<LauncherModel>())100 , model_(std::make_shared<LauncherModel>())
101 , matcher_(bamf_matcher_get_default())101 , matcher_(bamf_matcher_get_default())
102 , xdnd_manager_(xdnd_manager)
102 , device_section_(std::make_shared<VolumeMonitorWrapper>(), std::make_shared<DevicesSettingsImp>())103 , device_section_(std::make_shared<VolumeMonitorWrapper>(), std::make_shared<DevicesSettingsImp>())
103 , expo_icon_(new ExpoLauncherIcon())104 , expo_icon_(new ExpoLauncherIcon())
104 , desktop_icon_(new DesktopLauncherIcon())105 , desktop_icon_(new DesktopLauncherIcon())
@@ -161,6 +162,10 @@
161 });162 });
162163
163 parent_->AddChild(model_.get());164 parent_->AddChild(model_.get());
165
166 xdnd_manager_->dnd_started.connect(sigc::mem_fun(this, &Impl::OnDndStarted));
167 xdnd_manager_->dnd_finished.connect(sigc::mem_fun(this, &Impl::OnDndFinished));
168 xdnd_manager_->monitor_changed.connect(sigc::mem_fun(this, &Impl::OnDndMonitorChanged));
164}169}
165170
166Controller::Impl::~Impl()171Controller::Impl::~Impl()
@@ -255,11 +260,47 @@
255 }260 }
256}261}
257262
263void Controller::Impl::OnDndStarted(std::string const& data, int monitor)
264{
265 if (parent_->multiple_launchers)
266 {
267 last_dnd_monitor_ = monitor;
268 launchers[last_dnd_monitor_]->DndStarted(data);
269 }
270 else
271 {
272 launcher_->DndStarted(data);
273 }
274}
275
276void Controller::Impl::OnDndFinished()
277{
278 if (parent_->multiple_launchers)
279 {
280 launchers[last_dnd_monitor_]->DndFinished();
281 last_dnd_monitor_ = -1;
282 }
283 else
284 {
285 launcher_->DndFinished();
286 }
287}
288
289void Controller::Impl::OnDndMonitorChanged(int monitor)
290{
291 if (parent_->multiple_launchers)
292 {
293 launchers[last_dnd_monitor_]->UnsetDndQuirk();
294 last_dnd_monitor_ = monitor;
295 launchers[last_dnd_monitor_]->SetDndQuirk();
296 }
297}
298
258Launcher* Controller::Impl::CreateLauncher(int monitor)299Launcher* Controller::Impl::CreateLauncher(int monitor)
259{300{
260 nux::BaseWindow* launcher_window = new nux::BaseWindow(TEXT("LauncherWindow"));301 nux::BaseWindow* launcher_window = new nux::BaseWindow(TEXT("LauncherWindow"));
261302
262 Launcher* launcher = new Launcher(launcher_window, nux::ObjectPtr<DNDCollectionWindow>(new DNDCollectionWindow));303 Launcher* launcher = new Launcher(launcher_window);
263 launcher->monitor = monitor;304 launcher->monitor = monitor;
264 launcher->options = parent_->options();305 launcher->options = parent_->options();
265 launcher->SetModel(model_);306 launcher->SetModel(model_);
@@ -974,10 +1015,10 @@
974 g_variant_new("(sus)", "home.lens", dash::NOT_HANDLED, ""));1015 g_variant_new("(sus)", "home.lens", dash::NOT_HANDLED, ""));
975}1016}
9761017
977Controller::Controller()1018Controller::Controller(XdndManager::Ptr const& xdnd_manager)
978 : options(Options::Ptr(new Options()))1019 : options(Options::Ptr(new Options()))
979 , multiple_launchers(true)1020 , multiple_launchers(true)
980 , pimpl(new Impl(this))1021 , pimpl(new Impl(this, xdnd_manager))
981{1022{
982 multiple_launchers.changed.connect([&](bool value) -> void {1023 multiple_launchers.changed.connect([&](bool value) -> void {
983 UScreen* uscreen = UScreen::GetDefault();1024 UScreen* uscreen = UScreen::GetDefault();
9841025
=== modified file 'launcher/LauncherController.h'
--- launcher/LauncherController.h 2012-11-06 18:19:09 +0000
+++ launcher/LauncherController.h 2012-11-24 14:30:27 +0000
@@ -27,6 +27,7 @@
2727
28#include "LauncherOptions.h"28#include "LauncherOptions.h"
29#include "SoftwareCenterLauncherIcon.h"29#include "SoftwareCenterLauncherIcon.h"
30#include "XdndManager.h"
3031
31namespace unity32namespace unity
32{33{
@@ -47,7 +48,7 @@
47 nux::Property<Options::Ptr> options;48 nux::Property<Options::Ptr> options;
48 nux::Property<bool> multiple_launchers;49 nux::Property<bool> multiple_launchers;
4950
50 Controller();51 Controller(XdndManager::Ptr const& xdnd_manager);
51 ~Controller();52 ~Controller();
5253
53 Launcher& launcher() const;54 Launcher& launcher() const;
5455
=== modified file 'launcher/LauncherControllerPrivate.h'
--- launcher/LauncherControllerPrivate.h 2012-11-15 17:56:23 +0000
+++ launcher/LauncherControllerPrivate.h 2012-11-24 14:30:27 +0000
@@ -39,6 +39,7 @@
39#include "SoftwareCenterLauncherIcon.h"39#include "SoftwareCenterLauncherIcon.h"
40#include "unity-shared/UBusWrapper.h"40#include "unity-shared/UBusWrapper.h"
41#include "VolumeMonitorWrapper.h"41#include "VolumeMonitorWrapper.h"
42#include "XdndManager.h"
4243
43namespace unity44namespace unity
44{45{
@@ -48,7 +49,7 @@
48class Controller::Impl49class Controller::Impl
49{50{
50public:51public:
51 Impl(Controller* parent);52 Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager);
52 ~Impl();53 ~Impl();
5354
54 void UpdateNumWorkspaces(int workspaces);55 void UpdateNumWorkspaces(int workspaces);
@@ -111,6 +112,10 @@
111112
112 void OpenQuicklist();113 void OpenQuicklist();
113114
115 void OnDndStarted(std::string const& data, int monitor);
116 void OnDndFinished();
117 void OnDndMonitorChanged(int monitor);
118
114 static void OnBusAcquired(GDBusConnection* connection, const gchar* name, gpointer user_data);119 static void OnBusAcquired(GDBusConnection* connection, const gchar* name, gpointer user_data);
115 static void OnDBusMethodCall(GDBusConnection* connection, const gchar* sender, const gchar* object_path,120 static void OnDBusMethodCall(GDBusConnection* connection, const gchar* sender, const gchar* object_path,
116 const gchar* interface_name, const gchar* method_name,121 const gchar* interface_name, const gchar* method_name,
@@ -124,6 +129,7 @@
124 glib::Object<BamfMatcher> matcher_;129 glib::Object<BamfMatcher> matcher_;
125 nux::ObjectPtr<Launcher> launcher_;130 nux::ObjectPtr<Launcher> launcher_;
126 nux::ObjectPtr<Launcher> keyboard_launcher_;131 nux::ObjectPtr<Launcher> keyboard_launcher_;
132 XdndManager::Ptr xdnd_manager_;
127 DeviceLauncherSection device_section_;133 DeviceLauncherSection device_section_;
128 LauncherEntryRemoteModel remote_model_;134 LauncherEntryRemoteModel remote_model_;
129 AbstractLauncherIcon::Ptr expo_icon_;135 AbstractLauncherIcon::Ptr expo_icon_;
@@ -143,6 +149,7 @@
143 int reactivate_index;149 int reactivate_index;
144 bool keynav_restore_window_;150 bool keynav_restore_window_;
145 int launcher_key_press_time_;151 int launcher_key_press_time_;
152 int last_dnd_monitor_;
146153
147 unsigned dbus_owner_;154 unsigned dbus_owner_;
148 GDBusConnection* gdbus_connection_;155 GDBusConnection* gdbus_connection_;
149156
=== modified file 'launcher/LauncherIcon.cpp'
--- launcher/LauncherIcon.cpp 2012-11-15 17:56:23 +0000
+++ launcher/LauncherIcon.cpp 2012-11-24 14:30:27 +0000
@@ -801,6 +801,7 @@
801801
802 _present_urgency = CLAMP(present_urgency, 0.0f, 1.0f);802 _present_urgency = CLAMP(present_urgency, 0.0f, 1.0f);
803 SetQuirk(Quirk::PRESENTED, true);803 SetQuirk(Quirk::PRESENTED, true);
804 SetQuirk(Quirk::UNFOLDED, true);
804}805}
805806
806void807void
@@ -811,6 +812,7 @@
811812
812 _source_manager.Remove(PRESENT_TIMEOUT);813 _source_manager.Remove(PRESENT_TIMEOUT);
813 SetQuirk(Quirk::PRESENTED, false);814 SetQuirk(Quirk::PRESENTED, false);
815 SetQuirk(Quirk::UNFOLDED, false);
814}816}
815817
816void818void
817819
=== modified file 'launcher/StandaloneLauncher.cpp'
--- launcher/StandaloneLauncher.cpp 2012-10-17 22:16:48 +0000
+++ launcher/StandaloneLauncher.cpp 2012-11-24 14:30:27 +0000
@@ -35,8 +35,8 @@
3535
36void ThreadWidgetInit(nux::NThread* thread, void* InitData)36void ThreadWidgetInit(nux::NThread* thread, void* InitData)
37{37{
38// launcherWindow->SetGeometry (nux::Geometry(0, 0, 300, 800));38 auto xdnd_manager = std::make_shared<XdndManager>();
39 controller.reset(new launcher::Controller());39 controller = std::make_shared<launcher::Controller>(xdnd_manager);
40}40}
4141
42int main(int argc, char** argv)42int main(int argc, char** argv)
4343
=== added file 'launcher/XdndCollectionWindow.h'
--- launcher/XdndCollectionWindow.h 1970-01-01 00:00:00 +0000
+++ launcher/XdndCollectionWindow.h 2012-11-24 14:30:27 +0000
@@ -0,0 +1,51 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#ifndef UNITYSHELL_XDND_COLLECTION_WINDOW_H
21#define UNITYSHELL_XDND_COLLECTION_WINDOW_H
22
23#include <boost/noncopyable.hpp>
24#include <memory>
25#include <sigc++/signal.h>
26#include <string>
27#include <vector>
28
29namespace unity {
30
31/**
32 * XdndCollectionWindow makes it possible to collect drag and drop data as
33 * soon as dnd starts and not when the mouse pointer enter the x window.
34 **/
35
36class XdndCollectionWindow : boost::noncopyable
37{
38public:
39 typedef std::shared_ptr<XdndCollectionWindow> Ptr;
40
41 virtual ~XdndCollectionWindow() {}
42
43 virtual void Collect() = 0;
44 virtual void Deactivate() = 0;
45
46 sigc::signal<void, std::vector<std::string>> collected;
47};
48
49}
50
51#endif
052
=== added file 'launcher/XdndCollectionWindowImp.cpp'
--- launcher/XdndCollectionWindowImp.cpp 1970-01-01 00:00:00 +0000
+++ launcher/XdndCollectionWindowImp.cpp 2012-11-24 14:30:27 +0000
@@ -0,0 +1,112 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2011 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <azzaronea@gmail.com>
18*/
19
20#include "XdndCollectionWindowImp.h"
21#include "unity-shared/UScreen.h"
22#include "unity-shared/WindowManager.h"
23
24namespace unity {
25namespace {
26
27class PrivateWindow : public nux::BaseWindow
28{
29public:
30 PrivateWindow(XdndCollectionWindowImp* parent)
31 : nux::BaseWindow("")
32 , parent_(parent)
33 {
34 // Make it invisible...
35 SetBackgroundColor(nux::color::Transparent);
36 SetOpacity(0.0f);
37 // ... and as big as the whole screen.
38 auto uscreen = UScreen::GetDefault();
39 SetGeometry(uscreen->GetScreenGeometry());
40
41 ShowWindow(true);
42 PushToBack();
43 // Hack to create the X Window as soon as possible.
44 EnableInputWindow(true, "XdndCollectionWindowImp");
45 EnableInputWindow(false, "XdndCollectionWindowImp");
46 SetDndEnabled(false, true);
47
48 uscreen->changed.connect(sigc::mem_fun(this, &PrivateWindow::OnScreenChanged));
49 WindowManager::Default().window_moved.connect(sigc::mem_fun(this, &PrivateWindow::OnWindowMoved));
50 }
51
52 void OnScreenChanged(int /*primary*/, std::vector<nux::Geometry>& /*monitors*/)
53 {
54 auto uscreen = UScreen::GetDefault();
55 SetGeometry(uscreen->GetScreenGeometry());
56 }
57
58 /**
59 * EnableInputWindow doesn't show the window immediately.
60 * Since nux::EnableInputWindow uses XMoveResizeWindow the best way to know if
61 * the X Window is really on/off screen is receiving WindowManager::window_moved
62 * signal. Please don't hate me!
63 **/
64 void OnWindowMoved(Window window_id)
65 {
66 if (G_LIKELY(window_id != GetInputWindowId()))
67 return;
68
69 // Create a fake mouse move because sometimes an extra one is required.
70 auto display = nux::GetGraphicsDisplay()->GetX11Display();
71 XWarpPointer(display, None, None, 0, 0, 0, 0, 0, 0);
72 XFlush(display);
73 }
74
75 void ProcessDndMove(int x, int y, std::list<char*> mimes)
76 {
77 // Hide the window as soon as possible.
78 PushToBack();
79 EnableInputWindow(false, "XdndCollectionWindowImp");
80
81 std::vector<std::string> data;
82 for (auto mime : mimes)
83 if (mime) data.push_back(mime);
84
85 parent_->collected.emit(data);
86 }
87
88 XdndCollectionWindowImp* parent_;
89};
90
91}
92
93XdndCollectionWindowImp::XdndCollectionWindowImp()
94 : window_(new PrivateWindow(this))
95{}
96
97void XdndCollectionWindowImp::Collect()
98{
99 // Using PushToFront we're sure that the window is shown over the panel window,
100 // the launcher window and the dash window. Don't forget to call PushToBack as
101 // soon as possible.
102 window_->PushToFront();
103 window_->EnableInputWindow(true, "XdndCollectionWindowImp");
104}
105
106void XdndCollectionWindowImp::Deactivate()
107{
108 window_->PushToBack();
109 window_->EnableInputWindow(false, "XdndCollectionWindowImp");
110}
111
112}
0113
=== added file 'launcher/XdndCollectionWindowImp.h'
--- launcher/XdndCollectionWindowImp.h 1970-01-01 00:00:00 +0000
+++ launcher/XdndCollectionWindowImp.h 2012-11-24 14:30:27 +0000
@@ -0,0 +1,44 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2011-2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#ifndef UNITYSHELL_XDND_COLLECTION_WINDOW_IMP_H
21#define UNITYSHELL_XDND_COLLECTION_WINDOW_IMP_H
22
23#include "XdndCollectionWindow.h"
24
25#include <Nux/Nux.h>
26#include <Nux/BaseWindow.h>
27
28namespace unity {
29
30class XdndCollectionWindowImp : public XdndCollectionWindow
31{
32public:
33 XdndCollectionWindowImp();
34
35 void Collect();
36 void Deactivate();
37
38private:
39 nux::ObjectPtr<nux::BaseWindow> window_;
40};
41
42}
43
44#endif
045
=== added file 'launcher/XdndManager.h'
--- launcher/XdndManager.h 1970-01-01 00:00:00 +0000
+++ launcher/XdndManager.h 2012-11-24 14:30:27 +0000
@@ -0,0 +1,43 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#ifndef UNITYSHELL_XDND_MANAGER_H
21#define UNITYSHELL_XDND_MANAGER_H
22
23#include <boost/noncopyable.hpp>
24#include <memory>
25#include <sigc++/signal.h>
26#include <string>
27
28namespace unity {
29
30class XdndManager : boost::noncopyable {
31public:
32 typedef std::shared_ptr<XdndManager> Ptr;
33
34 virtual ~XdndManager() {}
35
36 sigc::signal<void, std::string, int> dnd_started;
37 sigc::signal<void> dnd_finished;
38 sigc::signal<void, int> monitor_changed;
39};
40
41}
42
43#endif
044
=== added file 'launcher/XdndManagerImp.cpp'
--- launcher/XdndManagerImp.cpp 1970-01-01 00:00:00 +0000
+++ launcher/XdndManagerImp.cpp 2012-11-24 14:30:27 +0000
@@ -0,0 +1,98 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#include "XdndManagerImp.h"
21
22#include "unity-shared/UScreen.h"
23
24namespace unity {
25
26XdndManagerImp::XdndManagerImp(XdndStartStopNotifier::Ptr const& xdnd_start_stop_notifier,
27 XdndCollectionWindow::Ptr const& xdnd_collection_window)
28 : xdnd_start_stop_notifier_(xdnd_start_stop_notifier)
29 , xdnd_collection_window_(xdnd_collection_window)
30 , last_monitor_(-1)
31 , valid_dnd_in_progress_(false)
32{
33 xdnd_start_stop_notifier_->started.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndStarted));
34 xdnd_start_stop_notifier_->finished.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndFinished));
35
36 xdnd_collection_window_->collected.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndDataCollected));
37}
38
39void XdndManagerImp::OnDndStarted()
40{
41 xdnd_collection_window_->Collect();
42}
43
44void XdndManagerImp::OnDndFinished()
45{
46 xdnd_collection_window_->Deactivate();
47 mouse_poller_timeout_.reset();
48
49 if (valid_dnd_in_progress_)
50 {
51 valid_dnd_in_progress_ = false;
52 dnd_finished.emit();
53 }
54}
55
56void XdndManagerImp::OnDndDataCollected(std::vector<std::string> const& mimes)
57{
58 if (!IsAValidDnd(mimes))
59 return;
60
61 valid_dnd_in_progress_ = true;
62
63 auto& gp_display = nux::GetWindowThread()->GetGraphicsDisplay();
64 char target[] = "text/uri-list";
65 glib::String data(gp_display.GetDndData(target));
66
67 auto uscreen = UScreen::GetDefault();
68 last_monitor_ = uscreen->GetMonitorWithMouse();
69
70 mouse_poller_timeout_.reset(new glib::Timeout(20, sigc::mem_fun(this, &XdndManagerImp::CheckMousePosition)));
71
72 dnd_started.emit(data.Str(), last_monitor_);
73}
74
75bool XdndManagerImp::IsAValidDnd(std::vector<std::string> const& mimes)
76{
77 auto end = std::end(mimes);
78 auto it = std::find(std::begin(mimes), end, "text/uri-list");
79
80 return it != end;
81}
82
83bool XdndManagerImp::CheckMousePosition()
84{
85 auto uscreen = UScreen::GetDefault();
86 auto monitor = uscreen->GetMonitorWithMouse();
87
88 if (valid_dnd_in_progress_ && monitor != last_monitor_)
89 {
90 last_monitor_ = monitor;
91 monitor_changed.emit(last_monitor_);
92 }
93
94 return true;
95}
96
97}
98
099
=== added file 'launcher/XdndManagerImp.h'
--- launcher/XdndManagerImp.h 1970-01-01 00:00:00 +0000
+++ launcher/XdndManagerImp.h 2012-11-24 14:30:27 +0000
@@ -0,0 +1,54 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#ifndef UNITYSHELL_XDND_MANAGER_IMP_H
21#define UNITYSHELL_XDND_MANAGER_IMP_H
22
23#include <sigc++/trackable.h>
24
25#include "XdndManager.h"
26
27#include "XdndCollectionWindow.h"
28#include "XdndStartStopNotifier.h"
29#include "UnityCore/GLibSource.h"
30
31namespace unity {
32
33class XdndManagerImp : public XdndManager, public sigc::trackable {
34public:
35 XdndManagerImp(XdndStartStopNotifier::Ptr const&, XdndCollectionWindow::Ptr const&);
36
37private:
38 void OnDndStarted();
39 void OnDndFinished();
40 void OnDndDataCollected(std::vector<std::string> const& mimes);
41 bool IsAValidDnd(std::vector<std::string> const& mimes);
42 bool CheckMousePosition();
43
44 XdndStartStopNotifier::Ptr xdnd_start_stop_notifier_;
45 XdndCollectionWindow::Ptr xdnd_collection_window_;
46 int last_monitor_;
47 bool valid_dnd_in_progress_;
48
49 glib::Source::UniquePtr mouse_poller_timeout_;
50};
51
52}
53
54#endif
055
=== added file 'launcher/XdndStartStopNotifier.cpp'
--- launcher/XdndStartStopNotifier.cpp 1970-01-01 00:00:00 +0000
+++ launcher/XdndStartStopNotifier.cpp 2012-11-24 14:30:27 +0000
@@ -0,0 +1,27 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#include "XdndStartStopNotifier.h"
21
22namespace unity {
23
24XdndStartStopNotifier::~XdndStartStopNotifier()
25{}
26
27}
0\ No newline at end of file28\ No newline at end of file
129
=== added file 'launcher/XdndStartStopNotifier.h'
--- launcher/XdndStartStopNotifier.h 1970-01-01 00:00:00 +0000
+++ launcher/XdndStartStopNotifier.h 2012-11-24 14:30:27 +0000
@@ -0,0 +1,41 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#ifndef UNITYSHELL_XDND_START_STOP_NOTIFIER_H
21#define UNITYSHELL_XDND_START_STOP_NOTIFIER_H
22
23#include <boost/noncopyable.hpp>
24#include <memory>
25#include <sigc++/signal.h>
26
27namespace unity {
28
29class XdndStartStopNotifier : boost::noncopyable {
30public:
31 typedef std::shared_ptr<XdndStartStopNotifier> Ptr;
32
33 virtual ~XdndStartStopNotifier() = 0;
34
35 sigc::signal<void> started;
36 sigc::signal<void> finished;
37};
38
39}
40
41#endif
042
=== added file 'launcher/XdndStartStopNotifierImp.cpp'
--- launcher/XdndStartStopNotifierImp.cpp 1970-01-01 00:00:00 +0000
+++ launcher/XdndStartStopNotifierImp.cpp 2012-11-24 14:30:27 +0000
@@ -0,0 +1,77 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#include "XdndStartStopNotifierImp.h"
21
22#include <Nux/Nux.h>
23
24#include "unity-shared/WindowManager.h"
25
26namespace unity {
27
28XdndStartStopNotifierImp::XdndStartStopNotifierImp()
29 : display_(nux::GetGraphicsDisplay()->GetX11Display())
30 , selection_(XInternAtom(display_, "XdndSelection", false))
31 , dnd_in_progress_(false)
32{
33 WindowManager& wm = WindowManager::Default();
34 wm.window_mapped.connect(sigc::hide(sigc::mem_fun(this, &XdndStartStopNotifierImp::DndTimeoutSetup)));
35 wm.window_unmapped.connect(sigc::hide(sigc::mem_fun(this, &XdndStartStopNotifierImp::DndTimeoutSetup)));
36 }
37
38void XdndStartStopNotifierImp::DndTimeoutSetup()
39{
40 if (timeout_ && timeout_->IsRunning())
41 return;
42
43 auto cb_func = sigc::mem_fun(this, &XdndStartStopNotifierImp::OnTimeout);
44 timeout_.reset(new glib::Timeout(200, cb_func));
45}
46
47bool XdndStartStopNotifierImp::OnTimeout()
48{
49 Window drag_owner = XGetSelectionOwner(display_, selection_);
50
51 // evil hack because Qt does not release the selction owner on drag finished
52 Window root_r, child_r;
53 int root_x_r, root_y_r, win_x_r, win_y_r;
54 unsigned int mask;
55 XQueryPointer(display_, DefaultRootWindow(display_), &root_r, &child_r, &root_x_r, &root_y_r, &win_x_r, &win_y_r, &mask);
56
57 if (drag_owner && (mask & (Button1Mask | Button2Mask | Button3Mask)))
58 {
59 if (!dnd_in_progress_)
60 {
61 started.emit();
62 dnd_in_progress_ = true;
63 }
64
65 return true;
66 }
67
68 if (dnd_in_progress_)
69 {
70 finished.emit();
71 dnd_in_progress_ = false;
72 }
73
74 return false;
75}
76
77}
078
=== added file 'launcher/XdndStartStopNotifierImp.h'
--- launcher/XdndStartStopNotifierImp.h 1970-01-01 00:00:00 +0000
+++ launcher/XdndStartStopNotifierImp.h 2012-11-24 14:30:27 +0000
@@ -0,0 +1,47 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#ifndef UNITYSHELL_XDND_START_STOP_NOTIFIER_IMP_H
21#define UNITYSHELL_XDND_START_STOP_NOTIFIER_IMP_H
22
23#include "XdndStartStopNotifier.h"
24
25#include <UnityCore/GLibSource.h>
26#include <X11/Xlib.h>
27
28namespace unity {
29
30class XdndStartStopNotifierImp : public XdndStartStopNotifier {
31public:
32 XdndStartStopNotifierImp();
33
34private:
35 void DndTimeoutSetup();
36 bool OnTimeout();
37
38 Display* display_;
39 Atom selection_;
40 bool dnd_in_progress_;
41
42 glib::Source::UniquePtr timeout_;
43};
44
45}
46
47#endif
0\ No newline at end of file48\ No newline at end of file
149
=== modified file 'plugins/unityshell/src/unitya11ytests.cpp'
--- plugins/unityshell/src/unitya11ytests.cpp 2012-08-15 14:05:18 +0000
+++ plugins/unityshell/src/unitya11ytests.cpp 2012-11-24 14:30:27 +0000
@@ -210,7 +210,7 @@
210 AtkObject* launcher_icon_accessible = NULL;210 AtkObject* launcher_icon_accessible = NULL;
211211
212 window = new nux::BaseWindow(TEXT(""));212 window = new nux::BaseWindow(TEXT(""));
213 launcher = new Launcher(window, nux::ObjectPtr<unity::DNDCollectionWindow>(new unity::DNDCollectionWindow), NULL);213 launcher = new Launcher(window, NULL);
214 launcher->SinkReference();214 launcher->SinkReference();
215 launcher_accessible = unity_a11y_get_accessible(launcher);215 launcher_accessible = unity_a11y_get_accessible(launcher);
216216
217217
=== modified file 'plugins/unityshell/src/unityshell.cpp'
--- plugins/unityshell/src/unityshell.cpp 2012-11-21 23:44:37 +0000
+++ plugins/unityshell/src/unityshell.cpp 2012-11-24 14:30:27 +0000
@@ -41,6 +41,9 @@
41#include "unityshell.h"41#include "unityshell.h"
42#include "BackgroundEffectHelper.h"42#include "BackgroundEffectHelper.h"
43#include "UnityGestureBroker.h"43#include "UnityGestureBroker.h"
44#include "launcher/XdndCollectionWindowImp.h"
45#include "launcher/XdndManagerImp.h"
46#include "launcher/XdndStartStopNotifierImp.h"
4447
45#include <glib/gi18n-lib.h>48#include <glib/gi18n-lib.h>
46#include <gtk/gtk.h>49#include <gtk/gtk.h>
@@ -3096,7 +3099,12 @@
3096void UnityScreen::initLauncher()3099void UnityScreen::initLauncher()
3097{3100{
3098 Timer timer;3101 Timer timer;
3099 launcher_controller_ = std::make_shared<launcher::Controller>();3102
3103 auto xdnd_collection_window = std::make_shared<XdndCollectionWindowImp>();
3104 auto xdnd_start_stop_notifier = std::make_shared<XdndStartStopNotifierImp>();
3105 auto xdnd_manager = std::make_shared<XdndManagerImp>(xdnd_start_stop_notifier, xdnd_collection_window);
3106
3107 launcher_controller_ = std::make_shared<launcher::Controller>(xdnd_manager);
3100 AddChild(launcher_controller_.get());3108 AddChild(launcher_controller_.get());
31013109
3102 switcher_controller_ = std::make_shared<switcher::Controller>();3110 switcher_controller_ = std::make_shared<switcher::Controller>();
31033111
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2012-11-23 23:49:46 +0000
+++ tests/CMakeLists.txt 2012-11-24 14:30:27 +0000
@@ -251,6 +251,8 @@
251 test_unity_settings.cpp251 test_unity_settings.cpp
252 test_volume_imp.cpp252 test_volume_imp.cpp
253 test_volume_launcher_icon.cpp253 test_volume_launcher_icon.cpp
254 test_xdnd_manager_imp.cpp
255 test_xdnd_start_stop_notifier_imp.cpp
254 bamf-mock-application.c256 bamf-mock-application.c
255 gmockmount.c257 gmockmount.c
256 gmockvolume.c258 gmockvolume.c
257259
=== modified file 'tests/test_launcher.cpp'
--- tests/test_launcher.cpp 2012-11-09 09:18:37 +0000
+++ tests/test_launcher.cpp 2012-11-24 14:30:27 +0000
@@ -26,7 +26,6 @@
26#include <Nux/Nux.h>26#include <Nux/Nux.h>
27#include <Nux/BaseWindow.h>27#include <Nux/BaseWindow.h>
2828
29#include "launcher/DNDCollectionWindow.h"
30#include "launcher/MockLauncherIcon.h"29#include "launcher/MockLauncherIcon.h"
31#include "launcher/Launcher.h"30#include "launcher/Launcher.h"
32#include "unity-shared/PanelStyle.h"31#include "unity-shared/PanelStyle.h"
@@ -63,8 +62,8 @@
63 class MockLauncher : public Launcher62 class MockLauncher : public Launcher
64 {63 {
65 public:64 public:
66 MockLauncher(nux::BaseWindow* parent, nux::ObjectPtr<DNDCollectionWindow> const& collection_window)65 MockLauncher(nux::BaseWindow* parent)
67 : Launcher(parent, collection_window)66 : Launcher(parent)
68 {}67 {}
6968
70 AbstractLauncherIcon::Ptr MouseIconIntersection(int x, int y) const69 AbstractLauncherIcon::Ptr MouseIconIntersection(int x, int y) const
@@ -119,10 +118,9 @@
119118
120 TestLauncher()119 TestLauncher()
121 : parent_window_(new nux::BaseWindow("TestLauncherWindow"))120 : parent_window_(new nux::BaseWindow("TestLauncherWindow"))
122 , dnd_collection_window_(new DNDCollectionWindow)
123 , model_(new LauncherModel)121 , model_(new LauncherModel)
124 , options_(new Options)122 , options_(new Options)
125 , launcher_(new MockLauncher(parent_window_, dnd_collection_window_))123 , launcher_(new MockLauncher(parent_window_))
126 {124 {
127 launcher_->options = options_;125 launcher_->options = options_;
128 launcher_->SetModel(model_);126 launcher_->SetModel(model_);
@@ -153,7 +151,6 @@
153151
154 MockUScreen uscreen;152 MockUScreen uscreen;
155 nux::BaseWindow* parent_window_;153 nux::BaseWindow* parent_window_;
156 nux::ObjectPtr<DNDCollectionWindow> dnd_collection_window_;
157 Settings settings;154 Settings settings;
158 panel::Style panel_style;155 panel::Style panel_style;
159 LauncherModel::Ptr model_;156 LauncherModel::Ptr model_;
@@ -189,9 +186,7 @@
189 EXPECT_CALL(*third, ShouldHighlightOnDrag(_))186 EXPECT_CALL(*third, ShouldHighlightOnDrag(_))
190 .WillRepeatedly(Return(false));187 .WillRepeatedly(Return(false));
191188
192 std::list<char*> uris;189 launcher_->DndStarted("");
193 dnd_collection_window_->collected.emit(uris);
194
195 Utils::WaitForTimeout(1);190 Utils::WaitForTimeout(1);
196191
197 EXPECT_FALSE(first->GetQuirk(launcher::AbstractLauncherIcon::Quirk::DESAT));192 EXPECT_FALSE(first->GetQuirk(launcher::AbstractLauncherIcon::Quirk::DESAT));
198193
=== modified file 'tests/test_launcher_controller.cpp'
--- tests/test_launcher_controller.cpp 2012-11-15 17:56:23 +0000
+++ tests/test_launcher_controller.cpp 2012-11-24 14:30:27 +0000
@@ -200,6 +200,11 @@
200{200{
201struct TestLauncherController : public testing::Test201struct TestLauncherController : public testing::Test
202{202{
203 TestLauncherController()
204 : xdnd_manager_(std::make_shared<XdndManager>())
205 , lc(xdnd_manager_)
206 {}
207
203 virtual void SetUp()208 virtual void SetUp()
204 {209 {
205 lc.multiple_launchers = true;210 lc.multiple_launchers = true;
@@ -216,6 +221,10 @@
216protected:221protected:
217 struct MockLauncherController : Controller222 struct MockLauncherController : Controller
218 {223 {
224 MockLauncherController(XdndManager::Ptr const& xdnd_manager)
225 : Controller(xdnd_manager)
226 {}
227
219 Controller::Impl* Impl() const { return pimpl.get(); }228 Controller::Impl* Impl() const { return pimpl.get(); }
220229
221 AbstractLauncherIcon::Ptr GetIconByDesktop(std::string const& path) const230 AbstractLauncherIcon::Ptr GetIconByDesktop(std::string const& path) const
@@ -258,6 +267,7 @@
258 Settings settings;267 Settings settings;
259 panel::Style panel_style;268 panel::Style panel_style;
260 MockFavoriteStore favorite_store;269 MockFavoriteStore favorite_store;
270 XdndManager::Ptr xdnd_manager_;
261 MockLauncherController lc;271 MockLauncherController lc;
262};272};
263}273}
@@ -1544,4 +1554,50 @@
1544 ASSERT_EQ(lc.Impl()->model_->Selection()->tooltip_text(), last_selection_change);1554 ASSERT_EQ(lc.Impl()->model_->Selection()->tooltip_text(), last_selection_change);
1545}1555}
15461556
1557TEST_F(TestLauncherController, DragAndDrop_MultipleLaunchers)
1558{
1559 lc.multiple_launchers = true;
1560 uscreen.SetupFakeMultiMonitor();
1561 lc.options()->hide_mode = LAUNCHER_HIDE_AUTOHIDE;
1562
1563 auto check_fn = [this](int index) {
1564 return lc.launchers()[index]->Hidden();
1565 };
1566
1567 xdnd_manager_->dnd_started.emit("my_awesome_file", 0);
1568
1569 for (int i = 0; i < max_num_monitors; ++i)
1570 Utils::WaitUntil(std::bind(check_fn, i), i != 0);
1571
1572 xdnd_manager_->monitor_changed.emit(3);
1573
1574 for (int i = 0; i < max_num_monitors; ++i)
1575 Utils::WaitUntil(std::bind(check_fn, i), i != 3);
1576
1577 xdnd_manager_->dnd_finished.emit();
1578
1579 for (int i = 0; i < max_num_monitors; ++i)
1580 Utils::WaitUntil(std::bind(check_fn, i), true);
1581}
1582
1583TEST_F(TestLauncherController, DragAndDrop_SingleLauncher)
1584{
1585 lc.multiple_launchers = false;
1586 uscreen.SetupFakeMultiMonitor(2);
1587 lc.options()->hide_mode = LAUNCHER_HIDE_AUTOHIDE;
1588
1589 auto check_fn = [this]() {
1590 return lc.launcher().Hidden();
1591 };
1592
1593 xdnd_manager_->dnd_started.emit("my_awesome_file", 0);
1594 Utils::WaitUntil(check_fn, false);
1595
1596 xdnd_manager_->monitor_changed.emit(2);
1597 Utils::WaitUntil(check_fn, false);
1598
1599 xdnd_manager_->dnd_finished.emit();
1600 Utils::WaitUntil(check_fn, true);
1601}
1602
1547}1603}
15481604
=== added file 'tests/test_xdnd_manager_imp.cpp'
--- tests/test_xdnd_manager_imp.cpp 1970-01-01 00:00:00 +0000
+++ tests/test_xdnd_manager_imp.cpp 2012-11-24 14:30:27 +0000
@@ -0,0 +1,130 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#include <gmock/gmock.h>
21using namespace testing;
22
23#include "launcher/XdndManagerImp.h"
24#include "launcher/XdndCollectionWindow.h"
25#include "launcher/XdndStartStopNotifier.h"
26
27#include "test_utils.h"
28
29#include <Nux/Nux.h>
30#include <X11/Xlib.h>
31
32namespace {
33
34class MockXdndStartStopNotifier : public unity::XdndStartStopNotifier {
35public:
36 typedef std::shared_ptr<MockXdndStartStopNotifier> Ptr;
37};
38
39class MockXdndCollectionWindow : public unity::XdndCollectionWindow {
40public:
41 typedef std::shared_ptr<MockXdndCollectionWindow> Ptr;
42
43 MOCK_METHOD0(Collect, void(void));
44 MOCK_METHOD0(Deactivate, void(void));
45};
46
47class TestXdndManager : public Test {
48public:
49 TestXdndManager()
50 : xdnd_start_stop_notifier_(new MockXdndStartStopNotifier())
51 , xdnd_collection_window_(new MockXdndCollectionWindow())
52 , xdnd_manager(xdnd_start_stop_notifier_, xdnd_collection_window_)
53 {}
54
55 void SetUp()
56 {
57 // Evil hack to avoid crashes.
58 XEvent xevent;
59 xevent.type = ClientMessage;
60 xevent.xany.display = nux::GetGraphicsDisplay()->GetX11Display();
61 xevent.xclient.message_type = XInternAtom(xevent.xany.display, "XdndEnter", false);
62 xevent.xclient.data.l[1] = 5 >> 24;
63
64 nux::GetGraphicsDisplay()->ProcessXEvent(xevent, true);
65 }
66
67 MockXdndStartStopNotifier::Ptr xdnd_start_stop_notifier_;
68 MockXdndCollectionWindow::Ptr xdnd_collection_window_;
69 unity::XdndManagerImp xdnd_manager;
70};
71
72TEST_F(TestXdndManager, SignalDndStartedAndFinished)
73{
74 std::vector<std::string> mimes;
75 mimes.push_back("text/uri-list");
76 mimes.push_back("hello/world");
77
78 auto emit_collected_signal = [&] () {
79 xdnd_collection_window_->collected.emit(mimes);
80 };
81
82 EXPECT_CALL(*xdnd_collection_window_, Collect())
83 .Times(1)
84 .WillOnce(Invoke(emit_collected_signal));
85
86 bool dnd_started_emitted = false;
87 xdnd_manager.dnd_started.connect([&] (std::string const& /*data*/, int /*monitor*/) {
88 dnd_started_emitted = true;
89 });
90
91 xdnd_start_stop_notifier_->started.emit();
92 Utils::WaitUntil(dnd_started_emitted);
93
94 EXPECT_CALL(*xdnd_collection_window_, Deactivate())
95 .Times(1);
96
97 bool dnd_finished_emitted = false;
98 xdnd_manager.dnd_finished.connect([&] () {
99 dnd_finished_emitted = true;
100 });
101
102 xdnd_start_stop_notifier_->finished.emit();
103 Utils::WaitUntil(dnd_finished_emitted);
104}
105
106TEST_F(TestXdndManager, SignalDndStarted_InvalidMimes)
107{
108 std::vector<std::string> mimes;
109 mimes.push_back("hello/world");
110 mimes.push_back("invalid/mimes");
111
112 auto emit_collected_signal = [&] () {
113 xdnd_collection_window_->collected.emit(mimes);
114 };
115
116 EXPECT_CALL(*xdnd_collection_window_, Collect())
117 .Times(1)
118 .WillOnce(Invoke(emit_collected_signal));
119
120 bool dnd_started_emitted = false;
121 xdnd_manager.dnd_started.connect([&] (std::string const& /*data*/, int /*monitor*/) {
122 dnd_started_emitted = true;
123 });
124
125 xdnd_start_stop_notifier_->started.emit();
126
127 EXPECT_FALSE(dnd_started_emitted);
128}
129
130}
0131
=== added file 'tests/test_xdnd_start_stop_notifier_imp.cpp'
--- tests/test_xdnd_start_stop_notifier_imp.cpp 1970-01-01 00:00:00 +0000
+++ tests/test_xdnd_start_stop_notifier_imp.cpp 2012-11-24 14:30:27 +0000
@@ -0,0 +1,107 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3* Copyright (C) 2012 Canonical Ltd
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 3 as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with this program. If not, see <http://www.gnu.org/licenses/>.
16*
17* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18*/
19
20#include <gmock/gmock.h>
21using namespace testing;
22
23#include "XdndStartStopNotifierImp.h"
24
25#include <Nux/Nux.h>
26#include <X11/Xlib.h>
27//#include <X11/extensions/XTest.h>
28
29#include "unity-shared/WindowManager.h"
30#include "test_utils.h"
31
32namespace {
33
34struct TestXdndStartStopNotifierImp : public Test {
35 TestXdndStartStopNotifierImp()
36 : display_(nux::GetGraphicsDisplay()->GetX11Display())
37 , selection_(XInternAtom(display_, "XdndSelection", false))
38 {
39 Window root = DefaultRootWindow(display_);
40 owner_= XCreateSimpleWindow(display_, root, -1000, -1000, 10, 10, 0, 0, 0);
41 }
42
43 Display* display_;
44 Atom selection_;
45 Window owner_;
46
47 unity::XdndStartStopNotifierImp xdnd_start_stop_notifier;
48};
49
50TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalStarted)
51{
52 bool signal_received = false;
53 xdnd_start_stop_notifier.started.connect([&](){
54 signal_received = true;
55 });
56
57 XSetSelectionOwner(display_, selection_, owner_, CurrentTime);
58 //XTestFakeButtonEvent(display_, 1, True, CurrentTime);
59 auto& wm = unity::WindowManager::Default();
60 wm.window_mapped.emit(0);
61
62 Utils::WaitUntil(signal_received);
63 //XTestFakeButtonEvent(display_, 1, False, CurrentTime);
64}
65
66TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalFinished)
67{
68 bool signal_received = false;
69 xdnd_start_stop_notifier.finished.connect([&](){
70 signal_received = true;
71 });
72
73 XSetSelectionOwner(display_, selection_, owner_, CurrentTime);
74 //XTestFakeButtonEvent(display_, 1, True, CurrentTime);
75 auto& wm = unity::WindowManager::Default();
76 wm.window_mapped.emit(0);
77
78 Utils::WaitForTimeoutMSec(500);
79
80 XSetSelectionOwner(display_, selection_, None, CurrentTime);
81 //XTestFakeButtonEvent(display_, 1, False, CurrentTime);
82 wm.window_unmapped.emit(0);
83
84 Utils::WaitUntil(signal_received);
85}
86
87TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalFinished_QT)
88{
89 bool signal_received = false;
90 xdnd_start_stop_notifier.finished.connect([&](){
91 signal_received = true;
92 });
93
94 XSetSelectionOwner(display_, selection_, owner_, CurrentTime);
95 //XTestFakeButtonEvent(display_, 1, True, CurrentTime);
96 auto& wm = unity::WindowManager::Default();
97 wm.window_mapped.emit(0);
98
99 Utils::WaitForTimeoutMSec(500);
100
101 //XTestFakeButtonEvent(display_, 1, False, CurrentTime);
102 wm.window_unmapped.emit(0);
103
104 Utils::WaitUntil(signal_received);
105}
106
107}
0108
=== modified file 'unity-shared/UScreen.cpp'
--- unity-shared/UScreen.cpp 2012-10-29 09:34:54 +0000
+++ unity-shared/UScreen.cpp 2012-11-24 14:30:27 +0000
@@ -89,6 +89,13 @@
89 return monitors_;89 return monitors_;
90}90}
9191
92nux::Geometry UScreen::GetScreenGeometry()
93{
94 int width = gdk_screen_get_width(screen_);
95 int height = gdk_screen_get_height(screen_);
96 return nux::Geometry(0, 0, width, height);
97}
98
92void UScreen::Changed(GdkScreen* screen)99void UScreen::Changed(GdkScreen* screen)
93{100{
94 if (refresh_idle_)101 if (refresh_idle_)
95102
=== modified file 'unity-shared/UScreen.h'
--- unity-shared/UScreen.h 2012-07-24 01:07:58 +0000
+++ unity-shared/UScreen.h 2012-11-24 14:30:27 +0000
@@ -46,6 +46,7 @@
46 nux::Geometry& GetMonitorGeometry(int monitor);46 nux::Geometry& GetMonitorGeometry(int monitor);
4747
48 std::vector<nux::Geometry>& GetMonitors();48 std::vector<nux::Geometry>& GetMonitors();
49 nux::Geometry GetScreenGeometry();
4950
50 // <void, primary_monitor, monitors>51 // <void, primary_monitor, monitors>
51 sigc::signal<void, int, std::vector<nux::Geometry>&> changed;52 sigc::signal<void, int, std::vector<nux::Geometry>&> changed;
5253
=== modified file 'unity-standalone/StandaloneUnity.cpp'
--- unity-standalone/StandaloneUnity.cpp 2012-10-11 01:44:15 +0000
+++ unity-standalone/StandaloneUnity.cpp 2012-11-24 14:30:27 +0000
@@ -86,9 +86,10 @@
8686
87void UnityStandalone::Init ()87void UnityStandalone::Init ()
88{88{
89 launcher_controller.reset(new launcher::Controller());89 auto xdnd_manager = std::make_shared<XdndManager>();
90 panel_controller.reset(new panel::Controller());90 launcher_controller = std::make_shared<launcher::Controller>(xdnd_manager);
91 dash_controller.reset(new dash::Controller());91 panel_controller = std::make_shared<panel::Controller>();
92 dash_controller = std::make_shared<dash::Controller>();
9293
93 dash_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1;94 dash_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1;
94 panel_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1;95 panel_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1;
@@ -119,8 +120,9 @@
119120
120void UnityStandaloneTV::Init()121void UnityStandaloneTV::Init()
121{122{
122 launcher_controller.reset(new launcher::Controller());123 auto xdnd_manager = std::make_shared<XdndManager>();
123 dash_controller.reset(new dash::Controller());124 launcher_controller = std::make_shared<launcher::Controller>(xdnd_manager);
125 dash_controller = std::make_shared<dash::Controller>();
124 dash_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1;126 dash_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1;
125127
126 UBusManager().SendMessage(UBUS_DASH_EXTERNAL_ACTIVATION, nullptr);128 UBusManager().SendMessage(UBUS_DASH_EXTERNAL_ACTIVATION, nullptr);