OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/automation/ui_controls.h" | 5 #include "chrome/browser/automation/ui_controls.h" |
6 | 6 |
7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 | 24 |
25 // static | 25 // static |
26 guint32 XTimeNow() { | 26 guint32 XTimeNow() { |
27 struct timespec ts; | 27 struct timespec ts; |
28 clock_gettime(CLOCK_MONOTONIC, &ts); | 28 clock_gettime(CLOCK_MONOTONIC, &ts); |
29 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; | 29 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; |
30 } | 30 } |
31 | 31 |
32 class EventWaiter : public MessageLoopForUI::Observer { | 32 class EventWaiter : public MessageLoopForUI::Observer { |
33 public: | 33 public: |
34 EventWaiter(Task* task, GdkEventType type, int count) | 34 EventWaiter(const base::Closure& task, GdkEventType type, int count) |
35 : task_(task), | 35 : task_(task), |
36 type_(type), | 36 type_(type), |
37 count_(count) { | 37 count_(count) { |
38 MessageLoopForUI::current()->AddObserver(this); | 38 MessageLoopForUI::current()->AddObserver(this); |
39 } | 39 } |
40 | 40 |
41 virtual ~EventWaiter() { | 41 virtual ~EventWaiter() { |
42 MessageLoopForUI::current()->RemoveObserver(this); | 42 MessageLoopForUI::current()->RemoveObserver(this); |
43 } | 43 } |
44 #if defined(TOUCH_UI) | 44 #if defined(TOUCH_UI) |
(...skipping 19 matching lines...) Expand all Loading... |
64 delete this; | 64 delete this; |
65 } | 65 } |
66 } | 66 } |
67 | 67 |
68 virtual void DidProcessEvent(GdkEvent* event) { | 68 virtual void DidProcessEvent(GdkEvent* event) { |
69 // No-op. | 69 // No-op. |
70 } | 70 } |
71 #endif | 71 #endif |
72 | 72 |
73 private: | 73 private: |
74 // We pass ownership of task_ to MessageLoop when the current event is | 74 base::Closure task_; |
75 // received. | |
76 Task* task_; | |
77 GdkEventType type_; | 75 GdkEventType type_; |
78 // The number of events of this type to wait for. | 76 // The number of events of this type to wait for. |
79 int count_; | 77 int count_; |
80 }; | 78 }; |
81 | 79 |
82 void FakeAMouseMotionEvent(gint x, gint y) { | 80 void FakeAMouseMotionEvent(gint x, gint y) { |
83 GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY); | 81 GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY); |
84 | 82 |
85 event->motion.send_event = false; | 83 event->motion.send_event = false; |
86 event->motion.time = XTimeNow(); | 84 event->motion.time = XTimeNow(); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 152 |
155 return true; | 153 return true; |
156 } | 154 } |
157 | 155 |
158 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, | 156 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, |
159 ui::KeyboardCode key, | 157 ui::KeyboardCode key, |
160 bool control, | 158 bool control, |
161 bool shift, | 159 bool shift, |
162 bool alt, | 160 bool alt, |
163 bool command, | 161 bool command, |
164 Task* task) { | 162 const base::Closure& task) { |
165 DCHECK(!command); // No command key on Linux | 163 DCHECK(!command); // No command key on Linux |
166 int release_count = 1; | 164 int release_count = 1; |
167 if (control) | 165 if (control) |
168 release_count++; | 166 release_count++; |
169 if (shift) | 167 if (shift) |
170 release_count++; | 168 release_count++; |
171 if (alt) | 169 if (alt) |
172 release_count++; | 170 release_count++; |
173 // This object will delete itself after running |task|. | 171 // This object will delete itself after running |task|. |
174 new EventWaiter(task, GDK_KEY_RELEASE, release_count); | 172 new EventWaiter(task, GDK_KEY_RELEASE, release_count); |
175 return SendKeyPress(window, key, control, shift, alt, command); | 173 return SendKeyPress(window, key, control, shift, alt, command); |
176 } | 174 } |
177 | 175 |
178 bool SendMouseMove(long x, long y) { | 176 bool SendMouseMove(long x, long y) { |
179 gdk_display_warp_pointer(gdk_display_get_default(), gdk_screen_get_default(), | 177 gdk_display_warp_pointer(gdk_display_get_default(), gdk_screen_get_default(), |
180 x, y); | 178 x, y); |
181 // Sometimes gdk_display_warp_pointer fails to send back any indication of | 179 // Sometimes gdk_display_warp_pointer fails to send back any indication of |
182 // the move, even though it succesfully moves the server cursor. We fake it in | 180 // the move, even though it succesfully moves the server cursor. We fake it in |
183 // order to get drags to work. | 181 // order to get drags to work. |
184 FakeAMouseMotionEvent(x, y); | 182 FakeAMouseMotionEvent(x, y); |
185 return true; | 183 return true; |
186 } | 184 } |
187 | 185 |
188 bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) { | 186 bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) { |
189 bool rv = SendMouseMove(x, y); | 187 bool rv = SendMouseMove(x, y); |
190 new EventWaiter(task, GDK_MOTION_NOTIFY, 1); | 188 new EventWaiter(task, GDK_MOTION_NOTIFY, 1); |
191 return rv; | 189 return rv; |
192 } | 190 } |
193 | 191 |
194 bool SendMouseEvents(MouseButton type, int state) { | 192 bool SendMouseEvents(MouseButton type, int state) { |
195 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); | 193 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); |
196 | 194 |
197 event->button.send_event = false; | 195 event->button.send_event = false; |
198 event->button.time = XTimeNow(); | 196 event->button.time = XTimeNow(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 release_event->button.time++; | 232 release_event->button.time++; |
235 if (state & UP) | 233 if (state & UP) |
236 gdk_event_put(release_event); | 234 gdk_event_put(release_event); |
237 | 235 |
238 gdk_event_free(event); | 236 gdk_event_free(event); |
239 gdk_event_free(release_event); | 237 gdk_event_free(release_event); |
240 | 238 |
241 return false; | 239 return false; |
242 } | 240 } |
243 | 241 |
244 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) { | 242 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, |
| 243 const base::Closure& task) { |
245 bool rv = SendMouseEvents(type, state); | 244 bool rv = SendMouseEvents(type, state); |
246 GdkEventType wait_type; | 245 GdkEventType wait_type; |
247 if (state & UP) { | 246 if (state & UP) { |
248 wait_type = GDK_BUTTON_RELEASE; | 247 wait_type = GDK_BUTTON_RELEASE; |
249 } else { | 248 } else { |
250 if (type == LEFT) | 249 if (type == LEFT) |
251 wait_type = GDK_BUTTON_PRESS; | 250 wait_type = GDK_BUTTON_PRESS; |
252 else if (type == MIDDLE) | 251 else if (type == MIDDLE) |
253 wait_type = GDK_2BUTTON_PRESS; | 252 wait_type = GDK_2BUTTON_PRESS; |
254 else | 253 else |
(...skipping 29 matching lines...) Expand all Loading... |
284 // resized. | 283 // resized. |
285 GtkWidget* gtk_widget = widget->GetNativeView(); | 284 GtkWidget* gtk_widget = widget->GetNativeView(); |
286 g_signal_connect(gtk_widget, "configure-event", | 285 g_signal_connect(gtk_widget, "configure-event", |
287 G_CALLBACK(&OnConfigure), widget); | 286 G_CALLBACK(&OnConfigure), widget); |
288 MessageLoop::current()->Run(); | 287 MessageLoop::current()->Run(); |
289 } | 288 } |
290 } | 289 } |
291 #endif | 290 #endif |
292 | 291 |
293 void MoveMouseToCenterAndPress(views::View* view, MouseButton button, | 292 void MoveMouseToCenterAndPress(views::View* view, MouseButton button, |
294 int state, Task* task) { | 293 int state, const base::Closure& task) { |
295 #if defined(OS_LINUX) && !defined(USE_AURA) | 294 #if defined(OS_LINUX) && !defined(USE_AURA) |
296 // X is asynchronous and we need to wait until the window gets | 295 // X is asynchronous and we need to wait until the window gets |
297 // resized to desired size. | 296 // resized to desired size. |
298 SynchronizeWidgetSize(view->GetWidget()); | 297 SynchronizeWidgetSize(view->GetWidget()); |
299 #endif | 298 #endif |
300 | 299 |
301 gfx::Point view_center(view->width() / 2, view->height() / 2); | 300 gfx::Point view_center(view->width() / 2, view->height() / 2); |
302 views::View::ConvertPointToScreen(view, &view_center); | 301 views::View::ConvertPointToScreen(view, &view_center); |
303 SendMouseMoveNotifyWhenDone(view_center.x(), view_center.y(), | 302 SendMouseMoveNotifyWhenDone(view_center.x(), view_center.y(), |
304 new ClickTask(button, state, task)); | 303 ClickTask(button, state, task)); |
305 } | 304 } |
306 #else | 305 #else |
307 void MoveMouseToCenterAndPress(GtkWidget* widget, | 306 void MoveMouseToCenterAndPress(GtkWidget* widget, |
308 MouseButton button, | 307 MouseButton button, |
309 int state, | 308 int state, |
310 Task* task) { | 309 const base::Closure& task) { |
311 gfx::Rect bounds = gtk_util::GetWidgetScreenBounds(widget); | 310 gfx::Rect bounds = gtk_util::GetWidgetScreenBounds(widget); |
312 SendMouseMoveNotifyWhenDone(bounds.x() + bounds.width() / 2, | 311 SendMouseMoveNotifyWhenDone(bounds.x() + bounds.width() / 2, |
313 bounds.y() + bounds.height() / 2, | 312 bounds.y() + bounds.height() / 2, |
314 new ClickTask(button, state, task)); | 313 ClickTask(button, state, task)); |
315 } | 314 } |
316 #endif | 315 #endif |
317 | 316 |
318 } // namespace ui_controls | 317 } // namespace ui_controls |
OLD | NEW |