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 "ash/drag_drop/drag_drop_tracker.h" 6 7 #include "ash/shell.h" 8 #include "ash/shell_window_ids.h" 9 #include "ash/wm/coordinate_conversion.h" 10 #include "ui/aura/client/window_tree_client.h" 11 #include "ui/aura/window.h" 12 #include "ui/aura/window_event_dispatcher.h" 13 #include "ui/events/event.h" 14 #include "ui/gfx/screen.h" 15 #include "ui/wm/core/coordinate_conversion.h" 16 #include "ui/wm/public/activation_delegate.h" 17 18 namespace ash { 19 namespace { 20 21 // An activation delegate which disables activating the drag and drop window. 22 class CaptureWindowActivationDelegate 23 : public aura::client::ActivationDelegate { 24 public: 25 CaptureWindowActivationDelegate() {} 26 virtual ~CaptureWindowActivationDelegate() {} 27 28 // aura::client::ActivationDelegate overrides: 29 virtual bool ShouldActivate() const OVERRIDE { 30 return false; 31 } 32 33 private: 34 35 DISALLOW_COPY_AND_ASSIGN(CaptureWindowActivationDelegate); 36 }; 37 38 // Creates a window for capturing drag events. 39 aura::Window* CreateCaptureWindow(aura::Window* context_root, 40 aura::WindowDelegate* delegate) { 41 static CaptureWindowActivationDelegate* activation_delegate_instance = NULL; 42 if (!activation_delegate_instance) 43 activation_delegate_instance = new CaptureWindowActivationDelegate; 44 aura::Window* window = new aura::Window(delegate); 45 // Set type of window as popup to prevent different window manager codes 46 // trying to manage this window. 47 window->SetType(ui::wm::WINDOW_TYPE_POPUP); 48 window->Init(aura::WINDOW_LAYER_NOT_DRAWN); 49 aura::client::ParentWindowWithContext(window, context_root, gfx::Rect()); 50 aura::client::SetActivationDelegate(window, activation_delegate_instance); 51 window->Show(); 52 DCHECK(window->bounds().size().IsEmpty()); 53 return window; 54 } 55 56 } // namespace 57 58 DragDropTracker::DragDropTracker(aura::Window* context_root, 59 aura::WindowDelegate* delegate) 60 : capture_window_(CreateCaptureWindow(context_root, delegate)) { 61 } 62 63 DragDropTracker::~DragDropTracker() { 64 capture_window_->ReleaseCapture(); 65 } 66 67 void DragDropTracker::TakeCapture() { 68 capture_window_->SetCapture(); 69 } 70 71 aura::Window* DragDropTracker::GetTarget(const ui::LocatedEvent& event) { 72 DCHECK(capture_window_.get()); 73 gfx::Point location_in_screen = event.location(); 74 ::wm::ConvertPointToScreen(capture_window_.get(), &location_in_screen); 75 aura::Window* root_window_at_point = 76 wm::GetRootWindowAt(location_in_screen); 77 gfx::Point location_in_root = location_in_screen; 78 ::wm::ConvertPointFromScreen(root_window_at_point, &location_in_root); 79 return root_window_at_point->GetEventHandlerForPoint(location_in_root); 80 } 81 82 ui::LocatedEvent* DragDropTracker::ConvertEvent( 83 aura::Window* target, 84 const ui::LocatedEvent& event) { 85 DCHECK(capture_window_.get()); 86 gfx::Point target_location = event.location(); 87 aura::Window::ConvertPointToTarget(capture_window_.get(), target, 88 &target_location); 89 gfx::Point location_in_screen = event.location(); 90 ::wm::ConvertPointToScreen(capture_window_.get(), &location_in_screen); 91 gfx::Point target_root_location = event.root_location(); 92 aura::Window::ConvertPointToTarget( 93 capture_window_->GetRootWindow(), 94 ash::wm::GetRootWindowAt(location_in_screen), 95 &target_root_location); 96 return new ui::MouseEvent(event.type(), 97 target_location, 98 target_root_location, 99 event.flags(), 100 static_cast<const ui::MouseEvent&>(event). 101 changed_button_flags()); 102 } 103 104 } // namespace ash 105