| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/base/test/ui_controls_internal_win.h" | 5 #include "ui/base/test/ui_controls_internal_win.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/threading/thread_task_runner_handle.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "ui/events/keycodes/keyboard_code_conversion_win.h" | 15 #include "ui/events/keycodes/keyboard_code_conversion_win.h" |
| 16 #include "ui/events/keycodes/keyboard_codes.h" | 16 #include "ui/events/keycodes/keyboard_codes.h" |
| 17 | 17 |
| 18 namespace ui_controls { |
| 19 |
| 20 // TODO(msw): Remove flaky test debug logging for http://crbug.com/639350. |
| 21 bool g_crbug_639350_logging = false; |
| 22 |
| 23 namespace internal { |
| 24 |
| 18 namespace { | 25 namespace { |
| 19 | 26 |
| 20 // InputDispatcher ------------------------------------------------------------ | 27 // InputDispatcher ------------------------------------------------------------ |
| 21 | 28 |
| 22 // InputDispatcher is used to listen for a mouse/keyboard event. When the | 29 // InputDispatcher is used to listen for a mouse/keyboard event. When the |
| 23 // appropriate event is received the task is notified. | 30 // appropriate event is received the task is notified. |
| 24 class InputDispatcher : public base::RefCounted<InputDispatcher> { | 31 class InputDispatcher : public base::RefCounted<InputDispatcher> { |
| 25 public: | 32 public: |
| 26 InputDispatcher(const base::Closure& task, WPARAM message_waiting_for); | 33 InputDispatcher(const base::Closure& task, WPARAM message_waiting_for); |
| 27 | 34 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 54 bool installed_hook_ = false; | 61 bool installed_hook_ = false; |
| 55 | 62 |
| 56 // Return value from SetWindowsHookEx. | 63 // Return value from SetWindowsHookEx. |
| 57 HHOOK next_hook_ = NULL; | 64 HHOOK next_hook_ = NULL; |
| 58 | 65 |
| 59 // If a hook is installed, this is the dispatcher. | 66 // If a hook is installed, this is the dispatcher. |
| 60 InputDispatcher* current_dispatcher_ = NULL; | 67 InputDispatcher* current_dispatcher_ = NULL; |
| 61 | 68 |
| 62 // Callback from hook when a mouse message is received. | 69 // Callback from hook when a mouse message is received. |
| 63 LRESULT CALLBACK MouseHook(int n_code, WPARAM w_param, LPARAM l_param) { | 70 LRESULT CALLBACK MouseHook(int n_code, WPARAM w_param, LPARAM l_param) { |
| 71 if (g_crbug_639350_logging) |
| 72 LOG(ERROR) << "crbug.com/639350 MouseHook A"; |
| 64 HHOOK next_hook = next_hook_; | 73 HHOOK next_hook = next_hook_; |
| 65 if (n_code == HC_ACTION) { | 74 if (n_code == HC_ACTION) { |
| 75 if (g_crbug_639350_logging) |
| 76 LOG(ERROR) << "crbug.com/639350 MouseHook B"; |
| 66 DCHECK(current_dispatcher_); | 77 DCHECK(current_dispatcher_); |
| 67 current_dispatcher_->DispatchedMessage(w_param); | 78 current_dispatcher_->DispatchedMessage(w_param); |
| 79 if (g_crbug_639350_logging) |
| 80 LOG(ERROR) << "crbug.com/639350 MouseHook C"; |
| 68 } | 81 } |
| 69 return CallNextHookEx(next_hook, n_code, w_param, l_param); | 82 if (g_crbug_639350_logging) |
| 83 LOG(ERROR) << "crbug.com/639350 MouseHook D"; |
| 84 LRESULT result = CallNextHookEx(next_hook, n_code, w_param, l_param); |
| 85 if (g_crbug_639350_logging) |
| 86 LOG(ERROR) << "crbug.com/639350 MouseHook E"; |
| 87 return result; |
| 70 } | 88 } |
| 71 | 89 |
| 72 // Callback from hook when a key message is received. | 90 // Callback from hook when a key message is received. |
| 73 LRESULT CALLBACK KeyHook(int n_code, WPARAM w_param, LPARAM l_param) { | 91 LRESULT CALLBACK KeyHook(int n_code, WPARAM w_param, LPARAM l_param) { |
| 92 if (g_crbug_639350_logging) |
| 93 LOG(ERROR) << "crbug.com/639350 KeyHook A"; |
| 74 HHOOK next_hook = next_hook_; | 94 HHOOK next_hook = next_hook_; |
| 75 if (n_code == HC_ACTION) { | 95 if (n_code == HC_ACTION) { |
| 96 if (g_crbug_639350_logging) |
| 97 LOG(ERROR) << "crbug.com/639350 KeyHook B"; |
| 76 DCHECK(current_dispatcher_); | 98 DCHECK(current_dispatcher_); |
| 77 if (l_param & (1 << 30)) { | 99 if (l_param & (1 << 30)) { |
| 100 if (g_crbug_639350_logging) |
| 101 LOG(ERROR) << "crbug.com/639350 KeyHook C"; |
| 78 // Only send on key up. | 102 // Only send on key up. |
| 79 current_dispatcher_->MatchingMessageFound(); | 103 current_dispatcher_->MatchingMessageFound(); |
| 80 } | 104 } |
| 81 } | 105 } |
| 82 return CallNextHookEx(next_hook, n_code, w_param, l_param); | 106 if (g_crbug_639350_logging) |
| 107 LOG(ERROR) << "crbug.com/639350 KeyHook D"; |
| 108 LRESULT result = CallNextHookEx(next_hook, n_code, w_param, l_param); |
| 109 if (g_crbug_639350_logging) |
| 110 LOG(ERROR) << "crbug.com/639350 KeyHook E"; |
| 111 return result; |
| 83 } | 112 } |
| 84 | 113 |
| 85 // Installs dispatcher as the current hook. | 114 // Installs dispatcher as the current hook. |
| 86 void InstallHook(InputDispatcher* dispatcher, bool key_hook) { | 115 void InstallHook(InputDispatcher* dispatcher, bool key_hook) { |
| 116 if (g_crbug_639350_logging) |
| 117 LOG(ERROR) << "crbug.com/639350 InstallHook A"; |
| 87 DCHECK(!installed_hook_); | 118 DCHECK(!installed_hook_); |
| 88 current_dispatcher_ = dispatcher; | 119 current_dispatcher_ = dispatcher; |
| 89 installed_hook_ = true; | 120 installed_hook_ = true; |
| 90 if (key_hook) { | 121 if (key_hook) { |
| 122 if (g_crbug_639350_logging) |
| 123 LOG(ERROR) << "crbug.com/639350 InstallHook B"; |
| 91 next_hook_ = SetWindowsHookEx(WH_KEYBOARD, &KeyHook, NULL, | 124 next_hook_ = SetWindowsHookEx(WH_KEYBOARD, &KeyHook, NULL, |
| 92 GetCurrentThreadId()); | 125 GetCurrentThreadId()); |
| 93 } else { | 126 } else { |
| 127 if (g_crbug_639350_logging) |
| 128 LOG(ERROR) << "crbug.com/639350 InstallHook C"; |
| 94 // NOTE: I originally tried WH_CALLWNDPROCRET, but for some reason I | 129 // NOTE: I originally tried WH_CALLWNDPROCRET, but for some reason I |
| 95 // didn't get a mouse message like I do with MouseHook. | 130 // didn't get a mouse message like I do with MouseHook. |
| 96 next_hook_ = SetWindowsHookEx(WH_MOUSE, &MouseHook, NULL, | 131 next_hook_ = SetWindowsHookEx(WH_MOUSE, &MouseHook, NULL, |
| 97 GetCurrentThreadId()); | 132 GetCurrentThreadId()); |
| 98 } | 133 } |
| 134 if (g_crbug_639350_logging) |
| 135 LOG(ERROR) << "crbug.com/639350 InstallHook D"; |
| 99 DCHECK(next_hook_); | 136 DCHECK(next_hook_); |
| 100 } | 137 } |
| 101 | 138 |
| 102 // Uninstalls the hook set in InstallHook. | 139 // Uninstalls the hook set in InstallHook. |
| 103 void UninstallHook(InputDispatcher* dispatcher) { | 140 void UninstallHook(InputDispatcher* dispatcher) { |
| 141 if (g_crbug_639350_logging) |
| 142 LOG(ERROR) << "crbug.com/639350 UninstallHook A"; |
| 104 if (current_dispatcher_ == dispatcher) { | 143 if (current_dispatcher_ == dispatcher) { |
| 144 if (g_crbug_639350_logging) |
| 145 LOG(ERROR) << "crbug.com/639350 UninstallHook B"; |
| 105 installed_hook_ = false; | 146 installed_hook_ = false; |
| 106 current_dispatcher_ = NULL; | 147 current_dispatcher_ = NULL; |
| 107 UnhookWindowsHookEx(next_hook_); | 148 UnhookWindowsHookEx(next_hook_); |
| 108 } | 149 } |
| 150 if (g_crbug_639350_logging) |
| 151 LOG(ERROR) << "crbug.com/639350 UninstallHook C"; |
| 109 } | 152 } |
| 110 | 153 |
| 111 InputDispatcher::InputDispatcher(const base::Closure& task, | 154 InputDispatcher::InputDispatcher(const base::Closure& task, |
| 112 WPARAM message_waiting_for) | 155 WPARAM message_waiting_for) |
| 113 : task_(task), message_waiting_for_(message_waiting_for) { | 156 : task_(task), message_waiting_for_(message_waiting_for) { |
| 157 if (g_crbug_639350_logging) |
| 158 LOG(ERROR) << "crbug.com/639350 InputDispatcher::InputDispatcher A"; |
| 114 InstallHook(this, message_waiting_for == WM_KEYUP); | 159 InstallHook(this, message_waiting_for == WM_KEYUP); |
| 160 if (g_crbug_639350_logging) |
| 161 LOG(ERROR) << "crbug.com/639350 InputDispatcher::InputDispatcher B"; |
| 115 } | 162 } |
| 116 | 163 |
| 117 InputDispatcher::~InputDispatcher() { | 164 InputDispatcher::~InputDispatcher() { |
| 165 if (g_crbug_639350_logging) |
| 166 LOG(ERROR) << "crbug.com/639350 InputDispatcher::~InputDispatcher A"; |
| 118 // Make sure the hook isn't installed. | 167 // Make sure the hook isn't installed. |
| 119 UninstallHook(this); | 168 UninstallHook(this); |
| 169 if (g_crbug_639350_logging) |
| 170 LOG(ERROR) << "crbug.com/639350 InputDispatcher::~InputDispatcher B"; |
| 120 } | 171 } |
| 121 | 172 |
| 122 void InputDispatcher::DispatchedMessage(WPARAM message) { | 173 void InputDispatcher::DispatchedMessage(WPARAM message) { |
| 123 if (message == message_waiting_for_) | 174 if (g_crbug_639350_logging) |
| 175 LOG(ERROR) << "crbug.com/639350 InputDispatcher::DispatchedMessage A"; |
| 176 if (message == message_waiting_for_) { |
| 177 if (g_crbug_639350_logging) |
| 178 LOG(ERROR) << "crbug.com/639350 InputDispatcher::DispatchedMessage B"; |
| 124 MatchingMessageFound(); | 179 MatchingMessageFound(); |
| 180 } |
| 181 if (g_crbug_639350_logging) |
| 182 LOG(ERROR) << "crbug.com/639350 InputDispatcher::DispatchedMessage C"; |
| 125 } | 183 } |
| 126 | 184 |
| 127 void InputDispatcher::MatchingMessageFound() { | 185 void InputDispatcher::MatchingMessageFound() { |
| 186 if (g_crbug_639350_logging) |
| 187 LOG(ERROR) << "crbug.com/639350 InputDispatcher::MatchingMessageFound A"; |
| 128 UninstallHook(this); | 188 UninstallHook(this); |
| 189 if (g_crbug_639350_logging) |
| 190 LOG(ERROR) << "crbug.com/639350 InputDispatcher::MatchingMessageFound B"; |
| 129 // At the time we're invoked the event has not actually been processed. | 191 // At the time we're invoked the event has not actually been processed. |
| 130 // Use PostTask to make sure the event has been processed before notifying. | 192 // Use PostTask to make sure the event has been processed before notifying. |
| 131 base::ThreadTaskRunnerHandle::Get()->PostTask( | 193 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 132 FROM_HERE, base::Bind(&InputDispatcher::NotifyTask, this)); | 194 FROM_HERE, base::Bind(&InputDispatcher::NotifyTask, this)); |
| 195 if (g_crbug_639350_logging) |
| 196 LOG(ERROR) << "crbug.com/639350 InputDispatcher::MatchingMessageFound C"; |
| 133 } | 197 } |
| 134 | 198 |
| 135 void InputDispatcher::NotifyTask() { | 199 void InputDispatcher::NotifyTask() { |
| 200 if (g_crbug_639350_logging) |
| 201 LOG(ERROR) << "crbug.com/639350 InputDispatcher::NotifyTask A"; |
| 136 task_.Run(); | 202 task_.Run(); |
| 203 if (g_crbug_639350_logging) |
| 204 LOG(ERROR) << "crbug.com/639350 InputDispatcher::NotifyTask B"; |
| 137 Release(); | 205 Release(); |
| 206 if (g_crbug_639350_logging) |
| 207 LOG(ERROR) << "crbug.com/639350 InputDispatcher::NotifyTask C"; |
| 138 } | 208 } |
| 139 | 209 |
| 140 // Private functions ---------------------------------------------------------- | 210 // Private functions ---------------------------------------------------------- |
| 141 | 211 |
| 142 // Populate the INPUT structure with the appropriate keyboard event | 212 // Populate the INPUT structure with the appropriate keyboard event |
| 143 // parameters required by SendInput | 213 // parameters required by SendInput |
| 144 bool FillKeyboardInput(ui::KeyboardCode key, INPUT* input, bool key_up) { | 214 bool FillKeyboardInput(ui::KeyboardCode key, INPUT* input, bool key_up) { |
| 215 if (g_crbug_639350_logging) |
| 216 LOG(ERROR) << "crbug.com/639350 FillKeyboardInput A"; |
| 145 memset(input, 0, sizeof(INPUT)); | 217 memset(input, 0, sizeof(INPUT)); |
| 146 input->type = INPUT_KEYBOARD; | 218 input->type = INPUT_KEYBOARD; |
| 147 input->ki.wVk = ui::WindowsKeyCodeForKeyboardCode(key); | 219 input->ki.wVk = ui::WindowsKeyCodeForKeyboardCode(key); |
| 148 input->ki.dwFlags = key_up ? KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP : | 220 input->ki.dwFlags = key_up ? KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP : |
| 149 KEYEVENTF_EXTENDEDKEY; | 221 KEYEVENTF_EXTENDEDKEY; |
| 222 if (g_crbug_639350_logging) |
| 223 LOG(ERROR) << "crbug.com/639350 FillKeyboardInput B"; |
| 150 | 224 |
| 151 return true; | 225 return true; |
| 152 } | 226 } |
| 153 | 227 |
| 154 } // namespace | 228 } // namespace |
| 155 | 229 |
| 156 namespace ui_controls { | |
| 157 namespace internal { | |
| 158 | |
| 159 bool SendKeyPressImpl(HWND window, | 230 bool SendKeyPressImpl(HWND window, |
| 160 ui::KeyboardCode key, | 231 ui::KeyboardCode key, |
| 161 bool control, | 232 bool control, |
| 162 bool shift, | 233 bool shift, |
| 163 bool alt, | 234 bool alt, |
| 164 const base::Closure& task) { | 235 const base::Closure& task) { |
| 236 if (g_crbug_639350_logging) |
| 237 LOG(ERROR) << "crbug.com/639350 SendKeyPressImpl A"; |
| 165 // SendInput only works as we expect it if one of our windows is the | 238 // SendInput only works as we expect it if one of our windows is the |
| 166 // foreground window already. | 239 // foreground window already. |
| 167 HWND target_window = (::GetActiveWindow() && | 240 HWND target_window = (::GetActiveWindow() && |
| 168 ::GetWindow(::GetActiveWindow(), GW_OWNER) == window) ? | 241 ::GetWindow(::GetActiveWindow(), GW_OWNER) == window) ? |
| 169 ::GetActiveWindow() : | 242 ::GetActiveWindow() : |
| 170 window; | 243 window; |
| 244 if (g_crbug_639350_logging) |
| 245 LOG(ERROR) << "crbug.com/639350 SendKeyPressImpl B"; |
| 171 if (window && ::GetForegroundWindow() != target_window) | 246 if (window && ::GetForegroundWindow() != target_window) |
| 172 return false; | 247 return false; |
| 248 if (g_crbug_639350_logging) |
| 249 LOG(ERROR) << "crbug.com/639350 SendKeyPressImpl C"; |
| 173 | 250 |
| 174 scoped_refptr<InputDispatcher> dispatcher( | 251 scoped_refptr<InputDispatcher> dispatcher( |
| 175 !task.is_null() ? new InputDispatcher(task, WM_KEYUP) : NULL); | 252 !task.is_null() ? new InputDispatcher(task, WM_KEYUP) : NULL); |
| 176 | 253 |
| 254 if (g_crbug_639350_logging) |
| 255 LOG(ERROR) << "crbug.com/639350 SendKeyPressImpl D"; |
| 256 |
| 177 // If a pop-up menu is open, it won't receive events sent using SendInput. | 257 // If a pop-up menu is open, it won't receive events sent using SendInput. |
| 178 // Check for a pop-up menu using its window class (#32768) and if one | 258 // Check for a pop-up menu using its window class (#32768) and if one |
| 179 // exists, send the key event directly there. | 259 // exists, send the key event directly there. |
| 180 HWND popup_menu = ::FindWindow(L"#32768", 0); | 260 HWND popup_menu = ::FindWindow(L"#32768", 0); |
| 181 if (popup_menu != NULL && popup_menu == ::GetTopWindow(NULL)) { | 261 if (popup_menu != NULL && popup_menu == ::GetTopWindow(NULL)) { |
| 182 WPARAM w_param = ui::WindowsKeyCodeForKeyboardCode(key); | 262 WPARAM w_param = ui::WindowsKeyCodeForKeyboardCode(key); |
| 183 LPARAM l_param = 0; | 263 LPARAM l_param = 0; |
| 184 ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param); | 264 ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param); |
| 185 ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param); | 265 ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param); |
| 186 | 266 |
| 187 if (dispatcher.get()) | 267 if (dispatcher.get()) |
| 188 dispatcher->AddRef(); | 268 dispatcher->AddRef(); |
| 189 return true; | 269 return true; |
| 190 } | 270 } |
| 271 if (g_crbug_639350_logging) |
| 272 LOG(ERROR) << "crbug.com/639350 SendKeyPressImpl E"; |
| 191 | 273 |
| 192 INPUT input[8] = {}; // 8, assuming all the modifiers are activated. | 274 INPUT input[8] = {}; // 8, assuming all the modifiers are activated. |
| 193 | 275 |
| 194 UINT i = 0; | 276 UINT i = 0; |
| 195 if (control) { | 277 if (control) { |
| 196 if (!FillKeyboardInput(ui::VKEY_CONTROL, &input[i], false)) | 278 if (!FillKeyboardInput(ui::VKEY_CONTROL, &input[i], false)) |
| 197 return false; | 279 return false; |
| 198 i++; | 280 i++; |
| 199 } | 281 } |
| 200 | 282 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 228 if (!FillKeyboardInput(ui::VKEY_SHIFT, &input[i], true)) | 310 if (!FillKeyboardInput(ui::VKEY_SHIFT, &input[i], true)) |
| 229 return false; | 311 return false; |
| 230 i++; | 312 i++; |
| 231 } | 313 } |
| 232 | 314 |
| 233 if (control) { | 315 if (control) { |
| 234 if (!FillKeyboardInput(ui::VKEY_CONTROL, &input[i], true)) | 316 if (!FillKeyboardInput(ui::VKEY_CONTROL, &input[i], true)) |
| 235 return false; | 317 return false; |
| 236 i++; | 318 i++; |
| 237 } | 319 } |
| 320 if (g_crbug_639350_logging) |
| 321 LOG(ERROR) << "crbug.com/639350 SendKeyPressImpl F"; |
| 238 | 322 |
| 239 if (::SendInput(i, input, sizeof(INPUT)) != i) | 323 if (::SendInput(i, input, sizeof(INPUT)) != i) |
| 240 return false; | 324 return false; |
| 241 | 325 |
| 326 if (g_crbug_639350_logging) |
| 327 LOG(ERROR) << "crbug.com/639350 SendKeyPressImpl G"; |
| 242 if (dispatcher.get()) | 328 if (dispatcher.get()) |
| 243 dispatcher->AddRef(); | 329 dispatcher->AddRef(); |
| 244 | 330 |
| 331 if (g_crbug_639350_logging) |
| 332 LOG(ERROR) << "crbug.com/639350 SendKeyPressImpl H"; |
| 245 return true; | 333 return true; |
| 246 } | 334 } |
| 247 | 335 |
| 248 bool SendMouseMoveImpl(long screen_x, | 336 bool SendMouseMoveImpl(long screen_x, |
| 249 long screen_y, | 337 long screen_y, |
| 250 const base::Closure& task) { | 338 const base::Closure& task) { |
| 339 if (g_crbug_639350_logging) |
| 340 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl A"; |
| 251 // First check if the mouse is already there. | 341 // First check if the mouse is already there. |
| 252 POINT current_pos; | 342 POINT current_pos; |
| 253 ::GetCursorPos(¤t_pos); | 343 ::GetCursorPos(¤t_pos); |
| 344 if (g_crbug_639350_logging) |
| 345 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl B"; |
| 254 if (screen_x == current_pos.x && screen_y == current_pos.y) { | 346 if (screen_x == current_pos.x && screen_y == current_pos.y) { |
| 347 if (g_crbug_639350_logging) |
| 348 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl C"; |
| 255 if (!task.is_null()) | 349 if (!task.is_null()) |
| 256 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task); | 350 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task); |
| 351 if (g_crbug_639350_logging) |
| 352 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl D"; |
| 257 return true; | 353 return true; |
| 258 } | 354 } |
| 355 if (g_crbug_639350_logging) |
| 356 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl E"; |
| 259 | 357 |
| 260 INPUT input = { 0 }; | 358 INPUT input = { 0 }; |
| 261 | 359 |
| 262 int screen_width = ::GetSystemMetrics(SM_CXSCREEN) - 1; | 360 int screen_width = ::GetSystemMetrics(SM_CXSCREEN) - 1; |
| 263 int screen_height = ::GetSystemMetrics(SM_CYSCREEN) - 1; | 361 int screen_height = ::GetSystemMetrics(SM_CYSCREEN) - 1; |
| 264 LONG pixel_x = static_cast<LONG>(screen_x * (65535.0f / screen_width)); | 362 LONG pixel_x = static_cast<LONG>(screen_x * (65535.0f / screen_width)); |
| 265 LONG pixel_y = static_cast<LONG>(screen_y * (65535.0f / screen_height)); | 363 LONG pixel_y = static_cast<LONG>(screen_y * (65535.0f / screen_height)); |
| 266 | 364 |
| 267 input.type = INPUT_MOUSE; | 365 input.type = INPUT_MOUSE; |
| 268 input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; | 366 input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; |
| 269 input.mi.dx = pixel_x; | 367 input.mi.dx = pixel_x; |
| 270 input.mi.dy = pixel_y; | 368 input.mi.dy = pixel_y; |
| 271 | 369 |
| 370 if (g_crbug_639350_logging) |
| 371 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl F"; |
| 272 scoped_refptr<InputDispatcher> dispatcher( | 372 scoped_refptr<InputDispatcher> dispatcher( |
| 273 !task.is_null() ? new InputDispatcher(task, WM_MOUSEMOVE) : NULL); | 373 !task.is_null() ? new InputDispatcher(task, WM_MOUSEMOVE) : NULL); |
| 374 if (g_crbug_639350_logging) |
| 375 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl G"; |
| 274 | 376 |
| 275 if (!::SendInput(1, &input, sizeof(INPUT))) | 377 if (!::SendInput(1, &input, sizeof(INPUT))) |
| 276 return false; | 378 return false; |
| 277 | 379 |
| 380 if (g_crbug_639350_logging) |
| 381 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl H"; |
| 382 |
| 278 if (dispatcher.get()) | 383 if (dispatcher.get()) |
| 279 dispatcher->AddRef(); | 384 dispatcher->AddRef(); |
| 280 | 385 |
| 386 if (g_crbug_639350_logging) |
| 387 LOG(ERROR) << "crbug.com/639350 SendMouseMoveImpl I"; |
| 281 return true; | 388 return true; |
| 282 } | 389 } |
| 283 | 390 |
| 284 bool SendMouseEventsImpl(MouseButton type, int state, | 391 bool SendMouseEventsImpl(MouseButton type, int state, |
| 285 const base::Closure& task) { | 392 const base::Closure& task) { |
| 393 if (g_crbug_639350_logging) |
| 394 LOG(ERROR) << "crbug.com/639350 SendMouseEventsImpl A"; |
| 286 DWORD down_flags = MOUSEEVENTF_ABSOLUTE; | 395 DWORD down_flags = MOUSEEVENTF_ABSOLUTE; |
| 287 DWORD up_flags = MOUSEEVENTF_ABSOLUTE; | 396 DWORD up_flags = MOUSEEVENTF_ABSOLUTE; |
| 288 UINT last_event; | 397 UINT last_event; |
| 289 | 398 |
| 290 switch (type) { | 399 switch (type) { |
| 291 case LEFT: | 400 case LEFT: |
| 292 down_flags |= MOUSEEVENTF_LEFTDOWN; | 401 down_flags |= MOUSEEVENTF_LEFTDOWN; |
| 293 up_flags |= MOUSEEVENTF_LEFTUP; | 402 up_flags |= MOUSEEVENTF_LEFTUP; |
| 294 last_event = (state & UP) ? WM_LBUTTONUP : WM_LBUTTONDOWN; | 403 last_event = (state & UP) ? WM_LBUTTONUP : WM_LBUTTONDOWN; |
| 295 break; | 404 break; |
| 296 | 405 |
| 297 case MIDDLE: | 406 case MIDDLE: |
| 298 down_flags |= MOUSEEVENTF_MIDDLEDOWN; | 407 down_flags |= MOUSEEVENTF_MIDDLEDOWN; |
| 299 up_flags |= MOUSEEVENTF_MIDDLEUP; | 408 up_flags |= MOUSEEVENTF_MIDDLEUP; |
| 300 last_event = (state & UP) ? WM_MBUTTONUP : WM_MBUTTONDOWN; | 409 last_event = (state & UP) ? WM_MBUTTONUP : WM_MBUTTONDOWN; |
| 301 break; | 410 break; |
| 302 | 411 |
| 303 case RIGHT: | 412 case RIGHT: |
| 304 down_flags |= MOUSEEVENTF_RIGHTDOWN; | 413 down_flags |= MOUSEEVENTF_RIGHTDOWN; |
| 305 up_flags |= MOUSEEVENTF_RIGHTUP; | 414 up_flags |= MOUSEEVENTF_RIGHTUP; |
| 306 last_event = (state & UP) ? WM_RBUTTONUP : WM_RBUTTONDOWN; | 415 last_event = (state & UP) ? WM_RBUTTONUP : WM_RBUTTONDOWN; |
| 307 break; | 416 break; |
| 308 | 417 |
| 309 default: | 418 default: |
| 310 NOTREACHED(); | 419 NOTREACHED(); |
| 311 return false; | 420 return false; |
| 312 } | 421 } |
| 313 | 422 |
| 423 if (g_crbug_639350_logging) |
| 424 LOG(ERROR) << "crbug.com/639350 SendMouseEventsImpl B"; |
| 314 scoped_refptr<InputDispatcher> dispatcher( | 425 scoped_refptr<InputDispatcher> dispatcher( |
| 315 !task.is_null() ? new InputDispatcher(task, last_event) : NULL); | 426 !task.is_null() ? new InputDispatcher(task, last_event) : NULL); |
| 427 if (g_crbug_639350_logging) |
| 428 LOG(ERROR) << "crbug.com/639350 SendMouseEventsImpl C"; |
| 316 | 429 |
| 317 INPUT input = { 0 }; | 430 INPUT input = { 0 }; |
| 318 input.type = INPUT_MOUSE; | 431 input.type = INPUT_MOUSE; |
| 319 input.mi.dwFlags = down_flags; | 432 input.mi.dwFlags = down_flags; |
| 320 if ((state & DOWN) && !::SendInput(1, &input, sizeof(INPUT))) | 433 if ((state & DOWN) && !::SendInput(1, &input, sizeof(INPUT))) |
| 321 return false; | 434 return false; |
| 322 | 435 |
| 436 if (g_crbug_639350_logging) |
| 437 LOG(ERROR) << "crbug.com/639350 SendMouseEventsImpl D"; |
| 323 input.mi.dwFlags = up_flags; | 438 input.mi.dwFlags = up_flags; |
| 324 if ((state & UP) && !::SendInput(1, &input, sizeof(INPUT))) | 439 if ((state & UP) && !::SendInput(1, &input, sizeof(INPUT))) |
| 325 return false; | 440 return false; |
| 441 if (g_crbug_639350_logging) |
| 442 LOG(ERROR) << "crbug.com/639350 SendMouseEventsImpl E"; |
| 326 | 443 |
| 327 if (dispatcher.get()) | 444 if (dispatcher.get()) |
| 328 dispatcher->AddRef(); | 445 dispatcher->AddRef(); |
| 446 if (g_crbug_639350_logging) |
| 447 LOG(ERROR) << "crbug.com/639350 SendMouseEventsImpl F"; |
| 329 | 448 |
| 330 return true; | 449 return true; |
| 331 } | 450 } |
| 332 | 451 |
| 333 } // namespace internal | 452 } // namespace internal |
| 334 } // namespace ui_controls | 453 } // namespace ui_controls |
| OLD | NEW |