| 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 |