1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/aura/window_targeter.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/client/capture_client.h" 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/aura/client/event_client.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/aura/client/focus_client.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/aura/window.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/aura/window_delegate.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/window_tree_host.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/events/event_target.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace aura { 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool IsLocatedEvent(const ui::Event& event) { 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return event.IsMouseEvent() || event.IsTouchEvent() || 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch event.IsScrollEvent() || event.IsGestureEvent(); 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)WindowTargeter::WindowTargeter() {} 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)WindowTargeter::~WindowTargeter() {} 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root, 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ui::Event* event) { 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Window* window = static_cast<Window*>(root); 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Window* target = event->IsKeyEvent() ? 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event)) : 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<Window*>(EventTargeter::FindTargetForEvent(root, event)); 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (target && !window->parent() && !window->Contains(target)) { 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // |window| is the root window, but |target| is not a descendent of 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // |window|. So do not allow dispatching from here. Instead, dispatch the 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // event through the WindowEventDispatcher that owns |target|. 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch aura::Window* new_root = target->GetRootWindow(); 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (IsLocatedEvent(*event)) { 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The event has been transformed to be in |target|'s coordinate system. 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // But dispatching the event through the EventProcessor requires the event 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // to be in the host's coordinate system. So, convert the event to be in 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the root's coordinate space, and then to the host's coordinate space by 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // applying the host's transform. 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event); 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch located_event->ConvertLocationToTarget(target, new_root); 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch located_event->UpdateForRootTransform( 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new_root->GetHost()->GetRootTransform()); 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ui::EventDispatchDetails details ALLOW_UNUSED = 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new_root->GetHost()->event_processor()->OnEventFromSource(event); 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch target = NULL; 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return target; 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool WindowTargeter::SubtreeCanAcceptEvent( 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui::EventTarget* target, 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ui::LocatedEvent& event) const { 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) aura::Window* window = static_cast<aura::Window*>(target); 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!window->IsVisible()) 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (window->ignore_events()) 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) client::EventClient* client = client::GetEventClient(window->GetRootWindow()); 68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (client && !client->CanProcessEventsWithinSubtree(window)) 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Window* parent = window->parent(); 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (parent && parent->delegate_ && !parent->delegate_-> 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ShouldDescendIntoChildForEventHandling(window, event.location())) { 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return true; 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool WindowTargeter::EventLocationInsideBounds( 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui::EventTarget* target, 81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ui::LocatedEvent& event) const { 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) aura::Window* window = static_cast<aura::Window*>(target); 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) gfx::Point point = event.location(); 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (window->parent()) 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) aura::Window::ConvertPointToTarget(window->parent(), window, &point); 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return gfx::Rect(window->bounds().size()).Contains(point); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ui::EventTarget* WindowTargeter::FindTargetForLocatedEvent( 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::EventTarget* root, 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::LocatedEvent* event) { 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Window* window = static_cast<Window*>(root); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!window->parent()) { 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Window* target = FindTargetInRootWindow(window, *event); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (target) { 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window->ConvertEventToTarget(target, event); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return target; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return EventTargeter::FindTargetForLocatedEvent(root, event); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)Window* WindowTargeter::FindTargetForKeyEvent(Window* window, 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ui::KeyEvent& key) { 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Window* root_window = window->GetRootWindow(); 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (key.key_code() == ui::VKEY_UNKNOWN && 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (key.flags() & ui::EF_IME_FABRICATED_KEY) == 0 && 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) key.GetCharacter() == 0) 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return NULL; 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client::FocusClient* focus_client = client::GetFocusClient(root_window); 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Window* focused_window = focus_client->GetFocusedWindow(); 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!focused_window) 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return window; 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client::EventClient* event_client = client::GetEventClient(root_window); 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (event_client && 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !event_client->CanProcessEventsWithinSubtree(focused_window)) { 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) focus_client->FocusWindow(NULL); 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return NULL; 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return focused_window ? focused_window : window; 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Window* WindowTargeter::FindTargetInRootWindow(Window* root_window, 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ui::LocatedEvent& event) { 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(root_window, root_window->GetRootWindow()); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Mouse events should be dispatched to the window that processed the 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // mouse-press events (if any). 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (event.IsScrollEvent() || event.IsMouseEvent()) { 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WindowEventDispatcher* dispatcher = root_window->GetHost()->dispatcher(); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (dispatcher->mouse_pressed_handler()) 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return dispatcher->mouse_pressed_handler(); 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // All events should be directed towards the capture window (if any). 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Window* capture_window = client::GetCaptureWindow(root_window); 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (capture_window) 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return capture_window; 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (event.IsTouchEvent()) { 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Query the gesture-recognizer to find targets for touch events. 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event); 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::GestureConsumer* consumer = 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch); 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (consumer) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return static_cast<Window*>(consumer); 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) consumer = 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::GestureRecognizer::Get()->GetTargetForLocation( 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) event.location(), touch.source_device_id()); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (consumer) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return static_cast<Window*>(consumer); 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the initial touch is outside the root window, target the root. 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!root_window->bounds().Contains(event.location())) 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return root_window; 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace aura 163