summaryrefslogtreecommitdiffstats
path: root/chrome/browser/automation
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-21 22:14:41 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-21 22:14:41 +0000
commitfc2e0870089a2cf644e29ec14e58f3bc6168e591 (patch)
tree11cea988309da72f2efabb6bacbee60e07977c2d /chrome/browser/automation
parent7bd394d220e29b212b9480cb8a7f4986cb8275ce (diff)
downloadchromium_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.cc57
-rw-r--r--chrome/browser/automation/automation_provider_gtk.cc23
-rw-r--r--chrome/browser/automation/ui_controls.h26
-rw-r--r--chrome/browser/automation/ui_controls_linux.cc59
-rw-r--r--chrome/browser/automation/ui_controls_win.cc15
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(&current_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);
}