Merge lp:~brandontschaefer/unity/alt+tab-mouse into lp:unity
- alt+tab-mouse
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Brandon Schaefer |
Approved revision: | 3444 |
Merged at revision: | 3462 |
Proposed branch: | lp:~brandontschaefer/unity/alt+tab-mouse |
Merge into: | lp:unity |
Diff against target: |
1214 lines (+599/-73) 16 files modified
launcher/StandaloneSwitcher.cpp (+0/-1) launcher/SwitcherController.cpp (+59/-23) launcher/SwitcherController.h (+1/-2) launcher/SwitcherControllerImpl.h (+2/-1) launcher/SwitcherModel.cpp (+6/-0) launcher/SwitcherModel.h (+1/-0) launcher/SwitcherView.cpp (+241/-6) launcher/SwitcherView.h (+35/-3) plugins/unityshell/src/unityshell.cpp (+73/-35) plugins/unityshell/src/unityshell.h (+3/-0) tests/autopilot/unity/emulators/switcher.py (+14/-0) tests/autopilot/unity/tests/test_switcher.py (+99/-0) tests/test_switcher_controller.cpp (+28/-0) unity-shared/AbstractIconRenderer.h (+15/-1) unity-shared/LayoutSystem.cpp (+14/-0) unity-shared/LayoutSystem.h (+8/-1) |
To merge this branch: | bzr merge lp:~brandontschaefer/unity/alt+tab-mouse |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marco Trevisan (Treviño) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Christopher Townsend | Approve | ||
Review via email:
|
Commit message
Adds the ability to use the mouse in the switcher.
Description of the change
We use compiz to grab the screen, and from there send all the grabbed events down to nux, which then nux emits them back up to the SwitcherView.
From there we have to figure out where the mouse is located x/y, if its over an icon change selection, same with detail mode. As the SwitcherView takes up most of the screen.
Right clicking toggles detail mode.

PS Jenkins bot (ps-jenkins) wrote : | # |

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3432
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3433
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3435
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

Marco Trevisan (Treviño) (3v1n0) wrote : | # |
I like a lot the change and the cleanup in event handling for the switcher we had. Even more that we can reuse some code we wrote to get things work easily.
Some comments.
It would be nice if you could abastract a little these signal names:
right_clicked_icon (detail request?)
mouse_moving_
131 + introspection_
Do we really need to keep them around? Why not just a local var?
Anyway:
135 + for (auto target : render_targets_)
322 + int half_size = icon_size.Get() / 2 + 10;
10? Magic number? :)
use auto const& please.
Also there are other behaviors to fix:
* The logic of the scroll wheel, as now here it's inverted to the one we had before.
* The click activation, as it should make sure that you activate an icon only if the mouse-up happened where mouse down happened before.
* The detail selection doesn't work on secondary monitors.
* It would be nice to remove the spread offset (or at least to define it in the controller, just once)

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3436
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

Christopher Townsend (townsend) wrote : | # |
Jenkins failures are due to an undefined member:
/tmp/buildd/
/tmp/buildd/
controller-
^

Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Good... Some comments:
124 + monitor_geo.x += XY_OFFSET;
125 + monitor_geo.y += XY_OFFSET;
126 + monitor_geo.width -= WH_OFFSET;
127 + monitor_geo.height -= WH_OFFSET;
What about monitor_
139 + view_->
Since both have a bool as parameter, you can just use sigc::mem_fun or std::bind there...
994
LayoutWindow::Ptr layout_window(0);
No need to set it to 0, however you can also just return inside the loop and return nullptr otherwise, g++ will be smart enough to convert.
UnityScreen::get (screen)
Get rid of the spaces
825 + LayoutWindow::Ptr const &layout_window = UnityScreen:
826 + GetSwitcherDeta
One line please (in case use auto const&).
Some code in lines 659-673 and 681-696 (middle click mouse handling in UnityWindow) is duplicated, what about adding a function to check if the position hits a window thumbnail (that basically checks the case of the switcher and of the scale).
I've also incurred into a regression: if I select the top-left window in detail mode (or the only one existent in case we have just one), then the switcher selects the window but it doesn't hide.
Finally, this not happen always, but when I do click -> move the mouse outside the clicked area -> release, the switcher closes

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3437
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3438
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3439
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3440
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

Christopher Townsend (townsend) wrote : | # |
I'm running all of the unity.tests.
The stack trace shows the crash manifests itself in unity/launcher/

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3441
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:3442
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3443
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3444
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

Christopher Townsend (townsend) wrote : | # |
The unity.tests.

Christopher Townsend (townsend) wrote : | # |
Well, I think the failing AP test is caused by something on my machine. It failed twice in a row, then after that, has passed at least 5 times with no issue.
Since Marco has weighed in and all of his concerns are addressed and now all AP tests pass, I'm going to approve this thing.

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
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://
FAILURE: http://
FAILURE: http://

PS Jenkins bot (ps-jenkins) : | # |

Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Cool, I see all the changes I requested are in the merged version, nice! :)
Preview Diff
1 | === modified file 'launcher/StandaloneSwitcher.cpp' |
2 | --- launcher/StandaloneSwitcher.cpp 2013-02-06 17:27:24 +0000 |
3 | +++ launcher/StandaloneSwitcher.cpp 2013-08-09 17:51:48 +0000 |
4 | @@ -131,7 +131,6 @@ |
5 | nux::VLayout* layout = new nux::VLayout(TEXT(""), NUX_TRACKER_LOCATION); |
6 | |
7 | controller = std::make_shared<Controller>(); |
8 | - controller->SetWorkspace(nux::Geometry(0, 0, 900, 600), 0); |
9 | |
10 | layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER); |
11 | layout->SetHorizontalExternalMargin (10); |
12 | |
13 | === modified file 'launcher/SwitcherController.cpp' |
14 | --- launcher/SwitcherController.cpp 2013-06-18 19:04:55 +0000 |
15 | +++ launcher/SwitcherController.cpp 2013-08-09 17:51:48 +0000 |
16 | @@ -23,6 +23,7 @@ |
17 | |
18 | #include "unity-shared/UBusMessages.h" |
19 | #include "unity-shared/WindowManager.h" |
20 | +#include "unity-shared/UScreen.h" |
21 | |
22 | #include "SwitcherController.h" |
23 | #include "SwitcherControllerImpl.h" |
24 | @@ -41,6 +42,8 @@ |
25 | const std::string DETAIL_TIMEOUT = "detail-timeout"; |
26 | const std::string VIEW_CONSTRUCT_IDLE = "view-construct-idle"; |
27 | const unsigned FADE_DURATION = 80; |
28 | +const int XY_OFFSET = 100; |
29 | +const int WH_OFFSET = -200; |
30 | |
31 | /** |
32 | * Helper comparison functor for sorting application icons. |
33 | @@ -78,7 +81,6 @@ |
34 | , impl_(new Controller::Impl(this, 20, create_window)) |
35 | {} |
36 | |
37 | - |
38 | Controller::~Controller() |
39 | {} |
40 | |
41 | @@ -93,6 +95,9 @@ |
42 | SortMode sort, |
43 | std::vector<AbstractLauncherIcon::Ptr> results) |
44 | { |
45 | + auto uscreen = UScreen::GetDefault(); |
46 | + monitor_ = uscreen->GetMonitorWithMouse(); |
47 | + |
48 | impl_->Show(show, sort, results); |
49 | } |
50 | |
51 | @@ -102,15 +107,6 @@ |
52 | impl_->model_->Select(index); |
53 | } |
54 | |
55 | -void Controller::SetWorkspace(nux::Geometry geo, int monitor) |
56 | -{ |
57 | - monitor_ = monitor; |
58 | - impl_->workarea_ = geo; |
59 | - |
60 | - if (impl_->view_) |
61 | - impl_->view_->monitor = monitor_; |
62 | -} |
63 | - |
64 | void Controller::Hide(bool accept_state) |
65 | { |
66 | if (Visible()) |
67 | @@ -124,6 +120,14 @@ |
68 | return visible_; |
69 | } |
70 | |
71 | +nux::Geometry Controller::GetInputWindowGeometry() const |
72 | +{ |
73 | + if (impl_->view_window_) |
74 | + return impl_->view_window_->GetGeometry(); |
75 | + |
76 | + return {0, 0, 0, 0}; |
77 | +} |
78 | + |
79 | bool Controller::StartDetailMode() |
80 | { |
81 | if (visible_) |
82 | @@ -333,6 +337,7 @@ |
83 | obj_->AddChild(model_.get()); |
84 | model_->selection_changed.connect(sigc::mem_fun(this, &Controller::Impl::OnModelSelectionChanged)); |
85 | model_->detail_selection.changed.connect([this] (bool) { sources_.Remove(DETAIL_TIMEOUT); }); |
86 | + model_->request_detail_hide.connect(sigc::mem_fun(this, &Controller::Impl::DetailHide)); |
87 | model_->only_detail_on_viewport = (show == ShowMode::CURRENT_VIEWPORT); |
88 | |
89 | SelectFirstItem(); |
90 | @@ -350,17 +355,21 @@ |
91 | ShowView(); |
92 | } |
93 | |
94 | - if (obj_->detail_on_timeout) |
95 | - { |
96 | - auto cb_func = sigc::mem_fun(this, &Controller::Impl::OnDetailTimer); |
97 | - sources_.AddTimeout(obj_->initial_detail_timeout_length, cb_func, DETAIL_TIMEOUT); |
98 | - } |
99 | + ResetDetailTimer(obj_->initial_detail_timeout_length); |
100 | |
101 | ubus_manager_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); |
102 | ubus_manager_.SendMessage(UBUS_SWITCHER_SHOWN, |
103 | g_variant_new("(bi)", true, obj_->monitor_)); |
104 | } |
105 | |
106 | +void Controller::Impl::ResetDetailTimer(int timeout_length) |
107 | +{ |
108 | + if (obj_->detail_on_timeout) |
109 | + { |
110 | + auto cb_func = sigc::mem_fun(this, &Controller::Impl::OnDetailTimer); |
111 | + sources_.AddTimeout(timeout_length, cb_func, DETAIL_TIMEOUT); |
112 | + } |
113 | +} |
114 | |
115 | bool Controller::Impl::OnDetailTimer() |
116 | { |
117 | @@ -375,11 +384,7 @@ |
118 | |
119 | void Controller::Impl::OnModelSelectionChanged(AbstractLauncherIcon::Ptr const& icon) |
120 | { |
121 | - if (obj_->detail_on_timeout) |
122 | - { |
123 | - auto cb_func = sigc::mem_fun(this, &Controller::Impl::OnDetailTimer); |
124 | - sources_.AddTimeout(obj_->detail_timeout_length, cb_func, DETAIL_TIMEOUT); |
125 | - } |
126 | + ResetDetailTimer(obj_->detail_timeout_length); |
127 | |
128 | if (icon) |
129 | { |
130 | @@ -434,10 +439,21 @@ |
131 | view_window_->SetOpacity(0.0f); |
132 | view_window_->SetLayout(main_layout_); |
133 | view_window_->SetBackgroundColor(nux::color::Transparent); |
134 | - view_window_->SetGeometry(workarea_); |
135 | } |
136 | } |
137 | |
138 | +nux::Geometry GetSwitcherViewsGeometry() |
139 | +{ |
140 | + auto uscreen = UScreen::GetDefault(); |
141 | + int monitor = uscreen->GetMonitorWithMouse(); |
142 | + auto monitor_geo = uscreen->GetMonitorGeometry(monitor); |
143 | + |
144 | + monitor_geo.OffsetPosition(XY_OFFSET, XY_OFFSET); |
145 | + monitor_geo.OffsetSize(WH_OFFSET, WH_OFFSET); |
146 | + |
147 | + return monitor_geo; |
148 | +} |
149 | + |
150 | void Controller::Impl::ConstructView() |
151 | { |
152 | if (view_ || !model_) |
153 | @@ -451,10 +467,22 @@ |
154 | view_->background_color = bg_color_; |
155 | view_->monitor = obj_->monitor_; |
156 | |
157 | + view_->hide_request.connect(sigc::mem_fun(this, &Controller::Impl::Hide)); |
158 | + |
159 | + view_->switcher_mouse_up.connect([this] (int icon_index, int button) { |
160 | + if (button == 3) |
161 | + InitiateDetail(true); |
162 | + }); |
163 | + |
164 | + view_->switcher_mouse_move.connect([this] (int icon_index) { |
165 | + if (icon_index >= 0) |
166 | + ResetDetailTimer(obj_->detail_timeout_length); |
167 | + }); |
168 | + |
169 | ConstructWindow(); |
170 | main_layout_->AddView(view_.GetPointer(), 1); |
171 | view_window_->SetEnterFocusInputArea(view_.GetPointer()); |
172 | - view_window_->SetGeometry(workarea_); |
173 | + view_window_->SetGeometry(GetSwitcherViewsGeometry()); |
174 | |
175 | view_built.emit(); |
176 | } |
177 | @@ -491,6 +519,14 @@ |
178 | } |
179 | } |
180 | |
181 | +void Controller::Impl::DetailHide() |
182 | +{ |
183 | + // FIXME We need to refactor SwitcherModel so we can add/remove icons without causing |
184 | + // a crash. If you remove the last application in the list it crashes. |
185 | + model_->detail_selection = false; |
186 | + Hide(false); |
187 | +} |
188 | + |
189 | void Controller::Impl::HideWindow() |
190 | { |
191 | main_layout_->RemoveChildObject(view_.GetPointer()); |
192 | @@ -579,7 +615,7 @@ |
193 | obj_->detail_mode_ = DetailMode::TAB_NEXT_WINDOW; |
194 | } |
195 | else |
196 | - { |
197 | + { |
198 | model_->detail_selection = false; |
199 | } |
200 | } |
201 | |
202 | === modified file 'launcher/SwitcherController.h' |
203 | --- launcher/SwitcherController.h 2013-06-18 18:48:31 +0000 |
204 | +++ launcher/SwitcherController.h 2013-08-09 17:51:48 +0000 |
205 | @@ -88,6 +88,7 @@ |
206 | bool CanShowSwitcher(const std::vector<launcher::AbstractLauncherIcon::Ptr>& resutls) const; |
207 | |
208 | bool Visible(); |
209 | + nux::Geometry GetInputWindowGeometry() const; |
210 | |
211 | bool StartDetailMode(); |
212 | bool StopDetailMode(); |
213 | @@ -107,8 +108,6 @@ |
214 | |
215 | void SelectFirstItem(); |
216 | |
217 | - void SetWorkspace(nux::Geometry geo, int monitor); |
218 | - |
219 | nux::ObjectPtr<SwitcherView> GetView() const; |
220 | |
221 | ui::LayoutWindow::Vector ExternalRenderTargets(); |
222 | |
223 | === modified file 'launcher/SwitcherControllerImpl.h' |
224 | --- launcher/SwitcherControllerImpl.h 2013-06-14 00:23:34 +0000 |
225 | +++ launcher/SwitcherControllerImpl.h 2013-08-09 17:51:48 +0000 |
226 | @@ -48,6 +48,7 @@ |
227 | |
228 | void Show(ShowMode show, SortMode sort, std::vector<launcher::AbstractLauncherIcon::Ptr> results); |
229 | void Hide(bool accept_state); |
230 | + void DetailHide(); |
231 | |
232 | void Next(); |
233 | void Prev(); |
234 | @@ -82,6 +83,7 @@ |
235 | void ShowView(); |
236 | void HideWindow(); |
237 | |
238 | + void ResetDetailTimer(int timeout_length); |
239 | bool OnDetailTimer(); |
240 | void OnModelSelectionChanged(launcher::AbstractLauncherIcon::Ptr const& icon); |
241 | void OnBackgroundUpdate(GVariant* data); |
242 | @@ -94,7 +96,6 @@ |
243 | SwitcherView::Ptr view_; |
244 | |
245 | // @todo move these view data into the SwitcherView class |
246 | - nux::Geometry workarea_; |
247 | Controller::WindowCreator create_window_; |
248 | MockableBaseWindow::Ptr view_window_; |
249 | nux::HLayout* main_layout_; |
250 | |
251 | === modified file 'launcher/SwitcherModel.cpp' |
252 | --- launcher/SwitcherModel.cpp 2013-06-20 20:46:40 +0000 |
253 | +++ launcher/SwitcherModel.cpp 2013-08-09 17:51:48 +0000 |
254 | @@ -149,6 +149,12 @@ |
255 | results.push_back(xid); |
256 | } |
257 | |
258 | + if (results.empty() && detail_selection) |
259 | + { |
260 | + request_detail_hide.emit(); |
261 | + return results; |
262 | + } |
263 | + |
264 | std::sort(results.begin(), results.end(), [&wm](Window first, Window second) { |
265 | return wm.GetWindowActiveNumber(first) > wm.GetWindowActiveNumber(second); |
266 | }); |
267 | |
268 | === modified file 'launcher/SwitcherModel.h' |
269 | --- launcher/SwitcherModel.h 2013-06-17 23:56:23 +0000 |
270 | +++ launcher/SwitcherModel.h 2013-08-09 17:51:48 +0000 |
271 | @@ -101,6 +101,7 @@ |
272 | void Select(unsigned int index); |
273 | |
274 | sigc::signal<void, launcher::AbstractLauncherIcon::Ptr const&> selection_changed; |
275 | + sigc::signal<void> request_detail_hide; |
276 | |
277 | protected: |
278 | // Introspectable methods |
279 | |
280 | === modified file 'launcher/SwitcherView.cpp' |
281 | --- launcher/SwitcherView.cpp 2013-07-29 17:17:43 +0000 |
282 | +++ launcher/SwitcherView.cpp 2013-08-09 17:51:48 +0000 |
283 | @@ -21,6 +21,7 @@ |
284 | #include "SwitcherView.h" |
285 | #include "unity-shared/IconRenderer.h" |
286 | #include "unity-shared/TimeUtil.h" |
287 | +#include "unity-shared/UScreen.h" |
288 | |
289 | #include <Nux/Nux.h> |
290 | #include <UnityCore/Variant.h> |
291 | @@ -36,6 +37,8 @@ |
292 | namespace |
293 | { |
294 | const unsigned int VERTICAL_PADDING = 45; |
295 | + const unsigned int SPREAD_OFFSET = 100; |
296 | + const unsigned int EXTRA_ICON_SPACE = 10; |
297 | } |
298 | |
299 | NUX_IMPLEMENT_OBJECT_TYPE(SwitcherView); |
300 | @@ -55,6 +58,8 @@ |
301 | , spread_size(3.5f) |
302 | , icon_renderer_(std::make_shared<IconRenderer>()) |
303 | , text_view_(new StaticCairoText("")) |
304 | + , last_icon_selected_(-1) |
305 | + , last_detail_icon_selected_(-1) |
306 | , target_sizes_set_(false) |
307 | { |
308 | icon_renderer_->pip_style = OVER_TILE; |
309 | @@ -68,7 +73,13 @@ |
310 | icon_size.changed.connect (sigc::mem_fun (this, &SwitcherView::OnIconSizeChanged)); |
311 | tile_size.changed.connect (sigc::mem_fun (this, &SwitcherView::OnTileSizeChanged)); |
312 | |
313 | + mouse_move.connect (sigc::mem_fun(this, &SwitcherView::RecvMouseMove)); |
314 | + mouse_down.connect (sigc::mem_fun(this, &SwitcherView::RecvMouseDown)); |
315 | + mouse_up.connect (sigc::mem_fun(this, &SwitcherView::RecvMouseUp)); |
316 | + mouse_wheel.connect(sigc::mem_fun(this, &SwitcherView::RecvMouseWheel)); |
317 | + |
318 | CaptureMouseDownAnyWhereElse(true); |
319 | + SetAcceptMouseWheelEvent(true); |
320 | ResetTimer(); |
321 | |
322 | animate.changed.connect([this] (bool enabled) { |
323 | @@ -103,9 +114,32 @@ |
324 | .add("animation-length", animation_length) |
325 | .add("spread-size", (float)spread_size) |
326 | .add("label", text_view_->GetText()) |
327 | + .add("spread_offset", SPREAD_OFFSET) |
328 | .add("label_visible", text_view_->IsVisible()); |
329 | } |
330 | |
331 | +debug::Introspectable::IntrospectableList SwitcherView::GetIntrospectableChildren() |
332 | +{ |
333 | + std::list<unity::debug::Introspectable*> introspection_results; |
334 | + |
335 | + if (model_->detail_selection) |
336 | + { |
337 | + for (auto const& target : render_targets_) |
338 | + { |
339 | + introspection_results.push_back(target.get()); |
340 | + } |
341 | + } |
342 | + else if (!last_args_.empty()) |
343 | + { |
344 | + for (auto& args : last_args_) |
345 | + { |
346 | + introspection_results.push_back(&args); |
347 | + } |
348 | + } |
349 | + |
350 | + return introspection_results; |
351 | +} |
352 | + |
353 | LayoutWindow::Vector SwitcherView::ExternalTargets () |
354 | { |
355 | return render_targets_; |
356 | @@ -118,6 +152,8 @@ |
357 | model->detail_selection.changed.connect (sigc::mem_fun (this, &SwitcherView::OnDetailSelectionChanged)); |
358 | model->detail_selection_index.changed.connect (sigc::mem_fun (this, &SwitcherView::OnDetailSelectionIndexChanged)); |
359 | |
360 | + last_icon_selected_ = -1; |
361 | + |
362 | if (!model->Selection()) |
363 | return; |
364 | |
365 | @@ -129,12 +165,12 @@ |
366 | |
367 | void SwitcherView::OnIconSizeChanged (int size) |
368 | { |
369 | - icon_renderer_->SetTargetSize(tile_size, icon_size, 10); |
370 | + icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing); |
371 | } |
372 | |
373 | void SwitcherView::OnTileSizeChanged (int size) |
374 | { |
375 | - icon_renderer_->SetTargetSize(tile_size, icon_size, 10); |
376 | + icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing); |
377 | vertical_size = tile_size + VERTICAL_PADDING * 2; |
378 | } |
379 | |
380 | @@ -167,6 +203,8 @@ |
381 | { |
382 | text_view_->SetVisible(!detail); |
383 | |
384 | + last_detail_icon_selected_ = -1; |
385 | + |
386 | if (!detail) |
387 | { |
388 | text_view_->SetText(model_->Selection()->tooltip_text()); |
389 | @@ -186,6 +224,181 @@ |
390 | QueueDraw(); |
391 | } |
392 | |
393 | +nux::Point CalculateMouseMonitorOffset(int x, int y) |
394 | +{ |
395 | + int monitor = unity::UScreen::GetDefault()->GetMonitorWithMouse(); |
396 | + nux::Geometry const& geo = unity::UScreen::GetDefault()->GetMonitorGeometry(monitor); |
397 | + |
398 | + return {geo.x + x, geo.y + y}; |
399 | +} |
400 | + |
401 | +void SwitcherView::RecvMouseMove(int x, int y, int /*dx*/, int /*dy*/, unsigned long /*button_flags*/, unsigned long /*key_flags*/) |
402 | +{ |
403 | + if (model_->detail_selection) |
404 | + { |
405 | + HandleDetailMouseMove(x, y); |
406 | + } |
407 | + else |
408 | + { |
409 | + HandleMouseMove(x, y); |
410 | + } |
411 | +} |
412 | + |
413 | +void SwitcherView::HandleDetailMouseMove(int x, int y) |
414 | +{ |
415 | + nux::Point const& mouse_pos = CalculateMouseMonitorOffset(x, y); |
416 | + int detail_icon_index = DetailIconIdexAt(mouse_pos.x, mouse_pos.y); |
417 | + |
418 | + if (detail_icon_index >= 0 && detail_icon_index != last_detail_icon_selected_) |
419 | + { |
420 | + model_->detail_selection_index = detail_icon_index; |
421 | + last_detail_icon_selected_ = detail_icon_index; |
422 | + } |
423 | +} |
424 | + |
425 | +void SwitcherView::HandleMouseMove(int x, int y) |
426 | +{ |
427 | + int icon_index = IconIndexAt(x, y); |
428 | + |
429 | + if (icon_index >= 0) |
430 | + { |
431 | + if (icon_index != last_icon_selected_) |
432 | + { |
433 | + if (icon_index != model_->SelectionIndex()) |
434 | + { |
435 | + model_->Select(icon_index); |
436 | + } |
437 | + |
438 | + last_icon_selected_ = icon_index; |
439 | + } |
440 | + |
441 | + switcher_mouse_move.emit(icon_index); |
442 | + } |
443 | +} |
444 | + |
445 | +void SwitcherView::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long /*key_flags*/) |
446 | +{ |
447 | + int button = nux::GetEventButton(button_flags); |
448 | + |
449 | + if (!CheckMouseInsideBackground(x, y)) |
450 | + hide_request.emit(false); |
451 | + |
452 | + if (model_->detail_selection) |
453 | + { |
454 | + HandleDetailMouseDown(x, y, button); |
455 | + } |
456 | + else |
457 | + { |
458 | + HandleMouseDown(x, y, button); |
459 | + } |
460 | +} |
461 | + |
462 | +void SwitcherView::HandleDetailMouseDown(int x, int y, int button) |
463 | +{ |
464 | + nux::Point const& mouse_pos = CalculateMouseMonitorOffset(x, y); |
465 | + int detail_icon_index = DetailIconIdexAt(mouse_pos.x, mouse_pos.y); |
466 | + |
467 | + last_detail_icon_selected_ = detail_icon_index; |
468 | + |
469 | + switcher_mouse_down.emit(detail_icon_index, button); |
470 | +} |
471 | + |
472 | +void SwitcherView::HandleMouseDown(int x, int y, int button) |
473 | +{ |
474 | + int icon_index = IconIndexAt(x,y); |
475 | + |
476 | + last_icon_selected_ = icon_index; |
477 | + |
478 | + switcher_mouse_down.emit(icon_index, button); |
479 | +} |
480 | + |
481 | +void SwitcherView::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long /*key_flags*/) |
482 | +{ |
483 | + int button = nux::GetEventButton(button_flags); |
484 | + |
485 | + if (model_->detail_selection) |
486 | + { |
487 | + HandleDetailMouseUp(x, y, button); |
488 | + } |
489 | + else |
490 | + { |
491 | + HandleMouseUp(x, y, button); |
492 | + } |
493 | +} |
494 | + |
495 | +void SwitcherView::HandleDetailMouseUp(int x, int y, int button) |
496 | +{ |
497 | + nux::Point const& mouse_pos = CalculateMouseMonitorOffset(x, y); |
498 | + int detail_icon_index = DetailIconIdexAt(mouse_pos.x, mouse_pos.y); |
499 | + |
500 | + switcher_mouse_up.emit(detail_icon_index, button); |
501 | + |
502 | + if (button == 1) |
503 | + { |
504 | + if (detail_icon_index >= 0 && detail_icon_index == last_detail_icon_selected_) |
505 | + { |
506 | + model_->detail_selection_index = detail_icon_index; |
507 | + hide_request.emit(true); |
508 | + } |
509 | + } |
510 | + else if (button == 3) |
511 | + { |
512 | + model_->detail_selection = false; |
513 | + } |
514 | +} |
515 | + |
516 | +void SwitcherView::HandleMouseUp(int x, int y, int button) |
517 | +{ |
518 | + int icon_index = IconIndexAt(x,y); |
519 | + |
520 | + switcher_mouse_up.emit(icon_index, button); |
521 | + |
522 | + if (button == 1) |
523 | + { |
524 | + if (icon_index >= 0 && icon_index == last_icon_selected_) |
525 | + { |
526 | + model_->Select(icon_index); |
527 | + hide_request.emit(true); |
528 | + } |
529 | + } |
530 | +} |
531 | + |
532 | +void SwitcherView::RecvMouseWheel(int /*x*/, int /*y*/, int wheel_delta, unsigned long /*button_flags*/, unsigned long /*key_flags*/) |
533 | +{ |
534 | + if (model_->detail_selection) |
535 | + { |
536 | + HandleDetailMouseWheel(wheel_delta); |
537 | + } |
538 | + else |
539 | + { |
540 | + HandleMouseWheel(wheel_delta); |
541 | + } |
542 | +} |
543 | + |
544 | +void SwitcherView::HandleDetailMouseWheel(int wheel_delta) |
545 | +{ |
546 | + if (wheel_delta > 0) |
547 | + { |
548 | + model_->NextDetail(); |
549 | + } |
550 | + else |
551 | + { |
552 | + model_->PrevDetail(); |
553 | + } |
554 | +} |
555 | + |
556 | +void SwitcherView::HandleMouseWheel(int wheel_delta) |
557 | +{ |
558 | + if (wheel_delta > 0) |
559 | + { |
560 | + model_->Next(); |
561 | + } |
562 | + else |
563 | + { |
564 | + model_->Prev(); |
565 | + } |
566 | +} |
567 | + |
568 | SwitcherModel::Ptr SwitcherView::GetModel() |
569 | { |
570 | return model_; |
571 | @@ -420,7 +633,7 @@ |
572 | nux::Geometry const& spread_bounds = UpdateRenderTargets(progress); |
573 | ResizeRenderTargets(spread_bounds, progress); |
574 | // remove extra space consumed by spread |
575 | - spread_padded_width = spread_bounds.width + 100; |
576 | + spread_padded_width = spread_bounds.width + SPREAD_OFFSET; |
577 | max_width -= spread_padded_width - tile_size; |
578 | |
579 | int expansion = std::max(0, spread_bounds.height - icon_size); |
580 | @@ -551,7 +764,7 @@ |
581 | |
582 | if (!target_sizes_set_) |
583 | { |
584 | - icon_renderer_->SetTargetSize(tile_size, icon_size, 10); |
585 | + icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing); |
586 | target_sizes_set_ = true; |
587 | } |
588 | |
589 | @@ -640,9 +853,9 @@ |
590 | } |
591 | } |
592 | |
593 | -int SwitcherView::IconIndexAt(int x, int y) |
594 | +int SwitcherView::IconIndexAt(int x, int y) const |
595 | { |
596 | - int half_size = icon_size.Get() / 2; |
597 | + int half_size = icon_size.Get() / 2 + EXTRA_ICON_SPACE; |
598 | int icon_index = -1; |
599 | |
600 | // Taking icon rotation into consideration will make selection more |
601 | @@ -673,5 +886,27 @@ |
602 | return icon_index; |
603 | } |
604 | |
605 | +int SwitcherView::DetailIconIdexAt(int x, int y) const |
606 | +{ |
607 | + int index = -1; |
608 | + |
609 | + for (unsigned int i = 0; i < render_targets_.size(); ++i) |
610 | + { |
611 | + if (render_targets_[i]->result.IsPointInside(x + SPREAD_OFFSET, y + SPREAD_OFFSET)) |
612 | + return i; |
613 | + } |
614 | + |
615 | + return index; |
616 | +} |
617 | + |
618 | +bool SwitcherView::CheckMouseInsideBackground(int x, int y) const |
619 | +{ |
620 | + nux::Point p(x,y); |
621 | + if (last_background_.IsInside(p)) |
622 | + return true; |
623 | + |
624 | + return false; |
625 | +} |
626 | + |
627 | } |
628 | } |
629 | |
630 | === modified file 'launcher/SwitcherView.h' |
631 | --- launcher/SwitcherView.h 2013-02-13 01:45:00 +0000 |
632 | +++ launcher/SwitcherView.h 2013-08-09 17:51:48 +0000 |
633 | @@ -25,6 +25,7 @@ |
634 | #include "unity-shared/StaticCairoText.h" |
635 | #include "unity-shared/LayoutSystem.h" |
636 | #include "unity-shared/BackgroundEffectHelper.h" |
637 | +#include "unity-shared/Introspectable.h" |
638 | #include "unity-shared/UnityWindowView.h" |
639 | |
640 | #include <Nux/View.h> |
641 | @@ -70,13 +71,24 @@ |
642 | |
643 | // Returns the index of the icon at the given position, in window coordinates. |
644 | // If there's no icon there, -1 is returned. |
645 | - int IconIndexAt(int x, int y); |
646 | - |
647 | + int IconIndexAt(int x, int y) const; |
648 | + int DetailIconIdexAt(int x, int y) const; |
649 | + |
650 | + /* void; int icon_index, int button*/ |
651 | + sigc::signal<void, int, int> switcher_mouse_down; |
652 | + sigc::signal<void, int, int> switcher_mouse_up; |
653 | + |
654 | + /* void; int icon_index */ |
655 | + sigc::signal<void, int> switcher_mouse_move; |
656 | + |
657 | + /* void; bool visible */ |
658 | + sigc::signal<void, bool> hide_request; |
659 | |
660 | protected: |
661 | // Introspectable methods |
662 | std::string GetName() const; |
663 | void AddProperties(GVariantBuilder* builder); |
664 | + IntrospectableList GetIntrospectableChildren(); |
665 | |
666 | void PreDraw(nux::GraphicsEngine& GfxContext, bool force_draw); |
667 | void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry const& clip); |
668 | @@ -88,7 +100,24 @@ |
669 | std::list<ui::RenderArg> RenderArgsFlat(nux::Geometry& background_geo, int selection, float progress); |
670 | |
671 | ui::RenderArg CreateBaseArgForIcon(launcher::AbstractLauncherIcon::Ptr const& icon); |
672 | + |
673 | private: |
674 | + void RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags); |
675 | + void HandleDetailMouseMove(int x, int y); |
676 | + void HandleMouseMove(int x, int y); |
677 | + |
678 | + void RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags); |
679 | + void HandleDetailMouseDown(int x, int y, int button); |
680 | + void HandleMouseDown(int x, int y, int button); |
681 | + |
682 | + void RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags); |
683 | + void HandleDetailMouseUp(int x, int y, int button); |
684 | + void HandleMouseUp(int x, int y, int button); |
685 | + |
686 | + void RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags); |
687 | + void HandleDetailMouseWheel(int wheel_delta); |
688 | + void HandleMouseWheel(int wheel_delta); |
689 | + |
690 | void OnSelectionChanged(launcher::AbstractLauncherIcon::Ptr const& selection); |
691 | void OnDetailSelectionChanged (bool detail); |
692 | void OnDetailSelectionIndexChanged (unsigned int index); |
693 | @@ -111,14 +140,17 @@ |
694 | void ResetTimer(); |
695 | void SaveLast(); |
696 | |
697 | + bool CheckMouseInsideBackground(int x, int y) const; |
698 | + |
699 | SwitcherModel::Ptr model_; |
700 | ui::LayoutSystem layout_system_; |
701 | ui::AbstractIconRenderer::Ptr icon_renderer_; |
702 | nux::ObjectPtr<StaticCairoText> text_view_; |
703 | |
704 | + int last_icon_selected_; |
705 | + int last_detail_icon_selected_; |
706 | bool target_sizes_set_; |
707 | |
708 | - |
709 | std::list<ui::RenderArg> last_args_; |
710 | std::list<ui::RenderArg> saved_args_; |
711 | |
712 | |
713 | === modified file 'plugins/unityshell/src/unityshell.cpp' |
714 | --- plugins/unityshell/src/unityshell.cpp 2013-08-07 13:27:56 +0000 |
715 | +++ plugins/unityshell/src/unityshell.cpp 2013-08-09 17:51:48 +0000 |
716 | @@ -971,6 +971,19 @@ |
717 | return false; |
718 | } |
719 | |
720 | +LayoutWindow::Ptr UnityScreen::GetSwitcherDetailLayoutWindow(Window window) const |
721 | +{ |
722 | + LayoutWindow::Vector const& targets = switcher_controller_->ExternalRenderTargets(); |
723 | + |
724 | + for (LayoutWindow::Ptr const& target : targets) |
725 | + { |
726 | + if (target->xid == window) |
727 | + return target; |
728 | + } |
729 | + |
730 | + return nullptr; |
731 | +} |
732 | + |
733 | void UnityWindow::enterShowDesktop () |
734 | { |
735 | if (!mShowdesktopHandler) |
736 | @@ -1169,7 +1182,8 @@ |
737 | handled = true; |
738 | } |
739 | else if (event->xbutton.button == Button2 && |
740 | - GetScaledGeometry().IsPointInside(event->xbutton.x_root, event->xbutton.y_root)) |
741 | + (GetScaledGeometry().IsPointInside(event->xbutton.x_root, event->xbutton.y_root) || |
742 | + GetLayoutWindowGeometry().IsPointInside(event->xbutton.x_root, event->xbutton.y_root))) |
743 | { |
744 | middle_clicked_ = true; |
745 | handled = true; |
746 | @@ -1190,7 +1204,9 @@ |
747 | if (was_pressed) |
748 | { |
749 | if (close_button_geo_.IsPointInside(event->xbutton.x_root, event->xbutton.y_root)) |
750 | + { |
751 | window->close(0); |
752 | + } |
753 | |
754 | handled = true; |
755 | } |
756 | @@ -1198,7 +1214,8 @@ |
757 | if (middle_clicked_) |
758 | { |
759 | if (event->xbutton.button == Button2 && |
760 | - GetScaledGeometry().IsPointInside(event->xbutton.x_root, event->xbutton.y_root)) |
761 | + (GetScaledGeometry().IsPointInside(event->xbutton.x_root, event->xbutton.y_root) || |
762 | + GetLayoutWindowGeometry().IsPointInside(event->xbutton.x_root, event->xbutton.y_root))) |
763 | { |
764 | window->close(0); |
765 | } |
766 | @@ -1492,6 +1509,14 @@ |
767 | if (CompWindow *w = screen->findWindow(ss->getSelectedWindow())) |
768 | skip_other_plugins = UnityWindow::get(w)->handleEvent(event); |
769 | } |
770 | + else if (switcher_controller_->IsDetailViewShown()) |
771 | + { |
772 | + Window win = switcher_controller_->GetCurrentSelection().window_; |
773 | + CompWindow* w = screen->findWindow(win); |
774 | + |
775 | + if (w) |
776 | + skip_other_plugins = UnityWindow::get(w)->handleEvent(event); |
777 | + } |
778 | break; |
779 | case ButtonPress: |
780 | if (super_keypressed_) |
781 | @@ -1505,6 +1530,14 @@ |
782 | if (CompWindow *w = screen->findWindow(ss->getSelectedWindow())) |
783 | skip_other_plugins = UnityWindow::get(w)->handleEvent(event); |
784 | } |
785 | + else if (switcher_controller_->IsDetailViewShown()) |
786 | + { |
787 | + Window win = switcher_controller_->GetCurrentSelection().window_; |
788 | + CompWindow* w = screen->findWindow(win); |
789 | + |
790 | + if (w) |
791 | + skip_other_plugins = UnityWindow::get(w)->handleEvent(event); |
792 | + } |
793 | |
794 | if (dash_controller_->IsVisible()) |
795 | { |
796 | @@ -1532,8 +1565,7 @@ |
797 | } |
798 | } |
799 | } |
800 | - |
801 | - if (hud_controller_->IsVisible()) |
802 | + else if (hud_controller_->IsVisible()) |
803 | { |
804 | nux::Point pt(event->xbutton.x_root, event->xbutton.y_root); |
805 | nux::Geometry const& hud_geo = hud_controller_->GetInputWindowGeometry(); |
806 | @@ -1547,24 +1579,26 @@ |
807 | hud_controller_->HideHud(false); |
808 | } |
809 | } |
810 | + else if (switcher_controller_->Visible()) |
811 | + { |
812 | + nux::Point pt(event->xbutton.x_root, event->xbutton.y_root); |
813 | + nux::Geometry const& switcher_geo = switcher_controller_->GetInputWindowGeometry(); |
814 | + |
815 | + if (!switcher_geo.IsInside(pt)) |
816 | + { |
817 | + switcher_controller_->Hide(false); |
818 | + } |
819 | + } |
820 | break; |
821 | case ButtonRelease: |
822 | - if (switcher_controller_ && switcher_controller_->Visible()) |
823 | + |
824 | + if (switcher_controller_->IsDetailViewShown()) |
825 | { |
826 | - XButtonEvent *bev = reinterpret_cast<XButtonEvent*>(event); |
827 | - if (bev->time - last_scroll_event_ > 150) |
828 | - { |
829 | - if (bev->button == Button4 || bev->button == local::SCROLL_UP_BUTTON) |
830 | - { |
831 | - switcher_controller_->Prev(); |
832 | - last_scroll_event_ = bev->time; |
833 | - } |
834 | - else if (bev->button == Button5 || bev->button == local::SCROLL_DOWN_BUTTON) |
835 | - { |
836 | - switcher_controller_->Next(); |
837 | - last_scroll_event_ = bev->time; |
838 | - } |
839 | - } |
840 | + Window win = switcher_controller_->GetCurrentSelection().window_; |
841 | + CompWindow* w = screen->findWindow(win); |
842 | + |
843 | + if (w) |
844 | + skip_other_plugins = UnityWindow::get(w)->handleEvent(event); |
845 | } |
846 | else if (wm.IsScaleActive()) |
847 | { |
848 | @@ -1686,7 +1720,7 @@ |
849 | } |
850 | |
851 | if (!skip_other_plugins && |
852 | - screen->otherGrabExist("deco", "move", "switcher", "resize", "unity-switcher", nullptr)) |
853 | + screen->otherGrabExist("deco", "move", "switcher", "resize", nullptr)) |
854 | { |
855 | wt->ProcessForeignEvent(event, nullptr); |
856 | } |
857 | @@ -1890,7 +1924,7 @@ |
858 | bool UnityScreen::altTabInitiateCommon(CompAction* action, switcher::ShowMode show_mode) |
859 | { |
860 | if (!grab_index_) |
861 | - grab_index_ = screen->pushGrab (screen->invisibleCursor(), "unity-switcher"); |
862 | + grab_index_ = screen->pushGrab (screen->normalCursor(), "unity-switcher"); |
863 | |
864 | screen->addAction(&optionGetAltTabRight()); |
865 | screen->addAction(&optionGetAltTabDetailStart()); |
866 | @@ -1921,18 +1955,6 @@ |
867 | |
868 | void UnityScreen::SetUpAndShowSwitcher(switcher::ShowMode show_mode) |
869 | { |
870 | - // maybe check launcher position/hide state? |
871 | - |
872 | - auto uscreen = UScreen::GetDefault(); |
873 | - int monitor = uscreen->GetMonitorWithMouse(); |
874 | - auto monitor_geo = uscreen->GetMonitorGeometry(monitor); |
875 | - |
876 | - monitor_geo.x += 100; |
877 | - monitor_geo.y += 100; |
878 | - monitor_geo.width -= 200; |
879 | - monitor_geo.height -= 200; |
880 | - switcher_controller_->SetWorkspace(monitor_geo, monitor); |
881 | - |
882 | RaiseInputWindows(); |
883 | |
884 | auto results = launcher_controller_->GetAltTabIcons(show_mode == switcher::ShowMode::CURRENT_VIEWPORT, |
885 | @@ -3819,15 +3841,31 @@ |
886 | if (state != ScaleScreen::Wait && state != ScaleScreen::Out) |
887 | return; |
888 | |
889 | - auto const& scaled_geo = GetScaledGeometry(); |
890 | + nux::Geometry const& scale_geo = GetScaledGeometry(); |
891 | + |
892 | auto const& pos = scale_win->getCurrentPosition(); |
893 | |
894 | bool highlighted = (ss->getSelectedWindow() == window->id()); |
895 | - paintFakeDecoration(scaled_geo, attrib, transform, mask, highlighted, pos.scale); |
896 | + paintFakeDecoration(scale_geo, attrib, transform, mask, highlighted, pos.scale); |
897 | +} |
898 | + |
899 | +nux::Geometry UnityWindow::GetLayoutWindowGeometry() |
900 | +{ |
901 | + auto const& layout_window = UnityScreen::get(screen)->GetSwitcherDetailLayoutWindow(window->id()); |
902 | + |
903 | + if (layout_window) |
904 | + return layout_window->result; |
905 | + |
906 | + return nux::Geometry(); |
907 | } |
908 | |
909 | nux::Geometry UnityWindow::GetScaledGeometry() |
910 | { |
911 | + WindowManager& wm = WindowManager::Default(); |
912 | + |
913 | + if (!wm.IsScaleActive()) |
914 | + return nux::Geometry(); |
915 | + |
916 | ScaleWindow* scale_win = ScaleWindow::get(window); |
917 | |
918 | ScalePosition const& pos = scale_win->getCurrentPosition(); |
919 | |
920 | === modified file 'plugins/unityshell/src/unityshell.h' |
921 | --- plugins/unityshell/src/unityshell.h 2013-08-07 13:27:56 +0000 |
922 | +++ plugins/unityshell/src/unityshell.h 2013-08-09 17:51:48 +0000 |
923 | @@ -193,6 +193,8 @@ |
924 | |
925 | bool DoesPointIntersectUnityGeos(nux::Point const& pt); |
926 | |
927 | + ui::LayoutWindow::Ptr GetSwitcherDetailLayoutWindow(Window window) const; |
928 | + |
929 | protected: |
930 | std::string GetName() const; |
931 | void AddProperties(GVariantBuilder* builder); |
932 | @@ -392,6 +394,7 @@ |
933 | bool place(CompPoint& pos); |
934 | CompPoint tryNotIntersectUI(CompPoint& pos); |
935 | nux::Geometry GetScaledGeometry(); |
936 | + nux::Geometry GetLayoutWindowGeometry(); |
937 | |
938 | void paintThumbnail(nux::Geometry const& bounding, float parent_alpha, float alpha, float scale_ratio, unsigned deco_height, bool selected); |
939 | |
940 | |
941 | === modified file 'tests/autopilot/unity/emulators/switcher.py' |
942 | --- tests/autopilot/unity/emulators/switcher.py 2013-05-10 05:16:07 +0000 |
943 | +++ tests/autopilot/unity/emulators/switcher.py 2013-08-09 17:51:48 +0000 |
944 | @@ -234,6 +234,20 @@ |
945 | class SwitcherView(UnityIntrospectionObject): |
946 | """An emulator class for interacting with with SwitcherView.""" |
947 | |
948 | + @property |
949 | + def icon_args(self): |
950 | + return self.get_children_by_type(RenderArgs); |
951 | + |
952 | + @property |
953 | + def detail_icons(self): |
954 | + return self.get_children_by_type(LayoutWindow); |
955 | + |
956 | + |
957 | +class RenderArgs(UnityIntrospectionObject): |
958 | + """An emulator class for interacting with the RenderArgs class.""" |
959 | + |
960 | +class LayoutWindow(UnityIntrospectionObject): |
961 | + """An emulator class for interacting with the LayoutWindows class.""" |
962 | |
963 | class SwitcherModel(UnityIntrospectionObject): |
964 | """An emulator class for interacting with the SwitcherModel.""" |
965 | |
966 | === modified file 'tests/autopilot/unity/tests/test_switcher.py' |
967 | --- tests/autopilot/unity/tests/test_switcher.py 2013-06-15 02:24:01 +0000 |
968 | +++ tests/autopilot/unity/tests/test_switcher.py 2013-08-09 17:51:48 +0000 |
969 | @@ -512,3 +512,102 @@ |
970 | self.addCleanup(self.unity.switcher.terminate) |
971 | |
972 | self.assertThat(self.unity.switcher.visible, Eventually(Equals(False))) |
973 | + |
974 | +class SwitcherDetailsMouseTests(SwitcherTestCase): |
975 | + """ Test the interactions with the mouse and the switcher. """ |
976 | + |
977 | + def setUp(self): |
978 | + super(SwitcherDetailsMouseTests, self).setUp() |
979 | + self.set_timeout_setting(False) |
980 | + |
981 | + def test_mouse_highlights_switcher_icons(self): |
982 | + """ Tests that the mouse can hightlight all the switcher icons. """ |
983 | + |
984 | + self.process_manager.start_app("Character Map") |
985 | + |
986 | + self.unity.switcher.initiate() |
987 | + self.addCleanup(self.unity.switcher.terminate) |
988 | + |
989 | + icon_args = self.unity.switcher.view.icon_args |
990 | + offset = self.unity.switcher.view.spread_offset |
991 | + icon_cords = [] |
992 | + |
993 | + # Must collect the cords before moving mouse |
994 | + for args in icon_args: |
995 | + x = args.logical_center_x + offset |
996 | + y = args.logical_center_y + offset |
997 | + icon_cords.append((x,y)) |
998 | + |
999 | + index = 0; |
1000 | + for cords in icon_cords: |
1001 | + self.mouse.move(cords[0], cords[1]) |
1002 | + self.assertThat(index, Equals(self.unity.switcher.selection_index)) |
1003 | + index += 1 |
1004 | + |
1005 | + def test_mouse_clicks_activate_icon(self): |
1006 | + """ |
1007 | + Opens 2 different applications, CharMap being opened before TextEditor. |
1008 | + Then we get the index of the CharMap, and click on it, asserting CharMap is focused. |
1009 | + """ |
1010 | + |
1011 | + char_win1, char_win2 = self.start_applications("Character Map", "Text Editor") |
1012 | + self.assertVisibleWindowStack([char_win2, char_win1]) |
1013 | + self.assertProperty(char_win1, is_focused=False) |
1014 | + |
1015 | + self.unity.switcher.initiate() |
1016 | + self.addCleanup(self.unity.switcher.terminate) |
1017 | + |
1018 | + index = self.unity.switcher.selection_index |
1019 | + offset = self.unity.switcher.view.spread_offset |
1020 | + |
1021 | + icon_arg = self.unity.switcher.view.icon_args[index] |
1022 | + x = icon_arg.logical_center_x + offset |
1023 | + y = icon_arg.logical_center_y + offset |
1024 | + self.mouse.move(x, y) |
1025 | + self.mouse.click() |
1026 | + |
1027 | + self.assertProperty(char_win1, is_focused=True) |
1028 | + |
1029 | + def test_mouse_highlights_switcher_deatil_icons_motion(self): |
1030 | + """ |
1031 | + Gather the cords of all the detail icons, move the mouse through each |
1032 | + asserting the index of each icon we move through. |
1033 | + """ |
1034 | + |
1035 | + self.start_applications("Character Map", "Character Map", "Character Map") |
1036 | + |
1037 | + self.unity.switcher.initiate(SwitcherMode.DETAIL) |
1038 | + self.addCleanup(self.unity.switcher.terminate) |
1039 | + |
1040 | + offset = self.unity.switcher.view.spread_offset |
1041 | + cords = [] |
1042 | + |
1043 | + for icon in self.unity.switcher.view.detail_icons: |
1044 | + cords.append((icon.x + offset, icon.y + offset)) |
1045 | + |
1046 | + index = 0; |
1047 | + for cord in cords: |
1048 | + self.mouse.move(cord[0], cord[1]) |
1049 | + self.assertThat(index, Equals(self.unity.switcher.detail_selection_index)) |
1050 | + index += 1 |
1051 | + |
1052 | + def test_mouse_click_will_activate_detail_icon(self): |
1053 | + """ |
1054 | + Start 2 application of the same type, then click on index 0 in detail mode. This |
1055 | + will cause the focus from char_win2 to move to char_win1, showing clicking wokrs. |
1056 | + """ |
1057 | + |
1058 | + char_win1, char_win2 = self.start_applications("Character Map", "Character Map") |
1059 | + self.assertVisibleWindowStack([char_win2, char_win1]) |
1060 | + |
1061 | + self.unity.switcher.initiate(SwitcherMode.DETAIL) |
1062 | + self.addCleanup(self.unity.switcher.terminate) |
1063 | + |
1064 | + offset = self.unity.switcher.view.spread_offset |
1065 | + x = self.unity.switcher.view.detail_icons[0].x + offset |
1066 | + y = self.unity.switcher.view.detail_icons[0].y + offset |
1067 | + |
1068 | + self.mouse.move(x,y) |
1069 | + self.mouse.click() |
1070 | + |
1071 | + self.assertProperty(char_win1, is_focused=True) |
1072 | |
1073 | === modified file 'tests/test_switcher_controller.cpp' |
1074 | --- tests/test_switcher_controller.cpp 2013-06-21 18:58:17 +0000 |
1075 | +++ tests/test_switcher_controller.cpp 2013-08-09 17:51:48 +0000 |
1076 | @@ -272,3 +272,31 @@ |
1077 | EXPECT_EQ(mock_window_->GetOpacity(), 0.0f); |
1078 | Mock::VerifyAndClearExpectations(mock_window_.GetPointer()); |
1079 | } |
1080 | + |
1081 | +TEST_F(TestSwitcherController, TestRightClickedReceived) |
1082 | +{ |
1083 | + controller_->Show(ShowMode::ALL, SortMode::LAUNCHER_ORDER, icons_); |
1084 | + |
1085 | + auto const& view = controller_->GetView(); |
1086 | + auto const& model = view->GetModel(); |
1087 | + |
1088 | + ASSERT_FALSE(model->detail_selection()); |
1089 | + |
1090 | + view->switcher_mouse_up.emit(-1, 3); |
1091 | + view->switcher_mouse_down.emit(-1, 3); |
1092 | + |
1093 | + ASSERT_TRUE(model->detail_selection()); |
1094 | +} |
1095 | + |
1096 | +TEST_F(TestSwitcherController, TestHideRequest) |
1097 | +{ |
1098 | + controller_->Show(ShowMode::ALL, SortMode::LAUNCHER_ORDER, icons_); |
1099 | + |
1100 | + auto const& view = controller_->GetView(); |
1101 | + |
1102 | + ASSERT_TRUE(controller_->Visible()); |
1103 | + |
1104 | + view->hide_request.emit(false); |
1105 | + |
1106 | + ASSERT_FALSE(controller_->Visible()); |
1107 | +} |
1108 | |
1109 | === modified file 'unity-shared/AbstractIconRenderer.h' |
1110 | --- unity-shared/AbstractIconRenderer.h 2013-04-12 23:33:52 +0000 |
1111 | +++ unity-shared/AbstractIconRenderer.h 2013-08-09 17:51:48 +0000 |
1112 | @@ -22,8 +22,11 @@ |
1113 | |
1114 | #include <Nux/Nux.h> |
1115 | |
1116 | +#include "Introspectable.h" |
1117 | #include "IconTextureSource.h" |
1118 | |
1119 | +#include <UnityCore/Variant.h> |
1120 | + |
1121 | namespace unity |
1122 | { |
1123 | namespace ui |
1124 | @@ -35,7 +38,7 @@ |
1125 | OVER_TILE, |
1126 | }; |
1127 | |
1128 | -class RenderArg |
1129 | +class RenderArg : public debug::Introspectable |
1130 | { |
1131 | public: |
1132 | RenderArg() |
1133 | @@ -91,6 +94,17 @@ |
1134 | bool colorify_background; |
1135 | int window_indicators; |
1136 | char shortcut_label; |
1137 | + |
1138 | +protected: |
1139 | + // Introspectable methods |
1140 | + std::string GetName() const { return "RenderArgs"; } |
1141 | + void AddProperties(GVariantBuilder* builder) |
1142 | + { |
1143 | + unity::variant::BuilderWrapper(builder) |
1144 | + .add("logical_center_x", logical_center.x) |
1145 | + .add("logical_center_y", logical_center.y) |
1146 | + .add("logical_center_z", logical_center.z); |
1147 | + } |
1148 | }; |
1149 | |
1150 | class AbstractIconRenderer |
1151 | |
1152 | === modified file 'unity-shared/LayoutSystem.cpp' |
1153 | --- unity-shared/LayoutSystem.cpp 2013-06-17 23:56:23 +0000 |
1154 | +++ unity-shared/LayoutSystem.cpp 2013-08-09 17:51:48 +0000 |
1155 | @@ -19,6 +19,8 @@ |
1156 | |
1157 | #include "LayoutSystem.h" |
1158 | |
1159 | +#include <UnityCore/Variant.h> |
1160 | + |
1161 | namespace unity { |
1162 | namespace ui { |
1163 | |
1164 | @@ -290,5 +292,17 @@ |
1165 | } |
1166 | } |
1167 | |
1168 | +// Introspectable methods |
1169 | +std::string LayoutWindow::GetName() const |
1170 | +{ |
1171 | + return "LayoutWindow"; |
1172 | +} |
1173 | + |
1174 | +void LayoutWindow::AddProperties(GVariantBuilder* builder) |
1175 | +{ |
1176 | + unity::variant::BuilderWrapper(builder) |
1177 | + .add(result); |
1178 | +} |
1179 | + |
1180 | } |
1181 | } |
1182 | |
1183 | === modified file 'unity-shared/LayoutSystem.h' |
1184 | --- unity-shared/LayoutSystem.h 2013-06-14 00:23:34 +0000 |
1185 | +++ unity-shared/LayoutSystem.h 2013-08-09 17:51:48 +0000 |
1186 | @@ -24,13 +24,15 @@ |
1187 | #include <sigc++/sigc++.h> |
1188 | #include <Nux/Nux.h> |
1189 | |
1190 | +#include "unity-shared/Introspectable.h" |
1191 | #include "unity-shared/WindowManager.h" |
1192 | |
1193 | namespace unity { |
1194 | namespace ui { |
1195 | |
1196 | -struct LayoutWindow |
1197 | +class LayoutWindow : public debug::Introspectable |
1198 | { |
1199 | +public: |
1200 | typedef std::shared_ptr<LayoutWindow> Ptr; |
1201 | typedef std::vector<LayoutWindow::Ptr> Vector; |
1202 | |
1203 | @@ -45,6 +47,11 @@ |
1204 | bool selected; |
1205 | float aspect_ratio; |
1206 | float alpha; |
1207 | + |
1208 | +protected: |
1209 | + // Introspectable methods |
1210 | + std::string GetName() const; |
1211 | + void AddProperties(GVariantBuilder* builder); |
1212 | }; |
1213 | |
1214 | class LayoutSystem |
FAILED: Continuous integration, rev:3431 jenkins. qa.ubuntu. com/job/ unity-ci/ 253/ jenkins. qa.ubuntu. com/job/ unity-saucy- amd64-ci/ 142/console jenkins. qa.ubuntu. com/job/ unity-saucy- armhf-ci/ 140/console jenkins. qa.ubuntu. com/job/ unity-saucy- i386-ci/ 141/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ unity-ci/ 253/rebuild
http://