Merge lp:~3v1n0/unity/input-monitor-menus-scrubbing-triangolation into lp:unity
- input-monitor-menus-scrubbing-triangolation
- Merge into trunk
Proposed by
Marco Trevisan (Treviño)
Status: | Superseded |
---|---|
Proposed branch: | lp:~3v1n0/unity/input-monitor-menus-scrubbing-triangolation |
Merge into: | lp:unity |
Diff against target: |
2205 lines (+870/-400) 38 files modified
decorations/DecoratedWindow.cpp (+2/-9) decorations/DecorationsMenuLayout.cpp (+35/-37) decorations/DecorationsMenuLayout.h (+3/-2) decorations/DecorationsPriv.h (+0/-1) launcher/EdgeBarrierController.cpp (+32/-115) launcher/EdgeBarrierControllerPrivate.h (+1/-6) lockscreen/KylinLockScreenShield.cpp (+1/-1) lockscreen/LockScreenBaseShield.cpp (+0/-2) lockscreen/LockScreenBaseShield.h (+3/-4) lockscreen/LockScreenController.cpp (+3/-3) lockscreen/LockScreenController.h (+1/-2) lockscreen/LockScreenPanel.cpp (+25/-56) lockscreen/LockScreenPanel.h (+5/-9) lockscreen/LockScreenShield.cpp (+7/-6) lockscreen/LockScreenShield.h (+4/-3) lockscreen/LockScreenShieldFactory.cpp (+2/-2) lockscreen/LockScreenShieldFactory.h (+3/-3) panel/PanelIndicatorEntryView.cpp (+10/-0) panel/PanelMenuView.cpp (+1/-7) panel/PanelMenuView.h (+0/-2) panel/PanelView.cpp (+3/-115) panel/PanelView.h (+3/-12) plugins/unityshell/src/unityshell.h (+2/-0) tests/test_edge_barrier_controller.cpp (+2/-0) tests/test_lockscreen_controller.cpp (+2/-2) tests/test_panel_controller.cpp (+2/-0) tests/test_panel_view.cpp (+2/-0) unity-shared/CMakeLists.txt (+1/-0) unity-shared/InputMonitor.cpp (+408/-0) unity-shared/InputMonitor.h (+67/-0) unity-shared/MenuManager.cpp (+160/-1) unity-shared/MenuManager.h (+4/-0) unity-shared/SigcSlotHash.h (+64/-0) unity-shared/StandaloneWindowManager.cpp (+3/-0) unity-shared/StandaloneWindowManager.h (+1/-0) unity-shared/WindowManager.h (+1/-0) unity-shared/XWindowManager.cpp (+6/-0) unity-shared/XWindowManager.h (+1/-0) |
To merge this branch: | bzr merge lp:~3v1n0/unity/input-monitor-menus-scrubbing-triangolation |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity Team | Pending | ||
Review via email:
|
This proposal has been superseded by a proposal from 2016-08-30.
Commit message
MenuManager: add support for mouse trackers with triangle algorithm support
It allows to register pointer trackers with menu entries selection by using the triangle
technique which prevents menus items from being opened on quick menu scrubbing
Then use use menu::Manager pointer tracker for entries activation in PanelView, LockScreenPanel and DecorationsMenu
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'decorations/DecoratedWindow.cpp' |
2 | --- decorations/DecoratedWindow.cpp 2016-08-06 16:24:45 +0000 |
3 | +++ decorations/DecoratedWindow.cpp 2016-08-30 10:27:02 +0000 |
4 | @@ -37,7 +37,6 @@ |
5 | { |
6 | namespace |
7 | { |
8 | -const std::string MENUS_PANEL_NAME = "WindowLIM"; |
9 | const int SHADOW_BLUR_MARGIN_FACTOR = 2; |
10 | } |
11 | |
12 | @@ -55,7 +54,6 @@ |
13 | , deco_elements_(cu::DecorationElement::NONE) |
14 | , last_mwm_decor_(win_->mwmDecor()) |
15 | , last_actions_(win_->actions()) |
16 | - , panel_id_(MENUS_PANEL_NAME + std::to_string(win_->id())) |
17 | , cv_(Settings::Instance().em()) |
18 | { |
19 | active.changed.connect([this] (bool active) { |
20 | @@ -932,18 +930,13 @@ |
21 | sliding_layout->mouse_owner = grab_edge_->mouse_owner(); |
22 | } |
23 | |
24 | -inline std::string const& Window::Impl::GetMenusPanelID() const |
25 | -{ |
26 | - return panel_id_; |
27 | -} |
28 | - |
29 | void Window::Impl::UnsetAppMenu() |
30 | { |
31 | if (!menus_) |
32 | return; |
33 | |
34 | auto const& indicators = manager_->impl_->menu_manager_->Indicators(); |
35 | - indicators->SyncGeometries(GetMenusPanelID(), indicator::EntryLocationMap()); |
36 | + indicators->SyncGeometries(menus_->MenubarId(), indicator::EntryLocationMap()); |
37 | sliding_layout_->SetInputItem(nullptr); |
38 | grab_mouse_changed_->disconnect(); |
39 | } |
40 | @@ -956,7 +949,7 @@ |
41 | auto const& indicators = manager_->impl_->menu_manager_->Indicators(); |
42 | indicator::EntryLocationMap map; |
43 | menus_->ChildrenGeometries(map); |
44 | - indicators->SyncGeometries(GetMenusPanelID(), map); |
45 | + indicators->SyncGeometries(menus_->MenubarId(), map); |
46 | } |
47 | |
48 | bool Window::Impl::ActivateMenu(std::string const& entry_id) |
49 | |
50 | === modified file 'decorations/DecorationsMenuLayout.cpp' |
51 | --- decorations/DecorationsMenuLayout.cpp 2015-02-03 10:04:17 +0000 |
52 | +++ decorations/DecorationsMenuLayout.cpp 2016-08-30 10:27:02 +0000 |
53 | @@ -25,6 +25,10 @@ |
54 | { |
55 | namespace decoration |
56 | { |
57 | +namespace |
58 | +{ |
59 | +const std::string MENUS_PANEL_NAME = "WindowLIM"; |
60 | +} |
61 | |
62 | using namespace indicator; |
63 | |
64 | @@ -33,8 +37,8 @@ |
65 | , show_now(false) |
66 | , menu_manager_(menu) |
67 | , win_(win) |
68 | - , last_pointer_(-1, -1) |
69 | , dropdown_(std::make_shared<MenuDropdown>(menu_manager_->Indicators(), win)) |
70 | + , menubar_id_(MENUS_PANEL_NAME + std::to_string(win_->id())) |
71 | { |
72 | visible = false; |
73 | } |
74 | @@ -91,6 +95,11 @@ |
75 | Relayout(); |
76 | } |
77 | |
78 | +std::string const& MenuLayout::MenubarId() const |
79 | +{ |
80 | + return menubar_id_; |
81 | +} |
82 | + |
83 | bool MenuLayout::ActivateMenu(std::string const& entry_id) |
84 | { |
85 | MenuEntry::Ptr target; |
86 | @@ -117,16 +126,29 @@ |
87 | if (!activated) |
88 | activated = dropdown_->ActivateChild(target); |
89 | |
90 | - if (activated) |
91 | - { |
92 | - // Since this generally happens on keyboard activation we need to avoid that |
93 | - // the mouse position would interfere with this |
94 | - last_pointer_.set(pointerX, pointerY); |
95 | - } |
96 | - |
97 | return activated; |
98 | } |
99 | |
100 | +bool MenuLayout::ActivateMenu(CompPoint const& pos) |
101 | +{ |
102 | + if (!Geometry().contains(pos)) |
103 | + return false; |
104 | + |
105 | + for (auto const& item : items_) |
106 | + { |
107 | + if (!item->visible() || !item->sensitive()) |
108 | + continue; |
109 | + |
110 | + if (item->Geometry().contains(pos)) |
111 | + { |
112 | + std::static_pointer_cast<MenuEntry>(item)->ShowMenu(1); |
113 | + return true; |
114 | + } |
115 | + } |
116 | + |
117 | + return false; |
118 | +} |
119 | + |
120 | void MenuLayout::OnEntryMouseOwnershipChanged(bool owner) |
121 | { |
122 | mouse_owner = owner; |
123 | @@ -154,39 +176,15 @@ |
124 | { |
125 | active = actived; |
126 | |
127 | - if (active && !pointer_tracker_ && items_.size() > 1) |
128 | + if (active && items_.size() > 1) |
129 | { |
130 | - pointer_tracker_.reset(new glib::Timeout(16)); |
131 | - pointer_tracker_->Run([this] { |
132 | - Window win; |
133 | - int i, x, y; |
134 | - unsigned int ui; |
135 | - |
136 | - XQueryPointer(screen->dpy(), screen->root(), &win, &win, &x, &y, &i, &i, &ui); |
137 | - |
138 | - if (last_pointer_.x() != x || last_pointer_.y() != y) |
139 | - { |
140 | - last_pointer_.set(x, y); |
141 | - |
142 | - for (auto const& item : items_) |
143 | - { |
144 | - if (!item->visible() || !item->sensitive()) |
145 | - continue; |
146 | - |
147 | - if (item->Geometry().contains(last_pointer_)) |
148 | - { |
149 | - std::static_pointer_cast<MenuEntry>(item)->ShowMenu(1); |
150 | - break; |
151 | - } |
152 | - } |
153 | - } |
154 | - |
155 | - return true; |
156 | - }); |
157 | + menu_manager_->RegisterTracker(menubar_id_, (sigc::track_obj([this] (int x, int y, double speed) { |
158 | + ActivateMenu(CompPoint(x, y)); |
159 | + }, *this))); |
160 | } |
161 | else if (!active) |
162 | { |
163 | - pointer_tracker_.reset(); |
164 | + menu_manager_->UnregisterTracker(menubar_id_); |
165 | } |
166 | } |
167 | |
168 | |
169 | === modified file 'decorations/DecorationsMenuLayout.h' |
170 | --- decorations/DecorationsMenuLayout.h 2014-02-13 03:01:30 +0000 |
171 | +++ decorations/DecorationsMenuLayout.h 2016-08-30 10:27:02 +0000 |
172 | @@ -42,7 +42,9 @@ |
173 | |
174 | void Setup(); |
175 | bool ActivateMenu(std::string const& entry_id); |
176 | + bool ActivateMenu(CompPoint const&); |
177 | void ChildrenGeometries(indicator::EntryLocationMap&) const; |
178 | + std::string const& MenubarId() const; |
179 | |
180 | protected: |
181 | void DoRelayout() override; |
182 | @@ -55,10 +57,9 @@ |
183 | |
184 | menu::Manager::Ptr menu_manager_; |
185 | CompWindow* win_; |
186 | - CompPoint last_pointer_; |
187 | - glib::Source::UniquePtr pointer_tracker_; |
188 | glib::Source::UniquePtr show_now_timeout_; |
189 | std::shared_ptr<MenuDropdown> dropdown_; |
190 | + std::string menubar_id_; |
191 | }; |
192 | |
193 | } // decoration namespace |
194 | |
195 | === modified file 'decorations/DecorationsPriv.h' |
196 | --- decorations/DecorationsPriv.h 2016-08-06 16:24:45 +0000 |
197 | +++ decorations/DecorationsPriv.h 2016-08-30 10:27:02 +0000 |
198 | @@ -162,7 +162,6 @@ |
199 | connection::Wrapper dpi_changed_; |
200 | connection::Wrapper grab_mouse_changed_; |
201 | std::string last_title_; |
202 | - std::string panel_id_; |
203 | std::vector<cu::SimpleTextureQuad> bg_textures_; |
204 | cu::PixmapTexture::Ptr shaped_shadow_pixmap_; |
205 | std::shared_ptr<ForceQuitDialog> force_quit_; |
206 | |
207 | === modified file 'launcher/EdgeBarrierController.cpp' |
208 | --- launcher/EdgeBarrierController.cpp 2015-12-23 09:29:24 +0000 |
209 | +++ launcher/EdgeBarrierController.cpp 2016-08-30 10:27:02 +0000 |
210 | @@ -25,6 +25,7 @@ |
211 | #include <NuxCore/Logger.h> |
212 | #include "unity-shared/UnitySettings.h" |
213 | #include "unity-shared/UScreen.h" |
214 | +#include "unity-shared/InputMonitor.h" |
215 | #include "UnityCore/GLibSource.h" |
216 | |
217 | namespace unity |
218 | @@ -36,50 +37,12 @@ |
219 | { |
220 | int const Y_BREAK_BUFFER = 20; |
221 | int const X_BREAK_BUFFER = 20; |
222 | - int const MAJOR = 2; |
223 | - int const MINOR = 3; |
224 | } |
225 | |
226 | DECLARE_LOGGER(logger, "unity.edge_barrier_controller"); |
227 | |
228 | -int GetXI2OpCode() |
229 | -{ |
230 | - Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); |
231 | - |
232 | - int opcode, event_base, error_base; |
233 | - if (!XQueryExtension(dpy, "XFIXES", |
234 | - &opcode, |
235 | - &event_base, |
236 | - &error_base)) |
237 | - { |
238 | - LOG_ERROR(logger) << "Missing XFixes"; |
239 | - return -1; |
240 | - } |
241 | - |
242 | - if (!XQueryExtension (dpy, "XInputExtension", |
243 | - &opcode, |
244 | - &event_base, |
245 | - &error_base)) |
246 | - { |
247 | - LOG_ERROR(logger) << "Missing XInput"; |
248 | - return -1; |
249 | - } |
250 | - |
251 | - int maj = MAJOR; |
252 | - int min = MINOR; |
253 | - |
254 | - if (XIQueryVersion(dpy, &maj, &min) == BadRequest) |
255 | - { |
256 | - LOG_ERROR(logger) << "Need XInput version 2.3"; |
257 | - return -1; |
258 | - } |
259 | - |
260 | - return opcode; |
261 | -} |
262 | - |
263 | EdgeBarrierController::Impl::Impl(EdgeBarrierController *parent) |
264 | - : xi2_opcode_(-1) |
265 | - , edge_overcome_pressure_(0) |
266 | + : edge_overcome_pressure_(0) |
267 | , parent_(parent) |
268 | { |
269 | UScreen *uscreen = UScreen::GetDefault(); |
270 | @@ -119,8 +82,6 @@ |
271 | options->option_changed.connect(sigc::mem_fun(this, &EdgeBarrierController::Impl::OnOptionsChanged)); |
272 | SetupBarriers(UScreen::GetDefault()->GetMonitors()); |
273 | }); |
274 | - |
275 | - xi2_opcode_ = GetXI2OpCode(); |
276 | } |
277 | |
278 | EdgeBarrierController::Impl::~Impl() |
279 | @@ -202,36 +163,30 @@ |
280 | } |
281 | } |
282 | |
283 | -void SetupXI2Events() |
284 | -{ |
285 | - Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); |
286 | - |
287 | - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; |
288 | - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; |
289 | - |
290 | - XISetMask(mask.mask, XI_BarrierHit); |
291 | - XISetMask(mask.mask, XI_BarrierLeave); |
292 | - XISelectEvents (dpy, DefaultRootWindow(dpy), &mask, 1); |
293 | -} |
294 | - |
295 | void EdgeBarrierController::Impl::SetupBarriers(std::vector<nux::Geometry> const& layout) |
296 | { |
297 | if (parent_->force_disable()) |
298 | return; |
299 | |
300 | + size_t monitors_size = layout.size(); |
301 | + auto launcher_position = Settings::Instance().launcher_position(); |
302 | bool edge_resist = parent_->sticky_edges(); |
303 | - auto launcher_position = Settings::Instance().launcher_position(); |
304 | - |
305 | - for (unsigned i = 0; i < layout.size(); i++) |
306 | + bool needs_barrier = edge_resist && monitors_size > 1; |
307 | + bool needs_vertical_barrier = needs_barrier; |
308 | + |
309 | + if (parent_->options()->hide_mode() != launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER) |
310 | + needs_vertical_barrier = true; |
311 | + |
312 | + for (unsigned i = 0; i < layout.size(); ++i) |
313 | { |
314 | - auto vertical_barrier = vertical_barriers_[i]; |
315 | - auto horizontal_barrier = horizontal_barriers_[i]; |
316 | - auto monitor = layout[i]; |
317 | + auto const& vertical_barrier = vertical_barriers_[i]; |
318 | + auto const& horizontal_barrier = horizontal_barriers_[i]; |
319 | + auto const& monitor = layout[i]; |
320 | |
321 | vertical_barrier->DestroyBarrier(); |
322 | horizontal_barrier->DestroyBarrier(); |
323 | |
324 | - if (edge_resist) |
325 | + if (needs_barrier) |
326 | { |
327 | horizontal_barrier->x1 = monitor.x; |
328 | horizontal_barrier->x2 = monitor.x + monitor.width; |
329 | @@ -246,7 +201,7 @@ |
330 | horizontal_barrier->ConstructBarrier(); |
331 | } |
332 | |
333 | - if (!edge_resist && parent_->options()->hide_mode() == launcher::LauncherHideMode::LAUNCHER_HIDE_NEVER) |
334 | + if (!needs_vertical_barrier) |
335 | continue; |
336 | |
337 | if (launcher_position == LauncherPosition::LEFT) |
338 | @@ -273,8 +228,10 @@ |
339 | vertical_barrier->ConstructBarrier(); |
340 | } |
341 | |
342 | - SetupXI2Events(); |
343 | - AddEventFilter(); |
344 | + if (needs_barrier || needs_vertical_barrier) |
345 | + input::Monitor::Get().RegisterClient(input::Events::BARRIER, sigc::mem_fun(this, &Impl::HandleEvent)); |
346 | + else |
347 | + input::Monitor::Get().UnregisterClient(sigc::mem_fun(this, &Impl::HandleEvent)); |
348 | |
349 | float decay_responsiveness_mult = ((parent_->options()->edge_responsiveness() - 1) * .3f) + 1; |
350 | decaymulator_.rate_of_decay = parent_->options()->edge_decay_rate() * decay_responsiveness_mult; |
351 | @@ -283,65 +240,25 @@ |
352 | edge_overcome_pressure_ = parent_->options()->edge_overcome_pressure() * overcome_responsiveness_mult; |
353 | } |
354 | |
355 | -void EdgeBarrierController::Impl::AddEventFilter() |
356 | -{ |
357 | - // Remove an old one, if it exists |
358 | - nux::GetGraphicsDisplay()->RemoveEventFilter(this); |
359 | - |
360 | - nux::GraphicsDisplay::EventFilterArg event_filter; |
361 | - event_filter.filter = &HandleEventCB; |
362 | - event_filter.data = this; |
363 | - |
364 | - nux::GetGraphicsDisplay()->AddEventFilter(event_filter); |
365 | -} |
366 | - |
367 | -bool EdgeBarrierController::Impl::HandleEvent(XEvent xevent) |
368 | -{ |
369 | - Display *dpy = nux::GetGraphicsDisplay()->GetX11Display(); |
370 | - XGenericEventCookie *cookie = &xevent.xcookie; |
371 | - bool ret = false; |
372 | - |
373 | - switch (cookie->evtype) |
374 | - { |
375 | - case (XI_BarrierHit): |
376 | - { |
377 | - if (XGetEventData(dpy, cookie)) |
378 | - { |
379 | - XIBarrierEvent* barrier_event = (XIBarrierEvent*)cookie->data; |
380 | - PointerBarrierWrapper::Ptr wrapper = FindBarrierEventOwner(barrier_event); |
381 | - |
382 | - if (wrapper) |
383 | - ret = wrapper->HandleBarrierEvent(barrier_event); |
384 | - } |
385 | - |
386 | - XFreeEventData(dpy, cookie); |
387 | - break; |
388 | - } |
389 | - default: |
390 | - break; |
391 | - } |
392 | - |
393 | - return ret; |
394 | -} |
395 | - |
396 | -bool EdgeBarrierController::Impl::HandleEventCB(XEvent xevent, void* data) |
397 | -{ |
398 | - auto edge_barrier_controller = static_cast<EdgeBarrierController::Impl*>(data); |
399 | - int const xi2_opcode = edge_barrier_controller->xi2_opcode_; |
400 | - |
401 | - if (xevent.type != GenericEvent || xevent.xcookie.extension != xi2_opcode) |
402 | - return false; |
403 | - |
404 | - return edge_barrier_controller->HandleEvent(xevent); |
405 | +void EdgeBarrierController::Impl::HandleEvent(XEvent const& xevent) |
406 | +{ |
407 | + if (xevent.xcookie.evtype != XI_BarrierHit) |
408 | + return; |
409 | + |
410 | + auto* barrier_event = reinterpret_cast<XIBarrierEvent*>(xevent.xcookie.data); |
411 | + PointerBarrierWrapper::Ptr const& wrapper = FindBarrierEventOwner(barrier_event); |
412 | + |
413 | + if (wrapper) |
414 | + wrapper->HandleBarrierEvent(barrier_event); |
415 | } |
416 | |
417 | PointerBarrierWrapper::Ptr EdgeBarrierController::Impl::FindBarrierEventOwner(XIBarrierEvent* barrier_event) |
418 | { |
419 | - for (auto barrier : vertical_barriers_) |
420 | + for (auto const& barrier : vertical_barriers_) |
421 | if (barrier->OwnsBarrierEvent(barrier_event->barrier)) |
422 | return barrier; |
423 | |
424 | - for (auto barrier : horizontal_barriers_) |
425 | + for (auto const& barrier : horizontal_barriers_) |
426 | if (barrier->OwnsBarrierEvent(barrier_event->barrier)) |
427 | return barrier; |
428 | |
429 | |
430 | === modified file 'launcher/EdgeBarrierControllerPrivate.h' |
431 | --- launcher/EdgeBarrierControllerPrivate.h 2015-12-23 09:29:24 +0000 |
432 | +++ launcher/EdgeBarrierControllerPrivate.h 2016-08-30 10:27:02 +0000 |
433 | @@ -53,12 +53,8 @@ |
434 | bool EventIsInsideYBreakZone(BarrierEvent::Ptr const& event); |
435 | bool EventIsInsideXBreakZone(BarrierEvent::Ptr const& event); |
436 | |
437 | - void AddEventFilter(); |
438 | - |
439 | PointerBarrierWrapper::Ptr FindBarrierEventOwner(XIBarrierEvent* barrier_event); |
440 | - |
441 | - static bool HandleEventCB(XEvent event, void* data); |
442 | - bool HandleEvent(XEvent event); |
443 | + void HandleEvent(XEvent const&); |
444 | |
445 | std::vector<PointerBarrierWrapper::Ptr> vertical_barriers_; |
446 | std::vector<PointerBarrierWrapper::Ptr> horizontal_barriers_; |
447 | @@ -68,7 +64,6 @@ |
448 | |
449 | Decaymulator decaymulator_; |
450 | glib::Source::UniquePtr release_timeout_; |
451 | - int xi2_opcode_; |
452 | float edge_overcome_pressure_; |
453 | EdgeBarrierController* parent_; |
454 | }; |
455 | |
456 | === modified file 'lockscreen/KylinLockScreenShield.cpp' |
457 | --- lockscreen/KylinLockScreenShield.cpp 2015-12-07 03:09:28 +0000 |
458 | +++ lockscreen/KylinLockScreenShield.cpp 2016-08-30 10:27:02 +0000 |
459 | @@ -37,7 +37,7 @@ |
460 | Accelerators::Ptr const& accelerators, |
461 | nux::ObjectPtr<AbstractUserPromptView> const& prompt_view, |
462 | int monitor_num, bool is_primary) |
463 | - : BaseShield(session_manager, nullptr, accelerators, prompt_view, monitor_num, is_primary) |
464 | + : BaseShield(session_manager, accelerators, prompt_view, monitor_num, is_primary) |
465 | { |
466 | is_primary ? ShowPrimaryView() : ShowSecondaryView(); |
467 | EnableInputWindow(true); |
468 | |
469 | === modified file 'lockscreen/LockScreenBaseShield.cpp' |
470 | --- lockscreen/LockScreenBaseShield.cpp 2015-12-03 14:13:10 +0000 |
471 | +++ lockscreen/LockScreenBaseShield.cpp 2016-08-30 10:27:02 +0000 |
472 | @@ -38,7 +38,6 @@ |
473 | } |
474 | |
475 | BaseShield::BaseShield(session::Manager::Ptr const& session, |
476 | - indicator::Indicators::Ptr const& indicators, |
477 | Accelerators::Ptr const& accelerators, |
478 | nux::ObjectPtr<AbstractUserPromptView> const& prompt_view, |
479 | int monitor_num, bool is_primary) |
480 | @@ -47,7 +46,6 @@ |
481 | , monitor(monitor_num) |
482 | , scale(1.0) |
483 | , session_manager_(session) |
484 | - , indicators_(indicators) |
485 | , accelerators_(accelerators) |
486 | , prompt_view_(prompt_view) |
487 | , bg_settings_(std::make_shared<BackgroundSettings>()) |
488 | |
489 | === modified file 'lockscreen/LockScreenBaseShield.h' |
490 | --- lockscreen/LockScreenBaseShield.h 2016-03-31 09:51:33 +0000 |
491 | +++ lockscreen/LockScreenBaseShield.h 2016-08-30 10:27:02 +0000 |
492 | @@ -21,8 +21,8 @@ |
493 | #define UNITY_LOCKSCREEN_BASE_SHIELD_H |
494 | |
495 | #include <NuxCore/Property.h> |
496 | +#include "UnityCore/ConnectionManager.h" |
497 | #include "UnityCore/SessionManager.h" |
498 | -#include "UnityCore/Indicators.h" |
499 | #include "UnityCore/GLibSource.h" |
500 | #include "unity-shared/MockableBaseWindow.h" |
501 | |
502 | @@ -39,8 +39,8 @@ |
503 | class BaseShield : public MockableBaseWindow |
504 | { |
505 | public: |
506 | - BaseShield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, |
507 | - Accelerators::Ptr const&, nux::ObjectPtr<AbstractUserPromptView> const&, |
508 | + BaseShield(session::Manager::Ptr const&, Accelerators::Ptr const&, |
509 | + nux::ObjectPtr<AbstractUserPromptView> const&, |
510 | int monitor_num, bool is_primary); |
511 | |
512 | nux::Property<bool> primary; |
513 | @@ -69,7 +69,6 @@ |
514 | void UpdateScale(); |
515 | |
516 | session::Manager::Ptr session_manager_; |
517 | - indicator::Indicators::Ptr indicators_; |
518 | Accelerators::Ptr accelerators_; |
519 | nux::ObjectPtr<AbstractUserPromptView> prompt_view_; |
520 | std::shared_ptr<BackgroundSettings> bg_settings_; |
521 | |
522 | === modified file 'lockscreen/LockScreenController.cpp' |
523 | --- lockscreen/LockScreenController.cpp 2016-07-04 12:45:06 +0000 |
524 | +++ lockscreen/LockScreenController.cpp 2016-08-30 10:27:02 +0000 |
525 | @@ -130,7 +130,7 @@ |
526 | |
527 | upstart_wrapper_->Emit("desktop-unlock"); |
528 | accelerator_controller_.reset(); |
529 | - indicators_.reset(); |
530 | + menu_manager_.reset(); |
531 | } |
532 | else if (!prompt_activation_) |
533 | { |
534 | @@ -252,7 +252,7 @@ |
535 | |
536 | if (i >= shields_size) |
537 | { |
538 | - shield = shield_factory_->CreateShield(session_manager_, indicators_, accelerator_controller_->GetAccelerators(), prompt_view, i, i == primary); |
539 | + shield = shield_factory_->CreateShield(session_manager_, menu_manager_, accelerator_controller_->GetAccelerators(), prompt_view, i, i == primary); |
540 | is_new = true; |
541 | } |
542 | |
543 | @@ -462,7 +462,7 @@ |
544 | |
545 | void Controller::LockScreen() |
546 | { |
547 | - indicators_ = std::make_shared<indicator::LockScreenDBusIndicators>(); |
548 | + menu_manager_ = std::make_shared<menu::Manager>(std::make_shared<indicator::LockScreenDBusIndicators>(), key_grabber_); |
549 | upstart_wrapper_->Emit("desktop-lock"); |
550 | |
551 | accelerator_controller_ = std::make_shared<AcceleratorController>(key_grabber_); |
552 | |
553 | === modified file 'lockscreen/LockScreenController.h' |
554 | --- lockscreen/LockScreenController.h 2016-06-21 01:28:26 +0000 |
555 | +++ lockscreen/LockScreenController.h 2016-08-30 10:27:02 +0000 |
556 | @@ -30,7 +30,6 @@ |
557 | #include "SuspendInhibitorManager.h" |
558 | #include "ScreenSaverDBusManager.h" |
559 | #include "unity-shared/BackgroundEffectHelper.h" |
560 | -#include "unity-shared/KeyGrabber.h" |
561 | #include "unity-shared/UpstartWrapper.h" |
562 | |
563 | namespace unity |
564 | @@ -85,8 +84,8 @@ |
565 | |
566 | DBusManager::Ptr dbus_manager_; |
567 | session::Manager::Ptr session_manager_; |
568 | + menu::Manager::Ptr menu_manager_; |
569 | key::Grabber::Ptr key_grabber_; |
570 | - indicator::Indicators::Ptr indicators_; |
571 | AcceleratorController::Ptr accelerator_controller_; |
572 | UpstartWrapper::Ptr upstart_wrapper_; |
573 | ShieldFactoryInterface::Ptr shield_factory_; |
574 | |
575 | === modified file 'lockscreen/LockScreenPanel.cpp' |
576 | --- lockscreen/LockScreenPanel.cpp 2015-11-05 14:55:54 +0000 |
577 | +++ lockscreen/LockScreenPanel.cpp 2016-08-30 10:27:02 +0000 |
578 | @@ -24,7 +24,7 @@ |
579 | |
580 | #include "LockScreenSettings.h" |
581 | #include "panel/PanelIndicatorsView.h" |
582 | -#include "unity-shared/CairoTexture.h" |
583 | +#include "unity-shared/InputMonitor.h" |
584 | #include "unity-shared/StaticCairoText.h" |
585 | #include "unity-shared/PanelStyle.h" |
586 | #include "unity-shared/RawPixel.h" |
587 | @@ -38,24 +38,24 @@ |
588 | namespace |
589 | { |
590 | const RawPixel PADDING = 5_em; |
591 | +const nux::Color BG_COLOR(0.1, 0.1, 0.1, 0.4); |
592 | } |
593 | |
594 | using namespace indicator; |
595 | using namespace panel; |
596 | |
597 | -Panel::Panel(int monitor_, Indicators::Ptr const& indicators, session::Manager::Ptr const& session_manager) |
598 | +Panel::Panel(int monitor_, menu::Manager::Ptr const& menu_manager, session::Manager::Ptr const& session_manager) |
599 | : nux::View(NUX_TRACKER_LOCATION) |
600 | , active(false) |
601 | , monitor(monitor_) |
602 | - , indicators_(indicators) |
603 | + , menu_manager_(menu_manager) |
604 | , needs_geo_sync_(true) |
605 | { |
606 | double scale = unity::Settings::Instance().em(monitor)->DPIScale(); |
607 | auto* layout = new nux::HLayout(); |
608 | layout->SetLeftAndRightPadding(PADDING.CP(scale), 0); |
609 | SetLayout(layout); |
610 | - |
611 | - BuildTexture(); |
612 | + UpdateSize(); |
613 | |
614 | // Add setting |
615 | auto *hostname = new StaticCairoText(session_manager->HostName()); |
616 | @@ -72,34 +72,33 @@ |
617 | indicators_view_->on_indicator_updated.connect(sigc::mem_fun(this, &Panel::OnIndicatorViewUpdated)); |
618 | layout->AddView(indicators_view_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL); |
619 | |
620 | - for (auto const& indicator : indicators_->GetIndicators()) |
621 | + auto indicators = menu_manager_->Indicators(); |
622 | + menu_manager_->RegisterTracker(GetPanelName(), (sigc::track_obj([this] (int x, int y, double speed) { |
623 | + indicators_view_->ActivateEntryAt(x, y); |
624 | + }, *this))); |
625 | + |
626 | + for (auto const& indicator : indicators->GetIndicators()) |
627 | AddIndicator(indicator); |
628 | |
629 | - indicators_->on_object_added.connect(sigc::mem_fun(this, &Panel::AddIndicator)); |
630 | - indicators_->on_object_removed.connect(sigc::mem_fun(this, &Panel::RemoveIndicator)); |
631 | - indicators_->on_entry_show_menu.connect(sigc::mem_fun(this, &Panel::OnEntryShowMenu)); |
632 | - indicators_->on_entry_activated.connect(sigc::mem_fun(this, &Panel::OnEntryActivated)); |
633 | - indicators_->on_entry_activate_request.connect(sigc::mem_fun(this, &Panel::OnEntryActivateRequest)); |
634 | + indicators->on_object_added.connect(sigc::mem_fun(this, &Panel::AddIndicator)); |
635 | + indicators->on_object_removed.connect(sigc::mem_fun(this, &Panel::RemoveIndicator)); |
636 | + indicators->on_entry_show_menu.connect(sigc::mem_fun(this, &Panel::OnEntryShowMenu)); |
637 | + indicators->on_entry_activated.connect(sigc::mem_fun(this, &Panel::OnEntryActivated)); |
638 | + indicators->on_entry_activate_request.connect(sigc::mem_fun(this, &Panel::OnEntryActivateRequest)); |
639 | |
640 | monitor.changed.connect([this, hostname] (int monitor) { |
641 | double scale = unity::Settings::Instance().em(monitor)->DPIScale(); |
642 | hostname->SetScale(scale); |
643 | static_cast<nux::HLayout*>(GetLayout())->SetLeftAndRightPadding(PADDING.CP(scale), 0); |
644 | indicators_view_->SetMonitor(monitor); |
645 | - BuildTexture(); |
646 | + UpdateSize(); |
647 | QueueRelayout(); |
648 | }); |
649 | } |
650 | |
651 | -void Panel::BuildTexture() |
652 | +void Panel::UpdateSize() |
653 | { |
654 | int height = panel::Style::Instance().PanelHeight(monitor); |
655 | - nux::CairoGraphics context(CAIRO_FORMAT_ARGB32, 1, height); |
656 | - auto* cr = context.GetInternalContext(); |
657 | - cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); |
658 | - cairo_paint_with_alpha(cr, 0.4); |
659 | - bg_texture_ = texture_ptr_from_cairo_graphics(context); |
660 | - |
661 | view_layout_->SetMinimumHeight(height); |
662 | view_layout_->SetMaximumHeight(height); |
663 | } |
664 | @@ -165,12 +164,7 @@ |
665 | if (!GetInputEventSensitivity()) |
666 | return; |
667 | |
668 | - if (!active) |
669 | - { |
670 | - // This is ugly... But Nux fault! |
671 | - WindowManager::Default().UnGrabMousePointer(CurrentTime, button, x, y); |
672 | - active = true; |
673 | - } |
674 | + active = true; |
675 | } |
676 | |
677 | void Panel::OnEntryActivateRequest(std::string const& entry_id) |
678 | @@ -184,36 +178,16 @@ |
679 | if (!GetInputEventSensitivity() || (!panel.empty() && panel != GetPanelName())) |
680 | return; |
681 | |
682 | - bool active = !entry_id.empty(); |
683 | + bool valid_entry = !entry_id.empty(); |
684 | |
685 | - if (active && !WindowManager::Default().IsScreenGrabbed()) |
686 | + if (valid_entry && !WindowManager::Default().IsScreenGrabbed()) |
687 | { |
688 | // The menu didn't grab the keyboard, let's take it back. |
689 | nux::GetWindowCompositor().GrabKeyboardAdd(static_cast<nux::BaseWindow*>(GetTopLevelViewWindow())); |
690 | } |
691 | |
692 | - if (active && !track_menu_pointer_timeout_) |
693 | - { |
694 | - track_menu_pointer_timeout_.reset(new glib::Timeout(16)); |
695 | - track_menu_pointer_timeout_->Run([this] { |
696 | - nux::Point const& mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); |
697 | - if (tracked_pointer_pos_ != mouse) |
698 | - { |
699 | - if (GetAbsoluteGeometry().IsPointInside(mouse.x, mouse.y)) |
700 | - indicators_view_->ActivateEntryAt(mouse.x, mouse.y); |
701 | - |
702 | - tracked_pointer_pos_ = mouse; |
703 | - } |
704 | - |
705 | - return true; |
706 | - }); |
707 | - } |
708 | - else if (!active) |
709 | - { |
710 | - track_menu_pointer_timeout_.reset(); |
711 | - tracked_pointer_pos_ = {-1, -1}; |
712 | - this->active = false; |
713 | - } |
714 | + if (!valid_entry) |
715 | + active = valid_entry; |
716 | } |
717 | |
718 | void Panel::Draw(nux::GraphicsEngine& graphics_engine, bool force_draw) |
719 | @@ -227,12 +201,7 @@ |
720 | graphics_engine.PushClippingRectangle(geo); |
721 | nux::GetPainter().PaintBackground(graphics_engine, geo); |
722 | |
723 | - nux::TexCoordXForm texxform; |
724 | - texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_CLAMP); |
725 | - graphics_engine.QRP_1Tex(geo.x, geo.y, geo.width, geo.height, |
726 | - bg_texture_->GetDeviceTexture(), texxform, |
727 | - nux::color::White); |
728 | - |
729 | + graphics_engine.QRP_Color(geo.x, geo.y, geo.width, geo.height, BG_COLOR); |
730 | view_layout_->ProcessDraw(graphics_engine, force_draw); |
731 | |
732 | graphics_engine.PopClippingRectangle(); |
733 | @@ -242,7 +211,7 @@ |
734 | { |
735 | EntryLocationMap locations; |
736 | indicators_view_->GetGeometryForSync(locations); |
737 | - indicators_->SyncGeometries(GetPanelName(), locations); |
738 | + menu_manager_->Indicators()->SyncGeometries(GetPanelName(), locations); |
739 | needs_geo_sync_ = false; |
740 | } |
741 | } |
742 | |
743 | === modified file 'lockscreen/LockScreenPanel.h' |
744 | --- lockscreen/LockScreenPanel.h 2016-03-31 09:51:33 +0000 |
745 | +++ lockscreen/LockScreenPanel.h 2016-08-30 10:27:02 +0000 |
746 | @@ -22,9 +22,9 @@ |
747 | |
748 | #include <Nux/Nux.h> |
749 | #include <Nux/View.h> |
750 | -#include "UnityCore/Indicators.h" |
751 | #include "UnityCore/GLibSource.h" |
752 | #include "UnityCore/SessionManager.h" |
753 | +#include "unity-shared/MenuManager.h" |
754 | |
755 | namespace unity |
756 | { |
757 | @@ -39,7 +39,7 @@ |
758 | class Panel : public nux::View |
759 | { |
760 | public: |
761 | - Panel(int monitor, indicator::Indicators::Ptr const&, session::Manager::Ptr const&); |
762 | + Panel(int monitor, menu::Manager::Ptr const&, session::Manager::Ptr const&); |
763 | |
764 | nux::Property<bool> active; |
765 | nux::Property<int> monitor; |
766 | @@ -55,20 +55,16 @@ |
767 | void AddIndicator(indicator::Indicator::Ptr const&); |
768 | void RemoveIndicator(indicator::Indicator::Ptr const&); |
769 | void OnIndicatorViewUpdated(); |
770 | - void OnEntryActivated(std::string const& panel, std::string const& entry_id, nux::Rect const& geo); |
771 | + void OnEntryActivated(std::string const& panel, std::string const& entry_id, nux::Rect const&); |
772 | void OnEntryShowMenu(std::string const& entry_id, unsigned xid, int x, int y, unsigned button); |
773 | void OnEntryActivateRequest(std::string const& entry_id); |
774 | |
775 | - void BuildTexture(); |
776 | + void UpdateSize(); |
777 | std::string GetPanelName() const; |
778 | |
779 | - indicator::Indicators::Ptr indicators_; |
780 | + menu::Manager::Ptr menu_manager_; |
781 | panel::PanelIndicatorsView* indicators_view_; |
782 | - nux::ObjectPtr<nux::BaseTexture> bg_texture_; |
783 | - |
784 | bool needs_geo_sync_; |
785 | - nux::Point tracked_pointer_pos_; |
786 | - glib::Source::UniquePtr track_menu_pointer_timeout_; |
787 | }; |
788 | |
789 | } // lockscreen namespace |
790 | |
791 | === modified file 'lockscreen/LockScreenShield.cpp' |
792 | --- lockscreen/LockScreenShield.cpp 2015-12-03 14:13:10 +0000 |
793 | +++ lockscreen/LockScreenShield.cpp 2016-08-30 10:27:02 +0000 |
794 | @@ -32,11 +32,12 @@ |
795 | { |
796 | |
797 | Shield::Shield(session::Manager::Ptr const& session_manager, |
798 | - indicator::Indicators::Ptr const& indicators, |
799 | + menu::Manager::Ptr const& menu_manager, |
800 | Accelerators::Ptr const& accelerators, |
801 | nux::ObjectPtr<AbstractUserPromptView> const& prompt_view, |
802 | int monitor_num, bool is_primary) |
803 | - : BaseShield(session_manager, indicators, accelerators, prompt_view, monitor_num, is_primary) |
804 | + : BaseShield(session_manager, accelerators, prompt_view, monitor_num, is_primary) |
805 | + , menu_manager_(menu_manager) |
806 | , panel_view_(nullptr) |
807 | { |
808 | is_primary ? ShowPrimaryView() : ShowSecondaryView(); |
809 | @@ -91,11 +92,11 @@ |
810 | |
811 | Panel* Shield::CreatePanel() |
812 | { |
813 | - if (!indicators_ || !session_manager_) |
814 | + if (!menu_manager_ || !session_manager_) |
815 | return nullptr; |
816 | |
817 | - panel_view_ = new Panel(monitor, indicators_, session_manager_); |
818 | - panel_active_conn_ = panel_view_->active.changed.connect([this] (bool active) { |
819 | + panel_view_ = new Panel(monitor, menu_manager_, session_manager_); |
820 | + panel_view_->active.changed.connect(sigc::track_obj([this] (bool active) { |
821 | if (primary()) |
822 | { |
823 | if (active) |
824 | @@ -109,7 +110,7 @@ |
825 | GrabScreen(false); |
826 | } |
827 | } |
828 | - }); |
829 | + }, *this)); |
830 | |
831 | return panel_view_; |
832 | } |
833 | |
834 | === modified file 'lockscreen/LockScreenShield.h' |
835 | --- lockscreen/LockScreenShield.h 2015-12-03 14:13:10 +0000 |
836 | +++ lockscreen/LockScreenShield.h 2016-08-30 10:27:02 +0000 |
837 | @@ -20,8 +20,9 @@ |
838 | #ifndef UNITY_LOCKSCREEN_SHIELD_H |
839 | #define UNITY_LOCKSCREEN_SHIELD_H |
840 | |
841 | -#include <UnityCore/ConnectionManager.h> |
842 | #include "LockScreenBaseShield.h" |
843 | +#include "unity-shared/MenuManager.h" |
844 | + |
845 | |
846 | namespace unity |
847 | { |
848 | @@ -35,7 +36,7 @@ |
849 | { |
850 | public: |
851 | Shield(session::Manager::Ptr const&, |
852 | - indicator::Indicators::Ptr const&, |
853 | + menu::Manager::Ptr const&, |
854 | Accelerators::Ptr const&, |
855 | nux::ObjectPtr<AbstractUserPromptView> const&, |
856 | int monitor, bool is_primary); |
857 | @@ -50,7 +51,7 @@ |
858 | void ShowPrimaryView() override; |
859 | Panel* CreatePanel(); |
860 | |
861 | - connection::Wrapper panel_active_conn_; |
862 | + menu::Manager::Ptr menu_manager_; |
863 | Panel* panel_view_; |
864 | }; |
865 | |
866 | |
867 | === modified file 'lockscreen/LockScreenShieldFactory.cpp' |
868 | --- lockscreen/LockScreenShieldFactory.cpp 2015-12-04 08:17:46 +0000 |
869 | +++ lockscreen/LockScreenShieldFactory.cpp 2016-08-30 10:27:02 +0000 |
870 | @@ -28,7 +28,7 @@ |
871 | { |
872 | |
873 | nux::ObjectPtr<BaseShield> ShieldFactory::CreateShield(session::Manager::Ptr const& session_manager, |
874 | - indicator::Indicators::Ptr const& indicators, |
875 | + menu::Manager::Ptr const& menu_manager, |
876 | Accelerators::Ptr const& accelerators, |
877 | nux::ObjectPtr<AbstractUserPromptView> const& prompt_view, |
878 | int monitor, bool is_primary) |
879 | @@ -38,7 +38,7 @@ |
880 | if (Settings::Instance().desktop_type() == DesktopType::UBUNTUKYLIN) |
881 | shield = new KylinShield(session_manager, accelerators, prompt_view, monitor, is_primary); |
882 | else |
883 | - shield = new Shield(session_manager, indicators, accelerators, prompt_view, monitor, is_primary); |
884 | + shield = new Shield(session_manager, menu_manager, accelerators, prompt_view, monitor, is_primary); |
885 | |
886 | return shield; |
887 | } |
888 | |
889 | === modified file 'lockscreen/LockScreenShieldFactory.h' |
890 | --- lockscreen/LockScreenShieldFactory.h 2016-03-31 09:51:33 +0000 |
891 | +++ lockscreen/LockScreenShieldFactory.h 2016-08-30 10:27:02 +0000 |
892 | @@ -22,7 +22,7 @@ |
893 | |
894 | #include <NuxCore/NuxCore.h> |
895 | #include "UnityCore/SessionManager.h" |
896 | -#include "UnityCore/Indicators.h" |
897 | +#include "unity-shared/MenuManager.h" |
898 | #include "LockScreenAccelerators.h" |
899 | |
900 | namespace unity |
901 | @@ -41,7 +41,7 @@ |
902 | virtual ~ShieldFactoryInterface() = default; |
903 | |
904 | virtual nux::ObjectPtr<BaseShield> CreateShield(session::Manager::Ptr const&, |
905 | - indicator::Indicators::Ptr const&, |
906 | + menu::Manager::Ptr const&, |
907 | Accelerators::Ptr const&, |
908 | nux::ObjectPtr<AbstractUserPromptView> const&, |
909 | int monitor, bool is_primary) = 0; |
910 | @@ -50,7 +50,7 @@ |
911 | struct ShieldFactory : ShieldFactoryInterface |
912 | { |
913 | nux::ObjectPtr<BaseShield> CreateShield(session::Manager::Ptr const&, |
914 | - indicator::Indicators::Ptr const&, |
915 | + menu::Manager::Ptr const&, |
916 | Accelerators::Ptr const&, |
917 | nux::ObjectPtr<AbstractUserPromptView> const&, |
918 | int monitor, bool is_primary) override; |
919 | |
920 | === modified file 'panel/PanelIndicatorEntryView.cpp' |
921 | --- panel/PanelIndicatorEntryView.cpp 2016-02-17 13:14:37 +0000 |
922 | +++ panel/PanelIndicatorEntryView.cpp 2016-08-30 10:27:02 +0000 |
923 | @@ -33,6 +33,8 @@ |
924 | #include "unity-shared/RawPixel.h" |
925 | #include "unity-shared/WindowManager.h" |
926 | #include "unity-shared/ThemeSettings.h" |
927 | +#include "unity-shared/UBusWrapper.h" |
928 | +#include "unity-shared/UBusMessages.h" |
929 | #include "unity-shared/UnitySettings.h" |
930 | |
931 | namespace unity |
932 | @@ -117,6 +119,9 @@ |
933 | } |
934 | else |
935 | { |
936 | + if (overlay_showing_) |
937 | + UBusManager::SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); |
938 | + |
939 | WindowManager& wm = WindowManager::Default(); |
940 | |
941 | if (wm.IsExpoActive()) |
942 | @@ -140,6 +145,11 @@ |
943 | wm.TerminateScale(); |
944 | } |
945 | |
946 | + // This is ugly... But Nux fault! |
947 | + auto const& abs_geo = GetAbsoluteGeometry(); |
948 | + guint64 timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp; |
949 | + WindowManager::Default().UnGrabMousePointer(timestamp, button, abs_geo.x, abs_geo.y); |
950 | + |
951 | Activate(button); |
952 | } |
953 | } |
954 | |
955 | === modified file 'panel/PanelMenuView.cpp' |
956 | --- panel/PanelMenuView.cpp 2015-12-16 15:12:05 +0000 |
957 | +++ panel/PanelMenuView.cpp 2016-08-30 10:27:02 +0000 |
958 | @@ -102,7 +102,6 @@ |
959 | , ignore_menu_visibility_(false) |
960 | , integrated_menus_(menu_manager_->integrated_menus()) |
961 | , always_show_menus_(menu_manager_->always_show_menus()) |
962 | - , ignore_leave_events_(false) |
963 | , desktop_name_(get_current_desktop()) |
964 | { |
965 | if (ApplicationWindowPtr const& win = ApplicationManager::Default().GetActiveWindow()) |
966 | @@ -1814,14 +1813,9 @@ |
967 | } |
968 | } |
969 | |
970 | -void PanelMenuView::IgnoreLeaveEvents(bool ignore) |
971 | -{ |
972 | - ignore_leave_events_ = ignore; |
973 | -} |
974 | - |
975 | void PanelMenuView::OnPanelViewMouseLeave(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state) |
976 | { |
977 | - if (always_show_menus_ || ignore_leave_events_) |
978 | + if (always_show_menus_) |
979 | return; |
980 | |
981 | if (is_inside_) |
982 | |
983 | === modified file 'panel/PanelMenuView.h' |
984 | --- panel/PanelMenuView.h 2015-11-05 14:54:13 +0000 |
985 | +++ panel/PanelMenuView.h 2016-08-30 10:27:02 +0000 |
986 | @@ -56,7 +56,6 @@ |
987 | bool HasKeyActivableMenus() const; |
988 | |
989 | void NotifyAllMenusClosed(); |
990 | - void IgnoreLeaveEvents(bool); |
991 | |
992 | virtual void AddIndicator(indicator::Indicator::Ptr const& indicator); |
993 | |
994 | @@ -192,7 +191,6 @@ |
995 | bool ignore_menu_visibility_; |
996 | bool integrated_menus_; |
997 | bool always_show_menus_; |
998 | - bool ignore_leave_events_; |
999 | |
1000 | nux::Geometry monitor_geo_; |
1001 | const std::string desktop_name_; |
1002 | |
1003 | === modified file 'panel/PanelView.cpp' |
1004 | --- panel/PanelView.cpp 2016-08-12 13:57:19 +0000 |
1005 | +++ panel/PanelView.cpp 2016-08-30 10:27:02 +0000 |
1006 | @@ -42,6 +42,7 @@ |
1007 | namespace |
1008 | { |
1009 | const RawPixel TRIANGLE_THRESHOLD = 5_em; |
1010 | +const double SCRUB_VELOCITY_THRESHOLD = 0.05; |
1011 | const int refine_gradient_midpoint = 959; |
1012 | } |
1013 | |
1014 | @@ -113,10 +114,9 @@ |
1015 | |
1016 | remote_->on_object_added.connect(sigc::mem_fun(this, &PanelView::OnObjectAdded)); |
1017 | remote_->on_object_removed.connect(sigc::mem_fun(this, &PanelView::OnObjectRemoved)); |
1018 | - remote_->on_entry_activated.connect(sigc::mem_fun(this, &PanelView::OnEntryActivated)); |
1019 | - remote_->on_entry_show_menu.connect(sigc::mem_fun(this, &PanelView::OnEntryShowMenu)); |
1020 | menus->key_activate_entry.connect(sigc::mem_fun(this, &PanelView::ActivateEntry)); |
1021 | menus->open_first.connect(sigc::mem_fun(this, &PanelView::ActivateFirstSensitive)); |
1022 | + menus->RegisterTracker(GetPanelName(), sigc::mem_fun(this, &PanelView::OnMenuPointerMoved)); |
1023 | |
1024 | ubus_manager_.RegisterInterest(UBUS_OVERLAY_HIDDEN, sigc::mem_fun(this, &PanelView::OnOverlayHidden)); |
1025 | ubus_manager_.RegisterInterest(UBUS_OVERLAY_SHOWN, sigc::mem_fun(this, &PanelView::OnOverlayShown)); |
1026 | @@ -627,7 +627,7 @@ |
1027 | QueueDraw(); |
1028 | } |
1029 | |
1030 | -void PanelView::OnMenuPointerMoved(int x, int y) |
1031 | +void PanelView::OnMenuPointerMoved(int x, int y, double speed) |
1032 | { |
1033 | nux::Geometry const& geo = GetAbsoluteGeometry(); |
1034 | |
1035 | @@ -648,116 +648,6 @@ |
1036 | } |
1037 | } |
1038 | |
1039 | -static bool PointInTriangle(nux::Point const& p, nux::Point const& t0, nux::Point const& t1, nux::Point const& t2) |
1040 | -{ |
1041 | - int s = t0.y * t2.x - t0.x * t2.y + (t2.y - t0.y) * p.x + (t0.x - t2.x) * p.y; |
1042 | - int t = t0.x * t1.y - t0.y * t1.x + (t0.y - t1.y) * p.x + (t1.x - t0.x) * p.y; |
1043 | - |
1044 | - if ((s < 0) != (t < 0)) |
1045 | - return false; |
1046 | - |
1047 | - int A = -t1.y * t2.x + t0.y * (t2.x - t1.x) + t0.x * (t1.y - t2.y) + t1.x * t2.y; |
1048 | - if (A < 0) |
1049 | - { |
1050 | - s = -s; |
1051 | - t = -t; |
1052 | - A = -A; |
1053 | - } |
1054 | - |
1055 | - return s > 0 && t > 0 && (s + t) < A; |
1056 | -} |
1057 | - |
1058 | -static double GetMouseVelocity(nux::Point const& p0, nux::Point const& p1, util::Timer &timer) |
1059 | -{ |
1060 | - int dx, dy; |
1061 | - double speed; |
1062 | - auto millis = timer.ElapsedMicroSeconds(); |
1063 | - |
1064 | - if (millis == 0) |
1065 | - return 1; |
1066 | - |
1067 | - dx = p0.x - p1.x; |
1068 | - dy = p0.y - p1.y; |
1069 | - |
1070 | - speed = sqrt(dx * dx + dy * dy) / millis * 1000; |
1071 | - |
1072 | - return speed; |
1073 | -} |
1074 | - |
1075 | -bool PanelView::TrackMenuPointer() |
1076 | -{ |
1077 | - nux::Point const& mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); |
1078 | - double speed = GetMouseVelocity(mouse, tracked_pointer_pos_, mouse_tracker_timer_); |
1079 | - |
1080 | - mouse_tracker_timer_.Reset(); |
1081 | - tracked_pointer_pos_ = mouse; |
1082 | - |
1083 | - double scale = Settings::Instance().em(monitor_)->DPIScale(); |
1084 | - if (speed > 0 && PointInTriangle(mouse, |
1085 | - nux::Point(triangle_top_corner_.x, std::max(triangle_top_corner_.y - TRIANGLE_THRESHOLD.CP(scale), 0)), |
1086 | - nux::Point(menu_geo_.x, menu_geo_.y), |
1087 | - nux::Point(menu_geo_.x + menu_geo_.width, menu_geo_.y))) |
1088 | - { |
1089 | - return true; |
1090 | - } |
1091 | - |
1092 | - if (mouse != triangle_top_corner_) |
1093 | - { |
1094 | - triangle_top_corner_ = mouse; |
1095 | - OnMenuPointerMoved(mouse.x, mouse.y); |
1096 | - } |
1097 | - |
1098 | - return true; |
1099 | -} |
1100 | - |
1101 | -void PanelView::OnEntryActivated(std::string const& panel, std::string const& entry_id, nux::Rect const& menu_geo) |
1102 | -{ |
1103 | - if (!panel.empty() && panel != GetPanelName()) |
1104 | - return; |
1105 | - |
1106 | - menu_geo_ = menu_geo; |
1107 | - |
1108 | - bool active = !entry_id.empty(); |
1109 | - if (active && !track_menu_pointer_timeout_) |
1110 | - { |
1111 | - // |
1112 | - // Track menus being scrubbed at 60Hz (about every 16 millisec) |
1113 | - // It might sound ugly, but it's far nicer (and more responsive) than the |
1114 | - // code it replaces which used to capture motion events in another process |
1115 | - // (unity-panel-service) and send them to us over dbus. |
1116 | - // NOTE: The reason why we have to use a timer instead of tracking motion |
1117 | - // events is because the motion events will never be delivered to this |
1118 | - // process. All the motion events will go to unity-panel-service while |
1119 | - // scrubbing because the active panel menu has (needs) the pointer grab. |
1120 | - // |
1121 | - mouse_tracker_timer_.Reset(); |
1122 | - triangle_top_corner_ = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); |
1123 | - track_menu_pointer_timeout_.reset(new glib::Timeout(16)); |
1124 | - track_menu_pointer_timeout_->Run(sigc::mem_fun(this, &PanelView::TrackMenuPointer)); |
1125 | - } |
1126 | - else if (!active) |
1127 | - { |
1128 | - track_menu_pointer_timeout_.reset(); |
1129 | - menu_view_->NotifyAllMenusClosed(); |
1130 | - tracked_pointer_pos_ = {-1, -1}; |
1131 | - } |
1132 | - |
1133 | - if (overlay_is_open_) |
1134 | - ubus_manager_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST); |
1135 | -} |
1136 | - |
1137 | -void PanelView::OnEntryShowMenu(std::string const& entry_id, unsigned xid, |
1138 | - int x, int y, unsigned button) |
1139 | -{ |
1140 | - if (!track_menu_pointer_timeout_) |
1141 | - { |
1142 | - // This is ugly... But Nux fault! |
1143 | - menu_view_->IgnoreLeaveEvents(true); |
1144 | - WindowManager::Default().UnGrabMousePointer(CurrentTime, button, x, y); |
1145 | - menu_view_->IgnoreLeaveEvents(false); |
1146 | - } |
1147 | -} |
1148 | - |
1149 | bool PanelView::ActivateFirstSensitive() |
1150 | { |
1151 | if (!IsActive()) |
1152 | @@ -768,7 +658,6 @@ |
1153 | { |
1154 | // Since this only happens on keyboard events, we need to prevent that the |
1155 | // pointer tracker would select another entry. |
1156 | - tracked_pointer_pos_ = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); |
1157 | return true; |
1158 | } |
1159 | |
1160 | @@ -785,7 +674,6 @@ |
1161 | { |
1162 | // Since this only happens on keyboard events, we need to prevent that the |
1163 | // pointer tracker would select another entry. |
1164 | - tracked_pointer_pos_ = nux::GetGraphicsDisplay()->GetMouseScreenCoord(); |
1165 | return true; |
1166 | } |
1167 | |
1168 | |
1169 | === modified file 'panel/PanelView.h' |
1170 | --- panel/PanelView.h 2016-03-30 18:18:07 +0000 |
1171 | +++ panel/PanelView.h 2016-08-30 10:27:02 +0000 |
1172 | @@ -35,7 +35,6 @@ |
1173 | #include "unity-shared/Introspectable.h" |
1174 | #include "unity-shared/MenuManager.h" |
1175 | #include "unity-shared/MockableBaseWindow.h" |
1176 | -#include "unity-shared/Timer.h" |
1177 | #include "PanelMenuView.h" |
1178 | #include "PanelTray.h" |
1179 | #include "PanelIndicatorsView.h" |
1180 | @@ -88,9 +87,6 @@ |
1181 | void OnObjectAdded(indicator::Indicator::Ptr const& proxy); |
1182 | void OnObjectRemoved(indicator::Indicator::Ptr const& proxy); |
1183 | void OnIndicatorViewUpdated(); |
1184 | - void OnMenuPointerMoved(int x, int y); |
1185 | - void OnEntryActivated(std::string const& panel, std::string const& entry_id, nux::Rect const& geo); |
1186 | - void OnEntryShowMenu(std::string const& entry_id, unsigned xid, int x, int y, unsigned button); |
1187 | |
1188 | private: |
1189 | std::string GetPanelName() const; |
1190 | @@ -100,6 +96,8 @@ |
1191 | void OnSpreadInitiate(); |
1192 | void OnSpreadTerminate(); |
1193 | void OnLowGfxChanged(); |
1194 | + void OnMenuPointerMoved(int x, int y, double speed); |
1195 | + void OnActiveEntryEvent(XEvent const&); |
1196 | void EnableOverlayMode(bool); |
1197 | void LoadTextures(); |
1198 | |
1199 | @@ -109,7 +107,6 @@ |
1200 | bool IsTransparent(); |
1201 | void UpdateBackground(); |
1202 | void ForceUpdateBackground(); |
1203 | - bool TrackMenuPointer(); |
1204 | void SyncGeometries(); |
1205 | void AddPanelView(PanelIndicatorsView* child, unsigned int stretchFactor); |
1206 | |
1207 | @@ -133,10 +130,6 @@ |
1208 | BaseTexturePtr bg_refine_single_column_tex_; |
1209 | std::unique_ptr<nux::AbstractPaintLayer> bg_refine_single_column_layer_; |
1210 | |
1211 | - std::string active_overlay_; |
1212 | - nux::Point tracked_pointer_pos_, triangle_top_corner_; |
1213 | - util::Timer mouse_tracker_timer_; |
1214 | - |
1215 | bool is_dirty_; |
1216 | bool opacity_maximized_toggle_; |
1217 | bool needs_geo_sync_; |
1218 | @@ -144,15 +137,13 @@ |
1219 | float opacity_; |
1220 | int monitor_; |
1221 | int stored_dash_width_; |
1222 | - |
1223 | - nux::Geometry menu_geo_; |
1224 | + std::string active_overlay_; |
1225 | |
1226 | connection::Manager on_indicator_updated_connections_; |
1227 | connection::Manager maximized_opacity_toggle_connections_; |
1228 | BackgroundEffectHelper bg_effect_helper_; |
1229 | nux::ObjectPtr<nux::IOpenGLBaseTexture> bg_blur_texture_; |
1230 | UBusManager ubus_manager_; |
1231 | - glib::Source::UniquePtr track_menu_pointer_timeout_; |
1232 | }; |
1233 | |
1234 | } // namespace panel |
1235 | |
1236 | === modified file 'plugins/unityshell/src/unityshell.h' |
1237 | --- plugins/unityshell/src/unityshell.h 2016-08-12 11:21:48 +0000 |
1238 | +++ plugins/unityshell/src/unityshell.h 2016-08-30 10:27:02 +0000 |
1239 | @@ -56,6 +56,7 @@ |
1240 | #include "DashStyle.h" |
1241 | #include "EdgeBarrierController.h" |
1242 | #include "FavoriteStoreGSettings.h" |
1243 | +#include "InputMonitor.h" |
1244 | #include "ShortcutController.h" |
1245 | #include "LauncherController.h" |
1246 | #include "LockScreenController.h" |
1247 | @@ -317,6 +318,7 @@ |
1248 | internal::FavoriteStoreGSettings favorite_store_; |
1249 | ThumbnailGenerator thumbnail_generator_; |
1250 | lockscreen::Settings lockscreen_settings_; |
1251 | + input::Monitor input_monitor_; |
1252 | |
1253 | /* The window thread should be the last thing removed, as c++ does it in reverse order */ |
1254 | std::unique_ptr<nux::WindowThread> wt; |
1255 | |
1256 | === modified file 'tests/test_edge_barrier_controller.cpp' |
1257 | --- tests/test_edge_barrier_controller.cpp 2015-01-15 15:02:24 +0000 |
1258 | +++ tests/test_edge_barrier_controller.cpp 2016-08-30 10:27:02 +0000 |
1259 | @@ -25,6 +25,7 @@ |
1260 | |
1261 | #include "EdgeBarrierController.h" |
1262 | #include "EdgeBarrierControllerPrivate.h" |
1263 | +#include "InputMonitor.h" |
1264 | |
1265 | using namespace unity; |
1266 | using namespace unity::ui; |
1267 | @@ -108,6 +109,7 @@ |
1268 | |
1269 | TestBarrierSubscriber horizontal_subscribers_[monitors::MAX]; |
1270 | TestBarrierSubscriber vertical_subscribers_[monitors::MAX]; |
1271 | + input::Monitor im; |
1272 | MockUScreen uscreen; |
1273 | EdgeBarrierController bc; |
1274 | }; |
1275 | |
1276 | === modified file 'tests/test_lockscreen_controller.cpp' |
1277 | --- tests/test_lockscreen_controller.cpp 2016-06-21 14:40:26 +0000 |
1278 | +++ tests/test_lockscreen_controller.cpp 2016-08-30 10:27:02 +0000 |
1279 | @@ -55,7 +55,7 @@ |
1280 | struct MockShield : BaseShield |
1281 | { |
1282 | MockShield() |
1283 | - : BaseShield(nullptr, nullptr, nullptr, nux::ObjectPtr<AbstractUserPromptView>(), 0, false) |
1284 | + : BaseShield(nullptr, nullptr, nux::ObjectPtr<AbstractUserPromptView>(), 0, false) |
1285 | {} |
1286 | |
1287 | MOCK_CONST_METHOD0(IsIndicatorOpen, bool()); |
1288 | @@ -67,7 +67,7 @@ |
1289 | struct ShieldFactoryMock : ShieldFactoryInterface |
1290 | { |
1291 | nux::ObjectPtr<BaseShield> CreateShield(session::Manager::Ptr const&, |
1292 | - indicator::Indicators::Ptr const&, |
1293 | + menu::Manager::Ptr const&, |
1294 | Accelerators::Ptr const&, |
1295 | nux::ObjectPtr<AbstractUserPromptView> const&, |
1296 | int, bool) override |
1297 | |
1298 | === modified file 'tests/test_panel_controller.cpp' |
1299 | --- tests/test_panel_controller.cpp 2014-03-21 04:40:12 +0000 |
1300 | +++ tests/test_panel_controller.cpp 2016-08-30 10:27:02 +0000 |
1301 | @@ -19,6 +19,7 @@ |
1302 | |
1303 | #include <gmock/gmock.h> |
1304 | |
1305 | +#include "InputMonitor.h" |
1306 | #include "PanelController.h" |
1307 | #include "PanelStyle.h" |
1308 | #include "PanelView.h" |
1309 | @@ -46,6 +47,7 @@ |
1310 | menu::MockManager::Ptr menus; |
1311 | ui::EdgeBarrierController::Ptr edge_barriers; |
1312 | launcher::Options::Ptr options; |
1313 | + input::Monitor im; |
1314 | }; |
1315 | |
1316 | TEST_F(TestPanelController, Construction) |
1317 | |
1318 | === modified file 'tests/test_panel_view.cpp' |
1319 | --- tests/test_panel_view.cpp 2014-12-12 22:33:24 +0000 |
1320 | +++ tests/test_panel_view.cpp 2016-08-30 10:27:02 +0000 |
1321 | @@ -25,6 +25,7 @@ |
1322 | #include "unity-shared/PanelStyle.h" |
1323 | #include "unity-shared/UBusMessages.h" |
1324 | #include "unity-shared/UBusWrapper.h" |
1325 | + #include "InputMonitor.h" |
1326 | |
1327 | #include "mock_menu_manager.h" |
1328 | #include "test_standalone_wm.h" |
1329 | @@ -43,6 +44,7 @@ |
1330 | nux::ObjectPtr<MockableBaseWindow> window_; |
1331 | nux::ObjectPtr<PanelView> panel_view_; |
1332 | testwrapper::StandaloneWM WM; |
1333 | + input::Monitor im; |
1334 | |
1335 | TestPanelView() |
1336 | : window_(new MockableBaseWindow()) |
1337 | |
1338 | === modified file 'unity-shared/CMakeLists.txt' |
1339 | --- unity-shared/CMakeLists.txt 2016-08-12 11:21:48 +0000 |
1340 | +++ unity-shared/CMakeLists.txt 2016-08-30 10:27:02 +0000 |
1341 | @@ -82,6 +82,7 @@ |
1342 | set (UNITY_SHARED_SOURCES |
1343 | XKeyboardUtil.cpp |
1344 | XWindowManager.cpp |
1345 | + InputMonitor.cpp |
1346 | ${UNITY_SHARED_SOURCES} |
1347 | ) |
1348 | else() |
1349 | |
1350 | === added file 'unity-shared/InputMonitor.cpp' |
1351 | --- unity-shared/InputMonitor.cpp 1970-01-01 00:00:00 +0000 |
1352 | +++ unity-shared/InputMonitor.cpp 2016-08-30 10:27:02 +0000 |
1353 | @@ -0,0 +1,408 @@ |
1354 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1355 | +/* |
1356 | + * Copyright (C) 2014 Canonical Ltd |
1357 | + * |
1358 | + * This program is free software: you can redistribute it and/or modify |
1359 | + * it under the terms of the GNU General Public License version 3 as |
1360 | + * published by the Free Software Foundation. |
1361 | + * |
1362 | + * This program is distributed in the hope that it will be useful, |
1363 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1364 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1365 | + * GNU General Public License for more details. |
1366 | + * |
1367 | + * You should have received a copy of the GNU General Public License |
1368 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1369 | + * |
1370 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1371 | + */ |
1372 | + |
1373 | +#include "InputMonitor.h" |
1374 | +#include "SigcSlotHash.h" |
1375 | + |
1376 | +#include <Nux/Nux.h> |
1377 | +#include <NuxCore/Logger.h> |
1378 | +#include <X11/extensions/XInput2.h> |
1379 | +#include <UnityCore/GLibSource.h> |
1380 | +#include <unordered_set> |
1381 | +#include <gdk/gdkx.h> |
1382 | +#include <glib.h> |
1383 | + |
1384 | +namespace unity |
1385 | +{ |
1386 | +namespace input |
1387 | +{ |
1388 | +namespace |
1389 | +{ |
1390 | +DECLARE_LOGGER(logger, "unity.input.monitor"); |
1391 | + |
1392 | +Monitor* instance_ = nullptr; |
1393 | + |
1394 | +const unsigned XINPUT_MAJOR_VERSION = 2; |
1395 | +const unsigned XINPUT_MINOR_VERSION = 3; |
1396 | + |
1397 | +bool operator&(Events l, Events r) |
1398 | +{ |
1399 | + typedef std::underlying_type<Events>::type ut; |
1400 | + return static_cast<ut>(static_cast<ut>(l) & static_cast<ut>(r)); |
1401 | +} |
1402 | + |
1403 | +Events& operator|=(Events& l, Events r) |
1404 | +{ |
1405 | + typedef std::underlying_type<Events>::type ut; |
1406 | + return l = static_cast<Events>(static_cast<ut>(l) | static_cast<ut>(r)); |
1407 | +} |
1408 | + |
1409 | +template <typename EVENT> |
1410 | +void initialize_event_common(EVENT* ev, XIDeviceEvent* xiev) |
1411 | +{ |
1412 | + ev->serial = xiev->serial; |
1413 | + ev->send_event = xiev->send_event; |
1414 | + ev->display = xiev->display; |
1415 | + ev->window = xiev->event; |
1416 | + ev->root = xiev->root; |
1417 | + ev->subwindow = xiev->child; |
1418 | + ev->time = xiev->time; |
1419 | + ev->x = std::round(xiev->event_x); |
1420 | + ev->y = std::round(xiev->event_y); |
1421 | + ev->x_root = std::round(xiev->root_x); |
1422 | + ev->y_root = std::round(xiev->root_y); |
1423 | + ev->state = xiev->mods.effective; |
1424 | + ev->same_screen = True; |
1425 | +} |
1426 | + |
1427 | +template <typename EVENT_TYPE, typename NATIVE_TYPE> |
1428 | +void initialize_event(XEvent* ev, NATIVE_TYPE* xiev); |
1429 | + |
1430 | +template <> |
1431 | +void initialize_event<XButtonEvent>(XEvent* ev, XIDeviceEvent* xiev) |
1432 | +{ |
1433 | + XButtonEvent* bev = &ev->xbutton; |
1434 | + ev->type = (xiev->evtype == XI_ButtonPress) ? ButtonPress : ButtonRelease; |
1435 | + initialize_event_common(bev, xiev); |
1436 | + bev->button = xiev->detail; |
1437 | +} |
1438 | + |
1439 | +template <> |
1440 | +void initialize_event<XKeyEvent>(XEvent* ev, XIDeviceEvent* xiev) |
1441 | +{ |
1442 | + XKeyEvent* kev = &ev->xkey; |
1443 | + ev->type = (xiev->evtype == XI_KeyPress) ? KeyPress : KeyRelease; |
1444 | + initialize_event_common(kev, xiev); |
1445 | + kev->keycode = xiev->detail; |
1446 | +} |
1447 | + |
1448 | +template <> |
1449 | +void initialize_event<XMotionEvent>(XEvent* ev, XIDeviceEvent* xiev) |
1450 | +{ |
1451 | + XMotionEvent* mev = &ev->xmotion; |
1452 | + ev->type = MotionNotify; |
1453 | + initialize_event_common(mev, xiev); |
1454 | + mev->is_hint = NotifyNormal; |
1455 | + |
1456 | + for (int i = 0; i < xiev->buttons.mask_len * 8; ++i) |
1457 | + { |
1458 | + if (XIMaskIsSet(xiev->buttons.mask, i)) |
1459 | + { |
1460 | + mev->is_hint = NotifyHint; |
1461 | + break; |
1462 | + } |
1463 | + } |
1464 | +} |
1465 | + |
1466 | +template <> |
1467 | +void initialize_event<XGenericEventCookie>(XEvent* ev, XIBarrierEvent* xiev) |
1468 | +{ |
1469 | + XGenericEventCookie* cev = &ev->xcookie; |
1470 | + cev->type = GenericEvent; |
1471 | + cev->serial = xiev->serial; |
1472 | + cev->send_event = xiev->send_event; |
1473 | + cev->display = xiev->display; |
1474 | + cev->evtype = xiev->evtype; |
1475 | + cev->data = xiev; |
1476 | +} |
1477 | +} |
1478 | + |
1479 | +struct Monitor::Impl |
1480 | +{ |
1481 | + Impl() |
1482 | + : xi_opcode_(0) |
1483 | + , event_filter_set_(false) |
1484 | + , invoking_callbacks_(false) |
1485 | + { |
1486 | + Display *dpy = gdk_x11_get_default_xdisplay(); |
1487 | + int event_base, error_base; |
1488 | + |
1489 | + if (XQueryExtension(dpy, "XInputExtension", &xi_opcode_, &event_base, &error_base)) |
1490 | + { |
1491 | + int maj = XINPUT_MAJOR_VERSION; |
1492 | + int min = XINPUT_MINOR_VERSION; |
1493 | + |
1494 | + if (XIQueryVersion(dpy, &maj, &min) == BadRequest) |
1495 | + { |
1496 | + LOG_ERROR(logger) << "Need XInput version "<< maj << "." << min << ", " |
1497 | + << "impossible, to setup an InputMonitor"; |
1498 | + } |
1499 | + } |
1500 | + else |
1501 | + { |
1502 | + LOG_ERROR(logger) << "Missing XInput, impossible to setup an InputMonitor"; |
1503 | + } |
1504 | + } |
1505 | + |
1506 | + ~Impl() |
1507 | + { |
1508 | + if (event_filter_set_) |
1509 | + { |
1510 | + pointer_callbacks_.clear(); |
1511 | + key_callbacks_.clear(); |
1512 | + barrier_callbacks_.clear(); |
1513 | + UpdateEventMonitor(); |
1514 | + } |
1515 | + } |
1516 | + |
1517 | + bool RegisterClient(Events type, EventCallback const& cb) |
1518 | + { |
1519 | + bool added = false; |
1520 | + |
1521 | + if (type & Events::POINTER) |
1522 | + added = pointer_callbacks_.insert(cb).second || added; |
1523 | + |
1524 | + if (type & Events::KEYS) |
1525 | + added = key_callbacks_.insert(cb).second || added; |
1526 | + |
1527 | + if (type & Events::BARRIER) |
1528 | + added = barrier_callbacks_.insert(cb).second || added; |
1529 | + |
1530 | + if (added) |
1531 | + UpdateEventMonitor(); |
1532 | + |
1533 | + return added; |
1534 | + } |
1535 | + |
1536 | + bool UnregisterClient(EventCallback const& cb) |
1537 | + { |
1538 | + if (invoking_callbacks_) |
1539 | + { |
1540 | + // Delay the event removal if we're currently invoking a callback |
1541 | + // not to break the callbacks loop |
1542 | + removal_queue_.insert(cb); |
1543 | + return false; |
1544 | + } |
1545 | + |
1546 | + bool removed = false; |
1547 | + removed = pointer_callbacks_.erase(cb) > 0 || removed; |
1548 | + removed = key_callbacks_.erase(cb) > 0 || removed; |
1549 | + removed = barrier_callbacks_.erase(cb) > 0 || removed; |
1550 | + |
1551 | + if (removed) |
1552 | + UpdateEventMonitor(); |
1553 | + |
1554 | + return removed; |
1555 | + } |
1556 | + |
1557 | + Events RegisteredEvents(EventCallback const& cb) const |
1558 | + { |
1559 | + Events events = Events::NONE; |
1560 | + |
1561 | + if (pointer_callbacks_.find(cb) != end(pointer_callbacks_)) |
1562 | + events |= Events::POINTER; |
1563 | + |
1564 | + if (key_callbacks_.find(cb) != end(key_callbacks_)) |
1565 | + events |= Events::KEYS; |
1566 | + |
1567 | + if (barrier_callbacks_.find(cb) != end(barrier_callbacks_)) |
1568 | + events |= Events::BARRIER; |
1569 | + |
1570 | + return events; |
1571 | + } |
1572 | + |
1573 | + void UpdateEventMonitor() |
1574 | + { |
1575 | + auto* dpy = nux::GetGraphicsDisplay()->GetX11Display(); |
1576 | + Window root = DefaultRootWindow(dpy); |
1577 | + |
1578 | + unsigned char master_dev_bits[XIMaskLen(XI_LASTEVENT)] = { 0 }; |
1579 | + XIEventMask master_dev = { XIAllMasterDevices, sizeof(master_dev_bits), master_dev_bits }; |
1580 | + |
1581 | + if (!barrier_callbacks_.empty()) |
1582 | + { |
1583 | + XISetMask(master_dev.mask, XI_BarrierHit); |
1584 | + XISetMask(master_dev.mask, XI_BarrierLeave); |
1585 | + } |
1586 | + |
1587 | + unsigned char all_devs_bits[XIMaskLen(XI_LASTEVENT)] = { 0 }; |
1588 | + XIEventMask all_devs = { XIAllDevices, sizeof(all_devs_bits), all_devs_bits }; |
1589 | + |
1590 | + if (!pointer_callbacks_.empty()) |
1591 | + { |
1592 | + XISetMask(all_devs.mask, XI_Motion); |
1593 | + XISetMask(all_devs.mask, XI_ButtonPress); |
1594 | + XISetMask(all_devs.mask, XI_ButtonRelease); |
1595 | + } |
1596 | + |
1597 | + if (!key_callbacks_.empty()) |
1598 | + { |
1599 | + XISetMask(all_devs.mask, XI_KeyPress); |
1600 | + XISetMask(all_devs.mask, XI_KeyRelease); |
1601 | + } |
1602 | + |
1603 | + XIEventMask selected[] = {master_dev, all_devs}; |
1604 | + XISelectEvents(dpy, root, selected, G_N_ELEMENTS(selected)); |
1605 | + XSync(dpy, False); |
1606 | + |
1607 | + if (!pointer_callbacks_.empty() || !key_callbacks_.empty() || !barrier_callbacks_.empty()) |
1608 | + { |
1609 | + if (!event_filter_set_) |
1610 | + { |
1611 | + nux::GetGraphicsDisplay()->AddEventFilter({[] (XEvent event, void* data) { |
1612 | + return static_cast<Impl*>(data)->HandleEvent(event); |
1613 | + }, this}); |
1614 | + |
1615 | + event_filter_set_ = true; |
1616 | + } |
1617 | + } |
1618 | + else if (event_filter_set_) |
1619 | + { |
1620 | + nux::GetGraphicsDisplay()->RemoveEventFilter(this); |
1621 | + event_filter_set_ = false; |
1622 | + } |
1623 | + } |
1624 | + |
1625 | + bool HandleEvent(XEvent& event) |
1626 | + { |
1627 | + bool handled = false; |
1628 | + |
1629 | + if (event.type != GenericEvent || event.xcookie.extension != xi_opcode_) |
1630 | + return handled; |
1631 | + |
1632 | + switch (event.xcookie.evtype) |
1633 | + { |
1634 | + case XI_ButtonPress: |
1635 | + case XI_ButtonRelease: |
1636 | + handled = InvokeCallbacks<XButtonEvent>(pointer_callbacks_, event); |
1637 | + break; |
1638 | + case XI_Motion: |
1639 | + handled = InvokeCallbacks<XMotionEvent>(pointer_callbacks_, event); |
1640 | + break; |
1641 | + case XI_KeyPress: |
1642 | + case XI_KeyRelease: |
1643 | + handled = InvokeCallbacks<XKeyEvent>(key_callbacks_, event); |
1644 | + break; |
1645 | + case XI_BarrierHit: |
1646 | + case XI_BarrierLeave: |
1647 | + handled = InvokeCallbacks<XGenericEventCookie, XIBarrierEvent>(barrier_callbacks_, event); |
1648 | + break; |
1649 | + } |
1650 | + |
1651 | + return handled; |
1652 | + } |
1653 | + |
1654 | + template <typename EVENT_TYPE, typename NATIVE_TYPE = XIDeviceEvent> |
1655 | + bool InvokeCallbacks(std::unordered_set<EventCallback>& callbacks, XEvent& xiev) |
1656 | + { |
1657 | + XGenericEventCookie *cookie = &xiev.xcookie; |
1658 | + |
1659 | + if (!XGetEventData(xiev.xany.display, cookie)) |
1660 | + return false; |
1661 | + |
1662 | + XEvent event; |
1663 | + initialize_event<EVENT_TYPE>(&event, reinterpret_cast<NATIVE_TYPE*>(cookie->data)); |
1664 | + invoking_callbacks_ = true; |
1665 | + |
1666 | + for (auto it = callbacks.begin(); it != callbacks.end();) |
1667 | + { |
1668 | + if (it->empty()) |
1669 | + { |
1670 | + it = callbacks.erase(it); |
1671 | + continue; |
1672 | + } |
1673 | + |
1674 | + (*it)(event); |
1675 | + ++it; |
1676 | + } |
1677 | + |
1678 | + XFreeEventData(xiev.xany.display, cookie); |
1679 | + invoking_callbacks_ = false; |
1680 | + |
1681 | + // A callback might unregister itself on the event callback, causing the |
1682 | + // above callbacks loop to crash, so in this case we save the event in the |
1683 | + // removal queue and eventually we unregistered these callbacks. |
1684 | + bool update_event_monitor = false; |
1685 | + for (auto it = removal_queue_.begin(); it != removal_queue_.end(); it = removal_queue_.erase(it)) |
1686 | + { |
1687 | + auto const& cb = *it; |
1688 | + pointer_callbacks_.erase(cb); |
1689 | + key_callbacks_.erase(cb); |
1690 | + barrier_callbacks_.erase(cb); |
1691 | + update_event_monitor = true; |
1692 | + } |
1693 | + |
1694 | + if (callbacks.empty() || update_event_monitor) |
1695 | + { |
1696 | + idle_removal_.reset(new glib::Idle([this] { |
1697 | + UpdateEventMonitor(); |
1698 | + return false; |
1699 | + })); |
1700 | + |
1701 | + return false; |
1702 | + } |
1703 | + |
1704 | + return true; |
1705 | + } |
1706 | + |
1707 | + int xi_opcode_; |
1708 | + bool event_filter_set_; |
1709 | + bool invoking_callbacks_; |
1710 | + glib::Source::UniquePtr idle_removal_; |
1711 | + std::unordered_set<EventCallback> pointer_callbacks_; |
1712 | + std::unordered_set<EventCallback> key_callbacks_; |
1713 | + std::unordered_set<EventCallback> barrier_callbacks_; |
1714 | + std::unordered_set<EventCallback> removal_queue_; |
1715 | +}; |
1716 | + |
1717 | +Monitor::Monitor() |
1718 | +{ |
1719 | + if (instance_) |
1720 | + { |
1721 | + LOG_WARN(logger) << "More than one input::Monitor created."; |
1722 | + return; |
1723 | + } |
1724 | + |
1725 | + instance_ = this; |
1726 | + impl_.reset(new Impl()); |
1727 | +} |
1728 | + |
1729 | +Monitor::~Monitor() |
1730 | +{ |
1731 | + if (this == instance_) |
1732 | + instance_ = nullptr; |
1733 | +} |
1734 | + |
1735 | +Monitor& Monitor::Get() |
1736 | +{ |
1737 | + if (!instance_) |
1738 | + { |
1739 | + LOG_ERROR(logger) << "No input::Monitor created yet."; |
1740 | + } |
1741 | + |
1742 | + return *instance_; |
1743 | +} |
1744 | + |
1745 | +bool Monitor::RegisterClient(Events events, EventCallback const& cb) |
1746 | +{ |
1747 | + return impl_->RegisterClient(events, cb); |
1748 | +} |
1749 | + |
1750 | +bool Monitor::UnregisterClient(EventCallback const& cb) |
1751 | +{ |
1752 | + return impl_->UnregisterClient(cb); |
1753 | +} |
1754 | + |
1755 | +Events Monitor::RegisteredEvents(EventCallback const& cb) const |
1756 | +{ |
1757 | + return impl_->RegisteredEvents(cb); |
1758 | +} |
1759 | + |
1760 | +} // input namespace |
1761 | +} // unity namespace |
1762 | |
1763 | === added file 'unity-shared/InputMonitor.h' |
1764 | --- unity-shared/InputMonitor.h 1970-01-01 00:00:00 +0000 |
1765 | +++ unity-shared/InputMonitor.h 2016-08-30 10:27:02 +0000 |
1766 | @@ -0,0 +1,67 @@ |
1767 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
1768 | +/* |
1769 | + * Copyright (C) 2014 Canonical Ltd |
1770 | + * |
1771 | + * This program is free software: you can redistribute it and/or modify |
1772 | + * it under the terms of the GNU General Public License version 3 as |
1773 | + * published by the Free Software Foundation. |
1774 | + * |
1775 | + * This program is distributed in the hope that it will be useful, |
1776 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1777 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1778 | + * GNU General Public License for more details. |
1779 | + * |
1780 | + * You should have received a copy of the GNU General Public License |
1781 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1782 | + * |
1783 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
1784 | + */ |
1785 | + |
1786 | +#ifndef __UNITY_INPUT_MONITOR__ |
1787 | +#define __UNITY_INPUT_MONITOR__ |
1788 | + |
1789 | +#include <X11/Xlib.h> |
1790 | +#include <sigc++/slot.h> |
1791 | +#include <memory> |
1792 | + |
1793 | +namespace unity |
1794 | +{ |
1795 | +namespace input |
1796 | +{ |
1797 | +enum class Events : unsigned |
1798 | +{ |
1799 | + NONE = 0, |
1800 | + POINTER = (1 << 0), |
1801 | + KEYS = (1 << 1), |
1802 | + BARRIER = (1 << 2), |
1803 | + INPUT = POINTER | KEYS, |
1804 | + ALL = POINTER | KEYS | BARRIER |
1805 | +}; |
1806 | + |
1807 | +class Monitor : public sigc::trackable |
1808 | +{ |
1809 | +public: |
1810 | + typedef sigc::slot<void, XEvent const&> EventCallback; |
1811 | + |
1812 | + static Monitor& Get(); |
1813 | + |
1814 | + Monitor(); |
1815 | + virtual ~Monitor(); |
1816 | + |
1817 | + bool RegisterClient(Events, EventCallback const&); |
1818 | + bool UnregisterClient(EventCallback const&); |
1819 | + |
1820 | + Events RegisteredEvents(EventCallback const&) const; |
1821 | + |
1822 | +private: |
1823 | + Monitor(Monitor const&) = delete; |
1824 | + Monitor& operator=(Monitor const&) = delete; |
1825 | + |
1826 | + struct Impl; |
1827 | + std::unique_ptr<Impl> impl_; |
1828 | +}; |
1829 | + |
1830 | +} // input namespace |
1831 | +} // unity namespace |
1832 | + |
1833 | +#endif // __UNITY_INPUT_MONITOR__ |
1834 | |
1835 | === modified file 'unity-shared/MenuManager.cpp' |
1836 | --- unity-shared/MenuManager.cpp 2015-10-02 14:02:05 +0000 |
1837 | +++ unity-shared/MenuManager.cpp 2016-08-30 10:27:02 +0000 |
1838 | @@ -21,11 +21,16 @@ |
1839 | #include <gtk/gtk.h> |
1840 | #include <NuxCore/Logger.h> |
1841 | #include <UnityCore/GLibSignal.h> |
1842 | +#include <UnityCore/GLibSource.h> |
1843 | #include <UnityCore/GLibWrapper.h> |
1844 | #include <UnityCore/DBusIndicators.h> |
1845 | #include <unordered_map> |
1846 | |
1847 | #include "MenuManager.h" |
1848 | +#include "InputMonitor.h" |
1849 | +#include "RawPixel.h" |
1850 | +#include "UnitySettings.h" |
1851 | +#include "UScreen.h" |
1852 | #include "WindowManager.h" |
1853 | |
1854 | namespace unity |
1855 | @@ -40,6 +45,10 @@ |
1856 | const std::string LIM_KEY = "integrated-menus"; |
1857 | const std::string SHOW_MENUS_NOW_DELAY = "show-menus-now-delay"; |
1858 | const std::string ALWAYS_SHOW_MENUS_KEY = "always-show-menus"; |
1859 | + |
1860 | +const RawPixel TRIANGLE_THRESHOLD = 5_em; |
1861 | +const double SCRUB_VELOCITY_THRESHOLD = 0.05; |
1862 | +const unsigned MENU_OPEN_MOUSE_WAIT = 150; |
1863 | } |
1864 | |
1865 | using namespace indicator; |
1866 | @@ -51,6 +60,7 @@ |
1867 | , indicators_(indicators) |
1868 | , key_grabber_(grabber) |
1869 | , show_now_window_(0) |
1870 | + , last_pointer_time_(0) |
1871 | , settings_(g_settings_new(SETTINGS_NAME.c_str())) |
1872 | { |
1873 | for (auto const& indicator : indicators_->GetIndicators()) |
1874 | @@ -182,9 +192,15 @@ |
1875 | parent_->key_activate_entry.emit(entry_id); |
1876 | } |
1877 | |
1878 | - void EntryActivated(std::string const&, std::string const&, nux::Rect const& geo) |
1879 | + void EntryActivated(std::string const& menubar, std::string const&, nux::Rect const& geo) |
1880 | { |
1881 | parent_->menu_open = !geo.IsNull(); |
1882 | + |
1883 | + if (active_menubar_ != menubar) |
1884 | + { |
1885 | + active_menubar_ = menubar; |
1886 | + UpdateActiveTracker(); |
1887 | + } |
1888 | } |
1889 | |
1890 | void SetShowNowForWindow(Window xid, bool show) |
1891 | @@ -231,15 +247,147 @@ |
1892 | gtk_icon_theme_set_search_path(gtk_icon_theme_get_default(), gicon_paths.data(), gicon_paths.size()); |
1893 | } |
1894 | |
1895 | + bool PointInTriangle(nux::Point const& p, nux::Point const& t0, nux::Point const& t1, nux::Point const& t2) |
1896 | + { |
1897 | + int s = t0.y * t2.x - t0.x * t2.y + (t2.y - t0.y) * p.x + (t0.x - t2.x) * p.y; |
1898 | + int t = t0.x * t1.y - t0.y * t1.x + (t0.y - t1.y) * p.x + (t1.x - t0.x) * p.y; |
1899 | + |
1900 | + if ((s < 0) != (t < 0)) |
1901 | + return false; |
1902 | + |
1903 | + int A = -t1.y * t2.x + t0.y * (t2.x - t1.x) + t0.x * (t1.y - t2.y) + t1.x * t2.y; |
1904 | + if (A < 0) |
1905 | + { |
1906 | + s = -s; |
1907 | + t = -t; |
1908 | + A = -A; |
1909 | + } |
1910 | + |
1911 | + return s > 0 && t > 0 && (s + t) < A; |
1912 | + } |
1913 | + |
1914 | + double GetMouseVelocity(nux::Point const& p0, nux::Point const& p1, Time time_delta) |
1915 | + { |
1916 | + int dx, dy; |
1917 | + double speed; |
1918 | + |
1919 | + if (time_delta == 0) |
1920 | + return 1; |
1921 | + |
1922 | + dx = p0.x - p1.x; |
1923 | + dy = p0.y - p1.y; |
1924 | + |
1925 | + speed = sqrt(dx * dx + dy * dy) / time_delta; |
1926 | + |
1927 | + return speed; |
1928 | + } |
1929 | + |
1930 | + void OnActiveEntryEvent(XEvent const& e) |
1931 | + { |
1932 | + if (e.type != MotionNotify) |
1933 | + return; |
1934 | + |
1935 | + auto const& active_entry = indicators_->GetActiveEntry(); |
1936 | + |
1937 | + if (!active_entry) |
1938 | + return; |
1939 | + |
1940 | + nux::Point mouse(e.xmotion.x_root, e.xmotion.y_root); |
1941 | + auto monitor = UScreen::GetDefault()->GetMonitorAtPosition(mouse.x, mouse.y); |
1942 | + double scale = Settings::Instance().em(monitor)->DPIScale(); |
1943 | + double speed = GetMouseVelocity(mouse, tracked_pointer_pos_, e.xmotion.time - last_pointer_time_); |
1944 | + auto menu_geo = active_entry->geometry(); |
1945 | + |
1946 | + tracked_pointer_pos_ = mouse; |
1947 | + last_pointer_time_ = e.xmotion.time; |
1948 | + |
1949 | + if (speed > SCRUB_VELOCITY_THRESHOLD && |
1950 | + PointInTriangle(mouse, {mouse.x, std::max(mouse.y - TRIANGLE_THRESHOLD.CP(scale), 0)}, |
1951 | + menu_geo.GetPosition(), {menu_geo.x + menu_geo.width, menu_geo.y})) |
1952 | + { |
1953 | + pointer_movement_timeout_ = std::make_shared<glib::Timeout>(MENU_OPEN_MOUSE_WAIT, [this, mouse, speed] { |
1954 | + if (active_tracker_) |
1955 | + active_tracker_(mouse.x, mouse.y, speed); |
1956 | + |
1957 | + return false; |
1958 | + }); |
1959 | + |
1960 | + return; |
1961 | + } |
1962 | + |
1963 | + if (active_tracker_) |
1964 | + { |
1965 | + pointer_movement_timeout_.reset(); |
1966 | + active_tracker_(mouse.x, mouse.y, speed); |
1967 | + } |
1968 | + } |
1969 | + |
1970 | + bool RegisterTracker(std::string const& menubar, PositionTracker const& cb) |
1971 | + { |
1972 | + auto it = position_trackers_.find(menubar); |
1973 | + |
1974 | + if (it != end(position_trackers_)) |
1975 | + return false; |
1976 | + |
1977 | + position_trackers_.insert({menubar, cb}); |
1978 | + |
1979 | + if (active_menubar_ == menubar) |
1980 | + UpdateActiveTracker(); |
1981 | + |
1982 | + return true; |
1983 | + } |
1984 | + |
1985 | + bool UnregisterTracker(std::string const& menubar, PositionTracker const& cb) |
1986 | + { |
1987 | + auto it = position_trackers_.find(menubar); |
1988 | + |
1989 | + if (it == end(position_trackers_)) |
1990 | + return false; |
1991 | + |
1992 | + if (!cb || (cb && it->second == cb)) |
1993 | + { |
1994 | + position_trackers_.erase(it); |
1995 | + return true; |
1996 | + } |
1997 | + |
1998 | + return false; |
1999 | + } |
2000 | + |
2001 | + void UpdateActiveTracker() |
2002 | + { |
2003 | + auto it = position_trackers_.find(active_menubar_); |
2004 | + active_tracker_ = (it != end(position_trackers_)) ? it->second : PositionTracker(); |
2005 | + pointer_movement_timeout_.reset(); |
2006 | + |
2007 | + if (active_tracker_) |
2008 | + { |
2009 | + if (input::Monitor::Get().RegisterClient(input::Events::POINTER, sigc::mem_fun(this, &Impl::OnActiveEntryEvent))) |
2010 | + last_pointer_time_ = 0; |
2011 | + } |
2012 | + else |
2013 | + { |
2014 | + input::Monitor::Get().UnregisterClient(sigc::mem_fun(this, &Impl::OnActiveEntryEvent)); |
2015 | + |
2016 | + if (it != end(position_trackers_)) |
2017 | + position_trackers_.erase(it); |
2018 | + } |
2019 | + } |
2020 | + |
2021 | Manager* parent_; |
2022 | Indicators::Ptr indicators_; |
2023 | AppmenuIndicator::Ptr appmenu_; |
2024 | key::Grabber::Ptr key_grabber_; |
2025 | Window show_now_window_; |
2026 | + std::string active_menubar_; |
2027 | + PositionTracker active_tracker_; |
2028 | + nux::Point tracked_pointer_pos_; |
2029 | + Time last_pointer_time_; |
2030 | + glib::Source::Ptr pointer_movement_timeout_; |
2031 | connection::Manager appmenu_connections_; |
2032 | connection::Wrapper active_win_conn_; |
2033 | glib::Object<GSettings> settings_; |
2034 | glib::SignalManager signals_; |
2035 | + std::unordered_map<std::string, PositionTracker> position_trackers_; |
2036 | std::unordered_map<indicator::Entry::Ptr, uint32_t> entry_actions_; |
2037 | }; |
2038 | |
2039 | @@ -278,5 +426,16 @@ |
2040 | return impl_->key_grabber_; |
2041 | } |
2042 | |
2043 | +bool Manager::RegisterTracker(std::string const& menubar, PositionTracker const& cb) |
2044 | +{ |
2045 | + return impl_->RegisterTracker(menubar, cb); |
2046 | +} |
2047 | + |
2048 | +bool Manager::UnregisterTracker(std::string const& menubar, PositionTracker const& cb) |
2049 | +{ |
2050 | + return impl_->UnregisterTracker(menubar, cb); |
2051 | +} |
2052 | + |
2053 | + |
2054 | } // menu namespace |
2055 | } // unity namespace |
2056 | |
2057 | === modified file 'unity-shared/MenuManager.h' |
2058 | --- unity-shared/MenuManager.h 2015-06-05 14:28:27 +0000 |
2059 | +++ unity-shared/MenuManager.h 2016-08-30 10:27:02 +0000 |
2060 | @@ -67,6 +67,10 @@ |
2061 | |
2062 | key::Grabber::Ptr const& KeyGrabber() const; |
2063 | |
2064 | + typedef sigc::slot<void, int /*x*/, int /*y*/, double /*speed*/> PositionTracker; |
2065 | + bool RegisterTracker(std::string const& menubar, PositionTracker const&); |
2066 | + bool UnregisterTracker(std::string const& menubar, PositionTracker const& = PositionTracker()); |
2067 | + |
2068 | sigc::signal<void> appmenu_added; |
2069 | sigc::signal<void> appmenu_removed; |
2070 | sigc::signal<bool>::accumulated<any_true> open_first; |
2071 | |
2072 | === added file 'unity-shared/SigcSlotHash.h' |
2073 | --- unity-shared/SigcSlotHash.h 1970-01-01 00:00:00 +0000 |
2074 | +++ unity-shared/SigcSlotHash.h 2016-08-30 10:27:02 +0000 |
2075 | @@ -0,0 +1,64 @@ |
2076 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
2077 | +/* |
2078 | + * Copyright (C) 2016 Canonical Ltd |
2079 | + * |
2080 | + * This program is free software: you can redistribute it and/or modify |
2081 | + * it under the terms of the GNU General Public License version 3 as |
2082 | + * published by the Free Software Foundation. |
2083 | + * |
2084 | + * This program is distributed in the hope that it will be useful, |
2085 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2086 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2087 | + * GNU General Public License for more details. |
2088 | + * |
2089 | + * You should have received a copy of the GNU General Public License |
2090 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2091 | + * |
2092 | + * Authored by: Marco Trevisan <marco.trevisan@canonical.com> |
2093 | + */ |
2094 | + |
2095 | +#ifndef __UNITY_SIGC_SLOT_HASHER__ |
2096 | +#define __UNITY_SIGC_SLOT_HASHER__ |
2097 | + |
2098 | +#include <sigc++/slot.h> |
2099 | + |
2100 | +namespace std |
2101 | +{ |
2102 | + |
2103 | +template<> |
2104 | +struct hash<sigc::slot_base> |
2105 | +{ |
2106 | + size_t operator()(sigc::slot_base const& cb) const |
2107 | + { |
2108 | + if (cb.rep_) |
2109 | + return hash<size_t>()(reinterpret_cast<size_t>(cb.rep_->call_)); |
2110 | + |
2111 | + return hash<size_t>()(reinterpret_cast<size_t>(cb.rep_)); |
2112 | + } |
2113 | +}; |
2114 | + |
2115 | +template<> |
2116 | +struct equal_to<sigc::slot_base> |
2117 | +{ |
2118 | + bool operator()(sigc::slot_base const& lhs, sigc::slot_base const& rhs) const |
2119 | + { |
2120 | + if (!lhs.rep_ || !rhs.rep_) |
2121 | + return (lhs.rep_ == rhs.rep_); |
2122 | + |
2123 | + return (lhs.rep_->call_ == rhs.rep_->call_); |
2124 | + } |
2125 | +}; |
2126 | + |
2127 | +template<class T> |
2128 | +struct hash |
2129 | +{ |
2130 | + size_t operator()(T const& cb) const |
2131 | + { |
2132 | + static_assert(std::is_base_of<sigc::slot_base, T>::value, "Type is not derived from sigc::slot_base"); |
2133 | + return hash<sigc::slot_base>()(cb); |
2134 | + } |
2135 | +}; |
2136 | + |
2137 | +} // std namespace |
2138 | + |
2139 | +#endif // __UNITY_SIGC_SLOT_HASHER__ |
2140 | |
2141 | === modified file 'unity-shared/StandaloneWindowManager.cpp' |
2142 | --- unity-shared/StandaloneWindowManager.cpp 2015-11-20 11:33:38 +0000 |
2143 | +++ unity-shared/StandaloneWindowManager.cpp 2016-08-30 10:27:02 +0000 |
2144 | @@ -624,6 +624,9 @@ |
2145 | return std::string(); |
2146 | } |
2147 | |
2148 | +void StandaloneWindowManager::SetCardinalProperty(Window, Atom, std::vector<long> const&) |
2149 | +{} |
2150 | + |
2151 | std::vector<long> StandaloneWindowManager::GetCardinalProperty(Window, Atom) const |
2152 | { |
2153 | return std::vector<long>(); |
2154 | |
2155 | === modified file 'unity-shared/StandaloneWindowManager.h' |
2156 | --- unity-shared/StandaloneWindowManager.h 2016-03-18 18:58:26 +0000 |
2157 | +++ unity-shared/StandaloneWindowManager.h 2016-08-30 10:27:02 +0000 |
2158 | @@ -165,6 +165,7 @@ |
2159 | virtual std::string GetWindowName(Window window_id) const; |
2160 | virtual bool IsOnscreenKeyboard(Window window_id) const; |
2161 | virtual std::string GetStringProperty(Window window_id, Atom) const; |
2162 | + virtual void SetCardinalProperty(Window window_id, Atom, std::vector<long> const&); |
2163 | virtual std::vector<long> GetCardinalProperty(Window window_id, Atom) const; |
2164 | |
2165 | // Mock functions |
2166 | |
2167 | === modified file 'unity-shared/WindowManager.h' |
2168 | --- unity-shared/WindowManager.h 2016-03-18 18:58:26 +0000 |
2169 | +++ unity-shared/WindowManager.h 2016-08-30 10:27:02 +0000 |
2170 | @@ -170,6 +170,7 @@ |
2171 | virtual bool IsOnscreenKeyboard(Window window_id) const = 0; |
2172 | |
2173 | virtual std::string GetStringProperty(Window, Atom) const = 0; |
2174 | + virtual void SetCardinalProperty(Window, Atom, std::vector<long> const&) = 0; |
2175 | virtual std::vector<long> GetCardinalProperty(Window, Atom) const = 0; |
2176 | |
2177 | virtual Cursor GetCachedCursor(unsigned int cursor_name) const = 0; |
2178 | |
2179 | === modified file 'unity-shared/XWindowManager.cpp' |
2180 | --- unity-shared/XWindowManager.cpp 2015-01-21 15:28:59 +0000 |
2181 | +++ unity-shared/XWindowManager.cpp 2016-08-30 10:27:02 +0000 |
2182 | @@ -123,6 +123,12 @@ |
2183 | return std::string(val, n_items); |
2184 | } |
2185 | |
2186 | +void XWindowManager::SetCardinalProperty(Window window_id, Atom atom, std::vector<long> const& values) |
2187 | +{ |
2188 | + XChangeProperty(screen->dpy(), window_id, atom, XA_CARDINAL, 32, PropModeReplace, |
2189 | + (unsigned char *) values.data(), values.size()); |
2190 | +} |
2191 | + |
2192 | std::vector<long> XWindowManager::GetCardinalProperty(Window window_id, Atom atom) const |
2193 | { |
2194 | Atom type; |
2195 | |
2196 | === modified file 'unity-shared/XWindowManager.h' |
2197 | --- unity-shared/XWindowManager.h 2015-01-21 15:28:59 +0000 |
2198 | +++ unity-shared/XWindowManager.h 2016-08-30 10:27:02 +0000 |
2199 | @@ -36,6 +36,7 @@ |
2200 | std::string GetWindowName(Window window_id) const; |
2201 | bool IsOnscreenKeyboard(Window window_id) const; |
2202 | std::string GetStringProperty(Window window_id, Atom atom) const; |
2203 | + void SetCardinalProperty(Window, Atom, std::vector<long> const&); |
2204 | std::vector<long> GetCardinalProperty(Window, Atom) const; |
2205 | }; |
2206 |