Merge lp:~nick-dedekind/unity/lp857422.dash-mouse-steal into lp:unity

Proposed by Nick Dedekind
Status: Merged
Approved by: Brandon Schaefer
Approved revision: no longer in the source branch.
Merged at revision: 2715
Proposed branch: lp:~nick-dedekind/unity/lp857422.dash-mouse-steal
Merge into: lp:unity
Diff against target: 948 lines (+329/-111)
17 files modified
dash/DashController.cpp (+30/-13)
dash/DashController.h (+4/-5)
dash/DashView.cpp (+5/-0)
dash/DashView.h (+2/-0)
hud/HudAbstractView.h (+3/-1)
hud/HudController.cpp (+42/-11)
hud/HudController.h (+7/-3)
hud/HudView.cpp (+60/-65)
hud/HudView.h (+4/-5)
hud/StandaloneHud.cpp (+1/-4)
plugins/unityshell/src/unityshell.cpp (+45/-3)
plugins/unityshell/src/unityshell.h (+2/-0)
tests/autopilot/unity/emulators/dash.py (+4/-0)
tests/autopilot/unity/tests/test_dash.py (+33/-0)
tests/autopilot/unity/tests/test_hud.py (+32/-0)
tests/test_hud_controller.cpp (+2/-1)
unity-shared/ResizingBaseWindow.h (+53/-0)
To merge this branch: bzr merge lp:~nick-dedekind/unity/lp857422.dash-mouse-steal
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
Review via email: mp+124221@code.launchpad.net

Commit message

Dash/Hud no longer steal mouse events outside their content area. Better draw handling of hud animation.

Description of the change

Resize input window relative to the size of the dash/hud. Now only encompasses the required content area.
Added some draw performance fixes for the hud. (only redraw when needed)

To post a comment you must log in.
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

This is a bit of a cheeky fix.
The problem causing the events to be stolen is that the base window of the dash/hud takes the monitor geometry as it's own. The XInputWindow which is responsible for receiving the XEvents has the same geometry.

This branch side-steps this issue by resizing the XInputWindow to match the actual size of the dash/hud, so if a user clicks outside the dash, it doesnt receive the click.

Revision history for this message
Omer Akram (om26er) wrote :

Has conflicts?

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

Fixed conflicts.

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

I checked with trunk and the launcher looks the same as trunk so we are good there :).

Other then that everything looks awesome :). The tests worked for me, and it works manually for me as well. The launcher works, the Window buttons works...

soo this branch looks good to me :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'dash/DashController.cpp'
2--- dash/DashController.cpp 2012-09-17 10:00:38 +0000
3+++ dash/DashController.cpp 2012-09-18 17:41:27 +0000
4@@ -66,13 +66,13 @@
5 , timeline_animator_(90)
6 , dbus_connect_cancellable_(g_cancellable_new())
7 {
8- SetupRelayoutCallbacks();
9 RegisterUBusInterests();
10
11 ensure_timeout_.Run([&]() { EnsureDash(); return false; });
12 timeline_animator_.animation_updated.connect(sigc::mem_fun(this, &Controller::OnViewShowHideFrame));
13
14 SetupWindow();
15+ UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(true); });
16
17 Settings::Instance().changed.connect([&]()
18 {
19@@ -97,7 +97,12 @@
20
21 void Controller::SetupWindow()
22 {
23- window_ = new nux::BaseWindow(dash::window_title);
24+ window_ = new ResizingBaseWindow(dash::window_title, [this](nux::Geometry const& geo)
25+ {
26+ if (view_)
27+ return GetInputWindowGeometry();
28+ return geo;
29+ });
30 window_->SetBackgroundColor(nux::Color(0.0f, 0.0f, 0.0f, 0.0f));
31 window_->SetConfigureNotifyCallback(&Controller::OnWindowConfigure, this);
32 window_->ShowWindow(false);
33@@ -122,19 +127,13 @@
34 layout->SetContentDistribution(nux::eStackLeft);
35 layout->SetVerticalExternalMargin(0);
36 layout->SetHorizontalExternalMargin(0);
37-
38 window_->SetLayout(layout);
39+
40+ window_->UpdateInputWindowGeometry();
41+
42 ubus_manager_.UnregisterInterest(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST);
43 }
44
45-void Controller::SetupRelayoutCallbacks()
46-{
47- GdkScreen* screen = gdk_screen_get_default();
48- auto relayout_cb = sigc::mem_fun(this, &Controller::Relayout);
49- sig_manager_.Add<void, GdkScreen*>(screen, "monitors-changed", relayout_cb);
50- sig_manager_.Add<void, GdkScreen*>(screen, "size-changed", relayout_cb);
51-}
52-
53 void Controller::RegisterUBusInterests()
54 {
55 ubus_manager_.RegisterInterest(UBUS_DASH_EXTERNAL_ACTIVATION,
56@@ -218,13 +217,19 @@
57 monitor_geo.height - panel_style.panel_height);
58 }
59
60-void Controller::Relayout(GdkScreen*screen)
61+void Controller::Relayout(bool check_monitor)
62 {
63 EnsureDash();
64
65+ if (check_monitor)
66+ {
67+ monitor_ = CLAMP(GetIdealMonitor(), 0, static_cast<int>(UScreen::GetDefault()->GetMonitors().size()-1));
68+ printf("relayout on monitor:%d, monitor count:%d\n", monitor_, static_cast<int>(UScreen::GetDefault()->GetMonitors().size()));
69+ }
70+
71 nux::Geometry geo = GetIdealWindowGeometry();
72+ view_->Relayout();
73 window_->SetGeometry(geo);
74- view_->Relayout();
75 panel::Style &panel_style = panel::Style::Instance();
76 view_->SetMonitorOffset(launcher_width, panel_style.panel_height);
77 }
78@@ -291,7 +296,11 @@
79 window_->ShowWindow(true);
80 window_->PushToFront();
81 if (!Settings::Instance().is_standalone) // in standalone mode, we do not need an input window. we are one.
82+ {
83 window_->EnableInputWindow(true, dash::window_title, true, false);
84+ // update the input window geometry. This causes the input window to match the actual size of the dash.
85+ window_->UpdateInputWindowGeometry();
86+ }
87 window_->SetInputFocus();
88 window_->CaptureMouseDownAnyWhereElse(true);
89 window_->QueueDraw();
90@@ -445,6 +454,14 @@
91 }
92 }
93
94+nux::Geometry Controller::GetInputWindowGeometry()
95+{
96+ EnsureDash();
97+ nux::Geometry const& window_geo(window_->GetGeometry());
98+ nux::Geometry const& view_content_geo(view_->GetContentGeometry());
99+ return nux::Geometry(window_geo.x, window_geo.y, view_content_geo.width, view_content_geo.height);
100+}
101+
102
103 }
104 }
105
106=== modified file 'dash/DashController.h'
107--- dash/DashController.h 2012-09-13 10:56:42 +0000
108+++ dash/DashController.h 2012-09-18 17:41:27 +0000
109@@ -27,12 +27,12 @@
110 #include <NuxCore/Property.h>
111 #include <NuxGraphics/GraphicsEngine.h>
112 #include <Nux/Nux.h>
113-#include <Nux/BaseWindow.h>
114
115 #include "DashView.h"
116 #include "unity-shared/Animator.h"
117 #include "unity-shared/Introspectable.h"
118 #include "unity-shared/UBusWrapper.h"
119+#include "unity-shared/ResizingBaseWindow.h"
120
121 namespace unity
122 {
123@@ -60,6 +60,7 @@
124 void HideDash(bool restore_focus = true);
125
126 bool IsVisible() const;
127+ nux::Geometry GetInputWindowGeometry();
128
129 protected:
130 std::string GetName() const;
131@@ -69,12 +70,11 @@
132 void EnsureDash();
133 void SetupWindow();
134 void SetupDashView();
135- void SetupRelayoutCallbacks();
136 void RegisterUBusInterests();
137
138 nux::Geometry GetIdealWindowGeometry();
139 int GetIdealMonitor();
140- void Relayout(GdkScreen*screen=NULL);
141+ void Relayout(bool check_monitor =false);
142
143 void OnMouseDownOutsideWindow(int x, int y, unsigned long bflags, unsigned long kflags);
144 void OnScreenUngrabbed();
145@@ -96,7 +96,7 @@
146 static void OnWindowConfigure(int width, int height, nux::Geometry& geo, void* data);
147
148 private:
149- nux::ObjectPtr<nux::BaseWindow> window_;
150+ nux::ObjectPtr<ResizingBaseWindow> window_;
151 int monitor_;
152
153 bool visible_;
154@@ -104,7 +104,6 @@
155 DashView* view_;
156
157 sigc::connection screen_ungrabbed_slot_;
158- glib::SignalManager sig_manager_;
159 glib::TimeoutSeconds ensure_timeout_;
160 Animator timeline_animator_;
161 UBusManager ubus_manager_;
162
163=== modified file 'dash/DashView.cpp'
164--- dash/DashView.cpp 2012-09-18 13:29:09 +0000
165+++ dash/DashView.cpp 2012-09-18 17:41:27 +0000
166@@ -1078,5 +1078,10 @@
167 return (view == nullptr) ? this : view;
168 }
169
170+nux::Geometry const& DashView::GetContentGeometry() const
171+{
172+ return content_geo_;
173+}
174+
175 }
176 }
177
178=== modified file 'dash/DashView.h'
179--- dash/DashView.h 2012-08-17 07:28:10 +0000
180+++ dash/DashView.h 2012-09-18 17:41:27 +0000
181@@ -69,6 +69,8 @@
182
183 nux::View* default_focus() const;
184
185+ nux::Geometry const& GetContentGeometry() const;
186+
187 protected:
188 void ProcessDndEnter();
189
190
191=== modified file 'hud/HudAbstractView.h'
192--- hud/HudAbstractView.h 2012-06-09 08:42:53 +0000
193+++ hud/HudAbstractView.h 2012-09-18 17:41:27 +0000
194@@ -48,8 +48,9 @@
195 virtual void SearchFinished() = 0;
196 virtual void SetIcon(std::string const& icon_name, unsigned int tile_size, unsigned int size, unsigned int padding) = 0;
197 virtual void SetQueries(Hud::Queries queries) = 0;
198- virtual void SetWindowGeometry(nux::Geometry const& absolute_geo, nux::Geometry const& geo) = 0;
199+ virtual void SetMonitorOffset(int x, int y) = 0;
200 virtual void ShowEmbeddedIcon(bool show) = 0;
201+ virtual nux::Geometry GetContentGeometry() = 0;
202
203 virtual nux::View* default_focus() const = 0;
204
205@@ -58,6 +59,7 @@
206 sigc::signal<void, std::string> search_activated;
207 sigc::signal<void, Query::Ptr> query_activated;
208 sigc::signal<void, Query::Ptr> query_selected;
209+ sigc::signal<void> layout_changed;
210 };
211
212 } // namespace hud
213
214=== modified file 'hud/HudController.cpp'
215--- hud/HudController.cpp 2012-09-17 10:00:38 +0000
216+++ hud/HudController.cpp 2012-09-18 17:41:27 +0000
217@@ -54,7 +54,7 @@
218 {
219 LOG_DEBUG(logger) << "hud startup";
220 SetupWindow();
221- UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(); });
222+ UScreen::GetDefault()->changed.connect([&] (int, std::vector<nux::Geometry>&) { Relayout(true); });
223
224 ubus.RegisterInterest(UBUS_HUD_CLOSE_REQUEST, sigc::mem_fun(this, &Controller::OnExternalHideHud));
225
226@@ -90,7 +90,12 @@
227 // Since BaseWindow is a View it is initially unowned. This means that the first
228 // reference that is taken grabs ownership of the pointer. Since the smart pointer
229 // references it, it becomes the owner, so no need to adopt the pointer here.
230- window_ = new nux::BaseWindow("Hud");
231+ window_ = new ResizingBaseWindow("Hud", [this](nux::Geometry const& geo)
232+ {
233+ if (view_)
234+ return GetInputWindowGeometry();
235+ return geo;
236+ });
237 window_->SetBackgroundColor(nux::Color(0.0f, 0.0f, 0.0f, 0.0f));
238 window_->SetConfigureNotifyCallback(&Controller::OnWindowConfigure, this);
239 window_->ShowWindow(false);
240@@ -117,6 +122,8 @@
241 layout_->AddView(view_, 1, nux::MINOR_POSITION_TOP);
242 window_->SetLayout(layout_);
243
244+ window_->UpdateInputWindowGeometry();
245+
246 view_->mouse_down_outside_pointer_grab_area.connect(sigc::mem_fun(this, &Controller::OnMouseDownOutsideWindow));
247
248 LOG_DEBUG(logger) << "connecting to signals";
249@@ -124,6 +131,7 @@
250 view_->search_activated.connect(sigc::mem_fun(this, &Controller::OnSearchActivated));
251 view_->query_activated.connect(sigc::mem_fun(this, &Controller::OnQueryActivated));
252 view_->query_selected.connect(sigc::mem_fun(this, &Controller::OnQuerySelected));
253+ view_->layout_changed.connect(sigc::bind(sigc::mem_fun(this, &Controller::Relayout), nullptr));
254 // Add to the debug introspection.
255 AddChild(view_);
256 }
257@@ -155,13 +163,15 @@
258
259 void Controller::EnsureHud()
260 {
261- LOG_DEBUG(logger) << "Initializing Hud";
262-
263 if (!window_)
264+ {
265+ LOG_DEBUG(logger) << "Initializing Hud Window";
266 SetupWindow();
267+ }
268
269 if (!view_)
270 {
271+ LOG_DEBUG(logger) << "Initializing Hud View";
272 SetupHudView();
273 Relayout();
274 }
275@@ -212,16 +222,20 @@
276 return geo;
277 }
278
279-void Controller::Relayout()
280+void Controller::Relayout(bool check_monitor)
281 {
282 EnsureHud();
283- nux::Geometry const& content_geo = view_->GetGeometry();
284+
285+ if (check_monitor)
286+ {
287+ monitor_index_ = CLAMP(GetIdealMonitor(), 0, static_cast<int>(UScreen::GetDefault()->GetMonitors().size()-1));
288+ }
289 nux::Geometry const& geo = GetIdealWindowGeometry();
290
291+ view_->Relayout();
292 window_->SetGeometry(geo);
293- layout_->SetMinMaxSize(content_geo.width, content_geo.height);
294- view_->SetWindowGeometry(window_->GetAbsoluteGeometry(), window_->GetGeometry());
295- view_->Relayout();
296+ panel::Style &panel_style = panel::Style::Instance();
297+ view_->SetMonitorOffset(launcher_width, panel_style.panel_height);
298 }
299
300 void Controller::OnMouseDownOutsideWindow(int x, int y,
301@@ -255,7 +269,15 @@
302 {
303 LOG_DEBUG(logger) << "External Hiding the hud";
304 EnsureHud();
305- HideHud();
306+
307+ if (variant)
308+ {
309+ HideHud(g_variant_get_boolean(variant));
310+ }
311+ else
312+ {
313+ HideHud();
314+ }
315 }
316
317 void Controller::ShowHideHud()
318@@ -353,6 +375,7 @@
319 window_->ShowWindow(true);
320 window_->PushToFront();
321 window_->EnableInputWindow(true, "Hud", true, false);
322+ window_->UpdateInputWindowGeometry();
323 window_->SetInputFocus();
324 window_->CaptureMouseDownAnyWhereElse(true);
325 view_->CaptureMouseDownAnyWhereElse(true);
326@@ -363,7 +386,6 @@
327 visible_ = true;
328
329 StartShowHideTimeline();
330- view_->SetWindowGeometry(window_->GetAbsoluteGeometry(), window_->GetGeometry());
331
332 // hide the launcher
333 GVariant* message_data = g_variant_new("(b)", TRUE);
334@@ -504,6 +526,15 @@
335 .add("locked_to_launcher", IsLockedToLauncher(monitor_index_));
336 }
337
338+nux::Geometry Controller::GetInputWindowGeometry()
339+{
340+ EnsureHud();
341+ nux::Geometry const& window_geo(window_->GetGeometry());
342+ nux::Geometry const& view_content_geo(view_->GetContentGeometry());
343+ return nux::Geometry(window_geo.x, window_geo.y, view_content_geo.width, view_content_geo.height);
344+}
345+
346+
347
348 }
349 }
350
351=== modified file 'hud/HudController.h'
352--- hud/HudController.h 2012-09-13 10:56:42 +0000
353+++ hud/HudController.h 2012-09-18 17:41:27 +0000
354@@ -24,14 +24,15 @@
355
356 #include <gdk/gdk.h>
357 #include <UnityCore/Hud.h>
358+#include <UnityCore/GLibSignal.h>
359
360 #include <NuxCore/Property.h>
361 #include <NuxGraphics/GraphicsEngine.h>
362 #include <Nux/Nux.h>
363-#include <Nux/BaseWindow.h>
364
365 #include "unity-shared/Animator.h"
366 #include "unity-shared/UBusWrapper.h"
367+#include "unity-shared/ResizingBaseWindow.h"
368 #include "HudView.h"
369
370 namespace unity
371@@ -59,6 +60,8 @@
372 void HideHud(bool restore_focus = true);
373 bool IsVisible();
374
375+ nux::Geometry GetInputWindowGeometry();
376+
377 protected:
378 // Introspectable
379 std::string GetName() const;
380@@ -75,7 +78,7 @@
381 bool IsLockedToLauncher(int monitor);
382
383 nux::Geometry GetIdealWindowGeometry();
384- void Relayout();
385+ void Relayout(bool check_monitor =false);
386
387 void OnMouseDownOutsideWindow(int x, int y, unsigned long bflags, unsigned long kflags);
388 void OnScreenUngrabbed();
389@@ -96,8 +99,9 @@
390 void OnQueriesFinished(Hud::Queries queries);
391
392 private:
393- nux::ObjectPtr<nux::BaseWindow> window_;
394+ nux::ObjectPtr<ResizingBaseWindow> window_;
395 UBusManager ubus;
396+ glib::SignalManager sig_manager_;
397 Hud hud_service_;
398 bool visible_;
399 bool need_show_;
400
401=== modified file 'hud/HudView.cpp'
402--- hud/HudView.cpp 2012-09-13 10:56:42 +0000
403+++ hud/HudView.cpp 2012-09-18 17:41:27 +0000
404@@ -61,10 +61,10 @@
405 : AbstractView()
406 , button_views_(nullptr)
407 , visible_(false)
408+ , timeline_animating_(false)
409 , start_time_(0)
410 , last_known_height_(0)
411 , current_height_(0)
412- , timeline_need_more_draw_(false)
413 , selected_button_(0)
414 , show_embedded_icon_(true)
415 , keyboard_stole_focus_(false)
416@@ -122,6 +122,12 @@
417 {
418 }
419
420+void View::SetMonitorOffset(int x, int y)
421+{
422+ renderer_.x_offset = x;
423+ renderer_.y_offset = y;
424+}
425+
426 void View::ProcessGrowShrink()
427 {
428 float diff = g_get_monotonic_time() - start_time_;
429@@ -129,24 +135,25 @@
430 // only animate if we are after our defined pause time
431 if (diff > pause_before_grow_length)
432 {
433- float progress = (diff - pause_before_grow_length) / grow_anim_length;
434- int last_height = last_known_height_;
435- int new_height = 0;
436-
437- if (last_height < target_height)
438- {
439- // grow
440- new_height = last_height + ((target_height - last_height) * progress);
441- }
442- else
443- {
444- //shrink
445- new_height = last_height - ((last_height - target_height) * progress);
446- }
447-
448- LOG_DEBUG(logger) << "resizing to " << target_height << " (" << new_height << ")"
449+ float progress = (diff - pause_before_grow_length) / grow_anim_length;
450+ int last_height = last_known_height_;
451+ int new_height = 0;
452+
453+ if (last_height < target_height)
454+ {
455+ // grow
456+ new_height = last_height + ((target_height - last_height) * progress);
457+ }
458+ else
459+ {
460+ //shrink
461+ new_height = last_height - ((last_height - target_height) * progress);
462+ }
463+
464+
465+ LOG_DEBUG(logger) << "resizing to " << target_height << " (" << new_height << ")"
466 << "View height: " << GetGeometry().height;
467- current_height_ = new_height;
468+ current_height_ = new_height;
469 }
470
471 for (auto button : buttons_)
472@@ -154,14 +161,23 @@
473 button->SetSkipDraw((button->GetAbsoluteY() + button->GetBaseHeight()) > (GetAbsoluteY() + current_height_));
474 }
475
476- QueueDraw();
477-
478 if (diff > grow_anim_length + pause_before_grow_length)
479 {
480 // ensure we are at our final location and update last known height
481 current_height_ = target_height;
482 last_known_height_ = target_height;
483- timeline_need_more_draw_ = false;
484+
485+ layout_changed.emit();
486+ timeline_idle_.reset();
487+ timeline_animating_ = false;
488+ }
489+ else
490+ {
491+ timeline_idle_.reset(new glib::Timeout(0, [this]
492+ {
493+ QueueDraw();
494+ return false;
495+ }));
496 }
497 }
498
499@@ -187,27 +203,6 @@
500 QueueDraw();
501 }
502
503-long View::PostLayoutManagement(long LayoutResult)
504-{
505- Relayout();
506- if (GetGeometry().height != last_known_height_)
507- {
508- // Start the timeline of drawing the dash resize
509- if (timeline_need_more_draw_)
510- {
511- // already started, just reset the last known height
512- last_known_height_ = current_height_;
513- }
514-
515- timeline_need_more_draw_ = true;
516- start_time_ = g_get_monotonic_time();
517- QueueDraw();
518- }
519-
520- return LayoutResult;
521-}
522-
523-
524 nux::View* View::default_focus() const
525 {
526 return search_bar_->text_entry();
527@@ -361,14 +356,6 @@
528 renderer_.AboutToHide();
529 }
530
531-void View::SetWindowGeometry(nux::Geometry const& absolute_geo, nux::Geometry const& geo)
532-{
533- window_geometry_ = geo;
534- window_geometry_.x = 0;
535- window_geometry_.y = 0;
536- absolute_window_geometry_ = absolute_geo;
537-}
538-
539 void View::SetupViews()
540 {
541 dash::Style& style = dash::Style::Instance();
542@@ -405,6 +392,17 @@
543 content_layout_->AddLayout(button_views_.GetPointer(), 1, nux::MINOR_POSITION_LEFT);
544 }
545
546+ content_layout_->OnGeometryChanged.connect([&](nux::Area*, nux::Geometry& geo)
547+ {
548+ if (!timeline_animating_)
549+ {
550+ timeline_animating_ = true;
551+ start_time_ = g_get_monotonic_time();
552+ QueueDraw();
553+ }
554+ });
555+
556+
557 layout_->AddLayout(content_layout_.GetPointer(), 1, nux::MINOR_POSITION_TOP);
558 }
559
560@@ -450,14 +448,12 @@
561
562 void View::Draw(nux::GraphicsEngine& gfx_context, bool force_draw)
563 {
564- if (timeline_need_more_draw_)
565- {
566+ if (timeline_animating_)
567 ProcessGrowShrink();
568- }
569
570 nux::Geometry draw_content_geo(layout_->GetGeometry());
571 draw_content_geo.height = current_height_;
572- renderer_.DrawFull(gfx_context, draw_content_geo, absolute_window_geometry_, window_geometry_, true);
573+ renderer_.DrawFull(gfx_context, draw_content_geo, GetAbsoluteGeometry(), GetGeometry(), true);
574 }
575
576 void View::DrawContent(nux::GraphicsEngine& gfx_context, bool force_draw)
577@@ -465,7 +461,7 @@
578 nux::Geometry draw_content_geo(layout_->GetGeometry());
579 draw_content_geo.height = current_height_;
580
581- renderer_.DrawInner(gfx_context, draw_content_geo, absolute_window_geometry_, window_geometry_);
582+ renderer_.DrawInner(gfx_context, draw_content_geo, GetAbsoluteGeometry(), GetGeometry());
583
584 gfx_context.PushClippingRectangle(draw_content_geo);
585
586@@ -492,16 +488,7 @@
587 }
588 gfx_context.PopClippingRectangle();
589
590- renderer_.DrawInnerCleanup(gfx_context, draw_content_geo, absolute_window_geometry_, window_geometry_);
591-
592- if (timeline_need_more_draw_ && !timeline_idle_)
593- {
594- timeline_idle_.reset(new glib::Idle([&] () {
595- QueueDraw();
596- timeline_idle_.reset();
597- return false;
598- }));
599- }
600+ renderer_.DrawInnerCleanup(gfx_context, draw_content_geo, GetAbsoluteGeometry(), GetGeometry());
601 }
602
603 void View::MouseStealsHudButtonFocus()
604@@ -769,6 +756,14 @@
605 return search_bar_->text_entry();
606 }
607
608+nux::Geometry View::GetContentGeometry()
609+{
610+ nux::Geometry geo(content_geo_);
611+ geo.height = current_height_;
612+ return geo;
613+}
614+
615+
616 }
617 }
618
619
620=== modified file 'hud/HudView.h'
621--- hud/HudView.h 2012-09-04 18:15:34 +0000
622+++ hud/HudView.h 2012-09-18 17:41:27 +0000
623@@ -60,7 +60,9 @@
624 void AboutToShow();
625 void AboutToHide();
626
627- void SetWindowGeometry(nux::Geometry const& absolute_geo, nux::Geometry const& geo);
628+ void SetMonitorOffset(int x, int y);
629+
630+ nux::Geometry GetContentGeometry();
631
632 protected:
633 virtual Area* FindKeyFocusArea(unsigned int event_type,
634@@ -69,7 +71,6 @@
635
636 void SetupViews();
637 void OnSearchChanged(std::string const& search_string);
638- virtual long PostLayoutManagement(long LayoutResult);
639
640 private:
641 void OnMouseButtonDown(int x, int y, unsigned long button, unsigned long key);
642@@ -110,14 +111,12 @@
643 Hud::Queries queries_;
644 nux::Geometry content_geo_;
645 OverlayRenderer renderer_;
646- nux::Geometry window_geometry_;
647- nux::Geometry absolute_window_geometry_;
648 glib::Source::UniquePtr timeline_idle_;
649+ bool timeline_animating_;
650
651 guint64 start_time_;
652 int last_known_height_;
653 int current_height_;
654- bool timeline_need_more_draw_;
655 int selected_button_;
656 bool show_embedded_icon_;
657 bool activated_signal_sent_;
658
659=== modified file 'hud/StandaloneHud.cpp'
660--- hud/StandaloneHud.cpp 2012-06-01 15:24:14 +0000
661+++ hud/StandaloneHud.cpp 2012-09-18 17:41:27 +0000
662@@ -69,7 +69,7 @@
663
664 hud_view_ = new unity::hud::View();
665
666- layout->AddView (hud_view_, 0, nux::MINOR_POSITION_TOP);
667+ layout->AddView (hud_view_, 1, nux::MINOR_POSITION_TOP);
668 nux::GetWindowCompositor().SetKeyFocusArea(hud_view_->default_focus());
669
670 nux::GetWindowThread()->SetLayout (layout);
671@@ -109,9 +109,6 @@
672 });
673
674 hud_service_.RequestQuery("");
675-
676- hud_view_->SetWindowGeometry(layout->GetAbsoluteGeometry(), layout->GetGeometry());
677-
678 }
679
680 void TestRunner::InitWindowThread(nux::NThread* thread, void* InitData)
681
682=== modified file 'plugins/unityshell/src/unityshell.cpp'
683--- plugins/unityshell/src/unityshell.cpp 2012-09-18 01:41:46 +0000
684+++ plugins/unityshell/src/unityshell.cpp 2012-09-18 17:41:27 +0000
685@@ -913,6 +913,33 @@
686 }
687 }
688
689+bool UnityScreen::DoesPointIntersectUnityGeos(nux::Point const& pt)
690+{
691+ auto launchers = launcher_controller_->launchers();
692+ for (auto launcher : launchers)
693+ {
694+ nux::Geometry hud_geo = launcher->GetAbsoluteGeometry();
695+
696+ if (launcher->Hidden())
697+ continue;
698+
699+ if (hud_geo.IsInside(pt))
700+ {
701+ return true;
702+ }
703+ }
704+
705+ for (nux::Geometry &panel_geo : panel_controller_->GetGeometries ())
706+ {
707+ if (panel_geo.IsInside(pt))
708+ {
709+ return true;
710+ }
711+ }
712+
713+ return false;
714+}
715+
716 void UnityWindow::enterShowDesktop ()
717 {
718 if (!mShowdesktopHandler)
719@@ -1435,12 +1462,26 @@
720 if (CompWindow *w = screen->findWindow(ss->getSelectedWindow()))
721 skip_other_plugins = UnityWindow::get(w)->handleEvent(event);
722 }
723- if (launcher_controller_->IsOverlayOpen())
724+
725+
726+ if (dash_controller_->IsVisible())
727 {
728- int monitor_with_mouse = UScreen::GetDefault()->GetMonitorWithMouse();
729- if (overlay_monitor_ != monitor_with_mouse)
730+ nux::Point pt(event->xbutton.x_root, event->xbutton.y_root);
731+ nux::Geometry dash_geo = dash_controller_->GetInputWindowGeometry();
732+
733+ if (!dash_geo.IsInside(pt) && !DoesPointIntersectUnityGeos(pt))
734 {
735 dash_controller_->HideDash(false);
736+ }
737+ }
738+
739+ if (hud_controller_->IsVisible())
740+ {
741+ nux::Point pt(event->xbutton.x_root, event->xbutton.y_root);
742+ nux::Geometry hud_geo = hud_controller_->GetInputWindowGeometry();
743+
744+ if (!hud_geo.IsInside(pt) && !DoesPointIntersectUnityGeos(pt))
745+ {
746 hud_controller_->HideHud(false);
747 }
748 }
749@@ -2683,6 +2724,7 @@
750 return pos;
751 }
752
753+
754 bool UnityWindow::place(CompPoint& pos)
755 {
756 bool was_maximized = PluginAdapter::Default ()->MaximizeIfBigEnough(window);
757
758=== modified file 'plugins/unityshell/src/unityshell.h'
759--- plugins/unityshell/src/unityshell.h 2012-09-18 01:41:46 +0000
760+++ plugins/unityshell/src/unityshell.h 2012-09-18 17:41:27 +0000
761@@ -190,6 +190,8 @@
762 switcher::Controller::Ptr switcher_controller();
763 launcher::Controller::Ptr launcher_controller();
764
765+ bool DoesPointIntersectUnityGeos(nux::Point const& pt);
766+
767 protected:
768 std::string GetName() const;
769 void AddProperties(GVariantBuilder* builder);
770
771=== modified file 'tests/autopilot/unity/emulators/dash.py'
772--- tests/autopilot/unity/emulators/dash.py 2012-09-13 10:56:42 +0000
773+++ tests/autopilot/unity/emulators/dash.py 2012-09-18 17:41:27 +0000
774@@ -155,6 +155,10 @@
775 active_lens_name = self.view.get_lensbar().active_lens
776 return self.view.get_lensview_by_name(active_lens_name)
777
778+ @property
779+ def geometry(self):
780+ return (self.view.x, self.view.y, self.view.width, self.view.height)
781+
782
783 class DashController(UnityIntrospectionObject):
784 """The main dash controller object."""
785
786=== modified file 'tests/autopilot/unity/tests/test_dash.py'
787--- tests/autopilot/unity/tests/test_dash.py 2012-09-18 01:41:46 +0000
788+++ tests/autopilot/unity/tests/test_dash.py 2012-09-18 17:41:27 +0000
789@@ -107,6 +107,39 @@
790 self.dash.reveal_application_lens()
791 self.assertThat(self.dash.active_lens, Eventually(Equals('applications.lens')))
792
793+ def test_closes_mouse_down_outside(self):
794+ """Test that a mouse down outside of the dash closes the dash."""
795+
796+ self.dash.ensure_visible()
797+ current_monitor = self.dash.monitor
798+
799+ (x,y,w,h) = self.dash.geometry
800+ (screen_x,screen_y,screen_w,screen_h) = self.screen_geo.get_monitor_geometry(current_monitor)
801+
802+ self.mouse.move(x + w + (screen_w-((screen_x-x)+w))/2, y + h + (screen_h-((screen_y-y)+h))/2)
803+ self.mouse.click()
804+
805+ self.assertThat(self.dash.visible, Eventually(Equals(False)))
806+
807+ def test_closes_then_focuses_window_on_mouse_down(self):
808+ """If 2 windows are open with 1 maximized and the non-maxmized
809+ focused. Then from the Dash clicking on the maximized window
810+ must focus that window and close the dash.
811+ """
812+ char_win = self.start_app("Character Map")
813+ self.keybinding("window/maximize")
814+ self.start_app("Calculator")
815+
816+ self.dash.ensure_visible()
817+
818+ #Click bottom right of the screen
819+ w = self.screen_geo.get_screen_width()
820+ h = self.screen_geo.get_screen_height()
821+ self.mouse.move(w,h)
822+ self.mouse.click()
823+
824+ self.assertProperty(char_win, is_active=True)
825+
826
827 class DashSearchInputTests(DashTestCase):
828 """Test features involving input to the dash search"""
829
830=== modified file 'tests/autopilot/unity/tests/test_hud.py'
831--- tests/autopilot/unity/tests/test_hud.py 2012-09-18 01:41:46 +0000
832+++ tests/autopilot/unity/tests/test_hud.py 2012-09-18 17:41:27 +0000
833@@ -409,6 +409,38 @@
834 self.keyboard.type("HasFocus")
835 self.assertThat(self.hud.search_string, Eventually(Equals("HasFocus")))
836
837+ def test_closes_mouse_down_outside(self):
838+ """Test that a mouse down outside of the hud closes the hud."""
839+
840+ self.hud.ensure_visible()
841+ current_monitor = self.hud.monitor
842+
843+ (x,y,w,h) = self.hud.geometry
844+ (screen_x,screen_y,screen_w,screen_h) = self.screen_geo.get_monitor_geometry(current_monitor)
845+
846+ self.mouse.move(x + w + (screen_w-((screen_x-x)+w))/2, y + h + (screen_h-((screen_y-y)+h))/2)
847+ self.mouse.click()
848+
849+ self.assertThat(self.hud.visible, Eventually(Equals(False)))
850+
851+ def test_closes_then_focuses_window_on_mouse_down(self):
852+ """If 2 windows are open with 1 maximized and the non-maxmized
853+ focused. Then from the Hud clicking on the maximized window
854+ must focus that window and close the hud.
855+ """
856+ char_win = self.start_app("Character Map")
857+ self.keybinding("window/maximize")
858+ self.start_app("Calculator")
859+
860+ self.hud.ensure_visible()
861+
862+ #Click bottom right of the screen
863+ w = self.screen_geo.get_screen_width()
864+ h = self.screen_geo.get_screen_height()
865+ self.mouse.move(w,h)
866+ self.mouse.click()
867+
868+ self.assertProperty(char_win, is_active=True)
869
870 class HudLauncherInteractionsTests(HudTestsBase):
871
872
873=== modified file 'tests/test_hud_controller.cpp'
874--- tests/test_hud_controller.cpp 2012-07-04 02:37:23 +0000
875+++ tests/test_hud_controller.cpp 2012-09-18 17:41:27 +0000
876@@ -44,12 +44,13 @@
877 MOCK_METHOD0(SearchFinished, void());
878 MOCK_METHOD4(SetIcon, void(std::string const&, unsigned int tile_size, unsigned int size, unsigned int padding));
879 MOCK_METHOD1(SetQueries, void(hud::Hud::Queries queries));
880- MOCK_METHOD2(SetWindowGeometry, void(nux::Geometry const& absolute_geo, nux::Geometry const& geo));
881+ MOCK_METHOD2(SetMonitorOffset, void(int x, int y));
882 MOCK_METHOD1(ShowEmbeddedIcon, void(bool show));
883 MOCK_CONST_METHOD0(default_focus, nux::View*());
884 MOCK_CONST_METHOD0(GetName, std::string());
885 MOCK_METHOD1(AddProperties, void(GVariantBuilder*));
886 MOCK_METHOD2(Draw, void(nux::GraphicsEngine&, bool));
887+ MOCK_METHOD0(GetContentGeometry, nux::Geometry());
888
889 };
890
891
892=== added file 'unity-shared/ResizingBaseWindow.h'
893--- unity-shared/ResizingBaseWindow.h 1970-01-01 00:00:00 +0000
894+++ unity-shared/ResizingBaseWindow.h 2012-09-18 17:41:27 +0000
895@@ -0,0 +1,53 @@
896+/*
897+ * Copyright (C) 2012 Canonical Ltd
898+ *
899+ * This program is free software: you can redistribute it and/or modify
900+ * it under the terms of the GNU General Public License version 3 as
901+ * published by the Free Software Foundation.
902+ *
903+ * This program is distributed in the hope that it will be useful,
904+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
905+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
906+ * GNU General Public License for more details.
907+ *
908+ * You should have received a copy of the GNU General Public License
909+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
910+ *
911+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com>
912+ */
913+
914+#ifndef RESIZEDINPUTWINDOW_BASEWINDOW_H
915+#define RESIZEDINPUTWINDOW_BASEWINDOW_H
916+
917+#include <Nux/BaseWindow.h>
918+
919+namespace unity
920+{
921+
922+class ResizingBaseWindow : public nux::BaseWindow
923+{
924+public:
925+ ResizingBaseWindow(const char *WindowName, std::function<nux::Geometry (nux::Geometry const&)> geo_func)
926+ : BaseWindow(WindowName, NUX_TRACKER_LOCATION)
927+ {
928+ geo_func_ = geo_func;
929+ }
930+
931+ void UpdateInputWindowGeometry()
932+ {
933+ if (m_input_window && m_input_window_enabled)
934+ m_input_window->SetGeometry(geo_func_(GetGeometry()));
935+ }
936+
937+ virtual void SetGeometry(const nux::Geometry &geo)
938+ {
939+ Area::SetGeometry(geo);
940+ UpdateInputWindowGeometry();
941+ }
942+
943+private:
944+ std::function<nux::Geometry (nux::Geometry const&)> geo_func_;
945+};
946+
947+}
948+#endif // RESIZEDINPUTWINDOW_BASEWINDOW_H