| Index: chrome/browser/automation/ui_controls.cc
|
| ===================================================================
|
| --- chrome/browser/automation/ui_controls.cc (revision 23045)
|
| +++ chrome/browser/automation/ui_controls.cc (working copy)
|
| @@ -1,345 +0,0 @@
|
| -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/automation/ui_controls.h"
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/ref_counted.h"
|
| -#include "base/task.h"
|
| -#include "views/view.h"
|
| -
|
| -namespace ui_controls {
|
| -
|
| -namespace {
|
| -
|
| -// InputDispatcher ------------------------------------------------------------
|
| -
|
| -// InputDispatcher is used to listen for a mouse/keyboard event. When the
|
| -// appropriate event is received the task is notified.
|
| -class InputDispatcher : public base::RefCounted<InputDispatcher> {
|
| - public:
|
| - InputDispatcher(Task* task, WPARAM message_waiting_for);
|
| -
|
| - ~InputDispatcher();
|
| -
|
| - // Invoked from the hook. If mouse_message matches message_waiting_for_
|
| - // MatchingMessageFound is invoked.
|
| - void DispatchedMessage(WPARAM mouse_message);
|
| -
|
| - // Invoked when a matching event is found. Uninstalls the hook and schedules
|
| - // an event that notifies the task.
|
| - void MatchingMessageFound();
|
| -
|
| - private:
|
| - // Notifies the task and release this (which should delete it).
|
| - void NotifyTask();
|
| -
|
| - // The task we notify.
|
| - scoped_ptr<Task> task_;
|
| -
|
| - // Message we're waiting for. Not used for keyboard events.
|
| - const WPARAM message_waiting_for_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(InputDispatcher);
|
| -};
|
| -
|
| -// Have we installed the hook?
|
| -bool installed_hook_ = false;
|
| -
|
| -// Return value from SetWindowsHookEx.
|
| -HHOOK next_hook_ = NULL;
|
| -
|
| -// If a hook is installed, this is the dispatcher.
|
| -InputDispatcher* current_dispatcher_ = NULL;
|
| -
|
| -// Callback from hook when a mouse message is received.
|
| -LRESULT CALLBACK MouseHook(int n_code, WPARAM w_param, LPARAM l_param) {
|
| - HHOOK next_hook = next_hook_;
|
| - if (n_code == HC_ACTION) {
|
| - DCHECK(current_dispatcher_);
|
| - current_dispatcher_->DispatchedMessage(w_param);
|
| - }
|
| - return CallNextHookEx(next_hook, n_code, w_param, l_param);
|
| -}
|
| -
|
| -// Callback from hook when a key message is received.
|
| -LRESULT CALLBACK KeyHook(int n_code, WPARAM w_param, LPARAM l_param) {
|
| - HHOOK next_hook = next_hook_;
|
| - if (n_code == HC_ACTION) {
|
| - DCHECK(current_dispatcher_);
|
| - if (l_param & (1 << 30)) // Only send on key up.
|
| - current_dispatcher_->MatchingMessageFound();
|
| - }
|
| - return CallNextHookEx(next_hook, n_code, w_param, l_param);
|
| -}
|
| -
|
| -// Installs dispatcher as the current hook.
|
| -void InstallHook(InputDispatcher* dispatcher, bool key_hook) {
|
| - DCHECK(!installed_hook_);
|
| - current_dispatcher_ = dispatcher;
|
| - installed_hook_ = true;
|
| - if (key_hook) {
|
| - next_hook_ = SetWindowsHookEx(WH_KEYBOARD, &KeyHook, NULL,
|
| - GetCurrentThreadId());
|
| - } else {
|
| - // NOTE: I originally tried WH_CALLWNDPROCRET, but for some reason I
|
| - // didn't get a mouse message like I do with MouseHook.
|
| - next_hook_ = SetWindowsHookEx(WH_MOUSE, &MouseHook, NULL,
|
| - GetCurrentThreadId());
|
| - }
|
| - DCHECK(next_hook_);
|
| -}
|
| -
|
| -// Uninstalls the hook set in InstallHook.
|
| -void UninstallHook(InputDispatcher* dispatcher) {
|
| - if (current_dispatcher_ == dispatcher) {
|
| - installed_hook_ = false;
|
| - current_dispatcher_ = NULL;
|
| - UnhookWindowsHookEx(next_hook_);
|
| - }
|
| -}
|
| -
|
| -InputDispatcher::InputDispatcher(Task* task, UINT message_waiting_for)
|
| - : task_(task), message_waiting_for_(message_waiting_for) {
|
| - InstallHook(this, message_waiting_for == WM_KEYUP);
|
| -}
|
| -
|
| -InputDispatcher::~InputDispatcher() {
|
| - // Make sure the hook isn't installed.
|
| - UninstallHook(this);
|
| -}
|
| -
|
| -void InputDispatcher::DispatchedMessage(WPARAM message) {
|
| - if (message == message_waiting_for_)
|
| - MatchingMessageFound();
|
| -}
|
| -
|
| -void InputDispatcher::MatchingMessageFound() {
|
| - UninstallHook(this);
|
| - // At the time we're invoked the event has not actually been processed.
|
| - // Use PostTask to make sure the event has been processed before notifying.
|
| - MessageLoop::current()->PostDelayedTask(
|
| - FROM_HERE, NewRunnableMethod(this, &InputDispatcher::NotifyTask), 0);
|
| -}
|
| -
|
| -void InputDispatcher::NotifyTask() {
|
| - task_->Run();
|
| - Release();
|
| -}
|
| -
|
| -// Private functions ----------------------------------------------------------
|
| -
|
| -// Populate the INPUT structure with the appropriate keyboard event
|
| -// parameters required by SendInput
|
| -bool FillKeyboardInput(wchar_t key, INPUT* input, bool key_up) {
|
| - memset(input, 0, sizeof(INPUT));
|
| - input->type = INPUT_KEYBOARD;
|
| - input->ki.wVk = static_cast<WORD>(key);
|
| - input->ki.dwFlags = key_up ? KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP :
|
| - KEYEVENTF_EXTENDEDKEY;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// Send a key event (up/down)
|
| -bool SendKeyEvent(wchar_t key, bool up) {
|
| - INPUT input = { 0 };
|
| -
|
| - if (!FillKeyboardInput(key, &input, up))
|
| - return false;
|
| -
|
| - if (!::SendInput(1, &input, sizeof(INPUT)))
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool SendKeyPressImpl(wchar_t key, bool control, bool shift, bool alt,
|
| - Task* task) {
|
| - scoped_refptr<InputDispatcher> dispatcher(
|
| - task ? new InputDispatcher(task, WM_KEYUP) : NULL);
|
| -
|
| - INPUT input[8] = { 0 }; // 8, assuming all the modifiers are activated
|
| -
|
| - int i = 0;
|
| - if (control) {
|
| - if (!FillKeyboardInput(VK_CONTROL, &input[i], false))
|
| - return false;
|
| - i++;
|
| - }
|
| -
|
| - if (shift) {
|
| - if (!FillKeyboardInput(VK_SHIFT, &input[i], false))
|
| - return false;
|
| - i++;
|
| - }
|
| -
|
| - if (alt) {
|
| - if (!FillKeyboardInput(VK_MENU, &input[i], false))
|
| - return false;
|
| - i++;
|
| - }
|
| -
|
| - if (!FillKeyboardInput(key, &input[i], false))
|
| - return false;
|
| - i++;
|
| -
|
| - if (!FillKeyboardInput(key, &input[i], true))
|
| - return false;
|
| - i++;
|
| -
|
| - if (alt) {
|
| - if (!FillKeyboardInput(VK_MENU, &input[i], true))
|
| - return false;
|
| - i++;
|
| - }
|
| -
|
| - if (shift) {
|
| - if (!FillKeyboardInput(VK_SHIFT, &input[i], true))
|
| - return false;
|
| - i++;
|
| - }
|
| -
|
| - if (control) {
|
| - if (!FillKeyboardInput(VK_CONTROL, &input[i], true))
|
| - return false;
|
| - i++;
|
| - }
|
| -
|
| - unsigned int rv = ::SendInput(i, input, sizeof(INPUT));
|
| -
|
| - if (rv != i)
|
| - return false;
|
| -
|
| - if (dispatcher.get())
|
| - dispatcher->AddRef();
|
| - return true;
|
| -}
|
| -
|
| -bool SendMouseMoveImpl(long x, long y, Task* task) {
|
| - INPUT input = { 0 };
|
| -
|
| - int screen_width = ::GetSystemMetrics(SM_CXSCREEN) - 1;
|
| - int screen_height = ::GetSystemMetrics(SM_CYSCREEN) - 1;
|
| - LONG pixel_x = static_cast<LONG>(x * (65535.0f / screen_width));
|
| - LONG pixel_y = static_cast<LONG>(y * (65535.0f / screen_height));
|
| -
|
| - input.type = INPUT_MOUSE;
|
| - input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
|
| - input.mi.dx = pixel_x;
|
| - input.mi.dy = pixel_y;
|
| -
|
| - scoped_refptr<InputDispatcher> dispatcher(
|
| - task ? new InputDispatcher(task, WM_MOUSEMOVE) : NULL);
|
| -
|
| - if (!::SendInput(1, &input, sizeof(INPUT)))
|
| - return false;
|
| -
|
| - if (dispatcher.get())
|
| - dispatcher->AddRef();
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool SendMouseEventsImpl(MouseButton type, int state, Task* task) {
|
| - DWORD down_flags = MOUSEEVENTF_ABSOLUTE;
|
| - DWORD up_flags = MOUSEEVENTF_ABSOLUTE;
|
| - UINT last_event;
|
| -
|
| - switch(type) {
|
| - case LEFT:
|
| - down_flags |= MOUSEEVENTF_LEFTDOWN;
|
| - up_flags |= MOUSEEVENTF_LEFTUP;
|
| - last_event = (state & UP) ? WM_LBUTTONUP : WM_LBUTTONDOWN;
|
| - break;
|
| -
|
| - case MIDDLE:
|
| - down_flags |= MOUSEEVENTF_MIDDLEDOWN;
|
| - up_flags |= MOUSEEVENTF_MIDDLEUP;
|
| - last_event = (state & UP) ? WM_MBUTTONUP : WM_MBUTTONDOWN;
|
| - break;
|
| -
|
| - case RIGHT:
|
| - down_flags |= MOUSEEVENTF_RIGHTDOWN;
|
| - up_flags |= MOUSEEVENTF_RIGHTUP;
|
| - last_event = (state & UP) ? WM_RBUTTONUP : WM_RBUTTONDOWN;
|
| - break;
|
| -
|
| - default:
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| -
|
| - scoped_refptr<InputDispatcher> dispatcher(
|
| - task ? new InputDispatcher(task, last_event) : NULL);
|
| -
|
| - INPUT input = { 0 };
|
| - input.type = INPUT_MOUSE;
|
| - input.mi.dwFlags = down_flags;
|
| - if ((state & DOWN) && !::SendInput(1, &input, sizeof(INPUT)))
|
| - return false;
|
| -
|
| - input.mi.dwFlags = up_flags;
|
| - if ((state & UP) && !::SendInput(1, &input, sizeof(INPUT)))
|
| - return false;
|
| -
|
| - if (dispatcher.get())
|
| - dispatcher->AddRef();
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// public functions -----------------------------------------------------------
|
| -
|
| -bool SendKeyPress(wchar_t key, bool control, bool shift, bool alt) {
|
| - return SendKeyPressImpl(key, control, shift, alt, NULL);
|
| -}
|
| -
|
| -bool SendKeyPressNotifyWhenDone(wchar_t key, bool control, bool shift,
|
| - bool alt, Task* task) {
|
| - return SendKeyPressImpl(key, control, shift, alt, task);
|
| -}
|
| -
|
| -bool SendKeyDown(wchar_t key) {
|
| - return SendKeyEvent(key, false);
|
| -}
|
| -
|
| -bool SendKeyUp(wchar_t key) {
|
| - return SendKeyEvent(key, true);
|
| -}
|
| -
|
| -bool SendMouseMove(long x, long y) {
|
| - return SendMouseMoveImpl(x, y, NULL);
|
| -}
|
| -
|
| -void SendMouseMoveNotifyWhenDone(long x, long y, Task* task) {
|
| - SendMouseMoveImpl(x, y, task);
|
| -}
|
| -
|
| -bool SendMouseEvents(MouseButton type, int state) {
|
| - return SendMouseEventsImpl(type, state, NULL);
|
| -}
|
| -
|
| -void SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) {
|
| - SendMouseEventsImpl(type, state, task);
|
| -}
|
| -
|
| -bool SendMouseClick(MouseButton type) {
|
| - return SendMouseEventsImpl(type, UP | DOWN, NULL);
|
| -}
|
| -
|
| -void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
|
| - int state, Task* task) {
|
| - DCHECK(view);
|
| - DCHECK(view->GetWidget());
|
| - gfx::Point view_center(view->width() / 2, view->height() / 2);
|
| - views::View::ConvertPointToScreen(view, &view_center);
|
| - SendMouseMove(view_center.x(), view_center.y());
|
| - SendMouseEventsNotifyWhenDone(button, state, task);
|
| -}
|
| -
|
| -} // ui_controls
|
|
|