Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Unified Diff: chrome/browser/automation/ui_controls_win.cc

Issue 8585015: Implement ui_controls for aura (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: no mask for xsendevent Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/automation/ui_controls_mac.mm ('k') | chrome/browser/printing/print_dialog_cloud_uitest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/automation/ui_controls_win.cc
diff --git a/chrome/browser/automation/ui_controls_win.cc b/chrome/browser/automation/ui_controls_win.cc
index 9385df5eb3591a3befbada2c7e26845d61550c74..6db0e4a398ce851e049456d3dbb18d0419006237 100644
--- a/chrome/browser/automation/ui_controls_win.cc
+++ b/chrome/browser/automation/ui_controls_win.cc
@@ -4,331 +4,12 @@
#include "chrome/browser/automation/ui_controls.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "ui/base/keycodes/keyboard_codes.h"
-#include "ui/base/keycodes/keyboard_code_conversion_win.h"
+#include "chrome/browser/automation/ui_controls_internal.h"
+#include "ui/gfx/point.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(const base::Closure& task, WPARAM message_waiting_for);
-
- // 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:
- friend class base::RefCounted<InputDispatcher>;
-
- ~InputDispatcher();
-
- // Notifies the task and release this (which should delete it).
- void NotifyTask();
-
- // The task we notify.
- base::Closure 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(const base::Closure& 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()->PostTask(
- FROM_HERE, base::Bind(&InputDispatcher::NotifyTask, this));
-}
-
-void InputDispatcher::NotifyTask() {
- task_.Run();
- Release();
-}
-
-// Private functions ----------------------------------------------------------
-
-// Populate the INPUT structure with the appropriate keyboard event
-// parameters required by SendInput
-bool FillKeyboardInput(ui::KeyboardCode key, INPUT* input, bool key_up) {
- memset(input, 0, sizeof(INPUT));
- input->type = INPUT_KEYBOARD;
- input->ki.wVk = ui::WindowsKeyCodeForKeyboardCode(key);
- input->ki.dwFlags = key_up ? KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP :
- KEYEVENTF_EXTENDEDKEY;
-
- return true;
-}
-
-// Send a key event (up/down)
-bool SendKeyEvent(ui::KeyboardCode 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(ui::KeyboardCode key,
- bool control, bool shift, bool alt,
- const base::Closure& task) {
- scoped_refptr<InputDispatcher> dispatcher(
- !task.is_null() ? new InputDispatcher(task, WM_KEYUP) : NULL);
-
- // If a pop-up menu is open, it won't receive events sent using SendInput.
- // Check for a pop-up menu using its window class (#32768) and if one
- // exists, send the key event directly there.
- HWND popup_menu = ::FindWindow(L"#32768", 0);
- if (popup_menu != NULL && popup_menu == ::GetTopWindow(NULL)) {
- WPARAM w_param = ui::WindowsKeyCodeForKeyboardCode(key);
- LPARAM l_param = 0;
- ::SendMessage(popup_menu, WM_KEYDOWN, w_param, l_param);
- ::SendMessage(popup_menu, WM_KEYUP, w_param, l_param);
-
- if (dispatcher.get())
- dispatcher->AddRef();
- return true;
- }
-
- INPUT input[8] = { 0 }; // 8, assuming all the modifiers are activated.
-
- UINT i = 0;
- if (control) {
- if (!FillKeyboardInput(ui::VKEY_CONTROL, &input[i], false))
- return false;
- i++;
- }
-
- if (shift) {
- if (!FillKeyboardInput(ui::VKEY_SHIFT, &input[i], false))
- return false;
- i++;
- }
-
- if (alt) {
- if (!FillKeyboardInput(ui::VKEY_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(ui::VKEY_MENU, &input[i], true))
- return false;
- i++;
- }
-
- if (shift) {
- if (!FillKeyboardInput(ui::VKEY_SHIFT, &input[i], true))
- return false;
- i++;
- }
-
- if (control) {
- if (!FillKeyboardInput(ui::VKEY_CONTROL, &input[i], true))
- return false;
- i++;
- }
-
- if (::SendInput(i, input, sizeof(INPUT)) != i)
- return false;
-
- if (dispatcher.get())
- dispatcher->AddRef();
-
- return true;
-}
-
-bool SendMouseMoveImpl(long x, long y, const base::Closure& task) {
- // First check if the mouse is already there.
- POINT current_pos;
- ::GetCursorPos(&current_pos);
- if (x == current_pos.x && y == current_pos.y) {
- if (!task.is_null())
- MessageLoop::current()->PostTask(FROM_HERE, task);
- return true;
- }
-
- 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.is_null() ? 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,
- const base::Closure& 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.is_null() ? 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(gfx::NativeWindow window,
ui::KeyboardCode key,
bool control,
@@ -336,7 +17,7 @@ bool SendKeyPress(gfx::NativeWindow window,
bool alt,
bool command) {
DCHECK(!command); // No command key on Windows
- return SendKeyPressImpl(key, control, shift, alt, base::Closure());
+ return internal::SendKeyPressImpl(key, control, shift, alt, base::Closure());
}
bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
@@ -347,28 +28,28 @@ bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
bool command,
const base::Closure& task) {
DCHECK(!command); // No command key on Windows
- return SendKeyPressImpl(key, control, shift, alt, task);
+ return internal::SendKeyPressImpl(key, control, shift, alt, task);
}
bool SendMouseMove(long x, long y) {
- return SendMouseMoveImpl(x, y, base::Closure());
+ return internal::SendMouseMoveImpl(x, y, base::Closure());
}
bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) {
- return SendMouseMoveImpl(x, y, task);
+ return internal::SendMouseMoveImpl(x, y, task);
}
bool SendMouseEvents(MouseButton type, int state) {
- return SendMouseEventsImpl(type, state, base::Closure());
+ return internal::SendMouseEventsImpl(type, state, base::Closure());
}
bool SendMouseEventsNotifyWhenDone(MouseButton type, int state,
const base::Closure& task) {
- return SendMouseEventsImpl(type, state, task);
+ return internal::SendMouseEventsImpl(type, state, task);
}
bool SendMouseClick(MouseButton type) {
- return SendMouseEventsImpl(type, UP | DOWN, base::Closure());
+ return internal::SendMouseEventsImpl(type, UP | DOWN, base::Closure());
}
void MoveMouseToCenterAndPress(views::View* view,
« no previous file with comments | « chrome/browser/automation/ui_controls_mac.mm ('k') | chrome/browser/printing/print_dialog_cloud_uitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698