Merge lp:~azzar1/unity/fix-1035301 into lp:unity
- fix-1035301
- Merge into trunk
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 |
Related bugs: |
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:
# XdndStartStopNo
# XdndCollectionW
# XdndManager*
== Test ==
Unit test added.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Andrea Azzarone (azzar1) wrote : | # |
Ok thank you for the review :) Just one comment:
> 900 + std::vector<
> 901 + for (auto mime : mimes)
> 902 + data.push_
> Can't be happen that std::list<char>
What? :)
Andrea Azzarone (azzar1) wrote : | # |
>
> 1096 + char target[] = "text/uri-list";
>
No we can't. Because nux::..
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> > Can't be happen that std::list<char>
>
> What? :)
Contains a nullptr?
> No we can't. Because nux::..
Ok, we need to fix the API then.
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.
Brandon Schaefer (brandontschaefer) wrote : | # |
784 + controller.
Could we do a make_shared?
883 + SetBackgroundCo
Could you make that nux::color:
884 + SetOpacity(0.0f);
Do we need to set this if it is already transparent?
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.
Brandon Schaefer (brandontschaefer) wrote : | # |
Test pass now :). Looks good code wise, and works! +1
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Preview Diff
1 | === modified file 'launcher/AbstractLauncherIcon.h' |
2 | --- launcher/AbstractLauncherIcon.h 2012-11-15 17:56:23 +0000 |
3 | +++ launcher/AbstractLauncherIcon.h 2012-11-24 14:30:27 +0000 |
4 | @@ -103,6 +103,7 @@ |
5 | RUNNING, |
6 | URGENT, |
7 | PRESENTED, |
8 | + UNFOLDED, |
9 | STARTING, |
10 | SHIMMER, |
11 | CENTER_SAVED, |
12 | |
13 | === modified file 'launcher/CMakeLists.txt' |
14 | --- launcher/CMakeLists.txt 2012-11-15 18:44:55 +0000 |
15 | +++ launcher/CMakeLists.txt 2012-11-24 14:30:27 +0000 |
16 | @@ -33,7 +33,6 @@ |
17 | ApplicationLauncherIcon.cpp |
18 | BFBLauncherIcon.cpp |
19 | CairoBaseWindow.cpp |
20 | - DNDCollectionWindow.cpp |
21 | Decaymulator.cpp |
22 | DesktopLauncherIcon.cpp |
23 | DeviceLauncherSection.cpp |
24 | @@ -73,6 +72,10 @@ |
25 | VolumeImp.cpp |
26 | VolumeLauncherIcon.cpp |
27 | VolumeMonitorWrapper.cpp |
28 | + XdndCollectionWindowImp.cpp |
29 | + XdndManagerImp.cpp |
30 | + XdndStartStopNotifier.cpp |
31 | + XdndStartStopNotifierImp.cpp |
32 | ) |
33 | |
34 | if (ENABLE_X_SUPPORT) |
35 | |
36 | === removed file 'launcher/DNDCollectionWindow.cpp' |
37 | --- launcher/DNDCollectionWindow.cpp 2012-10-11 01:44:15 +0000 |
38 | +++ launcher/DNDCollectionWindow.cpp 1970-01-01 00:00:00 +0000 |
39 | @@ -1,99 +0,0 @@ |
40 | -// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
41 | -/* |
42 | -* Copyright (C) 2011 Canonical Ltd |
43 | -* |
44 | -* This program is free software: you can redistribute it and/or modify |
45 | -* it under the terms of the GNU General Public License version 3 as |
46 | -* published by the Free Software Foundation. |
47 | -* |
48 | -* This program is distributed in the hope that it will be useful, |
49 | -* but WITHOUT ANY WARRANTY; without even the implied warranty of |
50 | -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
51 | -* GNU General Public License for more details. |
52 | -* |
53 | -* You should have received a copy of the GNU General Public License |
54 | -* along with this program. If not, see <http://www.gnu.org/licenses/>. |
55 | -* |
56 | -* Authored by: Andrea Azzarone <azzaronea@gmail.com> |
57 | -*/ |
58 | - |
59 | -#include "DNDCollectionWindow.h" |
60 | - |
61 | -#include "unity-shared/WindowManager.h" |
62 | - |
63 | -namespace unity { |
64 | - |
65 | -NUX_IMPLEMENT_OBJECT_TYPE(DNDCollectionWindow); |
66 | - |
67 | -DNDCollectionWindow::DNDCollectionWindow() |
68 | - : nux::BaseWindow("") |
69 | - , display(NULL) |
70 | -{ |
71 | - // Make it invisible... |
72 | - SetBackgroundColor(nux::Color(0x00000000)); |
73 | - SetOpacity(0.0f); |
74 | - // ... and as big as the whole screen. |
75 | - WindowManager& wm = WindowManager::Default(); |
76 | - SetGeometry(wm.GetScreenGeometry()); |
77 | - |
78 | - ShowWindow(true); |
79 | - PushToBack(); |
80 | - // Hack to create the X Window as soon as possible. |
81 | - EnableInputWindow(true, "DNDCollectionWindow"); |
82 | - EnableInputWindow(false, "DNDCollectionWindow"); |
83 | - SetDndEnabled(false, true); |
84 | - |
85 | - wm.window_moved.connect(sigc::mem_fun(this, &DNDCollectionWindow::OnWindowMoved)); |
86 | -} |
87 | - |
88 | -DNDCollectionWindow::~DNDCollectionWindow() |
89 | -{ |
90 | - for (auto it : mimes_) |
91 | - g_free(it); |
92 | -} |
93 | - |
94 | -/** |
95 | - * EnableInputWindow doesn't show the window immediately. |
96 | - * Since nux::EnableInputWindow uses XMoveResizeWindow the best way to know if |
97 | - * the X Window is really on/off screen is receiving WindowManager::window_moved |
98 | - * signal. Please don't hate me! |
99 | - **/ |
100 | -void DNDCollectionWindow::OnWindowMoved(Window window_id) |
101 | -{ |
102 | - if (window_id == GetInputWindowId() && display() != NULL) |
103 | - { |
104 | - // Create a fake mouse move because sometimes an extra one is required. |
105 | - XWarpPointer(display(), None, None, 0, 0, 0, 0, 0, 0); |
106 | - XFlush(display()); |
107 | - } |
108 | -} |
109 | - |
110 | -void DNDCollectionWindow::Collect() |
111 | -{ |
112 | - // Using PushToFront we're sure that the window is shown over the panel window, |
113 | - // the launcher window and the dash window. Don't forget to call PushToBack as |
114 | - // soon as possible. |
115 | - PushToFront(); |
116 | - EnableInputWindow(true, "DndCollectionWindow"); |
117 | -} |
118 | - |
119 | -void DNDCollectionWindow::ProcessDndMove(int x, int y, std::list<char*> mimes) |
120 | -{ |
121 | - // Hide the window as soon as possible. |
122 | - PushToBack(); |
123 | - EnableInputWindow(false, "DNDCollectionWindow"); |
124 | - |
125 | - // Free mimes_ before fill it again. |
126 | - for (auto it : mimes_) |
127 | - g_free(it); |
128 | - mimes_.clear(); |
129 | - |
130 | - // Duplicate the list. |
131 | - for (auto it : mimes) |
132 | - mimes_.push_back(g_strdup(it)); |
133 | - |
134 | - // Emit the collected signal. |
135 | - collected.emit(mimes_); |
136 | -} |
137 | - |
138 | -} // namespace unity |
139 | |
140 | === removed file 'launcher/DNDCollectionWindow.h' |
141 | --- launcher/DNDCollectionWindow.h 2012-10-11 01:44:15 +0000 |
142 | +++ launcher/DNDCollectionWindow.h 1970-01-01 00:00:00 +0000 |
143 | @@ -1,63 +0,0 @@ |
144 | -// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
145 | -/* |
146 | -* Copyright (C) 2011 Canonical Ltd |
147 | -* |
148 | -* This program is free software: you can redistribute it and/or modify |
149 | -* it under the terms of the GNU General Public License version 3 as |
150 | -* published by the Free Software Foundation. |
151 | -* |
152 | -* This program is distributed in the hope that it will be useful, |
153 | -* but WITHOUT ANY WARRANTY; without even the implied warranty of |
154 | -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
155 | -* GNU General Public License for more details. |
156 | -* |
157 | -* You should have received a copy of the GNU General Public License |
158 | -* along with this program. If not, see <http://www.gnu.org/licenses/>. |
159 | -* |
160 | -* Authored by: Andrea Azzarone <azzaronea@gmail.com> |
161 | -*/ |
162 | - |
163 | -#ifndef DNDCOLLECTIONWINDOW_H |
164 | -#define DNDCOLLECTIONWINDOW_H |
165 | - |
166 | -#include <list> |
167 | - |
168 | -#include <Nux/Nux.h> |
169 | -#include <Nux/BaseWindow.h> |
170 | -#include <sigc++/sigc++.h> |
171 | - |
172 | -namespace unity { |
173 | - |
174 | -/** |
175 | - * DNDCollectionWindow makes it possible to collect drag and drop (dnd) data as |
176 | - * soon as dnd starts and not when the mouse pointer enter the x window. |
177 | - **/ |
178 | - |
179 | -class DNDCollectionWindow : public nux::BaseWindow |
180 | -{ |
181 | -NUX_DECLARE_OBJECT_TYPE(DNDCollectionWindow, nux::BaseWindow); |
182 | - |
183 | -// Methods |
184 | -public: |
185 | - DNDCollectionWindow(); |
186 | - ~DNDCollectionWindow(); |
187 | - |
188 | - void Collect(); |
189 | - |
190 | -private: |
191 | - void ProcessDndMove(int x, int y, std::list<char*> mimes); |
192 | - void OnWindowMoved(Window window_id); |
193 | - |
194 | -// Members |
195 | -public: |
196 | - nux::Property<Display*> display; |
197 | - |
198 | - sigc::signal<void, const std::list<char*>&> collected; |
199 | - |
200 | -private: |
201 | - std::list<char*> mimes_; |
202 | -}; |
203 | - |
204 | -} // namespace unity |
205 | - |
206 | -#endif // DNDCOLLECTIONWINDOW_H |
207 | |
208 | === modified file 'launcher/Launcher.cpp' |
209 | --- launcher/Launcher.cpp 2012-11-16 15:58:49 +0000 |
210 | +++ launcher/Launcher.cpp 2012-11-24 14:30:27 +0000 |
211 | @@ -91,7 +91,6 @@ |
212 | const int MOUSE_DEADZONE = 15; |
213 | const float DRAG_OUT_PIXELS = 300.0f; |
214 | |
215 | -const std::string DND_CHECK_TIMEOUT = "dnd-check-timeout"; |
216 | const std::string START_DRAGICON_TIMEOUT = "start-dragicon-timeout"; |
217 | const std::string SCROLL_TIMEOUT = "scroll-timeout"; |
218 | const std::string ANIMATION_IDLE = "animation-idle"; |
219 | @@ -103,7 +102,6 @@ |
220 | const int Launcher::Launcher::ANIM_DURATION_SHORT = 125; |
221 | |
222 | Launcher::Launcher(nux::BaseWindow* parent, |
223 | - nux::ObjectPtr<DNDCollectionWindow> const& collection_window, |
224 | NUX_FILE_LINE_DECL) |
225 | : View(NUX_FILE_LINE_PARAM) |
226 | #ifdef USE_X11 |
227 | @@ -145,14 +143,11 @@ |
228 | , _drag_out_delta_x(0.0f) |
229 | , _drag_gesture_ongoing(false) |
230 | , _last_reveal_progress(0.0f) |
231 | - , _collection_window(collection_window) |
232 | , _selection_atom(0) |
233 | , _background_color(nux::color::DimGray) |
234 | { |
235 | m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION); |
236 | |
237 | - _collection_window->collected.connect(sigc::mem_fun(this, &Launcher::OnDNDDataCollected)); |
238 | - |
239 | bg_effect_helper_.owner = this; |
240 | bg_effect_helper_.enabled = false; |
241 | |
242 | @@ -180,18 +175,12 @@ |
243 | ql_manager.quicklist_closed.connect(sigc::mem_fun(this, &Launcher::RecvQuicklistClosed)); |
244 | |
245 | WindowManager& wm = WindowManager::Default(); |
246 | - wm.window_mapped.connect(sigc::hide(sigc::mem_fun(this, &Launcher::DndTimeoutSetup))); |
247 | - wm.window_unmapped.connect(sigc::hide(sigc::mem_fun(this, &Launcher::DndTimeoutSetup))); |
248 | wm.initiate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); |
249 | wm.initiate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); |
250 | wm.terminate_spread.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); |
251 | wm.terminate_expo.connect(sigc::mem_fun(this, &Launcher::OnPluginStateChanged)); |
252 | wm.screen_viewport_switch_ended.connect(sigc::mem_fun(this, &Launcher::EnsureAnimation)); |
253 | |
254 | -#ifdef USE_X11 |
255 | - display.changed.connect(sigc::mem_fun(this, &Launcher::OnDisplayChanged)); |
256 | -#endif |
257 | - |
258 | // 0 out timers to avoid wonky startups |
259 | for (int i = 0; i < TIME_LAST; ++i) |
260 | { |
261 | @@ -227,11 +216,6 @@ |
262 | return "Launcher"; |
263 | } |
264 | |
265 | -void Launcher::OnDisplayChanged(Display* display) |
266 | -{ |
267 | - _collection_window->display = display; |
268 | -} |
269 | - |
270 | #ifdef NUX_GESTURES_SUPPORT |
271 | void Launcher::OnDragStart(const nux::GestureEvent &event) |
272 | { |
273 | @@ -399,6 +383,10 @@ |
274 | if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) |
275 | return true; |
276 | |
277 | + time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED); |
278 | + if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION) |
279 | + return true; |
280 | + |
281 | time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::SHIMMER); |
282 | if (unity::TimeUtil::TimeDelta(¤t, &time) < ANIM_DURATION_LONG) |
283 | return true; |
284 | @@ -552,6 +540,18 @@ |
285 | return 1.0f - result; |
286 | } |
287 | |
288 | +float Launcher::IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const |
289 | +{ |
290 | + struct timespec icon_unfold_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::UNFOLDED); |
291 | + int ms = unity::TimeUtil::TimeDelta(¤t, &icon_unfold_time); |
292 | + float result = CLAMP((float) ms / (float) ANIM_DURATION, 0.0f, 1.0f); |
293 | + |
294 | + if (icon->GetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED)) |
295 | + return result; |
296 | + else |
297 | + return 1.0f - result; |
298 | +} |
299 | + |
300 | float Launcher::IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const |
301 | { |
302 | struct timespec urgent_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::URGENT); |
303 | @@ -919,13 +919,14 @@ |
304 | |
305 | // goes for 0.0f when fully unfolded, to 1.0f folded |
306 | float folding_progress = CLAMP((center.y + _icon_size - folding_threshold) / (float) _icon_size, 0.0f, 1.0f); |
307 | - float present_progress = IconPresentProgress(icon, current); |
308 | + float unfold_progress = IconUnfoldProgress(icon, current); |
309 | |
310 | - folding_progress *= 1.0f - present_progress; |
311 | + folding_progress *= 1.0f - unfold_progress; |
312 | |
313 | float half_size = (folded_size / 2.0f) + (_icon_size / 2.0f - folded_size / 2.0f) * (1.0f - folding_progress); |
314 | float icon_hide_offset = autohide_offset; |
315 | |
316 | + float present_progress = IconPresentProgress(icon, current); |
317 | icon_hide_offset *= 1.0f - (present_progress * icon->PresentUrgency()); |
318 | |
319 | // icon is crossing threshold, start folding |
320 | @@ -1017,8 +1018,8 @@ |
321 | // magic constant must some day be explained, for now suffice to say this constant prevents the bottom from "marching"; |
322 | float magic_constant = 1.3f; |
323 | |
324 | - float present_progress = IconPresentProgress(*it, current); |
325 | - folding_threshold -= CLAMP(sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * present_progress); |
326 | + float unfold_progress = IconUnfoldProgress(*it, current); |
327 | + folding_threshold -= CLAMP(sum - launcher_height, 0.0f, height * magic_constant) * (folding_constant + (1.0f - folding_constant) * unfold_progress); |
328 | } |
329 | |
330 | if (sum - _space_between_icons <= launcher_height) |
331 | @@ -1366,59 +1367,6 @@ |
332 | return _mouse_position.y; |
333 | } |
334 | |
335 | -bool Launcher::OnUpdateDragManagerTimeout() |
336 | -{ |
337 | -#ifdef USE_X11 |
338 | - if (!display()) |
339 | - return false; |
340 | - |
341 | - if (!_selection_atom) |
342 | - _selection_atom = XInternAtom(display(), "XdndSelection", false); |
343 | - |
344 | - Window drag_owner = XGetSelectionOwner(display(), _selection_atom); |
345 | - |
346 | - // evil hack because Qt does not release the seelction owner on drag finished |
347 | - Window root_r, child_r; |
348 | - int root_x_r, root_y_r, win_x_r, win_y_r; |
349 | - unsigned int mask; |
350 | - XQueryPointer(display(), DefaultRootWindow(display()), &root_r, &child_r, &root_x_r, &root_y_r, &win_x_r, &win_y_r, &mask); |
351 | - |
352 | - if (drag_owner && (mask & (Button1Mask | Button2Mask | Button3Mask))) |
353 | - { |
354 | - if (_data_checked == false) |
355 | - { |
356 | - _data_checked = true; |
357 | - _collection_window->Collect(); |
358 | - } |
359 | - |
360 | - return true; |
361 | - } |
362 | - |
363 | - _data_checked = false; |
364 | - _collection_window->PushToBack(); |
365 | - _collection_window->EnableInputWindow(false, "DNDCollectionWindow"); |
366 | - |
367 | - if (IsOverlayOpen() && !_hovered) |
368 | - DesaturateIcons(); |
369 | - |
370 | - DndReset(); |
371 | - _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false); |
372 | - _hide_machine.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, false); |
373 | -#endif |
374 | - return false; |
375 | -} |
376 | - |
377 | -void Launcher::DndTimeoutSetup() |
378 | -{ |
379 | -#ifdef USE_X11 |
380 | - if (sources_.GetSource(DND_CHECK_TIMEOUT)) |
381 | - return; |
382 | - |
383 | - auto cb_func = sigc::mem_fun(this, &Launcher::OnUpdateDragManagerTimeout); |
384 | - sources_.AddTimeout(200, cb_func, DND_CHECK_TIMEOUT); |
385 | -#endif |
386 | -} |
387 | - |
388 | void Launcher::OnPluginStateChanged() |
389 | { |
390 | WindowManager& wm = WindowManager::Default(); |
391 | @@ -2566,53 +2514,6 @@ |
392 | return (boost::algorithm::ends_with(uri, ".desktop") || uri.find("device://") == 0); |
393 | } |
394 | |
395 | -void Launcher::OnDNDDataCollected(const std::list<char*>& mimes) |
396 | -{ |
397 | -#ifdef USE_X11 |
398 | - _dnd_data.Reset(); |
399 | - |
400 | - const std::string uri_list = "text/uri-list"; |
401 | - auto& display = nux::GetWindowThread()->GetGraphicsDisplay(); |
402 | - |
403 | - for (auto const& mime : mimes) |
404 | - { |
405 | - if (mime != uri_list) |
406 | - continue; |
407 | - |
408 | - _dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str()))); |
409 | - break; |
410 | - } |
411 | - |
412 | - _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true); |
413 | - |
414 | - auto const& uris = _dnd_data.Uris(); |
415 | - if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri) |
416 | - {return DndIsSpecialRequest(uri);}) != uris.end()) |
417 | - { |
418 | - _steal_drag = true; |
419 | - |
420 | - if (IsOverlayOpen()) |
421 | - SaturateIcons(); |
422 | - } |
423 | - else |
424 | - { |
425 | - for (auto const& it : *_model) |
426 | - { |
427 | - if (it->ShouldHighlightOnDrag(_dnd_data)) |
428 | - { |
429 | - it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false); |
430 | - it->SetQuirk(AbstractLauncherIcon::Quirk::PRESENTED, true); |
431 | - } |
432 | - else |
433 | - { |
434 | - it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true); |
435 | - it->SetQuirk(AbstractLauncherIcon::Quirk::PRESENTED, false); |
436 | - } |
437 | - } |
438 | - } |
439 | -#endif |
440 | -} |
441 | - |
442 | void Launcher::ProcessDndEnter() |
443 | { |
444 | #ifdef USE_X11 |
445 | @@ -2648,7 +2549,7 @@ |
446 | it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, is_overlay_open && !_hovered); |
447 | } |
448 | |
449 | - it->SetQuirk(AbstractLauncherIcon::Quirk::PRESENTED, false); |
450 | + it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false); |
451 | } |
452 | |
453 | DndHoveredIconReset(); |
454 | @@ -2873,5 +2774,69 @@ |
455 | return _launcher_drag_delta; |
456 | } |
457 | |
458 | +void Launcher::DndStarted(std::string const& data) |
459 | +{ |
460 | +#ifdef USE_X11 |
461 | + SetDndQuirk(); |
462 | + |
463 | + _dnd_data.Fill(data.c_str()); |
464 | + |
465 | + auto const& uris = _dnd_data.Uris(); |
466 | + if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri) |
467 | + {return DndIsSpecialRequest(uri);}) != uris.end()) |
468 | + { |
469 | + _steal_drag = true; |
470 | + |
471 | + if (IsOverlayOpen()) |
472 | + SaturateIcons(); |
473 | + } |
474 | + else |
475 | + { |
476 | + for (auto const& it : *_model) |
477 | + { |
478 | + if (it->ShouldHighlightOnDrag(_dnd_data)) |
479 | + { |
480 | + it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false); |
481 | + it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, true); |
482 | + } |
483 | + else |
484 | + { |
485 | + it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, true); |
486 | + it->SetQuirk(AbstractLauncherIcon::Quirk::UNFOLDED, false); |
487 | + } |
488 | + } |
489 | + } |
490 | +#endif |
491 | +} |
492 | + |
493 | +void Launcher::DndFinished() |
494 | +{ |
495 | +#ifdef USE_X11 |
496 | + UnsetDndQuirk(); |
497 | + |
498 | + _data_checked = false; |
499 | + |
500 | + if (IsOverlayOpen() && !_hovered) |
501 | + DesaturateIcons(); |
502 | + |
503 | + DndReset(); |
504 | +#endif |
505 | +} |
506 | + |
507 | +void Launcher::SetDndQuirk() |
508 | +{ |
509 | +#ifdef USE_X11 |
510 | + _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true); |
511 | +#endif |
512 | +} |
513 | + |
514 | +void Launcher::UnsetDndQuirk() |
515 | +{ |
516 | +#ifdef USE_X11 |
517 | + _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false); |
518 | + _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false); |
519 | +#endif |
520 | +} |
521 | + |
522 | } // namespace launcher |
523 | } // namespace unity |
524 | |
525 | === modified file 'launcher/Launcher.h' |
526 | --- launcher/Launcher.h 2012-11-13 22:39:49 +0000 |
527 | +++ launcher/Launcher.h 2012-11-24 14:30:27 +0000 |
528 | @@ -32,7 +32,6 @@ |
529 | #include "unity-shared/AbstractIconRenderer.h" |
530 | #include "unity-shared/BackgroundEffectHelper.h" |
531 | #include "DevicesSettings.h" |
532 | -#include "DNDCollectionWindow.h" |
533 | #include "DndData.h" |
534 | #include "unity-shared/Introspectable.h" |
535 | #include "LauncherModel.h" |
536 | @@ -66,7 +65,7 @@ |
537 | NUX_DECLARE_OBJECT_TYPE(Launcher, nux::View); |
538 | public: |
539 | |
540 | - Launcher(nux::BaseWindow* parent, nux::ObjectPtr<DNDCollectionWindow> const& collection_window, NUX_FILE_LINE_PROTO); |
541 | + Launcher(nux::BaseWindow* parent, NUX_FILE_LINE_PROTO); |
542 | |
543 | nux::Property<Display*> display; |
544 | nux::Property<int> monitor; |
545 | @@ -127,6 +126,11 @@ |
546 | int GetDragDelta() const; |
547 | void SetHover(bool hovered); |
548 | |
549 | + void DndStarted(std::string const& mimes); |
550 | + void DndFinished(); |
551 | + void SetDndQuirk(); |
552 | + void UnsetDndQuirk(); |
553 | + |
554 | sigc::signal<void, std::string const&, AbstractLauncherIcon::Ptr const&> add_request; |
555 | sigc::signal<void, AbstractLauncherIcon::Ptr const&> remove_request; |
556 | sigc::signal<void> selection_change; |
557 | @@ -213,7 +217,6 @@ |
558 | bool StrutHack(); |
559 | bool StartIconDragTimeout(int x, int y); |
560 | bool OnScrollTimeout(); |
561 | - bool OnUpdateDragManagerTimeout(); |
562 | |
563 | void SetMousePosition(int x, int y); |
564 | |
565 | @@ -248,6 +251,7 @@ |
566 | float DragOutProgress(struct timespec const& current) const; |
567 | float IconDesatValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; |
568 | float IconPresentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; |
569 | + float IconUnfoldProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; |
570 | float IconUrgentProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; |
571 | float IconShimmerProgress(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; |
572 | float IconUrgentPulseValue(AbstractLauncherIcon::Ptr const& icon, struct timespec const& current) const; |
573 | @@ -322,12 +326,8 @@ |
574 | |
575 | virtual long PostLayoutManagement(long LayoutResult); |
576 | |
577 | - void OnDisplayChanged(Display* display); |
578 | - void OnDNDDataCollected(const std::list<char*>& mimes); |
579 | - |
580 | void DndReset(); |
581 | void DndHoveredIconReset(); |
582 | - void DndTimeoutSetup(); |
583 | bool DndIsSpecialRequest(std::string const& uri) const; |
584 | |
585 | LauncherModel::Ptr _model; |
586 | @@ -383,7 +383,6 @@ |
587 | nux::Point2 _mouse_position; |
588 | nux::ObjectPtr<nux::IOpenGLBaseTexture> _offscreen_drag_texture; |
589 | nux::ObjectPtr<LauncherDragWindow> _drag_window; |
590 | - nux::ObjectPtr<unity::DNDCollectionWindow> _collection_window; |
591 | LauncherHideMachine _hide_machine; |
592 | LauncherHoverMachine _hover_machine; |
593 | |
594 | |
595 | === modified file 'launcher/LauncherController.cpp' |
596 | --- launcher/LauncherController.cpp 2012-11-15 17:56:23 +0000 |
597 | +++ launcher/LauncherController.cpp 2012-11-24 14:30:27 +0000 |
598 | @@ -95,10 +95,11 @@ |
599 | { Controller::Impl::OnDBusMethodCall, NULL, NULL}; |
600 | |
601 | |
602 | -Controller::Impl::Impl(Controller* parent) |
603 | +Controller::Impl::Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager) |
604 | : parent_(parent) |
605 | , model_(std::make_shared<LauncherModel>()) |
606 | , matcher_(bamf_matcher_get_default()) |
607 | + , xdnd_manager_(xdnd_manager) |
608 | , device_section_(std::make_shared<VolumeMonitorWrapper>(), std::make_shared<DevicesSettingsImp>()) |
609 | , expo_icon_(new ExpoLauncherIcon()) |
610 | , desktop_icon_(new DesktopLauncherIcon()) |
611 | @@ -161,6 +162,10 @@ |
612 | }); |
613 | |
614 | parent_->AddChild(model_.get()); |
615 | + |
616 | + xdnd_manager_->dnd_started.connect(sigc::mem_fun(this, &Impl::OnDndStarted)); |
617 | + xdnd_manager_->dnd_finished.connect(sigc::mem_fun(this, &Impl::OnDndFinished)); |
618 | + xdnd_manager_->monitor_changed.connect(sigc::mem_fun(this, &Impl::OnDndMonitorChanged)); |
619 | } |
620 | |
621 | Controller::Impl::~Impl() |
622 | @@ -255,11 +260,47 @@ |
623 | } |
624 | } |
625 | |
626 | +void Controller::Impl::OnDndStarted(std::string const& data, int monitor) |
627 | +{ |
628 | + if (parent_->multiple_launchers) |
629 | + { |
630 | + last_dnd_monitor_ = monitor; |
631 | + launchers[last_dnd_monitor_]->DndStarted(data); |
632 | + } |
633 | + else |
634 | + { |
635 | + launcher_->DndStarted(data); |
636 | + } |
637 | +} |
638 | + |
639 | +void Controller::Impl::OnDndFinished() |
640 | +{ |
641 | + if (parent_->multiple_launchers) |
642 | + { |
643 | + launchers[last_dnd_monitor_]->DndFinished(); |
644 | + last_dnd_monitor_ = -1; |
645 | + } |
646 | + else |
647 | + { |
648 | + launcher_->DndFinished(); |
649 | + } |
650 | +} |
651 | + |
652 | +void Controller::Impl::OnDndMonitorChanged(int monitor) |
653 | +{ |
654 | + if (parent_->multiple_launchers) |
655 | + { |
656 | + launchers[last_dnd_monitor_]->UnsetDndQuirk(); |
657 | + last_dnd_monitor_ = monitor; |
658 | + launchers[last_dnd_monitor_]->SetDndQuirk(); |
659 | + } |
660 | +} |
661 | + |
662 | Launcher* Controller::Impl::CreateLauncher(int monitor) |
663 | { |
664 | nux::BaseWindow* launcher_window = new nux::BaseWindow(TEXT("LauncherWindow")); |
665 | |
666 | - Launcher* launcher = new Launcher(launcher_window, nux::ObjectPtr<DNDCollectionWindow>(new DNDCollectionWindow)); |
667 | + Launcher* launcher = new Launcher(launcher_window); |
668 | launcher->monitor = monitor; |
669 | launcher->options = parent_->options(); |
670 | launcher->SetModel(model_); |
671 | @@ -974,10 +1015,10 @@ |
672 | g_variant_new("(sus)", "home.lens", dash::NOT_HANDLED, "")); |
673 | } |
674 | |
675 | -Controller::Controller() |
676 | +Controller::Controller(XdndManager::Ptr const& xdnd_manager) |
677 | : options(Options::Ptr(new Options())) |
678 | , multiple_launchers(true) |
679 | - , pimpl(new Impl(this)) |
680 | + , pimpl(new Impl(this, xdnd_manager)) |
681 | { |
682 | multiple_launchers.changed.connect([&](bool value) -> void { |
683 | UScreen* uscreen = UScreen::GetDefault(); |
684 | |
685 | === modified file 'launcher/LauncherController.h' |
686 | --- launcher/LauncherController.h 2012-11-06 18:19:09 +0000 |
687 | +++ launcher/LauncherController.h 2012-11-24 14:30:27 +0000 |
688 | @@ -27,6 +27,7 @@ |
689 | |
690 | #include "LauncherOptions.h" |
691 | #include "SoftwareCenterLauncherIcon.h" |
692 | +#include "XdndManager.h" |
693 | |
694 | namespace unity |
695 | { |
696 | @@ -47,7 +48,7 @@ |
697 | nux::Property<Options::Ptr> options; |
698 | nux::Property<bool> multiple_launchers; |
699 | |
700 | - Controller(); |
701 | + Controller(XdndManager::Ptr const& xdnd_manager); |
702 | ~Controller(); |
703 | |
704 | Launcher& launcher() const; |
705 | |
706 | === modified file 'launcher/LauncherControllerPrivate.h' |
707 | --- launcher/LauncherControllerPrivate.h 2012-11-15 17:56:23 +0000 |
708 | +++ launcher/LauncherControllerPrivate.h 2012-11-24 14:30:27 +0000 |
709 | @@ -39,6 +39,7 @@ |
710 | #include "SoftwareCenterLauncherIcon.h" |
711 | #include "unity-shared/UBusWrapper.h" |
712 | #include "VolumeMonitorWrapper.h" |
713 | +#include "XdndManager.h" |
714 | |
715 | namespace unity |
716 | { |
717 | @@ -48,7 +49,7 @@ |
718 | class Controller::Impl |
719 | { |
720 | public: |
721 | - Impl(Controller* parent); |
722 | + Impl(Controller* parent, XdndManager::Ptr const& xdnd_manager); |
723 | ~Impl(); |
724 | |
725 | void UpdateNumWorkspaces(int workspaces); |
726 | @@ -111,6 +112,10 @@ |
727 | |
728 | void OpenQuicklist(); |
729 | |
730 | + void OnDndStarted(std::string const& data, int monitor); |
731 | + void OnDndFinished(); |
732 | + void OnDndMonitorChanged(int monitor); |
733 | + |
734 | static void OnBusAcquired(GDBusConnection* connection, const gchar* name, gpointer user_data); |
735 | static void OnDBusMethodCall(GDBusConnection* connection, const gchar* sender, const gchar* object_path, |
736 | const gchar* interface_name, const gchar* method_name, |
737 | @@ -124,6 +129,7 @@ |
738 | glib::Object<BamfMatcher> matcher_; |
739 | nux::ObjectPtr<Launcher> launcher_; |
740 | nux::ObjectPtr<Launcher> keyboard_launcher_; |
741 | + XdndManager::Ptr xdnd_manager_; |
742 | DeviceLauncherSection device_section_; |
743 | LauncherEntryRemoteModel remote_model_; |
744 | AbstractLauncherIcon::Ptr expo_icon_; |
745 | @@ -143,6 +149,7 @@ |
746 | int reactivate_index; |
747 | bool keynav_restore_window_; |
748 | int launcher_key_press_time_; |
749 | + int last_dnd_monitor_; |
750 | |
751 | unsigned dbus_owner_; |
752 | GDBusConnection* gdbus_connection_; |
753 | |
754 | === modified file 'launcher/LauncherIcon.cpp' |
755 | --- launcher/LauncherIcon.cpp 2012-11-15 17:56:23 +0000 |
756 | +++ launcher/LauncherIcon.cpp 2012-11-24 14:30:27 +0000 |
757 | @@ -801,6 +801,7 @@ |
758 | |
759 | _present_urgency = CLAMP(present_urgency, 0.0f, 1.0f); |
760 | SetQuirk(Quirk::PRESENTED, true); |
761 | + SetQuirk(Quirk::UNFOLDED, true); |
762 | } |
763 | |
764 | void |
765 | @@ -811,6 +812,7 @@ |
766 | |
767 | _source_manager.Remove(PRESENT_TIMEOUT); |
768 | SetQuirk(Quirk::PRESENTED, false); |
769 | + SetQuirk(Quirk::UNFOLDED, false); |
770 | } |
771 | |
772 | void |
773 | |
774 | === modified file 'launcher/StandaloneLauncher.cpp' |
775 | --- launcher/StandaloneLauncher.cpp 2012-10-17 22:16:48 +0000 |
776 | +++ launcher/StandaloneLauncher.cpp 2012-11-24 14:30:27 +0000 |
777 | @@ -35,8 +35,8 @@ |
778 | |
779 | void ThreadWidgetInit(nux::NThread* thread, void* InitData) |
780 | { |
781 | -// launcherWindow->SetGeometry (nux::Geometry(0, 0, 300, 800)); |
782 | - controller.reset(new launcher::Controller()); |
783 | + auto xdnd_manager = std::make_shared<XdndManager>(); |
784 | + controller = std::make_shared<launcher::Controller>(xdnd_manager); |
785 | } |
786 | |
787 | int main(int argc, char** argv) |
788 | |
789 | === added file 'launcher/XdndCollectionWindow.h' |
790 | --- launcher/XdndCollectionWindow.h 1970-01-01 00:00:00 +0000 |
791 | +++ launcher/XdndCollectionWindow.h 2012-11-24 14:30:27 +0000 |
792 | @@ -0,0 +1,51 @@ |
793 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
794 | +/* |
795 | +* Copyright (C) 2012 Canonical Ltd |
796 | +* |
797 | +* This program is free software: you can redistribute it and/or modify |
798 | +* it under the terms of the GNU General Public License version 3 as |
799 | +* published by the Free Software Foundation. |
800 | +* |
801 | +* This program is distributed in the hope that it will be useful, |
802 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
803 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
804 | +* GNU General Public License for more details. |
805 | +* |
806 | +* You should have received a copy of the GNU General Public License |
807 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
808 | +* |
809 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
810 | +*/ |
811 | + |
812 | +#ifndef UNITYSHELL_XDND_COLLECTION_WINDOW_H |
813 | +#define UNITYSHELL_XDND_COLLECTION_WINDOW_H |
814 | + |
815 | +#include <boost/noncopyable.hpp> |
816 | +#include <memory> |
817 | +#include <sigc++/signal.h> |
818 | +#include <string> |
819 | +#include <vector> |
820 | + |
821 | +namespace unity { |
822 | + |
823 | +/** |
824 | + * XdndCollectionWindow makes it possible to collect drag and drop data as |
825 | + * soon as dnd starts and not when the mouse pointer enter the x window. |
826 | + **/ |
827 | + |
828 | +class XdndCollectionWindow : boost::noncopyable |
829 | +{ |
830 | +public: |
831 | + typedef std::shared_ptr<XdndCollectionWindow> Ptr; |
832 | + |
833 | + virtual ~XdndCollectionWindow() {} |
834 | + |
835 | + virtual void Collect() = 0; |
836 | + virtual void Deactivate() = 0; |
837 | + |
838 | + sigc::signal<void, std::vector<std::string>> collected; |
839 | +}; |
840 | + |
841 | +} |
842 | + |
843 | +#endif |
844 | |
845 | === added file 'launcher/XdndCollectionWindowImp.cpp' |
846 | --- launcher/XdndCollectionWindowImp.cpp 1970-01-01 00:00:00 +0000 |
847 | +++ launcher/XdndCollectionWindowImp.cpp 2012-11-24 14:30:27 +0000 |
848 | @@ -0,0 +1,112 @@ |
849 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
850 | +/* |
851 | +* Copyright (C) 2011 Canonical Ltd |
852 | +* |
853 | +* This program is free software: you can redistribute it and/or modify |
854 | +* it under the terms of the GNU General Public License version 3 as |
855 | +* published by the Free Software Foundation. |
856 | +* |
857 | +* This program is distributed in the hope that it will be useful, |
858 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
859 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
860 | +* GNU General Public License for more details. |
861 | +* |
862 | +* You should have received a copy of the GNU General Public License |
863 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
864 | +* |
865 | +* Authored by: Andrea Azzarone <azzaronea@gmail.com> |
866 | +*/ |
867 | + |
868 | +#include "XdndCollectionWindowImp.h" |
869 | +#include "unity-shared/UScreen.h" |
870 | +#include "unity-shared/WindowManager.h" |
871 | + |
872 | +namespace unity { |
873 | +namespace { |
874 | + |
875 | +class PrivateWindow : public nux::BaseWindow |
876 | +{ |
877 | +public: |
878 | + PrivateWindow(XdndCollectionWindowImp* parent) |
879 | + : nux::BaseWindow("") |
880 | + , parent_(parent) |
881 | + { |
882 | + // Make it invisible... |
883 | + SetBackgroundColor(nux::color::Transparent); |
884 | + SetOpacity(0.0f); |
885 | + // ... and as big as the whole screen. |
886 | + auto uscreen = UScreen::GetDefault(); |
887 | + SetGeometry(uscreen->GetScreenGeometry()); |
888 | + |
889 | + ShowWindow(true); |
890 | + PushToBack(); |
891 | + // Hack to create the X Window as soon as possible. |
892 | + EnableInputWindow(true, "XdndCollectionWindowImp"); |
893 | + EnableInputWindow(false, "XdndCollectionWindowImp"); |
894 | + SetDndEnabled(false, true); |
895 | + |
896 | + uscreen->changed.connect(sigc::mem_fun(this, &PrivateWindow::OnScreenChanged)); |
897 | + WindowManager::Default().window_moved.connect(sigc::mem_fun(this, &PrivateWindow::OnWindowMoved)); |
898 | + } |
899 | + |
900 | + void OnScreenChanged(int /*primary*/, std::vector<nux::Geometry>& /*monitors*/) |
901 | + { |
902 | + auto uscreen = UScreen::GetDefault(); |
903 | + SetGeometry(uscreen->GetScreenGeometry()); |
904 | + } |
905 | + |
906 | + /** |
907 | + * EnableInputWindow doesn't show the window immediately. |
908 | + * Since nux::EnableInputWindow uses XMoveResizeWindow the best way to know if |
909 | + * the X Window is really on/off screen is receiving WindowManager::window_moved |
910 | + * signal. Please don't hate me! |
911 | + **/ |
912 | + void OnWindowMoved(Window window_id) |
913 | + { |
914 | + if (G_LIKELY(window_id != GetInputWindowId())) |
915 | + return; |
916 | + |
917 | + // Create a fake mouse move because sometimes an extra one is required. |
918 | + auto display = nux::GetGraphicsDisplay()->GetX11Display(); |
919 | + XWarpPointer(display, None, None, 0, 0, 0, 0, 0, 0); |
920 | + XFlush(display); |
921 | + } |
922 | + |
923 | + void ProcessDndMove(int x, int y, std::list<char*> mimes) |
924 | + { |
925 | + // Hide the window as soon as possible. |
926 | + PushToBack(); |
927 | + EnableInputWindow(false, "XdndCollectionWindowImp"); |
928 | + |
929 | + std::vector<std::string> data; |
930 | + for (auto mime : mimes) |
931 | + if (mime) data.push_back(mime); |
932 | + |
933 | + parent_->collected.emit(data); |
934 | + } |
935 | + |
936 | + XdndCollectionWindowImp* parent_; |
937 | +}; |
938 | + |
939 | +} |
940 | + |
941 | +XdndCollectionWindowImp::XdndCollectionWindowImp() |
942 | + : window_(new PrivateWindow(this)) |
943 | +{} |
944 | + |
945 | +void XdndCollectionWindowImp::Collect() |
946 | +{ |
947 | + // Using PushToFront we're sure that the window is shown over the panel window, |
948 | + // the launcher window and the dash window. Don't forget to call PushToBack as |
949 | + // soon as possible. |
950 | + window_->PushToFront(); |
951 | + window_->EnableInputWindow(true, "XdndCollectionWindowImp"); |
952 | +} |
953 | + |
954 | +void XdndCollectionWindowImp::Deactivate() |
955 | +{ |
956 | + window_->PushToBack(); |
957 | + window_->EnableInputWindow(false, "XdndCollectionWindowImp"); |
958 | +} |
959 | + |
960 | +} |
961 | |
962 | === added file 'launcher/XdndCollectionWindowImp.h' |
963 | --- launcher/XdndCollectionWindowImp.h 1970-01-01 00:00:00 +0000 |
964 | +++ launcher/XdndCollectionWindowImp.h 2012-11-24 14:30:27 +0000 |
965 | @@ -0,0 +1,44 @@ |
966 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
967 | +/* |
968 | +* Copyright (C) 2011-2012 Canonical Ltd |
969 | +* |
970 | +* This program is free software: you can redistribute it and/or modify |
971 | +* it under the terms of the GNU General Public License version 3 as |
972 | +* published by the Free Software Foundation. |
973 | +* |
974 | +* This program is distributed in the hope that it will be useful, |
975 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
976 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
977 | +* GNU General Public License for more details. |
978 | +* |
979 | +* You should have received a copy of the GNU General Public License |
980 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
981 | +* |
982 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
983 | +*/ |
984 | + |
985 | +#ifndef UNITYSHELL_XDND_COLLECTION_WINDOW_IMP_H |
986 | +#define UNITYSHELL_XDND_COLLECTION_WINDOW_IMP_H |
987 | + |
988 | +#include "XdndCollectionWindow.h" |
989 | + |
990 | +#include <Nux/Nux.h> |
991 | +#include <Nux/BaseWindow.h> |
992 | + |
993 | +namespace unity { |
994 | + |
995 | +class XdndCollectionWindowImp : public XdndCollectionWindow |
996 | +{ |
997 | +public: |
998 | + XdndCollectionWindowImp(); |
999 | + |
1000 | + void Collect(); |
1001 | + void Deactivate(); |
1002 | + |
1003 | +private: |
1004 | + nux::ObjectPtr<nux::BaseWindow> window_; |
1005 | +}; |
1006 | + |
1007 | +} |
1008 | + |
1009 | +#endif |
1010 | |
1011 | === added file 'launcher/XdndManager.h' |
1012 | --- launcher/XdndManager.h 1970-01-01 00:00:00 +0000 |
1013 | +++ launcher/XdndManager.h 2012-11-24 14:30:27 +0000 |
1014 | @@ -0,0 +1,43 @@ |
1015 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1016 | +/* |
1017 | +* Copyright (C) 2012 Canonical Ltd |
1018 | +* |
1019 | +* This program is free software: you can redistribute it and/or modify |
1020 | +* it under the terms of the GNU General Public License version 3 as |
1021 | +* published by the Free Software Foundation. |
1022 | +* |
1023 | +* This program is distributed in the hope that it will be useful, |
1024 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1025 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1026 | +* GNU General Public License for more details. |
1027 | +* |
1028 | +* You should have received a copy of the GNU General Public License |
1029 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1030 | +* |
1031 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1032 | +*/ |
1033 | + |
1034 | +#ifndef UNITYSHELL_XDND_MANAGER_H |
1035 | +#define UNITYSHELL_XDND_MANAGER_H |
1036 | + |
1037 | +#include <boost/noncopyable.hpp> |
1038 | +#include <memory> |
1039 | +#include <sigc++/signal.h> |
1040 | +#include <string> |
1041 | + |
1042 | +namespace unity { |
1043 | + |
1044 | +class XdndManager : boost::noncopyable { |
1045 | +public: |
1046 | + typedef std::shared_ptr<XdndManager> Ptr; |
1047 | + |
1048 | + virtual ~XdndManager() {} |
1049 | + |
1050 | + sigc::signal<void, std::string, int> dnd_started; |
1051 | + sigc::signal<void> dnd_finished; |
1052 | + sigc::signal<void, int> monitor_changed; |
1053 | +}; |
1054 | + |
1055 | +} |
1056 | + |
1057 | +#endif |
1058 | |
1059 | === added file 'launcher/XdndManagerImp.cpp' |
1060 | --- launcher/XdndManagerImp.cpp 1970-01-01 00:00:00 +0000 |
1061 | +++ launcher/XdndManagerImp.cpp 2012-11-24 14:30:27 +0000 |
1062 | @@ -0,0 +1,98 @@ |
1063 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1064 | +/* |
1065 | +* Copyright (C) 2012 Canonical Ltd |
1066 | +* |
1067 | +* This program is free software: you can redistribute it and/or modify |
1068 | +* it under the terms of the GNU General Public License version 3 as |
1069 | +* published by the Free Software Foundation. |
1070 | +* |
1071 | +* This program is distributed in the hope that it will be useful, |
1072 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1073 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1074 | +* GNU General Public License for more details. |
1075 | +* |
1076 | +* You should have received a copy of the GNU General Public License |
1077 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1078 | +* |
1079 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1080 | +*/ |
1081 | + |
1082 | +#include "XdndManagerImp.h" |
1083 | + |
1084 | +#include "unity-shared/UScreen.h" |
1085 | + |
1086 | +namespace unity { |
1087 | + |
1088 | +XdndManagerImp::XdndManagerImp(XdndStartStopNotifier::Ptr const& xdnd_start_stop_notifier, |
1089 | + XdndCollectionWindow::Ptr const& xdnd_collection_window) |
1090 | + : xdnd_start_stop_notifier_(xdnd_start_stop_notifier) |
1091 | + , xdnd_collection_window_(xdnd_collection_window) |
1092 | + , last_monitor_(-1) |
1093 | + , valid_dnd_in_progress_(false) |
1094 | +{ |
1095 | + xdnd_start_stop_notifier_->started.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndStarted)); |
1096 | + xdnd_start_stop_notifier_->finished.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndFinished)); |
1097 | + |
1098 | + xdnd_collection_window_->collected.connect(sigc::mem_fun(this, &XdndManagerImp::OnDndDataCollected)); |
1099 | +} |
1100 | + |
1101 | +void XdndManagerImp::OnDndStarted() |
1102 | +{ |
1103 | + xdnd_collection_window_->Collect(); |
1104 | +} |
1105 | + |
1106 | +void XdndManagerImp::OnDndFinished() |
1107 | +{ |
1108 | + xdnd_collection_window_->Deactivate(); |
1109 | + mouse_poller_timeout_.reset(); |
1110 | + |
1111 | + if (valid_dnd_in_progress_) |
1112 | + { |
1113 | + valid_dnd_in_progress_ = false; |
1114 | + dnd_finished.emit(); |
1115 | + } |
1116 | +} |
1117 | + |
1118 | +void XdndManagerImp::OnDndDataCollected(std::vector<std::string> const& mimes) |
1119 | +{ |
1120 | + if (!IsAValidDnd(mimes)) |
1121 | + return; |
1122 | + |
1123 | + valid_dnd_in_progress_ = true; |
1124 | + |
1125 | + auto& gp_display = nux::GetWindowThread()->GetGraphicsDisplay(); |
1126 | + char target[] = "text/uri-list"; |
1127 | + glib::String data(gp_display.GetDndData(target)); |
1128 | + |
1129 | + auto uscreen = UScreen::GetDefault(); |
1130 | + last_monitor_ = uscreen->GetMonitorWithMouse(); |
1131 | + |
1132 | + mouse_poller_timeout_.reset(new glib::Timeout(20, sigc::mem_fun(this, &XdndManagerImp::CheckMousePosition))); |
1133 | + |
1134 | + dnd_started.emit(data.Str(), last_monitor_); |
1135 | +} |
1136 | + |
1137 | +bool XdndManagerImp::IsAValidDnd(std::vector<std::string> const& mimes) |
1138 | +{ |
1139 | + auto end = std::end(mimes); |
1140 | + auto it = std::find(std::begin(mimes), end, "text/uri-list"); |
1141 | + |
1142 | + return it != end; |
1143 | +} |
1144 | + |
1145 | +bool XdndManagerImp::CheckMousePosition() |
1146 | +{ |
1147 | + auto uscreen = UScreen::GetDefault(); |
1148 | + auto monitor = uscreen->GetMonitorWithMouse(); |
1149 | + |
1150 | + if (valid_dnd_in_progress_ && monitor != last_monitor_) |
1151 | + { |
1152 | + last_monitor_ = monitor; |
1153 | + monitor_changed.emit(last_monitor_); |
1154 | + } |
1155 | + |
1156 | + return true; |
1157 | +} |
1158 | + |
1159 | +} |
1160 | + |
1161 | |
1162 | === added file 'launcher/XdndManagerImp.h' |
1163 | --- launcher/XdndManagerImp.h 1970-01-01 00:00:00 +0000 |
1164 | +++ launcher/XdndManagerImp.h 2012-11-24 14:30:27 +0000 |
1165 | @@ -0,0 +1,54 @@ |
1166 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1167 | +/* |
1168 | +* Copyright (C) 2012 Canonical Ltd |
1169 | +* |
1170 | +* This program is free software: you can redistribute it and/or modify |
1171 | +* it under the terms of the GNU General Public License version 3 as |
1172 | +* published by the Free Software Foundation. |
1173 | +* |
1174 | +* This program is distributed in the hope that it will be useful, |
1175 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1176 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1177 | +* GNU General Public License for more details. |
1178 | +* |
1179 | +* You should have received a copy of the GNU General Public License |
1180 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1181 | +* |
1182 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1183 | +*/ |
1184 | + |
1185 | +#ifndef UNITYSHELL_XDND_MANAGER_IMP_H |
1186 | +#define UNITYSHELL_XDND_MANAGER_IMP_H |
1187 | + |
1188 | +#include <sigc++/trackable.h> |
1189 | + |
1190 | +#include "XdndManager.h" |
1191 | + |
1192 | +#include "XdndCollectionWindow.h" |
1193 | +#include "XdndStartStopNotifier.h" |
1194 | +#include "UnityCore/GLibSource.h" |
1195 | + |
1196 | +namespace unity { |
1197 | + |
1198 | +class XdndManagerImp : public XdndManager, public sigc::trackable { |
1199 | +public: |
1200 | + XdndManagerImp(XdndStartStopNotifier::Ptr const&, XdndCollectionWindow::Ptr const&); |
1201 | + |
1202 | +private: |
1203 | + void OnDndStarted(); |
1204 | + void OnDndFinished(); |
1205 | + void OnDndDataCollected(std::vector<std::string> const& mimes); |
1206 | + bool IsAValidDnd(std::vector<std::string> const& mimes); |
1207 | + bool CheckMousePosition(); |
1208 | + |
1209 | + XdndStartStopNotifier::Ptr xdnd_start_stop_notifier_; |
1210 | + XdndCollectionWindow::Ptr xdnd_collection_window_; |
1211 | + int last_monitor_; |
1212 | + bool valid_dnd_in_progress_; |
1213 | + |
1214 | + glib::Source::UniquePtr mouse_poller_timeout_; |
1215 | +}; |
1216 | + |
1217 | +} |
1218 | + |
1219 | +#endif |
1220 | |
1221 | === added file 'launcher/XdndStartStopNotifier.cpp' |
1222 | --- launcher/XdndStartStopNotifier.cpp 1970-01-01 00:00:00 +0000 |
1223 | +++ launcher/XdndStartStopNotifier.cpp 2012-11-24 14:30:27 +0000 |
1224 | @@ -0,0 +1,27 @@ |
1225 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1226 | +/* |
1227 | +* Copyright (C) 2012 Canonical Ltd |
1228 | +* |
1229 | +* This program is free software: you can redistribute it and/or modify |
1230 | +* it under the terms of the GNU General Public License version 3 as |
1231 | +* published by the Free Software Foundation. |
1232 | +* |
1233 | +* This program is distributed in the hope that it will be useful, |
1234 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1235 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1236 | +* GNU General Public License for more details. |
1237 | +* |
1238 | +* You should have received a copy of the GNU General Public License |
1239 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1240 | +* |
1241 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1242 | +*/ |
1243 | + |
1244 | +#include "XdndStartStopNotifier.h" |
1245 | + |
1246 | +namespace unity { |
1247 | + |
1248 | +XdndStartStopNotifier::~XdndStartStopNotifier() |
1249 | +{} |
1250 | + |
1251 | +} |
1252 | \ No newline at end of file |
1253 | |
1254 | === added file 'launcher/XdndStartStopNotifier.h' |
1255 | --- launcher/XdndStartStopNotifier.h 1970-01-01 00:00:00 +0000 |
1256 | +++ launcher/XdndStartStopNotifier.h 2012-11-24 14:30:27 +0000 |
1257 | @@ -0,0 +1,41 @@ |
1258 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1259 | +/* |
1260 | +* Copyright (C) 2012 Canonical Ltd |
1261 | +* |
1262 | +* This program is free software: you can redistribute it and/or modify |
1263 | +* it under the terms of the GNU General Public License version 3 as |
1264 | +* published by the Free Software Foundation. |
1265 | +* |
1266 | +* This program is distributed in the hope that it will be useful, |
1267 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1268 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1269 | +* GNU General Public License for more details. |
1270 | +* |
1271 | +* You should have received a copy of the GNU General Public License |
1272 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1273 | +* |
1274 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1275 | +*/ |
1276 | + |
1277 | +#ifndef UNITYSHELL_XDND_START_STOP_NOTIFIER_H |
1278 | +#define UNITYSHELL_XDND_START_STOP_NOTIFIER_H |
1279 | + |
1280 | +#include <boost/noncopyable.hpp> |
1281 | +#include <memory> |
1282 | +#include <sigc++/signal.h> |
1283 | + |
1284 | +namespace unity { |
1285 | + |
1286 | +class XdndStartStopNotifier : boost::noncopyable { |
1287 | +public: |
1288 | + typedef std::shared_ptr<XdndStartStopNotifier> Ptr; |
1289 | + |
1290 | + virtual ~XdndStartStopNotifier() = 0; |
1291 | + |
1292 | + sigc::signal<void> started; |
1293 | + sigc::signal<void> finished; |
1294 | +}; |
1295 | + |
1296 | +} |
1297 | + |
1298 | +#endif |
1299 | |
1300 | === added file 'launcher/XdndStartStopNotifierImp.cpp' |
1301 | --- launcher/XdndStartStopNotifierImp.cpp 1970-01-01 00:00:00 +0000 |
1302 | +++ launcher/XdndStartStopNotifierImp.cpp 2012-11-24 14:30:27 +0000 |
1303 | @@ -0,0 +1,77 @@ |
1304 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1305 | +/* |
1306 | +* Copyright (C) 2012 Canonical Ltd |
1307 | +* |
1308 | +* This program is free software: you can redistribute it and/or modify |
1309 | +* it under the terms of the GNU General Public License version 3 as |
1310 | +* published by the Free Software Foundation. |
1311 | +* |
1312 | +* This program is distributed in the hope that it will be useful, |
1313 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1314 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1315 | +* GNU General Public License for more details. |
1316 | +* |
1317 | +* You should have received a copy of the GNU General Public License |
1318 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1319 | +* |
1320 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1321 | +*/ |
1322 | + |
1323 | +#include "XdndStartStopNotifierImp.h" |
1324 | + |
1325 | +#include <Nux/Nux.h> |
1326 | + |
1327 | +#include "unity-shared/WindowManager.h" |
1328 | + |
1329 | +namespace unity { |
1330 | + |
1331 | +XdndStartStopNotifierImp::XdndStartStopNotifierImp() |
1332 | + : display_(nux::GetGraphicsDisplay()->GetX11Display()) |
1333 | + , selection_(XInternAtom(display_, "XdndSelection", false)) |
1334 | + , dnd_in_progress_(false) |
1335 | +{ |
1336 | + WindowManager& wm = WindowManager::Default(); |
1337 | + wm.window_mapped.connect(sigc::hide(sigc::mem_fun(this, &XdndStartStopNotifierImp::DndTimeoutSetup))); |
1338 | + wm.window_unmapped.connect(sigc::hide(sigc::mem_fun(this, &XdndStartStopNotifierImp::DndTimeoutSetup))); |
1339 | + } |
1340 | + |
1341 | +void XdndStartStopNotifierImp::DndTimeoutSetup() |
1342 | +{ |
1343 | + if (timeout_ && timeout_->IsRunning()) |
1344 | + return; |
1345 | + |
1346 | + auto cb_func = sigc::mem_fun(this, &XdndStartStopNotifierImp::OnTimeout); |
1347 | + timeout_.reset(new glib::Timeout(200, cb_func)); |
1348 | +} |
1349 | + |
1350 | +bool XdndStartStopNotifierImp::OnTimeout() |
1351 | +{ |
1352 | + Window drag_owner = XGetSelectionOwner(display_, selection_); |
1353 | + |
1354 | + // evil hack because Qt does not release the selction owner on drag finished |
1355 | + Window root_r, child_r; |
1356 | + int root_x_r, root_y_r, win_x_r, win_y_r; |
1357 | + unsigned int mask; |
1358 | + XQueryPointer(display_, DefaultRootWindow(display_), &root_r, &child_r, &root_x_r, &root_y_r, &win_x_r, &win_y_r, &mask); |
1359 | + |
1360 | + if (drag_owner && (mask & (Button1Mask | Button2Mask | Button3Mask))) |
1361 | + { |
1362 | + if (!dnd_in_progress_) |
1363 | + { |
1364 | + started.emit(); |
1365 | + dnd_in_progress_ = true; |
1366 | + } |
1367 | + |
1368 | + return true; |
1369 | + } |
1370 | + |
1371 | + if (dnd_in_progress_) |
1372 | + { |
1373 | + finished.emit(); |
1374 | + dnd_in_progress_ = false; |
1375 | + } |
1376 | + |
1377 | + return false; |
1378 | +} |
1379 | + |
1380 | +} |
1381 | |
1382 | === added file 'launcher/XdndStartStopNotifierImp.h' |
1383 | --- launcher/XdndStartStopNotifierImp.h 1970-01-01 00:00:00 +0000 |
1384 | +++ launcher/XdndStartStopNotifierImp.h 2012-11-24 14:30:27 +0000 |
1385 | @@ -0,0 +1,47 @@ |
1386 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1387 | +/* |
1388 | +* Copyright (C) 2012 Canonical Ltd |
1389 | +* |
1390 | +* This program is free software: you can redistribute it and/or modify |
1391 | +* it under the terms of the GNU General Public License version 3 as |
1392 | +* published by the Free Software Foundation. |
1393 | +* |
1394 | +* This program is distributed in the hope that it will be useful, |
1395 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1396 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1397 | +* GNU General Public License for more details. |
1398 | +* |
1399 | +* You should have received a copy of the GNU General Public License |
1400 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1401 | +* |
1402 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1403 | +*/ |
1404 | + |
1405 | +#ifndef UNITYSHELL_XDND_START_STOP_NOTIFIER_IMP_H |
1406 | +#define UNITYSHELL_XDND_START_STOP_NOTIFIER_IMP_H |
1407 | + |
1408 | +#include "XdndStartStopNotifier.h" |
1409 | + |
1410 | +#include <UnityCore/GLibSource.h> |
1411 | +#include <X11/Xlib.h> |
1412 | + |
1413 | +namespace unity { |
1414 | + |
1415 | +class XdndStartStopNotifierImp : public XdndStartStopNotifier { |
1416 | +public: |
1417 | + XdndStartStopNotifierImp(); |
1418 | + |
1419 | +private: |
1420 | + void DndTimeoutSetup(); |
1421 | + bool OnTimeout(); |
1422 | + |
1423 | + Display* display_; |
1424 | + Atom selection_; |
1425 | + bool dnd_in_progress_; |
1426 | + |
1427 | + glib::Source::UniquePtr timeout_; |
1428 | +}; |
1429 | + |
1430 | +} |
1431 | + |
1432 | +#endif |
1433 | \ No newline at end of file |
1434 | |
1435 | === modified file 'plugins/unityshell/src/unitya11ytests.cpp' |
1436 | --- plugins/unityshell/src/unitya11ytests.cpp 2012-08-15 14:05:18 +0000 |
1437 | +++ plugins/unityshell/src/unitya11ytests.cpp 2012-11-24 14:30:27 +0000 |
1438 | @@ -210,7 +210,7 @@ |
1439 | AtkObject* launcher_icon_accessible = NULL; |
1440 | |
1441 | window = new nux::BaseWindow(TEXT("")); |
1442 | - launcher = new Launcher(window, nux::ObjectPtr<unity::DNDCollectionWindow>(new unity::DNDCollectionWindow), NULL); |
1443 | + launcher = new Launcher(window, NULL); |
1444 | launcher->SinkReference(); |
1445 | launcher_accessible = unity_a11y_get_accessible(launcher); |
1446 | |
1447 | |
1448 | === modified file 'plugins/unityshell/src/unityshell.cpp' |
1449 | --- plugins/unityshell/src/unityshell.cpp 2012-11-21 23:44:37 +0000 |
1450 | +++ plugins/unityshell/src/unityshell.cpp 2012-11-24 14:30:27 +0000 |
1451 | @@ -41,6 +41,9 @@ |
1452 | #include "unityshell.h" |
1453 | #include "BackgroundEffectHelper.h" |
1454 | #include "UnityGestureBroker.h" |
1455 | +#include "launcher/XdndCollectionWindowImp.h" |
1456 | +#include "launcher/XdndManagerImp.h" |
1457 | +#include "launcher/XdndStartStopNotifierImp.h" |
1458 | |
1459 | #include <glib/gi18n-lib.h> |
1460 | #include <gtk/gtk.h> |
1461 | @@ -3096,7 +3099,12 @@ |
1462 | void UnityScreen::initLauncher() |
1463 | { |
1464 | Timer timer; |
1465 | - launcher_controller_ = std::make_shared<launcher::Controller>(); |
1466 | + |
1467 | + auto xdnd_collection_window = std::make_shared<XdndCollectionWindowImp>(); |
1468 | + auto xdnd_start_stop_notifier = std::make_shared<XdndStartStopNotifierImp>(); |
1469 | + auto xdnd_manager = std::make_shared<XdndManagerImp>(xdnd_start_stop_notifier, xdnd_collection_window); |
1470 | + |
1471 | + launcher_controller_ = std::make_shared<launcher::Controller>(xdnd_manager); |
1472 | AddChild(launcher_controller_.get()); |
1473 | |
1474 | switcher_controller_ = std::make_shared<switcher::Controller>(); |
1475 | |
1476 | === modified file 'tests/CMakeLists.txt' |
1477 | --- tests/CMakeLists.txt 2012-11-23 23:49:46 +0000 |
1478 | +++ tests/CMakeLists.txt 2012-11-24 14:30:27 +0000 |
1479 | @@ -251,6 +251,8 @@ |
1480 | test_unity_settings.cpp |
1481 | test_volume_imp.cpp |
1482 | test_volume_launcher_icon.cpp |
1483 | + test_xdnd_manager_imp.cpp |
1484 | + test_xdnd_start_stop_notifier_imp.cpp |
1485 | bamf-mock-application.c |
1486 | gmockmount.c |
1487 | gmockvolume.c |
1488 | |
1489 | === modified file 'tests/test_launcher.cpp' |
1490 | --- tests/test_launcher.cpp 2012-11-09 09:18:37 +0000 |
1491 | +++ tests/test_launcher.cpp 2012-11-24 14:30:27 +0000 |
1492 | @@ -26,7 +26,6 @@ |
1493 | #include <Nux/Nux.h> |
1494 | #include <Nux/BaseWindow.h> |
1495 | |
1496 | -#include "launcher/DNDCollectionWindow.h" |
1497 | #include "launcher/MockLauncherIcon.h" |
1498 | #include "launcher/Launcher.h" |
1499 | #include "unity-shared/PanelStyle.h" |
1500 | @@ -63,8 +62,8 @@ |
1501 | class MockLauncher : public Launcher |
1502 | { |
1503 | public: |
1504 | - MockLauncher(nux::BaseWindow* parent, nux::ObjectPtr<DNDCollectionWindow> const& collection_window) |
1505 | - : Launcher(parent, collection_window) |
1506 | + MockLauncher(nux::BaseWindow* parent) |
1507 | + : Launcher(parent) |
1508 | {} |
1509 | |
1510 | AbstractLauncherIcon::Ptr MouseIconIntersection(int x, int y) const |
1511 | @@ -119,10 +118,9 @@ |
1512 | |
1513 | TestLauncher() |
1514 | : parent_window_(new nux::BaseWindow("TestLauncherWindow")) |
1515 | - , dnd_collection_window_(new DNDCollectionWindow) |
1516 | , model_(new LauncherModel) |
1517 | , options_(new Options) |
1518 | - , launcher_(new MockLauncher(parent_window_, dnd_collection_window_)) |
1519 | + , launcher_(new MockLauncher(parent_window_)) |
1520 | { |
1521 | launcher_->options = options_; |
1522 | launcher_->SetModel(model_); |
1523 | @@ -153,7 +151,6 @@ |
1524 | |
1525 | MockUScreen uscreen; |
1526 | nux::BaseWindow* parent_window_; |
1527 | - nux::ObjectPtr<DNDCollectionWindow> dnd_collection_window_; |
1528 | Settings settings; |
1529 | panel::Style panel_style; |
1530 | LauncherModel::Ptr model_; |
1531 | @@ -189,9 +186,7 @@ |
1532 | EXPECT_CALL(*third, ShouldHighlightOnDrag(_)) |
1533 | .WillRepeatedly(Return(false)); |
1534 | |
1535 | - std::list<char*> uris; |
1536 | - dnd_collection_window_->collected.emit(uris); |
1537 | - |
1538 | + launcher_->DndStarted(""); |
1539 | Utils::WaitForTimeout(1); |
1540 | |
1541 | EXPECT_FALSE(first->GetQuirk(launcher::AbstractLauncherIcon::Quirk::DESAT)); |
1542 | |
1543 | === modified file 'tests/test_launcher_controller.cpp' |
1544 | --- tests/test_launcher_controller.cpp 2012-11-15 17:56:23 +0000 |
1545 | +++ tests/test_launcher_controller.cpp 2012-11-24 14:30:27 +0000 |
1546 | @@ -200,6 +200,11 @@ |
1547 | { |
1548 | struct TestLauncherController : public testing::Test |
1549 | { |
1550 | + TestLauncherController() |
1551 | + : xdnd_manager_(std::make_shared<XdndManager>()) |
1552 | + , lc(xdnd_manager_) |
1553 | + {} |
1554 | + |
1555 | virtual void SetUp() |
1556 | { |
1557 | lc.multiple_launchers = true; |
1558 | @@ -216,6 +221,10 @@ |
1559 | protected: |
1560 | struct MockLauncherController : Controller |
1561 | { |
1562 | + MockLauncherController(XdndManager::Ptr const& xdnd_manager) |
1563 | + : Controller(xdnd_manager) |
1564 | + {} |
1565 | + |
1566 | Controller::Impl* Impl() const { return pimpl.get(); } |
1567 | |
1568 | AbstractLauncherIcon::Ptr GetIconByDesktop(std::string const& path) const |
1569 | @@ -258,6 +267,7 @@ |
1570 | Settings settings; |
1571 | panel::Style panel_style; |
1572 | MockFavoriteStore favorite_store; |
1573 | + XdndManager::Ptr xdnd_manager_; |
1574 | MockLauncherController lc; |
1575 | }; |
1576 | } |
1577 | @@ -1544,4 +1554,50 @@ |
1578 | ASSERT_EQ(lc.Impl()->model_->Selection()->tooltip_text(), last_selection_change); |
1579 | } |
1580 | |
1581 | +TEST_F(TestLauncherController, DragAndDrop_MultipleLaunchers) |
1582 | +{ |
1583 | + lc.multiple_launchers = true; |
1584 | + uscreen.SetupFakeMultiMonitor(); |
1585 | + lc.options()->hide_mode = LAUNCHER_HIDE_AUTOHIDE; |
1586 | + |
1587 | + auto check_fn = [this](int index) { |
1588 | + return lc.launchers()[index]->Hidden(); |
1589 | + }; |
1590 | + |
1591 | + xdnd_manager_->dnd_started.emit("my_awesome_file", 0); |
1592 | + |
1593 | + for (int i = 0; i < max_num_monitors; ++i) |
1594 | + Utils::WaitUntil(std::bind(check_fn, i), i != 0); |
1595 | + |
1596 | + xdnd_manager_->monitor_changed.emit(3); |
1597 | + |
1598 | + for (int i = 0; i < max_num_monitors; ++i) |
1599 | + Utils::WaitUntil(std::bind(check_fn, i), i != 3); |
1600 | + |
1601 | + xdnd_manager_->dnd_finished.emit(); |
1602 | + |
1603 | + for (int i = 0; i < max_num_monitors; ++i) |
1604 | + Utils::WaitUntil(std::bind(check_fn, i), true); |
1605 | +} |
1606 | + |
1607 | +TEST_F(TestLauncherController, DragAndDrop_SingleLauncher) |
1608 | +{ |
1609 | + lc.multiple_launchers = false; |
1610 | + uscreen.SetupFakeMultiMonitor(2); |
1611 | + lc.options()->hide_mode = LAUNCHER_HIDE_AUTOHIDE; |
1612 | + |
1613 | + auto check_fn = [this]() { |
1614 | + return lc.launcher().Hidden(); |
1615 | + }; |
1616 | + |
1617 | + xdnd_manager_->dnd_started.emit("my_awesome_file", 0); |
1618 | + Utils::WaitUntil(check_fn, false); |
1619 | + |
1620 | + xdnd_manager_->monitor_changed.emit(2); |
1621 | + Utils::WaitUntil(check_fn, false); |
1622 | + |
1623 | + xdnd_manager_->dnd_finished.emit(); |
1624 | + Utils::WaitUntil(check_fn, true); |
1625 | +} |
1626 | + |
1627 | } |
1628 | |
1629 | === added file 'tests/test_xdnd_manager_imp.cpp' |
1630 | --- tests/test_xdnd_manager_imp.cpp 1970-01-01 00:00:00 +0000 |
1631 | +++ tests/test_xdnd_manager_imp.cpp 2012-11-24 14:30:27 +0000 |
1632 | @@ -0,0 +1,130 @@ |
1633 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1634 | +/* |
1635 | +* Copyright (C) 2012 Canonical Ltd |
1636 | +* |
1637 | +* This program is free software: you can redistribute it and/or modify |
1638 | +* it under the terms of the GNU General Public License version 3 as |
1639 | +* published by the Free Software Foundation. |
1640 | +* |
1641 | +* This program is distributed in the hope that it will be useful, |
1642 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1643 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1644 | +* GNU General Public License for more details. |
1645 | +* |
1646 | +* You should have received a copy of the GNU General Public License |
1647 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1648 | +* |
1649 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1650 | +*/ |
1651 | + |
1652 | +#include <gmock/gmock.h> |
1653 | +using namespace testing; |
1654 | + |
1655 | +#include "launcher/XdndManagerImp.h" |
1656 | +#include "launcher/XdndCollectionWindow.h" |
1657 | +#include "launcher/XdndStartStopNotifier.h" |
1658 | + |
1659 | +#include "test_utils.h" |
1660 | + |
1661 | +#include <Nux/Nux.h> |
1662 | +#include <X11/Xlib.h> |
1663 | + |
1664 | +namespace { |
1665 | + |
1666 | +class MockXdndStartStopNotifier : public unity::XdndStartStopNotifier { |
1667 | +public: |
1668 | + typedef std::shared_ptr<MockXdndStartStopNotifier> Ptr; |
1669 | +}; |
1670 | + |
1671 | +class MockXdndCollectionWindow : public unity::XdndCollectionWindow { |
1672 | +public: |
1673 | + typedef std::shared_ptr<MockXdndCollectionWindow> Ptr; |
1674 | + |
1675 | + MOCK_METHOD0(Collect, void(void)); |
1676 | + MOCK_METHOD0(Deactivate, void(void)); |
1677 | +}; |
1678 | + |
1679 | +class TestXdndManager : public Test { |
1680 | +public: |
1681 | + TestXdndManager() |
1682 | + : xdnd_start_stop_notifier_(new MockXdndStartStopNotifier()) |
1683 | + , xdnd_collection_window_(new MockXdndCollectionWindow()) |
1684 | + , xdnd_manager(xdnd_start_stop_notifier_, xdnd_collection_window_) |
1685 | + {} |
1686 | + |
1687 | + void SetUp() |
1688 | + { |
1689 | + // Evil hack to avoid crashes. |
1690 | + XEvent xevent; |
1691 | + xevent.type = ClientMessage; |
1692 | + xevent.xany.display = nux::GetGraphicsDisplay()->GetX11Display(); |
1693 | + xevent.xclient.message_type = XInternAtom(xevent.xany.display, "XdndEnter", false); |
1694 | + xevent.xclient.data.l[1] = 5 >> 24; |
1695 | + |
1696 | + nux::GetGraphicsDisplay()->ProcessXEvent(xevent, true); |
1697 | + } |
1698 | + |
1699 | + MockXdndStartStopNotifier::Ptr xdnd_start_stop_notifier_; |
1700 | + MockXdndCollectionWindow::Ptr xdnd_collection_window_; |
1701 | + unity::XdndManagerImp xdnd_manager; |
1702 | +}; |
1703 | + |
1704 | +TEST_F(TestXdndManager, SignalDndStartedAndFinished) |
1705 | +{ |
1706 | + std::vector<std::string> mimes; |
1707 | + mimes.push_back("text/uri-list"); |
1708 | + mimes.push_back("hello/world"); |
1709 | + |
1710 | + auto emit_collected_signal = [&] () { |
1711 | + xdnd_collection_window_->collected.emit(mimes); |
1712 | + }; |
1713 | + |
1714 | + EXPECT_CALL(*xdnd_collection_window_, Collect()) |
1715 | + .Times(1) |
1716 | + .WillOnce(Invoke(emit_collected_signal)); |
1717 | + |
1718 | + bool dnd_started_emitted = false; |
1719 | + xdnd_manager.dnd_started.connect([&] (std::string const& /*data*/, int /*monitor*/) { |
1720 | + dnd_started_emitted = true; |
1721 | + }); |
1722 | + |
1723 | + xdnd_start_stop_notifier_->started.emit(); |
1724 | + Utils::WaitUntil(dnd_started_emitted); |
1725 | + |
1726 | + EXPECT_CALL(*xdnd_collection_window_, Deactivate()) |
1727 | + .Times(1); |
1728 | + |
1729 | + bool dnd_finished_emitted = false; |
1730 | + xdnd_manager.dnd_finished.connect([&] () { |
1731 | + dnd_finished_emitted = true; |
1732 | + }); |
1733 | + |
1734 | + xdnd_start_stop_notifier_->finished.emit(); |
1735 | + Utils::WaitUntil(dnd_finished_emitted); |
1736 | +} |
1737 | + |
1738 | +TEST_F(TestXdndManager, SignalDndStarted_InvalidMimes) |
1739 | +{ |
1740 | + std::vector<std::string> mimes; |
1741 | + mimes.push_back("hello/world"); |
1742 | + mimes.push_back("invalid/mimes"); |
1743 | + |
1744 | + auto emit_collected_signal = [&] () { |
1745 | + xdnd_collection_window_->collected.emit(mimes); |
1746 | + }; |
1747 | + |
1748 | + EXPECT_CALL(*xdnd_collection_window_, Collect()) |
1749 | + .Times(1) |
1750 | + .WillOnce(Invoke(emit_collected_signal)); |
1751 | + |
1752 | + bool dnd_started_emitted = false; |
1753 | + xdnd_manager.dnd_started.connect([&] (std::string const& /*data*/, int /*monitor*/) { |
1754 | + dnd_started_emitted = true; |
1755 | + }); |
1756 | + |
1757 | + xdnd_start_stop_notifier_->started.emit(); |
1758 | + |
1759 | + EXPECT_FALSE(dnd_started_emitted); |
1760 | +} |
1761 | + |
1762 | +} |
1763 | |
1764 | === added file 'tests/test_xdnd_start_stop_notifier_imp.cpp' |
1765 | --- tests/test_xdnd_start_stop_notifier_imp.cpp 1970-01-01 00:00:00 +0000 |
1766 | +++ tests/test_xdnd_start_stop_notifier_imp.cpp 2012-11-24 14:30:27 +0000 |
1767 | @@ -0,0 +1,107 @@ |
1768 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1769 | +/* |
1770 | +* Copyright (C) 2012 Canonical Ltd |
1771 | +* |
1772 | +* This program is free software: you can redistribute it and/or modify |
1773 | +* it under the terms of the GNU General Public License version 3 as |
1774 | +* published by the Free Software Foundation. |
1775 | +* |
1776 | +* This program is distributed in the hope that it will be useful, |
1777 | +* but WITHOUT ANY WARRANTY; without even the implied warranty of |
1778 | +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1779 | +* GNU General Public License for more details. |
1780 | +* |
1781 | +* You should have received a copy of the GNU General Public License |
1782 | +* along with this program. If not, see <http://www.gnu.org/licenses/>. |
1783 | +* |
1784 | +* Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
1785 | +*/ |
1786 | + |
1787 | +#include <gmock/gmock.h> |
1788 | +using namespace testing; |
1789 | + |
1790 | +#include "XdndStartStopNotifierImp.h" |
1791 | + |
1792 | +#include <Nux/Nux.h> |
1793 | +#include <X11/Xlib.h> |
1794 | +//#include <X11/extensions/XTest.h> |
1795 | + |
1796 | +#include "unity-shared/WindowManager.h" |
1797 | +#include "test_utils.h" |
1798 | + |
1799 | +namespace { |
1800 | + |
1801 | +struct TestXdndStartStopNotifierImp : public Test { |
1802 | + TestXdndStartStopNotifierImp() |
1803 | + : display_(nux::GetGraphicsDisplay()->GetX11Display()) |
1804 | + , selection_(XInternAtom(display_, "XdndSelection", false)) |
1805 | + { |
1806 | + Window root = DefaultRootWindow(display_); |
1807 | + owner_= XCreateSimpleWindow(display_, root, -1000, -1000, 10, 10, 0, 0, 0); |
1808 | + } |
1809 | + |
1810 | + Display* display_; |
1811 | + Atom selection_; |
1812 | + Window owner_; |
1813 | + |
1814 | + unity::XdndStartStopNotifierImp xdnd_start_stop_notifier; |
1815 | +}; |
1816 | + |
1817 | +TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalStarted) |
1818 | +{ |
1819 | + bool signal_received = false; |
1820 | + xdnd_start_stop_notifier.started.connect([&](){ |
1821 | + signal_received = true; |
1822 | + }); |
1823 | + |
1824 | + XSetSelectionOwner(display_, selection_, owner_, CurrentTime); |
1825 | + //XTestFakeButtonEvent(display_, 1, True, CurrentTime); |
1826 | + auto& wm = unity::WindowManager::Default(); |
1827 | + wm.window_mapped.emit(0); |
1828 | + |
1829 | + Utils::WaitUntil(signal_received); |
1830 | + //XTestFakeButtonEvent(display_, 1, False, CurrentTime); |
1831 | +} |
1832 | + |
1833 | +TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalFinished) |
1834 | +{ |
1835 | + bool signal_received = false; |
1836 | + xdnd_start_stop_notifier.finished.connect([&](){ |
1837 | + signal_received = true; |
1838 | + }); |
1839 | + |
1840 | + XSetSelectionOwner(display_, selection_, owner_, CurrentTime); |
1841 | + //XTestFakeButtonEvent(display_, 1, True, CurrentTime); |
1842 | + auto& wm = unity::WindowManager::Default(); |
1843 | + wm.window_mapped.emit(0); |
1844 | + |
1845 | + Utils::WaitForTimeoutMSec(500); |
1846 | + |
1847 | + XSetSelectionOwner(display_, selection_, None, CurrentTime); |
1848 | + //XTestFakeButtonEvent(display_, 1, False, CurrentTime); |
1849 | + wm.window_unmapped.emit(0); |
1850 | + |
1851 | + Utils::WaitUntil(signal_received); |
1852 | +} |
1853 | + |
1854 | +TEST_F(TestXdndStartStopNotifierImp, DISABLED_SignalFinished_QT) |
1855 | +{ |
1856 | + bool signal_received = false; |
1857 | + xdnd_start_stop_notifier.finished.connect([&](){ |
1858 | + signal_received = true; |
1859 | + }); |
1860 | + |
1861 | + XSetSelectionOwner(display_, selection_, owner_, CurrentTime); |
1862 | + //XTestFakeButtonEvent(display_, 1, True, CurrentTime); |
1863 | + auto& wm = unity::WindowManager::Default(); |
1864 | + wm.window_mapped.emit(0); |
1865 | + |
1866 | + Utils::WaitForTimeoutMSec(500); |
1867 | + |
1868 | + //XTestFakeButtonEvent(display_, 1, False, CurrentTime); |
1869 | + wm.window_unmapped.emit(0); |
1870 | + |
1871 | + Utils::WaitUntil(signal_received); |
1872 | +} |
1873 | + |
1874 | +} |
1875 | |
1876 | === modified file 'unity-shared/UScreen.cpp' |
1877 | --- unity-shared/UScreen.cpp 2012-10-29 09:34:54 +0000 |
1878 | +++ unity-shared/UScreen.cpp 2012-11-24 14:30:27 +0000 |
1879 | @@ -89,6 +89,13 @@ |
1880 | return monitors_; |
1881 | } |
1882 | |
1883 | +nux::Geometry UScreen::GetScreenGeometry() |
1884 | +{ |
1885 | + int width = gdk_screen_get_width(screen_); |
1886 | + int height = gdk_screen_get_height(screen_); |
1887 | + return nux::Geometry(0, 0, width, height); |
1888 | +} |
1889 | + |
1890 | void UScreen::Changed(GdkScreen* screen) |
1891 | { |
1892 | if (refresh_idle_) |
1893 | |
1894 | === modified file 'unity-shared/UScreen.h' |
1895 | --- unity-shared/UScreen.h 2012-07-24 01:07:58 +0000 |
1896 | +++ unity-shared/UScreen.h 2012-11-24 14:30:27 +0000 |
1897 | @@ -46,6 +46,7 @@ |
1898 | nux::Geometry& GetMonitorGeometry(int monitor); |
1899 | |
1900 | std::vector<nux::Geometry>& GetMonitors(); |
1901 | + nux::Geometry GetScreenGeometry(); |
1902 | |
1903 | // <void, primary_monitor, monitors> |
1904 | sigc::signal<void, int, std::vector<nux::Geometry>&> changed; |
1905 | |
1906 | === modified file 'unity-standalone/StandaloneUnity.cpp' |
1907 | --- unity-standalone/StandaloneUnity.cpp 2012-10-11 01:44:15 +0000 |
1908 | +++ unity-standalone/StandaloneUnity.cpp 2012-11-24 14:30:27 +0000 |
1909 | @@ -86,9 +86,10 @@ |
1910 | |
1911 | void UnityStandalone::Init () |
1912 | { |
1913 | - launcher_controller.reset(new launcher::Controller()); |
1914 | - panel_controller.reset(new panel::Controller()); |
1915 | - dash_controller.reset(new dash::Controller()); |
1916 | + auto xdnd_manager = std::make_shared<XdndManager>(); |
1917 | + launcher_controller = std::make_shared<launcher::Controller>(xdnd_manager); |
1918 | + panel_controller = std::make_shared<panel::Controller>(); |
1919 | + dash_controller = std::make_shared<dash::Controller>(); |
1920 | |
1921 | dash_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1; |
1922 | panel_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1; |
1923 | @@ -119,8 +120,9 @@ |
1924 | |
1925 | void UnityStandaloneTV::Init() |
1926 | { |
1927 | - launcher_controller.reset(new launcher::Controller()); |
1928 | - dash_controller.reset(new dash::Controller()); |
1929 | + auto xdnd_manager = std::make_shared<XdndManager>(); |
1930 | + launcher_controller = std::make_shared<launcher::Controller>(xdnd_manager); |
1931 | + dash_controller = std::make_shared<dash::Controller>(); |
1932 | dash_controller->launcher_width = launcher_controller->launcher().GetAbsoluteWidth() - 1; |
1933 | |
1934 | UBusManager().SendMessage(UBUS_DASH_EXTERNAL_ACTIVATION, nullptr); |
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 XdndCollectionW indow : boost::noncopyable {
new line for {
820 +#endif
821 \ No newline at end of file
Add \n ;)
864 + SetGeometry( wm.GetScreenGeo metry() );
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::GetGraphic sDisplay( )->GetX11Displa y();
You can check for this value only if window_id is the target one, isn't it?
900 + std::vector< std::string> data; back(mime) ;
901 + for (auto mime : mimes)
902 + data.push_
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 .SignalDndStart ed, do you want to clean it up?