diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-21 22:14:41 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-21 22:14:41 +0000 |
commit | fc2e0870089a2cf644e29ec14e58f3bc6168e591 (patch) | |
tree | 11cea988309da72f2efabb6bacbee60e07977c2d /chrome/browser/automation | |
parent | 7bd394d220e29b212b9480cb8a7f4986cb8275ce (diff) | |
download | chromium_src-fc2e0870089a2cf644e29ec14e58f3bc6168e591.zip chromium_src-fc2e0870089a2cf644e29ec14e58f3bc6168e591.tar.gz chromium_src-fc2e0870089a2cf644e29ec14e58f3bc6168e591.tar.bz2 |
More interactive test porting for Linux.
Also fix a bug in the Windows implementation of SendMouseMoveNotifyWhenDone where the task would never be run if the cursor was already in the destination position before the call.
BUG=19076
BUG=19881
Review URL: http://codereview.chromium.org/174201
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24027 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/automation')
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 57 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_gtk.cc | 23 | ||||
-rw-r--r-- | chrome/browser/automation/ui_controls.h | 26 | ||||
-rw-r--r-- | chrome/browser/automation/ui_controls_linux.cc | 59 | ||||
-rw-r--r-- | chrome/browser/automation/ui_controls_win.cc | 15 |
5 files changed, 137 insertions, 43 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 7f364cb..6a22a23 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -836,7 +836,7 @@ class AutomationInterstitialPage : public InterstitialPage { #if !defined(OS_MACOSX) class ClickTask : public Task { public: - ClickTask(gfx::Point point, int flags) : point_(point), flags_(flags) {} + explicit ClickTask(int flags) : flags_(flags) {} virtual ~ClickTask() {} virtual void Run() { @@ -854,11 +854,10 @@ class ClickTask : public Task { NOTREACHED(); } - ui_controls::SendMouseClick(point_, button); + ui_controls::SendMouseClick(button); } private: - gfx::Point point_; int flags_; DISALLOW_COPY_AND_ASSIGN(ClickTask); @@ -1513,14 +1512,60 @@ void AutomationProvider::ExecuteBrowserCommand( Send(reply_message); } -#if !defined(OS_MACOSX) +// This task just adds another task to the event queue. This is useful if +// you want to ensure that any tasks added to the event queue after this one +// have already been processed by the time |task| is run. +class InvokeTaskLaterTask : public Task { + public: + explicit InvokeTaskLaterTask(Task* task) : task_(task) {} + virtual ~InvokeTaskLaterTask() {} + + virtual void Run() { + MessageLoop::current()->PostTask(FROM_HERE, task_); + } + + private: + Task* task_; + + DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask); +}; + +#if defined(OS_WIN) +// TODO(port): Replace POINT and other windowsisms. + +// This task sends a WindowDragResponse message with the appropriate +// routing ID to the automation proxy. This is implemented as a task so that +// we know that the mouse events (and any tasks that they spawn on the message +// loop) have been processed by the time this is sent. +class WindowDragResponseTask : public Task { + public: + WindowDragResponseTask(AutomationProvider* provider, + IPC::Message* reply_message) + : provider_(provider), reply_message_(reply_message) {} + virtual ~WindowDragResponseTask() {} + + virtual void Run() { + DCHECK(reply_message_ != NULL); + AutomationMsg_WindowDrag::WriteReplyParams(reply_message_, true); + provider_->Send(reply_message_); + } + + private: + AutomationProvider* provider_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(WindowDragResponseTask); +}; +#endif // defined(OS_WIN) + +#if defined(OS_WIN) || defined(OS_LINUX) void AutomationProvider::WindowSimulateClick(const IPC::Message& message, int handle, const gfx::Point& click, int flags) { if (window_tracker_->ContainsHandle(handle)) { ui_controls::SendMouseMoveNotifyWhenDone(click.x(), click.y(), - new ClickTask(click, flags)); + new ClickTask(flags)); } } @@ -1541,7 +1586,7 @@ void AutomationProvider::WindowSimulateKeyPress(const IPC::Message& message, ((flags & views::Event::EF_ALT_DOWN) == views::Event::EF_ALT_DOWN)); } -#endif // !defined(OS_MACOSX) +#endif // defined(OS_WIN) || defined(OS_LINUX) void AutomationProvider::IsWindowActive(int handle, bool* success, bool* is_active) { diff --git a/chrome/browser/automation/automation_provider_gtk.cc b/chrome/browser/automation/automation_provider_gtk.cc index 31a5c99..9e91b52 100644 --- a/chrome/browser/automation/automation_provider_gtk.cc +++ b/chrome/browser/automation/automation_provider_gtk.cc @@ -4,13 +4,16 @@ #include "chrome/browser/automation/automation_provider.h" +#include "base/gfx/point.h" +#include "base/gfx/rect.h" #include "chrome/browser/gtk/view_id_util.h" +#include "chrome/common/gtk_util.h" void AutomationProvider::SetWindowBounds(int handle, const gfx::Rect& bounds, bool* success) { *success = false; - if (window_tracker_->ContainsHandle(handle)) { - GtkWindow* window = window_tracker_->GetResource(handle); + GtkWindow* window = window_tracker_->GetResource(handle); + if (window) { gtk_window_move(window, bounds.x(), bounds.height()); gtk_window_resize(window, bounds.width(), bounds.height()); *success = true; @@ -20,8 +23,8 @@ void AutomationProvider::SetWindowBounds(int handle, const gfx::Rect& bounds, void AutomationProvider::SetWindowVisible(int handle, bool visible, bool* result) { *result = false; - if (window_tracker_->ContainsHandle(handle)) { - GtkWindow* window = window_tracker_->GetResource(handle); + GtkWindow* window = window_tracker_->GetResource(handle); + if (window) { if (visible) { gtk_window_present(window); } else { @@ -37,8 +40,8 @@ void AutomationProvider::WindowGetViewBounds(int handle, int view_id, gfx::Rect* bounds) { *success = false; - if (window_tracker_->ContainsHandle(handle)) { - gfx::NativeWindow window = window_tracker_->GetResource(handle); + GtkWindow* window = window_tracker_->GetResource(handle); + if (window) { GtkWidget* widget = ViewIDUtil::GetWidget(GTK_WIDGET(window), static_cast<ViewID>(view_id)); if (!widget) @@ -48,11 +51,9 @@ void AutomationProvider::WindowGetViewBounds(int handle, int view_id, widget->allocation.width, widget->allocation.height); gint x, y; if (screen_coordinates) { - gdk_window_get_origin(widget->window, &x, &y); - if (GTK_WIDGET_NO_WINDOW(widget)) { - x += widget->allocation.x; - y += widget->allocation.y; - } + gfx::Point point = gtk_util::GetWidgetScreenPosition(widget); + x = point.x(); + y = point.y(); } else { gtk_widget_translate_coordinates(widget, GTK_WIDGET(window), 0, 0, &x, &y); diff --git a/chrome/browser/automation/ui_controls.h b/chrome/browser/automation/ui_controls.h index 0df639f..5f3d9e3 100644 --- a/chrome/browser/automation/ui_controls.h +++ b/chrome/browser/automation/ui_controls.h @@ -62,21 +62,25 @@ enum MouseButtonState { DOWN = 2 }; -// Sends a mouse down and or up message. +// Sends a mouse down and/or up message. The click will be sent to wherever +// the cursor currently is, so be sure to move the cursor before calling this +// (and be sure the cursor has arrived!). bool SendMouseEvents(MouseButton type, int state); -void SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task); - -// Simulate a single mouse click with given button type. -// The click will be sent to whichever window is under the cursor, so make sure -// the cursor is where you want it before calling this. -bool SendMouseClick(const gfx::Point& point, MouseButton type); +bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task); +// Same as SendMouseEvents with UP | DOWN. +bool SendMouseClick(MouseButton type); // A combination of SendMouseMove to the middle of the view followed by // SendMouseEvents. -void MoveMouseToCenterAndPress(views::View* view, - MouseButton button, - int state, - Task* task); +void MoveMouseToCenterAndPress( +#if defined(OS_WIN) + views::View* view, +#elif defined(OS_LINUX) + GtkWidget* widget, +#endif + MouseButton button, + int state, + Task* task); } // ui_controls diff --git a/chrome/browser/automation/ui_controls_linux.cc b/chrome/browser/automation/ui_controls_linux.cc index c79dc68..bcaf6c5 100644 --- a/chrome/browser/automation/ui_controls_linux.cc +++ b/chrome/browser/automation/ui_controls_linux.cc @@ -7,8 +7,10 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> +#include "base/gfx/rect.h" #include "base/logging.h" #include "base/message_loop.h" +#include "chrome/common/gtk_util.h" #include "chrome/test/automation/automation_constants.h" namespace { @@ -46,6 +48,24 @@ class EventWaiter : public MessageLoopForUI::Observer { GdkEventType type_; }; +class ClickTask : public Task { + public: + ClickTask(ui_controls::MouseButton button, int state, Task* followup) + : button_(button), state_(state), followup_(followup) { + } + + virtual ~ClickTask() {} + + virtual void Run() { + ui_controls::SendMouseEventsNotifyWhenDone(button_, state_, followup_); + } + + private: + ui_controls::MouseButton button_; + int state_; + Task* followup_; +}; + } // namespace namespace ui_controls { @@ -109,20 +129,21 @@ bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) { return rv; } -bool SendMouseClick(const gfx::Point& point, MouseButton type) { +bool SendMouseEvents(MouseButton type, int state) { GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); - event->button.window = gdk_window_at_pointer(NULL, NULL); - g_object_ref(event->button.window); event->button.send_event = false; event->button.time = EventTimeNow(); - event->motion.x_root = point.x(); - event->motion.y_root = point.x(); + gint x, y; + event->button.window = gdk_window_at_pointer(&x, &y); + g_object_ref(event->button.window); + event->motion.x = x; + event->motion.y = y; gint origin_x, origin_y; gdk_window_get_origin(event->button.window, &origin_x, &origin_y); - event->button.x = point.x() - origin_x; - event->button.y = point.y() - origin_y; + event->button.x_root = x + origin_x; + event->button.y_root = y + origin_y; event->button.axes = NULL; // TODO(estade): as above, we may want to pack this with the actual state. @@ -131,13 +152,15 @@ bool SendMouseClick(const gfx::Point& point, MouseButton type) { event->button.device = gdk_device_get_core_pointer(); event->button.type = GDK_BUTTON_PRESS; - gdk_event_put(event); + if (state & DOWN) + gdk_event_put(event); // Also send a release event. GdkEvent* release_event = gdk_event_copy(event); release_event->button.type = GDK_BUTTON_RELEASE; release_event->button.time++; - gdk_event_put(release_event); + if (state & UP) + gdk_event_put(release_event); gdk_event_free(event); gdk_event_free(release_event); @@ -145,12 +168,24 @@ bool SendMouseClick(const gfx::Point& point, MouseButton type) { return false; } -// TODO(estade): need to figure out a better type for this than View. -void MoveMouseToCenterAndPress(views::View* view, +bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) { + bool rv = SendMouseEvents(type, state); + MessageLoop::current()->PostTask(FROM_HERE, task); + return rv; +} + +bool SendMouseClick(MouseButton type) { + return SendMouseEvents(type, UP | DOWN); +} + +void MoveMouseToCenterAndPress(GtkWidget* widget, MouseButton button, int state, Task* task) { - NOTIMPLEMENTED(); + gfx::Rect bounds = gtk_util::GetWidgetScreenBounds(widget); + SendMouseMoveNotifyWhenDone(bounds.x() + bounds.width() / 2, + bounds.y() + bounds.height() / 2, + new ClickTask(button, state, task)); } } // namespace ui_controls diff --git a/chrome/browser/automation/ui_controls_win.cc b/chrome/browser/automation/ui_controls_win.cc index d1b59ee..78b1acb 100644 --- a/chrome/browser/automation/ui_controls_win.cc +++ b/chrome/browser/automation/ui_controls_win.cc @@ -219,6 +219,15 @@ bool SendKeyPressImpl(wchar_t key, bool control, bool shift, bool alt, } bool SendMouseMoveImpl(long x, long y, Task* task) { + // First check if the mouse is already there. + POINT current_pos; + ::GetCursorPos(¤t_pos); + if (x == current_pos.x && y == current_pos.y) { + if (task) + MessageLoop::current()->PostTask(FROM_HERE, task); + return true; + } + INPUT input = { 0 }; int screen_width = ::GetSystemMetrics(SM_CXSCREEN) - 1; @@ -318,11 +327,11 @@ bool SendMouseEvents(MouseButton type, int state) { return SendMouseEventsImpl(type, state, NULL); } -void SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) { - SendMouseEventsImpl(type, state, task); +bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) { + return SendMouseEventsImpl(type, state, task); } -bool SendMouseClick(const gfx::Point& point, MouseButton type) { +bool SendMouseClick(MouseButton type) { return SendMouseEventsImpl(type, UP | DOWN, NULL); } |