Chromium Code Reviews| 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_; |
|
awong
2011/10/11 01:18:04
That comment scares me slightly. Are we okay with
James Hawkins
2011/10/11 21:11:22
Yes.
| |
| 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 |