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