Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(831)

Side by Side Diff: ui/aura/root_window.cc

Issue 174803002: Move root_window.* to window_event_dispatcher.* (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/aura/root_window.h ('k') | ui/aura/root_window_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/aura/root_window.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/client/cursor_client.h"
16 #include "ui/aura/client/event_client.h"
17 #include "ui/aura/client/focus_client.h"
18 #include "ui/aura/client/screen_position_client.h"
19 #include "ui/aura/env.h"
20 #include "ui/aura/root_window_observer.h"
21 #include "ui/aura/window.h"
22 #include "ui/aura/window_delegate.h"
23 #include "ui/aura/window_targeter.h"
24 #include "ui/aura/window_tracker.h"
25 #include "ui/aura/window_tree_host.h"
26 #include "ui/base/hit_test.h"
27 #include "ui/base/view_prop.h"
28 #include "ui/compositor/dip_util.h"
29 #include "ui/compositor/layer.h"
30 #include "ui/compositor/layer_animator.h"
31 #include "ui/events/event.h"
32 #include "ui/events/gestures/gesture_recognizer.h"
33 #include "ui/events/gestures/gesture_types.h"
34 #include "ui/gfx/screen.h"
35
36 using std::vector;
37
38 typedef ui::EventDispatchDetails DispatchDetails;
39
40 namespace aura {
41
42 namespace {
43
44 const char kRootWindowForAcceleratedWidget[] =
45 "__AURA_ROOT_WINDOW_ACCELERATED_WIDGET__";
46
47 // Returns true if |target| has a non-client (frame) component at |location|,
48 // in window coordinates.
49 bool IsNonClientLocation(Window* target, const gfx::Point& location) {
50 if (!target->delegate())
51 return false;
52 int hit_test_code = target->delegate()->GetNonClientComponent(location);
53 return hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE;
54 }
55
56 Window* ConsumerToWindow(ui::GestureConsumer* consumer) {
57 return consumer ? static_cast<Window*>(consumer) : NULL;
58 }
59
60 void SetLastMouseLocation(const Window* root_window,
61 const gfx::Point& location_in_root) {
62 client::ScreenPositionClient* client =
63 client::GetScreenPositionClient(root_window);
64 if (client) {
65 gfx::Point location_in_screen = location_in_root;
66 client->ConvertPointToScreen(root_window, &location_in_screen);
67 Env::GetInstance()->set_last_mouse_location(location_in_screen);
68 } else {
69 Env::GetInstance()->set_last_mouse_location(location_in_root);
70 }
71 }
72
73 WindowTreeHost* CreateHost(WindowEventDispatcher* dispatcher,
74 const WindowEventDispatcher::CreateParams& params) {
75 WindowTreeHost* host = params.host ?
76 params.host : WindowTreeHost::Create(params.initial_bounds);
77 host->set_delegate(dispatcher);
78 return host;
79 }
80
81 bool IsEventCandidateForHold(const ui::Event& event) {
82 if (event.type() == ui::ET_TOUCH_MOVED)
83 return true;
84 if (event.type() == ui::ET_MOUSE_DRAGGED)
85 return true;
86 if (event.IsMouseEvent() && (event.flags() & ui::EF_IS_SYNTHESIZED))
87 return true;
88 return false;
89 }
90
91 } // namespace
92
93 WindowEventDispatcher::CreateParams::CreateParams(
94 const gfx::Rect& a_initial_bounds)
95 : initial_bounds(a_initial_bounds),
96 host(NULL) {
97 }
98
99 ////////////////////////////////////////////////////////////////////////////////
100 // WindowEventDispatcher, public:
101
102 WindowEventDispatcher::WindowEventDispatcher(const CreateParams& params)
103 : window_(new Window(NULL)),
104 host_(CreateHost(this, params)),
105 touch_ids_down_(0),
106 mouse_pressed_handler_(NULL),
107 mouse_moved_handler_(NULL),
108 event_dispatch_target_(NULL),
109 old_dispatch_target_(NULL),
110 synthesize_mouse_move_(false),
111 move_hold_count_(0),
112 dispatching_held_event_(false),
113 repost_event_factory_(this),
114 held_event_factory_(this) {
115 window()->set_dispatcher(this);
116 window()->SetName("RootWindow");
117 window()->SetEventTargeter(
118 scoped_ptr<ui::EventTargeter>(new WindowTargeter()));
119
120 prop_.reset(new ui::ViewProp(host_->GetAcceleratedWidget(),
121 kRootWindowForAcceleratedWidget,
122 this));
123 ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
124 }
125
126 WindowEventDispatcher::~WindowEventDispatcher() {
127 TRACE_EVENT0("shutdown", "WindowEventDispatcher::Destructor");
128
129 ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
130
131 // An observer may have been added by an animation on the
132 // WindowEventDispatcher.
133 window()->layer()->GetAnimator()->RemoveObserver(this);
134
135 // Destroy child windows while we're still valid. This is also done by
136 // ~Window, but by that time any calls to virtual methods overriden here (such
137 // as GetRootWindow()) result in Window's implementation. By destroying here
138 // we ensure GetRootWindow() still returns this.
139 window()->RemoveOrDestroyChildren();
140
141 // Destroying/removing child windows may try to access |host_| (eg.
142 // GetAcceleratedWidget())
143 host_.reset(NULL);
144
145 window()->set_dispatcher(NULL);
146 }
147
148 // static
149 WindowEventDispatcher* WindowEventDispatcher::GetForAcceleratedWidget(
150 gfx::AcceleratedWidget widget) {
151 return reinterpret_cast<WindowEventDispatcher*>(
152 ui::ViewProp::GetValue(widget, kRootWindowForAcceleratedWidget));
153 }
154
155 void WindowEventDispatcher::PrepareForShutdown() {
156 host_->PrepareForShutdown();
157 // discard synthesize event request as well.
158 synthesize_mouse_move_ = false;
159 }
160
161 void WindowEventDispatcher::RepostEvent(const ui::LocatedEvent& event) {
162 DCHECK(event.type() == ui::ET_MOUSE_PRESSED ||
163 event.type() == ui::ET_GESTURE_TAP_DOWN);
164 // We allow for only one outstanding repostable event. This is used
165 // in exiting context menus. A dropped repost request is allowed.
166 if (event.type() == ui::ET_MOUSE_PRESSED) {
167 held_repostable_event_.reset(
168 new ui::MouseEvent(
169 static_cast<const ui::MouseEvent&>(event),
170 static_cast<aura::Window*>(event.target()),
171 window()));
172 base::MessageLoop::current()->PostNonNestableTask(
173 FROM_HERE, base::Bind(
174 base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents),
175 repost_event_factory_.GetWeakPtr()));
176 } else {
177 DCHECK(event.type() == ui::ET_GESTURE_TAP_DOWN);
178 held_repostable_event_.reset();
179 // TODO(rbyers): Reposing of gestures is tricky to get
180 // right, so it's not yet supported. crbug.com/170987.
181 }
182 }
183
184 WindowTreeHostDelegate* WindowEventDispatcher::AsWindowTreeHostDelegate() {
185 return this;
186 }
187
188 void WindowEventDispatcher::OnMouseEventsEnableStateChanged(bool enabled) {
189 // Send entered / exited so that visual state can be updated to match
190 // mouse events state.
191 PostMouseMoveEventAfterWindowChange();
192 // TODO(mazda): Add code to disable mouse events when |enabled| == false.
193 }
194
195 Window* WindowEventDispatcher::GetGestureTarget(ui::GestureEvent* event) {
196 Window* target = NULL;
197 if (!event->IsEndingEvent()) {
198 // The window that received the start event (e.g. scroll begin) needs to
199 // receive the end event (e.g. scroll end).
200 target = client::GetCaptureWindow(window());
201 }
202 if (!target) {
203 target = ConsumerToWindow(
204 ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event));
205 }
206
207 return target;
208 }
209
210 void WindowEventDispatcher::DispatchGestureEvent(ui::GestureEvent* event) {
211 DispatchDetails details = DispatchHeldEvents();
212 if (details.dispatcher_destroyed)
213 return;
214
215 Window* target = GetGestureTarget(event);
216 if (target) {
217 event->ConvertLocationToTarget(window(), target);
218 DispatchDetails details = DispatchEvent(target, event);
219 if (details.dispatcher_destroyed)
220 return;
221 }
222 }
223
224 void WindowEventDispatcher::OnWindowDestroying(Window* window) {
225 DispatchMouseExitToHidingWindow(window);
226 if (window->IsVisible() &&
227 window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
228 PostMouseMoveEventAfterWindowChange();
229 }
230
231 // Hiding the window releases capture which can implicitly destroy the window
232 // so the window may no longer be valid after this call.
233 OnWindowHidden(window, WINDOW_DESTROYED);
234 }
235
236 void WindowEventDispatcher::OnWindowBoundsChanged(Window* window,
237 bool contained_mouse_point) {
238 if (contained_mouse_point ||
239 (window->IsVisible() &&
240 window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
241 PostMouseMoveEventAfterWindowChange();
242 }
243 }
244
245 void WindowEventDispatcher::DispatchMouseExitToHidingWindow(Window* window) {
246 // The mouse capture is intentionally ignored. Think that a mouse enters
247 // to a window, the window sets the capture, the mouse exits the window,
248 // and then it releases the capture. In that case OnMouseExited won't
249 // be called. So it is natural not to emit OnMouseExited even though
250 // |window| is the capture window.
251 gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
252 if (window->Contains(mouse_moved_handler_) &&
253 window->ContainsPointInRoot(last_mouse_location))
254 DispatchMouseExitAtPoint(last_mouse_location);
255 }
256
257 void WindowEventDispatcher::DispatchMouseExitAtPoint(const gfx::Point& point) {
258 ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE,
259 ui::EF_NONE);
260 DispatchDetails details =
261 DispatchMouseEnterOrExit(event, ui::ET_MOUSE_EXITED);
262 if (details.dispatcher_destroyed)
263 return;
264 }
265
266 void WindowEventDispatcher::OnWindowVisibilityChanged(Window* window,
267 bool is_visible) {
268 if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
269 PostMouseMoveEventAfterWindowChange();
270
271 // Hiding the window releases capture which can implicitly destroy the window
272 // so the window may no longer be valid after this call.
273 if (!is_visible)
274 OnWindowHidden(window, WINDOW_HIDDEN);
275 }
276
277 void WindowEventDispatcher::OnWindowTransformed(Window* window,
278 bool contained_mouse) {
279 if (contained_mouse ||
280 (window->IsVisible() &&
281 window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
282 PostMouseMoveEventAfterWindowChange();
283 }
284 }
285
286 void WindowEventDispatcher::OnKeyboardMappingChanged() {
287 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
288 OnKeyboardMappingChanged(this));
289 }
290
291 void WindowEventDispatcher::OnWindowTreeHostCloseRequested() {
292 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
293 OnWindowTreeHostCloseRequested(this));
294 }
295
296 void WindowEventDispatcher::AddRootWindowObserver(
297 RootWindowObserver* observer) {
298 observers_.AddObserver(observer);
299 }
300
301 void WindowEventDispatcher::RemoveRootWindowObserver(
302 RootWindowObserver* observer) {
303 observers_.RemoveObserver(observer);
304 }
305
306 void WindowEventDispatcher::ProcessedTouchEvent(ui::TouchEvent* event,
307 Window* window,
308 ui::EventResult result) {
309 scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
310 gestures.reset(ui::GestureRecognizer::Get()->
311 ProcessTouchEventForGesture(*event, result, window));
312 DispatchDetails details = ProcessGestures(gestures.get());
313 if (details.dispatcher_destroyed)
314 return;
315 }
316
317 void WindowEventDispatcher::HoldPointerMoves() {
318 if (!move_hold_count_)
319 held_event_factory_.InvalidateWeakPtrs();
320 ++move_hold_count_;
321 TRACE_EVENT_ASYNC_BEGIN0("ui", "WindowEventDispatcher::HoldPointerMoves",
322 this);
323 }
324
325 void WindowEventDispatcher::ReleasePointerMoves() {
326 --move_hold_count_;
327 DCHECK_GE(move_hold_count_, 0);
328 if (!move_hold_count_ && held_move_event_) {
329 // We don't want to call DispatchHeldEvents directly, because this might be
330 // called from a deep stack while another event, in which case dispatching
331 // another one may not be safe/expected. Instead we post a task, that we
332 // may cancel if HoldPointerMoves is called again before it executes.
333 base::MessageLoop::current()->PostNonNestableTask(
334 FROM_HERE, base::Bind(
335 base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents),
336 held_event_factory_.GetWeakPtr()));
337 }
338 TRACE_EVENT_ASYNC_END0("ui", "WindowEventDispatcher::HoldPointerMoves", this);
339 }
340
341 gfx::Point WindowEventDispatcher::GetLastMouseLocationInRoot() const {
342 gfx::Point location = Env::GetInstance()->last_mouse_location();
343 client::ScreenPositionClient* client =
344 client::GetScreenPositionClient(window());
345 if (client)
346 client->ConvertPointFromScreen(window(), &location);
347 return location;
348 }
349
350 ////////////////////////////////////////////////////////////////////////////////
351 // WindowEventDispatcher, private:
352
353 void WindowEventDispatcher::TransformEventForDeviceScaleFactor(
354 ui::LocatedEvent* event) {
355 event->UpdateForRootTransform(host()->GetInverseRootTransform());
356 }
357
358 ui::EventDispatchDetails WindowEventDispatcher::DispatchMouseEnterOrExit(
359 const ui::MouseEvent& event,
360 ui::EventType type) {
361 if (event.type() != ui::ET_MOUSE_CAPTURE_CHANGED &&
362 !(event.flags() & ui::EF_IS_SYNTHESIZED)) {
363 SetLastMouseLocation(window(), event.root_location());
364 }
365
366 if (!mouse_moved_handler_ || !mouse_moved_handler_->delegate())
367 return DispatchDetails();
368
369 // |event| may be an event in the process of being dispatched to a target (in
370 // which case its locations will be in the event's target's coordinate
371 // system), or a synthetic event created in root-window (in which case, the
372 // event's target will be NULL, and the event will be in the root-window's
373 // coordinate system.
374 aura::Window* target = static_cast<Window*>(event.target());
375 if (!target)
376 target = window();
377 ui::MouseEvent translated_event(event,
378 target,
379 mouse_moved_handler_,
380 type,
381 event.flags() | ui::EF_IS_SYNTHESIZED);
382 return DispatchEvent(mouse_moved_handler_, &translated_event);
383 }
384
385 ui::EventDispatchDetails WindowEventDispatcher::ProcessGestures(
386 ui::GestureRecognizer::Gestures* gestures) {
387 DispatchDetails details;
388 if (!gestures || gestures->empty())
389 return details;
390
391 Window* target = GetGestureTarget(gestures->get().at(0));
392 for (size_t i = 0; i < gestures->size(); ++i) {
393 ui::GestureEvent* event = gestures->get().at(i);
394 event->ConvertLocationToTarget(window(), target);
395 details = DispatchEvent(target, event);
396 if (details.dispatcher_destroyed || details.target_destroyed)
397 break;
398 }
399 return details;
400 }
401
402 void WindowEventDispatcher::OnWindowAddedToRootWindow(Window* attached) {
403 if (attached->IsVisible() &&
404 attached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
405 PostMouseMoveEventAfterWindowChange();
406 }
407 }
408
409 void WindowEventDispatcher::OnWindowRemovedFromRootWindow(Window* detached,
410 Window* new_root) {
411 DCHECK(aura::client::GetCaptureWindow(window()) != window());
412
413 DispatchMouseExitToHidingWindow(detached);
414 if (detached->IsVisible() &&
415 detached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
416 PostMouseMoveEventAfterWindowChange();
417 }
418
419 // Hiding the window releases capture which can implicitly destroy the window
420 // so the window may no longer be valid after this call.
421 OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
422 }
423
424 void WindowEventDispatcher::OnWindowHidden(Window* invisible,
425 WindowHiddenReason reason) {
426 // If the window the mouse was pressed in becomes invisible, it should no
427 // longer receive mouse events.
428 if (invisible->Contains(mouse_pressed_handler_))
429 mouse_pressed_handler_ = NULL;
430 if (invisible->Contains(mouse_moved_handler_))
431 mouse_moved_handler_ = NULL;
432
433 CleanupGestureState(invisible);
434
435 // Do not clear the capture, and the |event_dispatch_target_| if the
436 // window is moving across root windows, because the target itself
437 // is actually still visible and clearing them stops further event
438 // processing, which can cause unexpected behaviors. See
439 // crbug.com/157583
440 if (reason != WINDOW_MOVING) {
441 Window* capture_window = aura::client::GetCaptureWindow(window());
442
443 if (invisible->Contains(event_dispatch_target_))
444 event_dispatch_target_ = NULL;
445
446 if (invisible->Contains(old_dispatch_target_))
447 old_dispatch_target_ = NULL;
448
449 // If the ancestor of the capture window is hidden, release the capture.
450 // Note that this may delete the window so do not use capture_window
451 // after this.
452 if (invisible->Contains(capture_window) && invisible != window())
453 capture_window->ReleaseCapture();
454 }
455 }
456
457 void WindowEventDispatcher::CleanupGestureState(Window* window) {
458 ui::GestureRecognizer::Get()->CancelActiveTouches(window);
459 ui::GestureRecognizer::Get()->CleanupStateForConsumer(window);
460 const Window::Windows& windows = window->children();
461 for (Window::Windows::const_iterator iter = windows.begin();
462 iter != windows.end();
463 ++iter) {
464 CleanupGestureState(*iter);
465 }
466 }
467
468 ////////////////////////////////////////////////////////////////////////////////
469 // WindowEventDispatcher, aura::client::CaptureDelegate implementation:
470
471 void WindowEventDispatcher::UpdateCapture(Window* old_capture,
472 Window* new_capture) {
473 // |mouse_moved_handler_| may have been set to a Window in a different root
474 // (see below). Clear it here to ensure we don't end up referencing a stale
475 // Window.
476 if (mouse_moved_handler_ && !window()->Contains(mouse_moved_handler_))
477 mouse_moved_handler_ = NULL;
478
479 if (old_capture && old_capture->GetRootWindow() == window() &&
480 old_capture->delegate()) {
481 // Send a capture changed event with bogus location data.
482 ui::MouseEvent event(ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(),
483 gfx::Point(), 0, 0);
484
485 DispatchDetails details = DispatchEvent(old_capture, &event);
486 if (details.dispatcher_destroyed)
487 return;
488
489 old_capture->delegate()->OnCaptureLost();
490 }
491
492 if (new_capture) {
493 // Make all subsequent mouse events go to the capture window. We shouldn't
494 // need to send an event here as OnCaptureLost() should take care of that.
495 if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown())
496 mouse_moved_handler_ = new_capture;
497 } else {
498 // Make sure mouse_moved_handler gets updated.
499 DispatchDetails details = SynthesizeMouseMoveEvent();
500 if (details.dispatcher_destroyed)
501 return;
502 }
503 mouse_pressed_handler_ = NULL;
504 }
505
506 void WindowEventDispatcher::OnOtherRootGotCapture() {
507 mouse_moved_handler_ = NULL;
508 mouse_pressed_handler_ = NULL;
509 }
510
511 void WindowEventDispatcher::SetNativeCapture() {
512 host_->SetCapture();
513 }
514
515 void WindowEventDispatcher::ReleaseNativeCapture() {
516 host_->ReleaseCapture();
517 }
518
519 ////////////////////////////////////////////////////////////////////////////////
520 // WindowEventDispatcher, ui::EventProcessor implementation:
521 ui::EventTarget* WindowEventDispatcher::GetRootTarget() {
522 return window();
523 }
524
525 void WindowEventDispatcher::PrepareEventForDispatch(ui::Event* event) {
526 if (dispatching_held_event_) {
527 // The held events are already in |window()|'s coordinate system. So it is
528 // not necessary to apply the transform to convert from the host's
529 // coordinate system to |window()|'s coordinate system.
530 return;
531 }
532 if (event->IsMouseEvent() ||
533 event->IsScrollEvent() ||
534 event->IsTouchEvent() ||
535 event->IsGestureEvent()) {
536 TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event));
537 }
538 }
539
540 ////////////////////////////////////////////////////////////////////////////////
541 // WindowEventDispatcher, ui::EventDispatcherDelegate implementation:
542
543 bool WindowEventDispatcher::CanDispatchToTarget(ui::EventTarget* target) {
544 return event_dispatch_target_ == target;
545 }
546
547 ui::EventDispatchDetails WindowEventDispatcher::PreDispatchEvent(
548 ui::EventTarget* target,
549 ui::Event* event) {
550 if (!dispatching_held_event_) {
551 bool can_be_held = IsEventCandidateForHold(*event);
552 if (!move_hold_count_ || !can_be_held) {
553 if (can_be_held)
554 held_move_event_.reset();
555 DispatchDetails details = DispatchHeldEvents();
556 if (details.dispatcher_destroyed || details.target_destroyed)
557 return details;
558 }
559 }
560
561 Window* target_window = static_cast<Window*>(target);
562 if (event->IsMouseEvent()) {
563 PreDispatchMouseEvent(target_window, static_cast<ui::MouseEvent*>(event));
564 } else if (event->IsScrollEvent()) {
565 PreDispatchLocatedEvent(target_window,
566 static_cast<ui::ScrollEvent*>(event));
567 } else if (event->IsTouchEvent()) {
568 PreDispatchTouchEvent(target_window, static_cast<ui::TouchEvent*>(event));
569 }
570 old_dispatch_target_ = event_dispatch_target_;
571 event_dispatch_target_ = static_cast<Window*>(target);
572 return DispatchDetails();
573 }
574
575 ui::EventDispatchDetails WindowEventDispatcher::PostDispatchEvent(
576 ui::EventTarget* target,
577 const ui::Event& event) {
578 DispatchDetails details;
579 if (target != event_dispatch_target_)
580 details.target_destroyed = true;
581 event_dispatch_target_ = old_dispatch_target_;
582 old_dispatch_target_ = NULL;
583 #ifndef NDEBUG
584 DCHECK(!event_dispatch_target_ || window()->Contains(event_dispatch_target_));
585 #endif
586
587 if (event.IsTouchEvent() && !details.target_destroyed) {
588 // Do not let 'held' touch events contribute to any gestures.
589 if (!held_move_event_ || !held_move_event_->IsTouchEvent()) {
590 ui::TouchEvent orig_event(static_cast<const ui::TouchEvent&>(event),
591 static_cast<Window*>(event.target()), window());
592 // Get the list of GestureEvents from GestureRecognizer.
593 scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
594 gestures.reset(ui::GestureRecognizer::Get()->
595 ProcessTouchEventForGesture(orig_event, event.result(),
596 static_cast<Window*>(target)));
597 return ProcessGestures(gestures.get());
598 }
599 }
600
601 return details;
602 }
603
604 ////////////////////////////////////////////////////////////////////////////////
605 // WindowEventDispatcher, ui::GestureEventHelper implementation:
606
607 bool WindowEventDispatcher::CanDispatchToConsumer(
608 ui::GestureConsumer* consumer) {
609 Window* consumer_window = ConsumerToWindow(consumer);;
610 return (consumer_window && consumer_window->GetRootWindow() == window());
611 }
612
613 void WindowEventDispatcher::DispatchPostponedGestureEvent(
614 ui::GestureEvent* event) {
615 DispatchGestureEvent(event);
616 }
617
618 void WindowEventDispatcher::DispatchCancelTouchEvent(ui::TouchEvent* event) {
619 DispatchDetails details = OnEventFromSource(event);
620 if (details.dispatcher_destroyed)
621 return;
622 }
623
624 ////////////////////////////////////////////////////////////////////////////////
625 // WindowEventDispatcher, ui::LayerAnimationObserver implementation:
626
627 void WindowEventDispatcher::OnLayerAnimationEnded(
628 ui::LayerAnimationSequence* animation) {
629 host()->UpdateRootWindowSize(host_->GetBounds().size());
630 }
631
632 void WindowEventDispatcher::OnLayerAnimationScheduled(
633 ui::LayerAnimationSequence* animation) {
634 }
635
636 void WindowEventDispatcher::OnLayerAnimationAborted(
637 ui::LayerAnimationSequence* animation) {
638 }
639
640 ////////////////////////////////////////////////////////////////////////////////
641 // WindowEventDispatcher, WindowTreeHostDelegate implementation:
642
643 void WindowEventDispatcher::OnHostCancelMode() {
644 ui::CancelModeEvent event;
645 Window* focused_window = client::GetFocusClient(window())->GetFocusedWindow();
646 DispatchDetails details =
647 DispatchEvent(focused_window ? focused_window : window(), &event);
648 if (details.dispatcher_destroyed)
649 return;
650 }
651
652 void WindowEventDispatcher::OnHostActivated() {
653 Env::GetInstance()->RootWindowActivated(this);
654 }
655
656 void WindowEventDispatcher::OnHostLostWindowCapture() {
657 Window* capture_window = client::GetCaptureWindow(window());
658 if (capture_window && capture_window->GetRootWindow() == window())
659 capture_window->ReleaseCapture();
660 }
661
662 void WindowEventDispatcher::OnHostLostMouseGrab() {
663 mouse_pressed_handler_ = NULL;
664 mouse_moved_handler_ = NULL;
665 }
666
667 void WindowEventDispatcher::OnHostMoved(const gfx::Point& origin) {
668 TRACE_EVENT1("ui", "WindowEventDispatcher::OnHostMoved",
669 "origin", origin.ToString());
670
671 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
672 OnWindowTreeHostMoved(this, origin));
673 }
674
675 void WindowEventDispatcher::OnHostResized(const gfx::Size& size) {
676 TRACE_EVENT1("ui", "WindowEventDispatcher::OnHostResized",
677 "size", size.ToString());
678
679 DispatchDetails details = DispatchHeldEvents();
680 if (details.dispatcher_destroyed)
681 return;
682 FOR_EACH_OBSERVER(RootWindowObserver, observers_,
683 OnWindowTreeHostResized(this));
684
685 // Constrain the mouse position within the new root Window size.
686 gfx::Point point;
687 if (host_->QueryMouseLocation(&point)) {
688 SetLastMouseLocation(window(),
689 ui::ConvertPointToDIP(window()->layer(), point));
690 }
691 synthesize_mouse_move_ = false;
692 }
693
694 void WindowEventDispatcher::OnCursorMovedToRootLocation(
695 const gfx::Point& root_location) {
696 SetLastMouseLocation(window(), root_location);
697 synthesize_mouse_move_ = false;
698 }
699
700 WindowEventDispatcher* WindowEventDispatcher::AsDispatcher() {
701 return this;
702 }
703
704 const WindowEventDispatcher* WindowEventDispatcher::AsDispatcher() const {
705 return this;
706 }
707
708 ui::EventProcessor* WindowEventDispatcher::GetEventProcessor() {
709 return this;
710 }
711
712 ////////////////////////////////////////////////////////////////////////////////
713 // WindowEventDispatcher, private:
714
715 ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() {
716 if (!held_repostable_event_ && !held_move_event_)
717 return DispatchDetails();
718
719 CHECK(!dispatching_held_event_);
720 dispatching_held_event_ = true;
721
722 DispatchDetails dispatch_details;
723 if (held_repostable_event_) {
724 if (held_repostable_event_->type() == ui::ET_MOUSE_PRESSED) {
725 scoped_ptr<ui::MouseEvent> mouse_event(
726 static_cast<ui::MouseEvent*>(held_repostable_event_.release()));
727 dispatch_details = OnEventFromSource(mouse_event.get());
728 } else {
729 // TODO(rbyers): GESTURE_TAP_DOWN not yet supported: crbug.com/170987.
730 NOTREACHED();
731 }
732 if (dispatch_details.dispatcher_destroyed)
733 return dispatch_details;
734 }
735
736 if (held_move_event_) {
737 // If a mouse move has been synthesized, the target location is suspect,
738 // so drop the held mouse event.
739 if (held_move_event_->IsTouchEvent() ||
740 (held_move_event_->IsMouseEvent() && !synthesize_mouse_move_)) {
741 dispatch_details = OnEventFromSource(held_move_event_.get());
742 }
743 if (!dispatch_details.dispatcher_destroyed)
744 held_move_event_.reset();
745 }
746
747 if (!dispatch_details.dispatcher_destroyed)
748 dispatching_held_event_ = false;
749 return dispatch_details;
750 }
751
752 void WindowEventDispatcher::PostMouseMoveEventAfterWindowChange() {
753 if (synthesize_mouse_move_)
754 return;
755 synthesize_mouse_move_ = true;
756 base::MessageLoop::current()->PostNonNestableTask(
757 FROM_HERE,
758 base::Bind(base::IgnoreResult(
759 &WindowEventDispatcher::SynthesizeMouseMoveEvent),
760 held_event_factory_.GetWeakPtr()));
761 }
762
763 ui::EventDispatchDetails WindowEventDispatcher::SynthesizeMouseMoveEvent() {
764 DispatchDetails details;
765 if (!synthesize_mouse_move_)
766 return details;
767 synthesize_mouse_move_ = false;
768 gfx::Point root_mouse_location = GetLastMouseLocationInRoot();
769 if (!window()->bounds().Contains(root_mouse_location))
770 return details;
771 gfx::Point host_mouse_location = root_mouse_location;
772 host()->ConvertPointToHost(&host_mouse_location);
773 ui::MouseEvent event(ui::ET_MOUSE_MOVED,
774 host_mouse_location,
775 host_mouse_location,
776 ui::EF_IS_SYNTHESIZED,
777 0);
778 return OnEventFromSource(&event);
779 }
780
781 void WindowEventDispatcher::PreDispatchLocatedEvent(Window* target,
782 ui::LocatedEvent* event) {
783 int flags = event->flags();
784 if (IsNonClientLocation(target, event->location()))
785 flags |= ui::EF_IS_NON_CLIENT;
786 event->set_flags(flags);
787
788 if (!dispatching_held_event_ &&
789 (event->IsMouseEvent() || event->IsScrollEvent()) &&
790 !(event->flags() & ui::EF_IS_SYNTHESIZED)) {
791 if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)
792 SetLastMouseLocation(window(), event->root_location());
793 synthesize_mouse_move_ = false;
794 }
795 }
796
797 void WindowEventDispatcher::PreDispatchMouseEvent(Window* target,
798 ui::MouseEvent* event) {
799 client::CursorClient* cursor_client = client::GetCursorClient(window());
800 if (cursor_client &&
801 !cursor_client->IsMouseEventsEnabled() &&
802 (event->flags() & ui::EF_IS_SYNTHESIZED)) {
803 event->SetHandled();
804 return;
805 }
806
807 if (IsEventCandidateForHold(*event) && !dispatching_held_event_) {
808 if (move_hold_count_) {
809 if (!(event->flags() & ui::EF_IS_SYNTHESIZED) &&
810 event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) {
811 SetLastMouseLocation(window(), event->root_location());
812 }
813 held_move_event_.reset(new ui::MouseEvent(*event, target, window()));
814 event->SetHandled();
815 return;
816 } else {
817 // We may have a held event for a period between the time move_hold_count_
818 // fell to 0 and the DispatchHeldEvents executes. Since we're going to
819 // dispatch the new event directly below, we can reset the old one.
820 held_move_event_.reset();
821 }
822 }
823
824 const int kMouseButtonFlagMask = ui::EF_LEFT_MOUSE_BUTTON |
825 ui::EF_MIDDLE_MOUSE_BUTTON |
826 ui::EF_RIGHT_MOUSE_BUTTON;
827 switch (event->type()) {
828 case ui::ET_MOUSE_EXITED:
829 if (!target || target == window()) {
830 DispatchDetails details =
831 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
832 if (details.dispatcher_destroyed) {
833 event->SetHandled();
834 return;
835 }
836 mouse_moved_handler_ = NULL;
837 }
838 break;
839 case ui::ET_MOUSE_MOVED:
840 // Send an exit to the current |mouse_moved_handler_| and an enter to
841 // |target|. Take care that both us and |target| aren't destroyed during
842 // dispatch.
843 if (target != mouse_moved_handler_) {
844 aura::Window* old_mouse_moved_handler = mouse_moved_handler_;
845 WindowTracker live_window;
846 live_window.Add(target);
847 DispatchDetails details =
848 DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_EXITED);
849 if (details.dispatcher_destroyed) {
850 event->SetHandled();
851 return;
852 }
853 // If the |mouse_moved_handler_| changes out from under us, assume a
854 // nested message loop ran and we don't need to do anything.
855 if (mouse_moved_handler_ != old_mouse_moved_handler) {
856 event->SetHandled();
857 return;
858 }
859 if (!live_window.Contains(target) || details.target_destroyed) {
860 mouse_moved_handler_ = NULL;
861 event->SetHandled();
862 return;
863 }
864 live_window.Remove(target);
865
866 mouse_moved_handler_ = target;
867 details = DispatchMouseEnterOrExit(*event, ui::ET_MOUSE_ENTERED);
868 if (details.dispatcher_destroyed || details.target_destroyed) {
869 event->SetHandled();
870 return;
871 }
872 }
873 break;
874 case ui::ET_MOUSE_PRESSED:
875 // Don't set the mouse pressed handler for non client mouse down events.
876 // These are only sent by Windows and are not always followed with non
877 // client mouse up events which causes subsequent mouse events to be
878 // sent to the wrong target.
879 if (!(event->flags() & ui::EF_IS_NON_CLIENT) && !mouse_pressed_handler_)
880 mouse_pressed_handler_ = target;
881 Env::GetInstance()->set_mouse_button_flags(
882 event->flags() & kMouseButtonFlagMask);
883 break;
884 case ui::ET_MOUSE_RELEASED:
885 mouse_pressed_handler_ = NULL;
886 Env::GetInstance()->set_mouse_button_flags(event->flags() &
887 kMouseButtonFlagMask & ~event->changed_button_flags());
888 break;
889 default:
890 break;
891 }
892
893 PreDispatchLocatedEvent(target, event);
894 }
895
896 void WindowEventDispatcher::PreDispatchTouchEvent(Window* target,
897 ui::TouchEvent* event) {
898 switch (event->type()) {
899 case ui::ET_TOUCH_PRESSED:
900 touch_ids_down_ |= (1 << event->touch_id());
901 Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
902 break;
903
904 // Handle ET_TOUCH_CANCELLED only if it has a native event.
905 case ui::ET_TOUCH_CANCELLED:
906 if (!event->HasNativeEvent())
907 break;
908 // fallthrough
909 case ui::ET_TOUCH_RELEASED:
910 touch_ids_down_ = (touch_ids_down_ | (1 << event->touch_id())) ^
911 (1 << event->touch_id());
912 Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
913 break;
914
915 case ui::ET_TOUCH_MOVED:
916 if (move_hold_count_ && !dispatching_held_event_) {
917 held_move_event_.reset(new ui::TouchEvent(*event, target, window()));
918 event->SetHandled();
919 return;
920 }
921 break;
922
923 default:
924 NOTREACHED();
925 break;
926 }
927 PreDispatchLocatedEvent(target, event);
928 }
929
930 } // namespace aura
OLDNEW
« no previous file with comments | « ui/aura/root_window.h ('k') | ui/aura/root_window_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698