1// Copyright 2014 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 "base/bind.h" 6#include "base/logging.h" 7#include "ui/aura/client/screen_position_client.h" 8#include "ui/aura/env.h" 9#include "ui/aura/test/aura_test_utils.h" 10#include "ui/aura/test/ui_controls_factory_aura.h" 11#include "ui/aura/window_tree_host.h" 12#include "ui/base/test/ui_controls_aura.h" 13 14namespace aura { 15namespace test { 16namespace { 17 18class UIControlsOzone : public ui_controls::UIControlsAura { 19 public: 20 UIControlsOzone(WindowTreeHost* host) : host_(host) {} 21 22 virtual bool SendKeyPress(gfx::NativeWindow window, 23 ui::KeyboardCode key, 24 bool control, 25 bool shift, 26 bool alt, 27 bool command) OVERRIDE { 28 return SendKeyPressNotifyWhenDone( 29 window, key, control, shift, alt, command, base::Closure()); 30 } 31 virtual bool SendKeyPressNotifyWhenDone( 32 gfx::NativeWindow window, 33 ui::KeyboardCode key, 34 bool control, 35 bool shift, 36 bool alt, 37 bool command, 38 const base::Closure& closure) OVERRIDE { 39 int flags = button_down_mask_; 40 41 if (control) { 42 flags |= ui::EF_CONTROL_DOWN; 43 PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags); 44 } 45 46 if (shift) { 47 flags |= ui::EF_SHIFT_DOWN; 48 PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags); 49 } 50 51 if (alt) { 52 flags |= ui::EF_ALT_DOWN; 53 PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags); 54 } 55 56 if (command) { 57 flags |= ui::EF_COMMAND_DOWN; 58 PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags); 59 } 60 61 PostKeyEvent(ui::ET_KEY_PRESSED, key, flags); 62 PostKeyEvent(ui::ET_KEY_RELEASED, key, flags); 63 64 if (alt) { 65 flags &= ~ui::EF_ALT_DOWN; 66 PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags); 67 } 68 69 if (shift) { 70 flags &= ~ui::EF_SHIFT_DOWN; 71 PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags); 72 } 73 74 if (control) { 75 flags &= ~ui::EF_CONTROL_DOWN; 76 PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags); 77 } 78 79 if (command) { 80 flags &= ~ui::EF_COMMAND_DOWN; 81 PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags); 82 } 83 84 RunClosureAfterAllPendingUIEvents(closure); 85 return true; 86 } 87 88 virtual bool SendMouseMove(long screen_x, long screen_y) OVERRIDE { 89 return SendMouseMoveNotifyWhenDone(screen_x, screen_y, base::Closure()); 90 } 91 virtual bool SendMouseMoveNotifyWhenDone( 92 long screen_x, 93 long screen_y, 94 const base::Closure& closure) OVERRIDE { 95 gfx::Point root_location(screen_x, screen_y); 96 aura::client::ScreenPositionClient* screen_position_client = 97 aura::client::GetScreenPositionClient(host_->window()); 98 if (screen_position_client) { 99 screen_position_client->ConvertPointFromScreen(host_->window(), 100 &root_location); 101 } 102 gfx::Point root_current_location = 103 QueryLatestMousePositionRequestInHost(host_); 104 host_->ConvertPointFromHost(&root_current_location); 105 106 if (button_down_mask_) 107 PostMouseEvent(ui::ET_MOUSE_DRAGGED, root_location, 0, 0); 108 else 109 PostMouseEvent(ui::ET_MOUSE_MOVED, root_location, 0, 0); 110 111 RunClosureAfterAllPendingUIEvents(closure); 112 return true; 113 } 114 virtual bool SendMouseEvents(ui_controls::MouseButton type, 115 int state) OVERRIDE { 116 return SendMouseEventsNotifyWhenDone(type, state, base::Closure()); 117 } 118 virtual bool SendMouseEventsNotifyWhenDone( 119 ui_controls::MouseButton type, 120 int state, 121 const base::Closure& closure) OVERRIDE { 122 gfx::Point loc = aura::Env::GetInstance()->last_mouse_location(); 123 aura::client::ScreenPositionClient* screen_position_client = 124 aura::client::GetScreenPositionClient(host_->window()); 125 if (screen_position_client) { 126 screen_position_client->ConvertPointFromScreen(host_->window(), &loc); 127 } 128 int flag = 0; 129 130 switch (type) { 131 case ui_controls::LEFT: 132 flag = ui::EF_LEFT_MOUSE_BUTTON; 133 break; 134 case ui_controls::MIDDLE: 135 flag = ui::EF_MIDDLE_MOUSE_BUTTON; 136 break; 137 case ui_controls::RIGHT: 138 flag = ui::EF_RIGHT_MOUSE_BUTTON; 139 break; 140 default: 141 NOTREACHED(); 142 break; 143 } 144 145 if (state & ui_controls::DOWN) { 146 button_down_mask_ |= flag; 147 PostMouseEvent(ui::ET_MOUSE_PRESSED, loc, button_down_mask_ | flag, flag); 148 } 149 if (state & ui_controls::UP) { 150 button_down_mask_ &= ~flag; 151 PostMouseEvent( 152 ui::ET_MOUSE_RELEASED, loc, button_down_mask_ | flag, flag); 153 } 154 155 RunClosureAfterAllPendingUIEvents(closure); 156 return true; 157 } 158 virtual bool SendMouseClick(ui_controls::MouseButton type) OVERRIDE { 159 return SendMouseEvents(type, ui_controls::UP | ui_controls::DOWN); 160 } 161 virtual void RunClosureAfterAllPendingUIEvents( 162 const base::Closure& closure) OVERRIDE { 163 if (!closure.is_null()) 164 base::MessageLoop::current()->PostTask(FROM_HERE, closure); 165 } 166 167 private: 168 void PostKeyEvent(ui::EventType type, ui::KeyboardCode key_code, int flags) { 169 base::MessageLoop::current()->PostTask( 170 FROM_HERE, 171 base::Bind(&UIControlsOzone::PostKeyEventTask, 172 base::Unretained(this), 173 type, 174 key_code, 175 flags)); 176 } 177 178 void PostKeyEventTask(ui::EventType type, 179 ui::KeyboardCode key_code, 180 int flags) { 181 // Do not rewrite injected events. See crbug.com/136465. 182 flags |= ui::EF_FINAL; 183 184 ui::KeyEvent key_event(type, key_code, flags); 185 host_->PostNativeEvent(&key_event); 186 } 187 188 void PostMouseEvent(ui::EventType type, 189 const gfx::PointF& location, 190 int flags, 191 int changed_button_flags) { 192 base::MessageLoop::current()->PostTask( 193 FROM_HERE, 194 base::Bind(&UIControlsOzone::PostMouseEventTask, 195 base::Unretained(this), 196 type, 197 location, 198 flags, 199 changed_button_flags)); 200 } 201 202 void PostMouseEventTask(ui::EventType type, 203 const gfx::PointF& location, 204 int flags, 205 int changed_button_flags) { 206 ui::MouseEvent mouse_event( 207 type, location, location, flags, changed_button_flags); 208 209 // This hack is necessary to set the repeat count for clicks. 210 ui::MouseEvent mouse_event2(&mouse_event); 211 212 host_->PostNativeEvent(&mouse_event2); 213 } 214 215 WindowTreeHost* host_; 216 217 // Mask of the mouse buttons currently down. 218 unsigned button_down_mask_ = 0; 219 220 DISALLOW_COPY_AND_ASSIGN(UIControlsOzone); 221}; 222 223} // namespace 224 225ui_controls::UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) { 226 return new UIControlsOzone(host); 227} 228 229} // namespace test 230} // namespace aura 231