• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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/window_targeter.h"
6 
7 #include "ui/aura/client/capture_client.h"
8 #include "ui/aura/client/event_client.h"
9 #include "ui/aura/client/focus_client.h"
10 #include "ui/aura/window.h"
11 #include "ui/aura/window_delegate.h"
12 #include "ui/aura/window_event_dispatcher.h"
13 #include "ui/aura/window_tree_host.h"
14 #include "ui/events/event_target.h"
15 
16 namespace aura {
17 
WindowTargeter()18 WindowTargeter::WindowTargeter() {}
~WindowTargeter()19 WindowTargeter::~WindowTargeter() {}
20 
FindTargetForEvent(ui::EventTarget * root,ui::Event * event)21 ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
22                                                     ui::Event* event) {
23   Window* window = static_cast<Window*>(root);
24   Window* target = event->IsKeyEvent() ?
25       FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event)) :
26       static_cast<Window*>(EventTargeter::FindTargetForEvent(root, event));
27   if (target && !window->parent()) {
28     // |window| is the root window.
29     if (!window->Contains(target)) {
30       // |target| is not a descendent of |window|. So do not allow dispatching
31       // from here. Instead, dispatch the event through the
32       // WindowEventDispatcher that owns |target|.
33       ui::EventDispatchDetails details ALLOW_UNUSED =
34           target->GetHost()->event_processor()->OnEventFromSource(event);
35       target = NULL;
36     }
37   }
38   return target;
39 }
40 
SubtreeCanAcceptEvent(ui::EventTarget * target,const ui::LocatedEvent & event) const41 bool WindowTargeter::SubtreeCanAcceptEvent(
42     ui::EventTarget* target,
43     const ui::LocatedEvent& event) const {
44   aura::Window* window = static_cast<aura::Window*>(target);
45   if (!window->IsVisible())
46     return false;
47   if (window->ignore_events())
48     return false;
49   client::EventClient* client = client::GetEventClient(window->GetRootWindow());
50   if (client && !client->CanProcessEventsWithinSubtree(window))
51     return false;
52 
53   Window* parent = window->parent();
54   if (parent && parent->delegate_ && !parent->delegate_->
55       ShouldDescendIntoChildForEventHandling(window, event.location())) {
56     return false;
57   }
58   return true;
59 }
60 
EventLocationInsideBounds(ui::EventTarget * target,const ui::LocatedEvent & event) const61 bool WindowTargeter::EventLocationInsideBounds(
62     ui::EventTarget* target,
63     const ui::LocatedEvent& event) const {
64   aura::Window* window = static_cast<aura::Window*>(target);
65   gfx::Point point = event.location();
66   if (window->parent())
67     aura::Window::ConvertPointToTarget(window->parent(), window, &point);
68   return gfx::Rect(window->bounds().size()).Contains(point);
69 }
70 
FindTargetForLocatedEvent(ui::EventTarget * root,ui::LocatedEvent * event)71 ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent(
72     ui::EventTarget* root,
73     ui::LocatedEvent* event) {
74   Window* window = static_cast<Window*>(root);
75   if (!window->parent()) {
76     Window* target = FindTargetInRootWindow(window, *event);
77     if (target) {
78       window->ConvertEventToTarget(target, event);
79       return target;
80     }
81   }
82   return EventTargeter::FindTargetForLocatedEvent(root, event);
83 }
84 
FindTargetForKeyEvent(Window * window,const ui::KeyEvent & key)85 Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
86                                               const ui::KeyEvent& key) {
87   Window* root_window = window->GetRootWindow();
88   if (key.key_code() == ui::VKEY_UNKNOWN &&
89       (key.flags() & ui::EF_IME_FABRICATED_KEY) == 0 &&
90       key.GetCharacter() == 0)
91     return NULL;
92   client::FocusClient* focus_client = client::GetFocusClient(root_window);
93   Window* focused_window = focus_client->GetFocusedWindow();
94   if (!focused_window)
95     return window;
96 
97   client::EventClient* event_client = client::GetEventClient(root_window);
98   if (event_client &&
99       !event_client->CanProcessEventsWithinSubtree(focused_window)) {
100     focus_client->FocusWindow(NULL);
101     return NULL;
102   }
103   return focused_window ? focused_window : window;
104 }
105 
FindTargetInRootWindow(Window * root_window,const ui::LocatedEvent & event)106 Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
107                                                const ui::LocatedEvent& event) {
108   DCHECK_EQ(root_window, root_window->GetRootWindow());
109 
110   // Mouse events should be dispatched to the window that processed the
111   // mouse-press events (if any).
112   if (event.IsScrollEvent() || event.IsMouseEvent()) {
113     WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher();
114     if (dispatcher->mouse_pressed_handler())
115       return dispatcher->mouse_pressed_handler();
116   }
117 
118   // All events should be directed towards the capture window (if any).
119   Window* capture_window = client::GetCaptureWindow(root_window);
120   if (capture_window)
121     return capture_window;
122 
123   if (event.IsTouchEvent()) {
124     // Query the gesture-recognizer to find targets for touch events.
125     const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event);
126     ui::GestureConsumer* consumer =
127         ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch);
128     if (consumer)
129       return static_cast<Window*>(consumer);
130     consumer =
131         ui::GestureRecognizer::Get()->GetTargetForLocation(
132             event.location(), touch.source_device_id());
133     if (consumer)
134       return static_cast<Window*>(consumer);
135 
136     // If the initial touch is outside the root window, target the root.
137     if (!root_window->bounds().Contains(event.location()))
138       return root_window;
139   }
140 
141   return NULL;
142 }
143 
144 }  // namespace aura
145