Home | History | Annotate | Download | only in aura
      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 
     18 namespace {
     19 
     20 bool IsLocatedEvent(const ui::Event& event) {
     21   return event.IsMouseEvent() || event.IsTouchEvent() ||
     22          event.IsScrollEvent() || event.IsGestureEvent();
     23 }
     24 
     25 }  // namespace
     26 
     27 WindowTargeter::WindowTargeter() {}
     28 WindowTargeter::~WindowTargeter() {}
     29 
     30 ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
     31                                                     ui::Event* event) {
     32   Window* window = static_cast<Window*>(root);
     33   Window* target = event->IsKeyEvent() ?
     34       FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event)) :
     35       static_cast<Window*>(EventTargeter::FindTargetForEvent(root, event));
     36   if (target && !window->parent() && !window->Contains(target)) {
     37     // |window| is the root window, but |target| is not a descendent of
     38     // |window|. So do not allow dispatching from here. Instead, dispatch the
     39     // event through the WindowEventDispatcher that owns |target|.
     40     aura::Window* new_root = target->GetRootWindow();
     41     if (IsLocatedEvent(*event)) {
     42       // The event has been transformed to be in |target|'s coordinate system.
     43       // But dispatching the event through the EventProcessor requires the event
     44       // to be in the host's coordinate system. So, convert the event to be in
     45       // the root's coordinate space, and then to the host's coordinate space by
     46       // applying the host's transform.
     47       ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event);
     48       located_event->ConvertLocationToTarget(target, new_root);
     49       located_event->UpdateForRootTransform(
     50           new_root->GetHost()->GetRootTransform());
     51     }
     52     ui::EventDispatchDetails details ALLOW_UNUSED =
     53         new_root->GetHost()->event_processor()->OnEventFromSource(event);
     54     target = NULL;
     55   }
     56   return target;
     57 }
     58 
     59 bool WindowTargeter::SubtreeCanAcceptEvent(
     60     ui::EventTarget* target,
     61     const ui::LocatedEvent& event) const {
     62   aura::Window* window = static_cast<aura::Window*>(target);
     63   if (!window->IsVisible())
     64     return false;
     65   if (window->ignore_events())
     66     return false;
     67   client::EventClient* client = client::GetEventClient(window->GetRootWindow());
     68   if (client && !client->CanProcessEventsWithinSubtree(window))
     69     return false;
     70 
     71   Window* parent = window->parent();
     72   if (parent && parent->delegate_ && !parent->delegate_->
     73       ShouldDescendIntoChildForEventHandling(window, event.location())) {
     74     return false;
     75   }
     76   return true;
     77 }
     78 
     79 bool WindowTargeter::EventLocationInsideBounds(
     80     ui::EventTarget* target,
     81     const ui::LocatedEvent& event) const {
     82   aura::Window* window = static_cast<aura::Window*>(target);
     83   gfx::Point point = event.location();
     84   if (window->parent())
     85     aura::Window::ConvertPointToTarget(window->parent(), window, &point);
     86   return gfx::Rect(window->bounds().size()).Contains(point);
     87 }
     88 
     89 ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent(
     90     ui::EventTarget* root,
     91     ui::LocatedEvent* event) {
     92   Window* window = static_cast<Window*>(root);
     93   if (!window->parent()) {
     94     Window* target = FindTargetInRootWindow(window, *event);
     95     if (target) {
     96       window->ConvertEventToTarget(target, event);
     97       return target;
     98     }
     99   }
    100   return EventTargeter::FindTargetForLocatedEvent(root, event);
    101 }
    102 
    103 Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
    104                                               const ui::KeyEvent& key) {
    105   Window* root_window = window->GetRootWindow();
    106   if (key.key_code() == ui::VKEY_UNKNOWN &&
    107       (key.flags() & ui::EF_IME_FABRICATED_KEY) == 0 &&
    108       key.GetCharacter() == 0)
    109     return NULL;
    110   client::FocusClient* focus_client = client::GetFocusClient(root_window);
    111   Window* focused_window = focus_client->GetFocusedWindow();
    112   if (!focused_window)
    113     return window;
    114 
    115   client::EventClient* event_client = client::GetEventClient(root_window);
    116   if (event_client &&
    117       !event_client->CanProcessEventsWithinSubtree(focused_window)) {
    118     focus_client->FocusWindow(NULL);
    119     return NULL;
    120   }
    121   return focused_window ? focused_window : window;
    122 }
    123 
    124 Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
    125                                                const ui::LocatedEvent& event) {
    126   DCHECK_EQ(root_window, root_window->GetRootWindow());
    127 
    128   // Mouse events should be dispatched to the window that processed the
    129   // mouse-press events (if any).
    130   if (event.IsScrollEvent() || event.IsMouseEvent()) {
    131     WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher();
    132     if (dispatcher->mouse_pressed_handler())
    133       return dispatcher->mouse_pressed_handler();
    134   }
    135 
    136   // All events should be directed towards the capture window (if any).
    137   Window* capture_window = client::GetCaptureWindow(root_window);
    138   if (capture_window)
    139     return capture_window;
    140 
    141   if (event.IsTouchEvent()) {
    142     // Query the gesture-recognizer to find targets for touch events.
    143     const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event);
    144     ui::GestureConsumer* consumer =
    145         ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch);
    146     if (consumer)
    147       return static_cast<Window*>(consumer);
    148     consumer =
    149         ui::GestureRecognizer::Get()->GetTargetForLocation(
    150             event.location(), touch.source_device_id());
    151     if (consumer)
    152       return static_cast<Window*>(consumer);
    153 
    154     // If the initial touch is outside the root window, target the root.
    155     if (!root_window->bounds().Contains(event.location()))
    156       return root_window;
    157   }
    158 
    159   return NULL;
    160 }
    161 
    162 }  // namespace aura
    163