Index: chrome/browser/automation/ui_controls_linux.cc |
=================================================================== |
--- chrome/browser/automation/ui_controls_linux.cc (revision 24301) |
+++ chrome/browser/automation/ui_controls_linux.cc (working copy) |
@@ -13,6 +13,11 @@ |
#include "chrome/common/gtk_util.h" |
#include "chrome/test/automation/automation_constants.h" |
+#if defined(TOOLKIT_VIEWS) |
+#include "views/view.h" |
+#include "views/widget/widget.h" |
+#endif |
+ |
namespace { |
guint32 EventTimeNow() { |
@@ -33,18 +38,26 @@ |
// MessageLoop::Observer implementation: |
virtual void WillProcessEvent(GdkEvent* event) { |
- // No-op. |
+ if (event->type == type_) { |
+ // 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. |
+ // NOTE: if processing a message results in running a nested message |
+ // loop, then DidProcessEvent isn't immediately sent. As such, we do |
+ // the processing in WillProcessEvent rather than DidProcessEvent. |
+ MessageLoop::current()->PostTask(FROM_HERE, task_); |
+ delete this; |
+ } |
} |
virtual void DidProcessEvent(GdkEvent* event) { |
- if (event->any.type == type_) { |
- task_->Run(); |
- delete this; |
- } |
+ // No-op. |
} |
private: |
- scoped_ptr<Task> task_; |
+ // We pass ownership of task_ to MessageLoop when the corrent event is |
+ // received. |
+ Task *task_; |
GdkEventType type_; |
}; |
@@ -57,7 +70,10 @@ |
virtual ~ClickTask() {} |
virtual void Run() { |
- ui_controls::SendMouseEventsNotifyWhenDone(button_, state_, followup_); |
+ if (followup_) |
+ ui_controls::SendMouseEventsNotifyWhenDone(button_, state_, followup_); |
+ else |
+ ui_controls::SendMouseEvents(button_, state_); |
} |
private: |
@@ -76,7 +92,25 @@ |
GdkEvent* event = gdk_event_new(GDK_KEY_PRESS); |
event->key.type = GDK_KEY_PRESS; |
- event->key.window = GTK_WIDGET(window)->window; |
+ GtkWidget* grab_widget = gtk_grab_get_current(); |
+ if (grab_widget) { |
+ // If there is a grab, send all events to the grabbed widget. |
+ event->key.window = grab_widget->window; |
+ } else if (window) { |
+ event->key.window = GTK_WIDGET(window)->window; |
+ } else { |
+ // No target was specified. Send the events to the focused window. |
+ GList* windows = gtk_window_list_toplevels(); |
+ for (GList* element = windows; element; element = g_list_next(element)) { |
+ GtkWindow* window = GTK_WINDOW(element->data); |
+ if (gtk_window_is_active(window)) { |
+ event->key.window = GTK_WIDGET(window)->window; |
+ break; |
+ } |
+ } |
+ g_list_free(windows); |
+ } |
+ DCHECK(event->key.window); |
g_object_ref(event->key.window); |
event->key.send_event = false; |
event->key.time = EventTimeNow(); |
@@ -136,7 +170,15 @@ |
event->button.time = EventTimeNow(); |
gint x, y; |
- event->button.window = gdk_window_at_pointer(&x, &y); |
+ GtkWidget* grab_widget = gtk_grab_get_current(); |
+ if (grab_widget) { |
+ // If there is a grab, we need to target all events at it regardless of |
+ // what widget the mouse is over. |
+ event->button.window = grab_widget->window; |
+ gdk_window_get_pointer(event->button.window, &x, &y, NULL); |
+ } else { |
+ event->button.window = gdk_window_at_pointer(&x, &y); |
+ } |
g_object_ref(event->button.window); |
event->motion.x = x; |
event->motion.y = y; |
@@ -170,7 +212,18 @@ |
bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) { |
bool rv = SendMouseEvents(type, state); |
- MessageLoop::current()->PostTask(FROM_HERE, task); |
+ GdkEventType wait_type; |
+ if (state & UP) { |
+ wait_type = GDK_BUTTON_RELEASE; |
+ } else { |
+ if (type == LEFT) |
+ wait_type = GDK_BUTTON_PRESS; |
+ else if (type == MIDDLE) |
+ wait_type = GDK_2BUTTON_PRESS; |
+ else |
+ wait_type = GDK_3BUTTON_PRESS; |
+ } |
+ new EventWaiter(task, wait_type); |
return rv; |
} |
@@ -178,6 +231,15 @@ |
return SendMouseEvents(type, UP | DOWN); |
} |
+#if defined(TOOLKIT_VIEWS) |
+void MoveMouseToCenterAndPress(views::View* view, MouseButton button, |
+ int state, Task* task) { |
+ gfx::Point view_center(view->width() / 2, view->height() / 2); |
+ views::View::ConvertPointToScreen(view, &view_center); |
+ SendMouseMoveNotifyWhenDone(view_center.x(), view_center.y(), |
+ new ClickTask(button, state, task)); |
+} |
+#else |
void MoveMouseToCenterAndPress(GtkWidget* widget, |
MouseButton button, |
int state, |
@@ -187,5 +249,6 @@ |
bounds.y() + bounds.height() / 2, |
new ClickTask(button, state, task)); |
} |
+#endif |
} // namespace ui_controls |