summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/automation/ui_controls_aura.cc70
-rw-r--r--chrome/browser/automation/ui_controls_aurawin.cc72
-rw-r--r--chrome/browser/automation/ui_controls_aurax11.cc227
-rw-r--r--chrome/browser/automation/ui_controls_gtk.cc17
-rw-r--r--chrome/browser/automation/ui_controls_internal.cc6
-rw-r--r--chrome/browser/automation/ui_controls_internal.h18
-rw-r--r--chrome/browser/automation/ui_controls_internal_win.cc331
-rw-r--r--chrome/browser/automation/ui_controls_mac.mm2
-rw-r--r--chrome/browser/automation/ui_controls_win.cc337
-rw-r--r--chrome/browser/printing/print_dialog_cloud_uitest.cc3
-rw-r--r--chrome/chrome_browser.gypi4
-rw-r--r--chrome/test/automation/automation_proxy.cc2
-rw-r--r--chrome/test/base/view_event_test_base.cc7
-rw-r--r--content/browser/renderer_host/test_render_view_host.cc2
-rw-r--r--content/browser/renderer_host/test_render_view_host.h2
-rw-r--r--ui/aura/desktop.cc5
-rw-r--r--ui/aura/desktop.h3
-rw-r--r--ui/aura/desktop_host.h3
-rw-r--r--ui/aura/desktop_host_linux.cc59
-rw-r--r--ui/aura/desktop_host_win.cc7
-rw-r--r--ui/aura/desktop_host_win.h1
-rw-r--r--ui/base/x/events_x.cc30
-rw-r--r--ui/ui.gyp1
-rw-r--r--ui/ui_unittests.gypi2
24 files changed, 770 insertions, 441 deletions
diff --git a/chrome/browser/automation/ui_controls_aura.cc b/chrome/browser/automation/ui_controls_aura.cc
deleted file mode 100644
index d3bbb96c..0000000
--- a/chrome/browser/automation/ui_controls_aura.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2011 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 "views/view.h"
-
-namespace ui_controls {
-
-bool SendKeyPress(gfx::NativeWindow window,
- ui::KeyboardCode key,
- bool control,
- bool shift,
- bool alt,
- bool command) {
- // http://crbug.com/104396
- NOTIMPLEMENTED();
- return true;
-}
-
-bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
- ui::KeyboardCode key,
- bool control,
- bool shift,
- bool alt,
- bool command,
- const base::Closure& task) {
- // http://crbug.com/104396
- NOTIMPLEMENTED();
- return true;
-}
-
-bool SendMouseMove(long x, long y) {
- // http://crbug.com/104396
- NOTIMPLEMENTED();
- return true;
-}
-
-bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) {
- // http://crbug.com/104396
- NOTIMPLEMENTED();
- return true;
-}
-
-bool SendMouseEvents(MouseButton type, int state) {
- // http://crbug.com/104396
- NOTIMPLEMENTED();
- return true;
-}
-
-bool SendMouseEventsNotifyWhenDone(MouseButton type, int state,
- const base::Closure& task) {
- // http://crbug.com/104396
- NOTIMPLEMENTED();
- return true;
-}
-
-bool SendMouseClick(MouseButton type) {
- return SendMouseEvents(type, UP | DOWN);
-}
-
-void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
- int state, const base::Closure& task) {
- // http://crbug.com/104396
- NOTIMPLEMENTED();
-}
-
-} // namespace ui_controls
diff --git a/chrome/browser/automation/ui_controls_aurawin.cc b/chrome/browser/automation/ui_controls_aurawin.cc
new file mode 100644
index 0000000..d23b3e7
--- /dev/null
+++ b/chrome/browser/automation/ui_controls_aurawin.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2011 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 "chrome/browser/automation/ui_controls_internal.h"
+#include "ui/aura/desktop.h"
+#include "views/view.h"
+
+namespace ui_controls {
+
+bool SendKeyPress(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command) {
+ DCHECK(!command); // No command key on Aura
+ return internal::SendKeyPressImpl(key, control, shift, alt, base::Closure());
+}
+
+bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command,
+ const base::Closure& task) {
+ DCHECK(!command); // No command key on Aura
+ return internal::SendKeyPressImpl(key, control, shift, alt, task);
+}
+
+bool SendMouseMove(long x, long y) {
+ gfx::Point point(x, y);
+ aura::Desktop::GetInstance()->ConvertPointToNativeScreen(&point);
+ return internal::SendMouseMoveImpl(point.x(), point.y(), base::Closure());
+}
+
+bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) {
+ gfx::Point point(x, y);
+ aura::Desktop::GetInstance()->ConvertPointToNativeScreen(&point);
+ return internal::SendMouseMoveImpl(point.x(), point.y(), task);
+}
+
+bool SendMouseEvents(MouseButton type, int state) {
+ return internal::SendMouseEventsImpl(type, state, base::Closure());
+}
+
+bool SendMouseEventsNotifyWhenDone(MouseButton type, int state,
+ const base::Closure& task) {
+ return internal::SendMouseEventsImpl(type, state, task);
+}
+
+bool SendMouseClick(MouseButton type) {
+ return SendMouseEvents(type, UP | DOWN);
+}
+
+void MoveMouseToCenterAndPress(views::View* view,
+ MouseButton button,
+ int state,
+ const base::Closure& 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);
+}
+
+} // namespace ui_controls
diff --git a/chrome/browser/automation/ui_controls_aurax11.cc b/chrome/browser/automation/ui_controls_aurax11.cc
new file mode 100644
index 0000000..43bc219c
--- /dev/null
+++ b/chrome/browser/automation/ui_controls_aurax11.cc
@@ -0,0 +1,227 @@
+// Copyright (c) 2011 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 <X11/keysym.h>
+#include <X11/Xlib.h>
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/message_pump_x.h"
+#include "chrome/browser/automation/ui_controls_internal.h"
+#include "ui/aura/desktop.h"
+#include "ui/base/keycodes/keyboard_code_conversion_x.h"
+#include "views/view.h"
+
+namespace {
+
+// Event waiter executes the specified closure|when a matching event
+// is found.
+// TODO(oshima): Move this to base.
+class EventWaiter : public MessageLoopForUI::Observer {
+ public:
+ typedef bool (*EventWaiterMatcher)(const base::NativeEvent& event);
+
+ EventWaiter(const base::Closure& closure, EventWaiterMatcher matcher)
+ : closure_(closure),
+ matcher_(matcher) {
+ MessageLoopForUI::current()->AddObserver(this);
+ }
+
+ virtual ~EventWaiter() {
+ MessageLoopForUI::current()->RemoveObserver(this);
+ }
+
+ // MessageLoop::Observer implementation:
+ virtual base::EventStatus WillProcessEvent(
+ const base::NativeEvent& event) OVERRIDE {
+ if ((*matcher_)(event)) {
+ MessageLoop::current()->PostTask(FROM_HERE, closure_);
+ delete this;
+ }
+ return base::EVENT_CONTINUE;
+ }
+
+ virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
+ }
+
+ private:
+ base::Closure closure_;
+ EventWaiterMatcher matcher_;
+ DISALLOW_COPY_AND_ASSIGN(EventWaiter);
+};
+
+// Latest mouse pointer location set by SendMouseMoveNotifyWhenDone.
+int g_current_x = -1000;
+int g_current_y = -1000;
+
+// Returns atom that indidates that the XEvent is marker event.
+Atom MarkerEventAtom() {
+ return XInternAtom(base::MessagePumpX::GetDefaultXDisplay(),
+ "marker_event",
+ False);
+}
+
+// Returns true when the event is a marker event.
+bool Matcher(const base::NativeEvent& event) {
+ return event->xany.type == ClientMessage &&
+ event->xclient.message_type == MarkerEventAtom();
+}
+
+void RunClosureAfterEvents(const base::Closure closure) {
+ if (closure.is_null())
+ return;
+ static XEvent* marker_event = NULL;
+ if (!marker_event) {
+ marker_event = new XEvent();
+ marker_event->xclient.type = ClientMessage;
+ marker_event->xclient.display = NULL;
+ marker_event->xclient.window = None;
+ marker_event->xclient.format = 8;
+ }
+ marker_event->xclient.message_type = MarkerEventAtom();
+ aura::Desktop::GetInstance()->PostNativeEvent(marker_event);
+ new EventWaiter(closure, &Matcher);
+}
+
+} // namespace
+
+namespace ui_controls {
+
+bool SendKeyPress(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command) {
+ DCHECK(!command); // No command key on Aura
+ return SendKeyPressNotifyWhenDone(
+ window, key, control, shift, alt, command, base::Closure());
+}
+
+void SetMaskAndKeycodeThenSend(XEvent* xevent,
+ unsigned int mask,
+ unsigned int keycode) {
+ xevent->xkey.state |= mask;
+ xevent->xkey.keycode = keycode;
+ aura::Desktop::GetInstance()->PostNativeEvent(xevent);
+}
+
+void SetKeycodeAndSendThenUnmask(XEvent* xevent,
+ unsigned int mask,
+ unsigned int keycode) {
+ xevent->xkey.keycode = keycode;
+ aura::Desktop::GetInstance()->PostNativeEvent(xevent);
+ xevent->xkey.state ^= mask;
+}
+
+bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
+ ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ bool command,
+ const base::Closure& closure) {
+ DCHECK(!command); // No command key on Aura
+ XEvent xevent = {0};
+ xevent.xkey.type = KeyPress;
+ if (control)
+ SetMaskAndKeycodeThenSend(&xevent, ControlMask, XK_Control_L);
+ if (shift)
+ SetMaskAndKeycodeThenSend(&xevent, ShiftMask, XK_Shift_L);
+ if (alt)
+ SetMaskAndKeycodeThenSend(&xevent, Mod1Mask, XK_Alt_L);
+ xevent.xkey.keycode = ui::XKeysymForWindowsKeyCode(key, shift);
+ aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
+
+ // Send key release events.
+ xevent.xkey.type = KeyRelease;
+ aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
+ if (alt)
+ SetKeycodeAndSendThenUnmask(&xevent, Mod1Mask, XK_Alt_L);
+ if (shift)
+ SetKeycodeAndSendThenUnmask(&xevent, ShiftMask, XK_Shift_L);
+ if (control)
+ SetKeycodeAndSendThenUnmask(&xevent, ControlMask, XK_Control_L);
+ DCHECK(!xevent.xkey.state);
+ RunClosureAfterEvents(closure);
+ return true;
+}
+
+bool SendMouseMove(long x, long y) {
+ return SendMouseMoveNotifyWhenDone(x, y, base::Closure());
+}
+
+bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& closure) {
+ XEvent xevent = {0};
+ XMotionEvent* xmotion = &xevent.xmotion;
+ xmotion->type = MotionNotify;
+ g_current_x = xmotion->x = x;
+ g_current_y = xmotion->y = y;
+ xmotion->same_screen = True;
+ // Desktop will take care of other necessary fields.
+ aura::Desktop::GetInstance()->PostNativeEvent(&xevent);
+ RunClosureAfterEvents(closure);
+ return false;
+}
+
+bool SendMouseEvents(MouseButton type, int state) {
+ return SendMouseEventsNotifyWhenDone(type, state, base::Closure());
+}
+
+bool SendMouseEventsNotifyWhenDone(MouseButton type,
+ int state,
+ const base::Closure& closure) {
+ XEvent xevent = {0};
+ XButtonEvent* xbutton = &xevent.xbutton;
+ DCHECK_NE(g_current_x, -1000);
+ DCHECK_NE(g_current_y, -1000);
+ xbutton->x = g_current_x;
+ xbutton->y = g_current_y;
+ xbutton->same_screen = True;
+ switch (type) {
+ case LEFT:
+ xbutton->button = Button1;
+ xbutton->state = Button1Mask;
+ break;
+ case MIDDLE:
+ xbutton->button = Button2;
+ xbutton->state = Button2Mask;
+ break;
+ case RIGHT:
+ xbutton->button = Button3;
+ xbutton->state = Button3Mask;
+ break;
+ }
+ // Desktop will take care of other necessary fields.
+
+ aura::Desktop* desktop = aura::Desktop::GetInstance();
+ if (state & DOWN) {
+ xevent.xbutton.type = ButtonPress;
+ desktop->PostNativeEvent(&xevent);
+ }
+ if (state & UP) {
+ xevent.xbutton.type = ButtonRelease;
+ desktop->PostNativeEvent(&xevent);
+ }
+ RunClosureAfterEvents(closure);
+ return false;
+}
+
+bool SendMouseClick(MouseButton type) {
+ return SendMouseEvents(type, UP | DOWN);
+}
+
+void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
+ int state, const base::Closure& closure) {
+ 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, closure);
+}
+
+} // namespace ui_controls
diff --git a/chrome/browser/automation/ui_controls_gtk.cc b/chrome/browser/automation/ui_controls_gtk.cc
index d9b02d1..1422031 100644
--- a/chrome/browser/automation/ui_controls_gtk.cc
+++ b/chrome/browser/automation/ui_controls_gtk.cc
@@ -44,7 +44,7 @@ class EventWaiter : public MessageLoopForUI::Observer {
}
// MessageLoop::Observer implementation:
- virtual void WillProcessEvent(GdkEvent* event) {
+ virtual void WillProcessEvent(GdkEvent* event) OVERRIDE {
if ((event->type == type_) && (--count_ == 0)) {
// At the time we're invoked the event has not actually been processed.
// Use PostTask to make sure the event has been processed before
@@ -57,7 +57,7 @@ class EventWaiter : public MessageLoopForUI::Observer {
}
}
- virtual void DidProcessEvent(GdkEvent* event) {
+ virtual void DidProcessEvent(GdkEvent* event) OVERRIDE {
// No-op.
}
@@ -230,7 +230,8 @@ bool SendMouseEvents(MouseButton type, int state) {
return false;
}
-bool SendMouseEventsNotifyWhenDone(MouseButton type, int state,
+bool SendMouseEventsNotifyWhenDone(MouseButton type,
+ int state,
const base::Closure& task) {
bool rv = SendMouseEvents(type, state);
GdkEventType wait_type;
@@ -280,8 +281,10 @@ void SynchronizeWidgetSize(views::Widget* widget) {
}
#endif
-void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
- int state, const base::Closure& task) {
+void MoveMouseToCenterAndPress(views::View* view,
+ MouseButton button,
+ int state,
+ const base::Closure& task) {
#if defined(OS_LINUX)
// X is asynchronous and we need to wait until the window gets
// resized to desired size.
@@ -292,7 +295,7 @@ void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
views::View::ConvertPointToScreen(view, &view_center);
SendMouseMoveNotifyWhenDone(
view_center.x(), view_center.y(),
- base::Bind(&ui_controls::ClickTask, button, state, task));
+ base::Bind(&ui_controls::internal::ClickTask, button, state, task));
}
#else
void MoveMouseToCenterAndPress(GtkWidget* widget,
@@ -303,7 +306,7 @@ void MoveMouseToCenterAndPress(GtkWidget* widget,
SendMouseMoveNotifyWhenDone(
bounds.x() + bounds.width() / 2,
bounds.y() + bounds.height() / 2,
- base::Bind(&ui_controls::ClickTask, button, state, task));
+ base::Bind(&ui_controls::internal::ClickTask, button, state, task));
}
#endif
diff --git a/chrome/browser/automation/ui_controls_internal.cc b/chrome/browser/automation/ui_controls_internal.cc
index 8cb5ec3..1263230 100644
--- a/chrome/browser/automation/ui_controls_internal.cc
+++ b/chrome/browser/automation/ui_controls_internal.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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_internal.h"
namespace ui_controls {
+namespace internal {
void ClickTask(MouseButton button, int state, const base::Closure& followup) {
if (!followup.is_null())
@@ -13,4 +14,5 @@ void ClickTask(MouseButton button, int state, const base::Closure& followup) {
SendMouseEvents(button, state);
}
-} // ui_controls
+} // namespace internal
+} // namespace ui_controls
diff --git a/chrome/browser/automation/ui_controls_internal.h b/chrome/browser/automation/ui_controls_internal.h
index 39d0c7df..d28f361 100644
--- a/chrome/browser/automation/ui_controls_internal.h
+++ b/chrome/browser/automation/ui_controls_internal.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -9,11 +9,27 @@
#include "chrome/browser/automation/ui_controls.h"
namespace ui_controls {
+namespace internal {
// A utility function to send a mouse click event in a closure. It's shared by
// ui_controls_linux.cc and ui_controls_mac.cc
void ClickTask(MouseButton button, int state, const base::Closure& followup);
+#if defined(OS_WIN)
+// A utility functions for windows to send key or mouse events and
+// run the task.
+bool SendKeyPressImpl(ui::KeyboardCode key,
+ bool control,
+ bool shift,
+ bool alt,
+ const base::Closure& task);
+bool SendMouseMoveImpl(long x, long y, const base::Closure& task);
+bool SendMouseEventsImpl(MouseButton type,
+ int state,
+ const base::Closure& task);
+#endif
+
+} // namespace internal
} // namespace ui_controls
#endif // CHROME_BROWSER_AUTOMATION_UI_CONTROLS_INTERNAL_H_
diff --git a/chrome/browser/automation/ui_controls_internal_win.cc b/chrome/browser/automation/ui_controls_internal_win.cc
new file mode 100644
index 0000000..76be27f
--- /dev/null
+++ b/chrome/browser/automation/ui_controls_internal_win.cc
@@ -0,0 +1,331 @@
+// Copyright (c) 2011 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_internal.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"
+
+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;
+}
+
+} // namespace
+
+namespace ui_controls {
+namespace internal {
+
+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 internal
+} // namespace ui_controls
diff --git a/chrome/browser/automation/ui_controls_mac.mm b/chrome/browser/automation/ui_controls_mac.mm
index 41a4fdd..110f467 100644
--- a/chrome/browser/automation/ui_controls_mac.mm
+++ b/chrome/browser/automation/ui_controls_mac.mm
@@ -381,7 +381,7 @@ void MoveMouseToCenterAndPress(
SendMouseMoveNotifyWhenDone(
center.x, center.y,
- base::Bind(&ui_controls::ClickTask, button, state, task));
+ base::Bind(&ui_controls::internal::ClickTask, button, state, task));
}
} // ui_controls
diff --git a/chrome/browser/automation/ui_controls_win.cc b/chrome/browser/automation/ui_controls_win.cc
index 9385df5..6db0e4a 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,
diff --git a/chrome/browser/printing/print_dialog_cloud_uitest.cc b/chrome/browser/printing/print_dialog_cloud_uitest.cc
index 0f93e8e..33aa437 100644
--- a/chrome/browser/printing/print_dialog_cloud_uitest.cc
+++ b/chrome/browser/printing/print_dialog_cloud_uitest.cc
@@ -227,9 +227,8 @@ net::URLRequestJob* PrintDialogCloudTest::Factory(net::URLRequest* request,
return new SimpleTestJob(request);
}
-#if defined(OS_WIN) || defined(USE_AURA)
+#if defined(OS_WIN) && !defined(USE_AURA)
// http://crbug.com/94864 for OS_WIN issue
-// http://crbug.com/103497 for USE_AURA issue
#define MAYBE_HandlersRegistered DISABLED_HandlersRegistered
#else
#define MAYBE_HandlersRegistered HandlersRegistered
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 02ab0d1..5ea8bba 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -238,9 +238,11 @@
'browser/automation/testing_automation_provider_views.cc',
'browser/automation/testing_automation_provider_win.cc',
'browser/automation/ui_controls.h',
+ 'browser/automation/ui_controls_aurawin.cc',
+ 'browser/automation/ui_controls_aurax11.cc',
'browser/automation/ui_controls_internal.cc',
'browser/automation/ui_controls_internal.h',
- 'browser/automation/ui_controls_aura.cc',
+ 'browser/automation/ui_controls_internal_win.cc',
'browser/automation/ui_controls_gtk.cc',
'browser/automation/ui_controls_mac.mm',
'browser/automation/ui_controls_win.cc',
diff --git a/chrome/test/automation/automation_proxy.cc b/chrome/test/automation/automation_proxy.cc
index 27de278..bfa4ade 100644
--- a/chrome/test/automation/automation_proxy.cc
+++ b/chrome/test/automation/automation_proxy.cc
@@ -490,7 +490,7 @@ scoped_refptr<TabProxy> AutomationProxy::CreateExternalTab(
return NULL;
}
-#if defined(OS_WIN)
+#if defined(OS_WIN) && !defined(USE_AURA)
DCHECK(IsWindow(*external_tab_container));
#else // defined(OS_WIN)
DCHECK(*external_tab_container);
diff --git a/chrome/test/base/view_event_test_base.cc b/chrome/test/base/view_event_test_base.cc
index cc414b2..91cced3 100644
--- a/chrome/test/base/view_event_test_base.cc
+++ b/chrome/test/base/view_event_test_base.cc
@@ -88,8 +88,7 @@ void ViewEventTestBase::TearDown() {
DestroyWindow(window_->GetNativeWindow());
#else
window_->Close();
- MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
- ui_test_utils::RunMessageLoop();
+ ui_test_utils::RunAllPendingInMessageLoop();
#endif
window_ = NULL;
}
@@ -134,7 +133,7 @@ void ViewEventTestBase::StartMessageLoopAndRunTest() {
#endif
// Flush any pending events to make sure we start with a clean slate.
- MessageLoop::current()->RunAllPending();
+ ui_test_utils::RunAllPendingInMessageLoop();
// Schedule a task that starts the test. Need to do this as we're going to
// run the message loop.
@@ -142,7 +141,7 @@ void ViewEventTestBase::StartMessageLoopAndRunTest() {
FROM_HERE,
base::Bind(&ViewEventTestBase::DoTestOnMessageLoop, this));
- MessageLoop::current()->Run();
+ ui_test_utils::RunMessageLoop();
}
gfx::Size ViewEventTestBase::GetPreferredSize() {
diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc
index abad243..84611a0 100644
--- a/content/browser/renderer_host/test_render_view_host.cc
+++ b/content/browser/renderer_host/test_render_view_host.cc
@@ -234,7 +234,7 @@ void TestRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped(
int gpu_host_id) {
}
-#elif defined(OS_WIN)
+#elif defined(OS_WIN) && !defined(USE_AURA)
void TestRenderWidgetHostView::WillWmDestroy() {
}
diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h
index 27468dd..7b531af 100644
--- a/content/browser/renderer_host/test_render_view_host.h
+++ b/content/browser/renderer_host/test_render_view_host.h
@@ -119,7 +119,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
int renderer_id,
int32 route_id,
int gpu_host_id) OVERRIDE;
-#elif defined(OS_WIN)
+#elif defined(OS_WIN) && !defined(USE_AURA)
virtual void WillWmDestroy() OVERRIDE;
#endif
#if defined(OS_POSIX) || defined(USE_AURA)
diff --git a/ui/aura/desktop.cc b/ui/aura/desktop.cc
index a4aa58e..b3a8b8a 100644
--- a/ui/aura/desktop.cc
+++ b/ui/aura/desktop.cc
@@ -377,6 +377,11 @@ void Desktop::PostNativeEvent(const base::NativeEvent& native_event) {
host_->PostNativeEvent(native_event);
}
+void Desktop::ConvertPointToNativeScreen(gfx::Point* point) const {
+ gfx::Point location = host_->GetLocationOnNativeScreen();
+ point->Offset(location.x(), location.y());
+}
+
void Desktop::SetCapture(Window* window) {
if (capture_window_ == window)
return;
diff --git a/ui/aura/desktop.h b/ui/aura/desktop.h
index 7e8d0dc..40963f4 100644
--- a/ui/aura/desktop.h
+++ b/ui/aura/desktop.h
@@ -131,6 +131,9 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate,
// Posts |native_event| to the platform's event queue.
void PostNativeEvent(const base::NativeEvent& native_event);
+ // Converts |point| from the desktop's coordinate system to native screen's.
+ void ConvertPointToNativeScreen(gfx::Point* point) const;
+
// Capture -------------------------------------------------------------------
// Sets capture to the specified window.
diff --git a/ui/aura/desktop_host.h b/ui/aura/desktop_host.h
index b276dea..0ac7be1 100644
--- a/ui/aura/desktop_host.h
+++ b/ui/aura/desktop_host.h
@@ -50,6 +50,9 @@ class DesktopHost : public MessageLoop::Dispatcher {
virtual gfx::Size GetSize() const = 0;
virtual void SetSize(const gfx::Size& size) = 0;
+ // Returns the location of the desktop on native screen.
+ virtual gfx::Point GetLocationOnNativeScreen() const = 0;
+
// Sets the currently displayed cursor.
virtual void SetCursor(gfx::NativeCursor cursor) = 0;
diff --git a/ui/aura/desktop_host_linux.cc b/ui/aura/desktop_host_linux.cc
index 2de31e6..7e9a5b1 100644
--- a/ui/aura/desktop_host_linux.cc
+++ b/ui/aura/desktop_host_linux.cc
@@ -238,6 +238,7 @@ class DesktopHostLinux : public DesktopHost {
virtual void ToggleFullScreen() OVERRIDE;
virtual gfx::Size GetSize() const OVERRIDE;
virtual void SetSize(const gfx::Size& size) OVERRIDE;
+ virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE;
virtual gfx::Point QueryMouseLocation() OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
@@ -256,8 +257,8 @@ class DesktopHostLinux : public DesktopHost {
// Current Aura cursor.
gfx::NativeCursor current_cursor_;
- // The size of |xwindow_|.
- gfx::Size size_;
+ // The bounds of |xwindow_|.
+ gfx::Rect bounds_;
DISALLOW_COPY_AND_ASSIGN(DesktopHostLinux);
};
@@ -267,7 +268,7 @@ DesktopHostLinux::DesktopHostLinux(const gfx::Rect& bounds)
xdisplay_(base::MessagePumpX::GetDefaultXDisplay()),
xwindow_(0),
current_cursor_(aura::kCursorNull),
- size_(bounds.size()) {
+ bounds_(bounds) {
xwindow_ = XCreateSimpleWindow(xdisplay_, DefaultRootWindow(xdisplay_),
bounds.x(), bounds.y(),
bounds.width(), bounds.height(),
@@ -331,11 +332,12 @@ base::MessagePumpDispatcher::DispatchStatus DesktopHostLinux::Dispatch(
// It's possible that the X window may be resized by some other means than
// from within aura (e.g. the X window manager can change the size). Make
// sure the desktop size is maintained properly.
- gfx::Size size(xev->xconfigure.width, xev->xconfigure.height);
- if (size_ != size) {
- size_ = size;
- desktop_->OnHostResized(size);
- }
+ gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
+ xev->xconfigure.width, xev->xconfigure.height);
+ bool size_changed = bounds_.size() != bounds.size();
+ bounds_ = bounds;
+ if (size_changed)
+ desktop_->OnHostResized(bounds.size());
handled = true;
break;
}
@@ -437,11 +439,11 @@ void DesktopHostLinux::ToggleFullScreen() {
}
gfx::Size DesktopHostLinux::GetSize() const {
- return size_;
+ return bounds_.size();
}
void DesktopHostLinux::SetSize(const gfx::Size& size) {
- if (size == size_)
+ if (size == bounds_.size())
return;
XResizeWindow(xdisplay_, xwindow_, size.width(), size.height());
@@ -450,11 +452,15 @@ void DesktopHostLinux::SetSize(const gfx::Size& size) {
// case if we're running without a window manager. If there's a window
// manager, it can modify or ignore the request, but (per ICCCM) we'll get a
// (possibly synthetic) ConfigureNotify about the actual size and correct
- // |size_| later.
- size_ = size;
+ // |bounds_| later.
+ bounds_.set_size(size);
desktop_->OnHostResized(size);
}
+gfx::Point DesktopHostLinux::GetLocationOnNativeScreen() const {
+ return bounds_.origin();
+}
+
void DesktopHostLinux::SetCursor(gfx::NativeCursor cursor) {
if (current_cursor_ == cursor)
return;
@@ -478,8 +484,8 @@ gfx::Point DesktopHostLinux::QueryMouseLocation() {
&root_x_return, &root_y_return,
&win_x_return, &win_y_return,
&mask_return);
- return gfx::Point(max(0, min(size_.width(), win_x_return)),
- max(0, min(size_.height(), win_y_return)));
+ return gfx::Point(max(0, min(bounds_.width(), win_x_return)),
+ max(0, min(bounds_.height(), win_y_return)));
}
void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) {
@@ -488,7 +494,30 @@ void DesktopHostLinux::PostNativeEvent(const base::NativeEvent& native_event) {
XEvent xevent = *native_event;
xevent.xany.display = xdisplay_;
xevent.xany.window = xwindow_;
- ::XPutBackEvent(xdisplay_, &xevent);
+
+ switch (xevent.type) {
+ case EnterNotify:
+ case LeaveNotify:
+ case MotionNotify:
+ case KeyPress:
+ case KeyRelease:
+ case ButtonPress:
+ case ButtonRelease: {
+ // The fields used below are in the same place for all of events
+ // above. Using xmotion from XEvent's unions to avoid repeating
+ // the code.
+ xevent.xmotion.root = DefaultRootWindow(xdisplay_);
+ xevent.xmotion.time = CurrentTime;
+
+ gfx::Point point(xevent.xmotion.x, xevent.xmotion.y);
+ desktop_->ConvertPointToNativeScreen(&point);
+ xevent.xmotion.x_root = point.x();
+ xevent.xmotion.y_root = point.y();
+ }
+ default:
+ break;
+ }
+ XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
}
bool DesktopHostLinux::IsWindowManagerPresent() {
diff --git a/ui/aura/desktop_host_win.cc b/ui/aura/desktop_host_win.cc
index 36399e2..3ad4f66 100644
--- a/ui/aura/desktop_host_win.cc
+++ b/ui/aura/desktop_host_win.cc
@@ -206,6 +206,13 @@ void DesktopHostWin::SetSize(const gfx::Size& size) {
SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOREPOSITION);
}
+gfx::Point DesktopHostWin::GetLocationOnNativeScreen() const {
+ RECT r;
+ GetClientRect(hwnd(), &r);
+ return gfx::Point(r.left, r.top);
+}
+
+
void DesktopHostWin::SetCursor(gfx::NativeCursor native_cursor) {
// Custom web cursors are handled directly.
if (native_cursor == kCursorCustom)
diff --git a/ui/aura/desktop_host_win.h b/ui/aura/desktop_host_win.h
index 9309d2b..cd9c136 100644
--- a/ui/aura/desktop_host_win.h
+++ b/ui/aura/desktop_host_win.h
@@ -27,6 +27,7 @@ class DesktopHostWin : public DesktopHost, public ui::WindowImpl {
virtual void ToggleFullScreen() OVERRIDE;
virtual gfx::Size GetSize() const OVERRIDE;
virtual void SetSize(const gfx::Size& size) OVERRIDE;
+ virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
virtual gfx::Point QueryMouseLocation() OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc
index 966fec2..765aed3 100644
--- a/ui/base/x/events_x.cc
+++ b/ui/base/x/events_x.cc
@@ -6,12 +6,17 @@
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
+#include <string.h>
#include "base/logging.h"
#include "ui/base/keycodes/keyboard_code_conversion_x.h"
#include "ui/base/touch/touch_factory.h"
#include "ui/gfx/point.h"
+#if !defined(TOOLKIT_USES_GTK)
+#include "base/message_pump_x.h"
+#endif
+
namespace {
// Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
@@ -356,12 +361,25 @@ float GetTouchForce(const base::NativeEvent& native_event) {
}
base::NativeEvent CreateNoopEvent() {
- static XEvent* noop = new XEvent();
- noop->xclient.type = ClientMessage;
- noop->xclient.display = NULL;
- noop->xclient.window = None;
- noop->xclient.message_type = 0;
- noop->xclient.format = 0;
+ static XEvent* noop = NULL;
+ if (!noop) {
+ noop = new XEvent();
+ memset(noop, 0, sizeof(XEvent));
+ noop->xclient.type = ClientMessage;
+ noop->xclient.window = None;
+ noop->xclient.format = 8;
+ DCHECK(!noop->xclient.display);
+ }
+ // TODO(oshima): Remove ifdef once gtk is removed from views.
+#if defined(TOOLKIT_USES_GTK)
+ NOTREACHED();
+#else
+ // Make sure we use atom from current xdisplay, which may
+ // change during the test.
+ noop->xclient.message_type = XInternAtom(
+ base::MessagePumpX::GetDefaultXDisplay(),
+ "noop", False);
+#endif
return noop;
}
diff --git a/ui/ui.gyp b/ui/ui.gyp
index 4ccf216..235fa44 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -572,6 +572,7 @@
'gfx/render_text_linux.h',
'gfx/render_text_win.cc',
'gfx/render_text_win.h',
+ 'base/x/events_x.cc',
],
}],
['OS=="android"', {
diff --git a/ui/ui_unittests.gypi b/ui/ui_unittests.gypi
index 5a4a8c4..cab407c 100644
--- a/ui/ui_unittests.gypi
+++ b/ui/ui_unittests.gypi
@@ -121,7 +121,7 @@
],
},
}],
- ['OS == "linux"', {
+ ['OS == "linux" and toolkit_views==1', {
'sources': [
'base/x/events_x_unittest.cc',
],