summaryrefslogtreecommitdiffstats
path: root/chrome/browser/automation/ui_controls_linux.cc
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-25 02:36:38 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-25 02:36:38 +0000
commit64b31ba0bc8d530b6a900f0fcf84e23da65bc883 (patch)
treef6649711ebe6e0096bf0a902fda28d4a153d7f29 /chrome/browser/automation/ui_controls_linux.cc
parenta8b1bc7935276f4c004ac4cffefa50f45a47c9ed (diff)
downloadchromium_src-64b31ba0bc8d530b6a900f0fcf84e23da65bc883.zip
chromium_src-64b31ba0bc8d530b6a900f0fcf84e23da65bc883.tar.gz
chromium_src-64b31ba0bc8d530b6a900f0fcf84e23da65bc883.tar.bz2
GTK: First cut at tab dragging automation.
Also make tab dragging slightly more robust. I tried really hard to avoid hackiness, but after many hours of wrestling with gtk and X, this is the best I could do. The main point of contention is that GTK (and our tab dragging code in particular) seems to be able to get X into a state where gdk_display_warp_pointer() doesn't send back any events (although it does move the X pointer). I tried to fix our code directly, but decided it was GTK that was broken. So I faked some mouse motion events to prod the tab dragging into working. This approach does not appear to be flaky, and is actually closer to the event stream that occurs when a user drags a tab than the obvious approach would be. (The tests themselves are somewhat flaky, but only due to WaitForURLDisplayedForTab() flakiness, which is a separate issue I'll look at later. The tests aren't on any buildbot for now so I'd like to leave them enabled.) BUG=22182 TEST=--gtest_filter=AutomatedUITest.Drag* Review URL: http://codereview.chromium.org/218017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27166 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/automation/ui_controls_linux.cc')
-rw-r--r--chrome/browser/automation/ui_controls_linux.cc50
1 files changed, 42 insertions, 8 deletions
diff --git a/chrome/browser/automation/ui_controls_linux.cc b/chrome/browser/automation/ui_controls_linux.cc
index aa18ce2..6b2deee 100644
--- a/chrome/browser/automation/ui_controls_linux.cc
+++ b/chrome/browser/automation/ui_controls_linux.cc
@@ -58,9 +58,9 @@ class EventWaiter : public MessageLoopForUI::Observer {
}
private:
- // We pass ownership of task_ to MessageLoop when the corrent event is
+ // We pass ownership of task_ to MessageLoop when the current event is
// received.
- Task *task_;
+ Task* task_;
GdkEventType type_;
// The number of events of this type to wait for.
int count_;
@@ -87,7 +87,6 @@ class ClickTask : public Task {
Task* followup_;
};
-
bool SendKeyEvent(GdkWindow* window, bool press, guint key, guint state) {
GdkEvent* event = gdk_event_new(press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
@@ -116,6 +115,35 @@ bool SendKeyEvent(GdkWindow* window, bool press, guint key, guint state) {
return true;
}
+void FakeAMouseMotionEvent(gint x, gint y) {
+ GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY);
+
+ event->motion.send_event = false;
+ event->motion.time = EventTimeNow();
+
+ 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->motion.window = grab_widget->window;
+ } else {
+ event->motion.window = gdk_window_at_pointer(&x, &y);
+ }
+ g_object_ref(event->motion.window);
+ event->motion.x = x;
+ event->motion.y = y;
+ gint origin_x, origin_y;
+ gdk_window_get_origin(event->motion.window, &origin_x, &origin_y);
+ event->motion.x_root = x + origin_x;
+ event->motion.y_root = y + origin_y;
+
+ event->motion.device = gdk_device_get_core_pointer();
+ event->type = GDK_MOTION_NOTIFY;
+
+ gdk_event_put(event);
+ gdk_event_free(event);
+}
+
} // namespace
namespace ui_controls {
@@ -205,13 +233,18 @@ bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, wchar_t key,
bool SendMouseMove(long x, long y) {
gdk_display_warp_pointer(gdk_display_get_default(), gdk_screen_get_default(),
x, y);
+ // Sometimes gdk_display_warp_pointer fails to send back any indication of
+ // the move, even though it succesfully moves the server cursor. We fake it in
+ // order to get drags to work.
+ FakeAMouseMotionEvent(x, y);
+
return true;
}
bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) {
bool rv = SendMouseMove(x, y);
// We can't rely on any particular event signalling the completion of the
- // mouse move. Posting the task to the message loop should gaurantee
+ // mouse move. Posting the task to the message loop hopefully guarantees
// the pointer has moved before task is run (although it may not run it as
// soon as it could).
MessageLoop::current()->PostTask(FROM_HERE, task);
@@ -234,17 +267,18 @@ bool SendMouseEvents(MouseButton type, int state) {
} else {
event->button.window = gdk_window_at_pointer(&x, &y);
}
+
g_object_ref(event->button.window);
- event->motion.x = x;
- event->motion.y = y;
+ event->button.x = x;
+ event->button.y = y;
gint origin_x, origin_y;
gdk_window_get_origin(event->button.window, &origin_x, &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.
- event->button.state = 0;
+ gdk_window_get_pointer(event->button.window, NULL, NULL,
+ reinterpret_cast<GdkModifierType*>(&event->button.state));
event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3);
event->button.device = gdk_device_get_core_pointer();