| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 8 #include <gdk/gdkkeysyms.h> | 8 #include <gdk/gdkkeysyms.h> |
| 9 | 9 |
| 10 #include "base/gfx/rect.h" |
| 10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 11 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "chrome/common/gtk_util.h" |
| 12 #include "chrome/test/automation/automation_constants.h" | 14 #include "chrome/test/automation/automation_constants.h" |
| 13 | 15 |
| 14 namespace { | 16 namespace { |
| 15 | 17 |
| 16 guint32 EventTimeNow() { | 18 guint32 EventTimeNow() { |
| 17 struct timespec ts; | 19 struct timespec ts; |
| 18 clock_gettime(CLOCK_MONOTONIC, &ts); | 20 clock_gettime(CLOCK_MONOTONIC, &ts); |
| 19 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; | 21 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; |
| 20 } | 22 } |
| 21 | 23 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 39 task_->Run(); | 41 task_->Run(); |
| 40 delete this; | 42 delete this; |
| 41 } | 43 } |
| 42 } | 44 } |
| 43 | 45 |
| 44 private: | 46 private: |
| 45 scoped_ptr<Task> task_; | 47 scoped_ptr<Task> task_; |
| 46 GdkEventType type_; | 48 GdkEventType type_; |
| 47 }; | 49 }; |
| 48 | 50 |
| 51 class ClickTask : public Task { |
| 52 public: |
| 53 ClickTask(ui_controls::MouseButton button, int state, Task* followup) |
| 54 : button_(button), state_(state), followup_(followup) { |
| 55 } |
| 56 |
| 57 virtual ~ClickTask() {} |
| 58 |
| 59 virtual void Run() { |
| 60 ui_controls::SendMouseEventsNotifyWhenDone(button_, state_, followup_); |
| 61 } |
| 62 |
| 63 private: |
| 64 ui_controls::MouseButton button_; |
| 65 int state_; |
| 66 Task* followup_; |
| 67 }; |
| 68 |
| 49 } // namespace | 69 } // namespace |
| 50 | 70 |
| 51 namespace ui_controls { | 71 namespace ui_controls { |
| 52 | 72 |
| 53 bool SendKeyPress(gfx::NativeWindow window, | 73 bool SendKeyPress(gfx::NativeWindow window, |
| 54 wchar_t key, bool control, bool shift, bool alt) { | 74 wchar_t key, bool control, bool shift, bool alt) { |
| 55 // TODO(estade): send a release as well? | 75 // TODO(estade): send a release as well? |
| 56 GdkEvent* event = gdk_event_new(GDK_KEY_PRESS); | 76 GdkEvent* event = gdk_event_new(GDK_KEY_PRESS); |
| 57 | 77 |
| 58 event->key.type = GDK_KEY_PRESS; | 78 event->key.type = GDK_KEY_PRESS; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) { | 122 bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) { |
| 103 bool rv = SendMouseMove(x, y); | 123 bool rv = SendMouseMove(x, y); |
| 104 // We can't rely on any particular event signalling the completion of the | 124 // We can't rely on any particular event signalling the completion of the |
| 105 // mouse move. Posting the task to the message loop should gaurantee | 125 // mouse move. Posting the task to the message loop should gaurantee |
| 106 // the pointer has moved before task is run (although it may not run it as | 126 // the pointer has moved before task is run (although it may not run it as |
| 107 // soon as it could). | 127 // soon as it could). |
| 108 MessageLoop::current()->PostTask(FROM_HERE, task); | 128 MessageLoop::current()->PostTask(FROM_HERE, task); |
| 109 return rv; | 129 return rv; |
| 110 } | 130 } |
| 111 | 131 |
| 112 bool SendMouseClick(const gfx::Point& point, MouseButton type) { | 132 bool SendMouseEvents(MouseButton type, int state) { |
| 113 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); | 133 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); |
| 114 | 134 |
| 115 event->button.window = gdk_window_at_pointer(NULL, NULL); | |
| 116 g_object_ref(event->button.window); | |
| 117 event->button.send_event = false; | 135 event->button.send_event = false; |
| 118 event->button.time = EventTimeNow(); | 136 event->button.time = EventTimeNow(); |
| 119 | 137 |
| 120 event->motion.x_root = point.x(); | 138 gint x, y; |
| 121 event->motion.y_root = point.x(); | 139 event->button.window = gdk_window_at_pointer(&x, &y); |
| 140 g_object_ref(event->button.window); |
| 141 event->motion.x = x; |
| 142 event->motion.y = y; |
| 122 gint origin_x, origin_y; | 143 gint origin_x, origin_y; |
| 123 gdk_window_get_origin(event->button.window, &origin_x, &origin_y); | 144 gdk_window_get_origin(event->button.window, &origin_x, &origin_y); |
| 124 event->button.x = point.x() - origin_x; | 145 event->button.x_root = x + origin_x; |
| 125 event->button.y = point.y() - origin_y; | 146 event->button.y_root = y + origin_y; |
| 126 | 147 |
| 127 event->button.axes = NULL; | 148 event->button.axes = NULL; |
| 128 // TODO(estade): as above, we may want to pack this with the actual state. | 149 // TODO(estade): as above, we may want to pack this with the actual state. |
| 129 event->button.state = 0; | 150 event->button.state = 0; |
| 130 event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3); | 151 event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3); |
| 131 event->button.device = gdk_device_get_core_pointer(); | 152 event->button.device = gdk_device_get_core_pointer(); |
| 132 | 153 |
| 133 event->button.type = GDK_BUTTON_PRESS; | 154 event->button.type = GDK_BUTTON_PRESS; |
| 134 gdk_event_put(event); | 155 if (state & DOWN) |
| 156 gdk_event_put(event); |
| 135 | 157 |
| 136 // Also send a release event. | 158 // Also send a release event. |
| 137 GdkEvent* release_event = gdk_event_copy(event); | 159 GdkEvent* release_event = gdk_event_copy(event); |
| 138 release_event->button.type = GDK_BUTTON_RELEASE; | 160 release_event->button.type = GDK_BUTTON_RELEASE; |
| 139 release_event->button.time++; | 161 release_event->button.time++; |
| 140 gdk_event_put(release_event); | 162 if (state & UP) |
| 163 gdk_event_put(release_event); |
| 141 | 164 |
| 142 gdk_event_free(event); | 165 gdk_event_free(event); |
| 143 gdk_event_free(release_event); | 166 gdk_event_free(release_event); |
| 144 | 167 |
| 145 return false; | 168 return false; |
| 146 } | 169 } |
| 147 | 170 |
| 148 // TODO(estade): need to figure out a better type for this than View. | 171 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) { |
| 149 void MoveMouseToCenterAndPress(views::View* view, | 172 bool rv = SendMouseEvents(type, state); |
| 173 MessageLoop::current()->PostTask(FROM_HERE, task); |
| 174 return rv; |
| 175 } |
| 176 |
| 177 bool SendMouseClick(MouseButton type) { |
| 178 return SendMouseEvents(type, UP | DOWN); |
| 179 } |
| 180 |
| 181 void MoveMouseToCenterAndPress(GtkWidget* widget, |
| 150 MouseButton button, | 182 MouseButton button, |
| 151 int state, | 183 int state, |
| 152 Task* task) { | 184 Task* task) { |
| 153 NOTIMPLEMENTED(); | 185 gfx::Rect bounds = gtk_util::GetWidgetScreenBounds(widget); |
| 186 SendMouseMoveNotifyWhenDone(bounds.x() + bounds.width() / 2, |
| 187 bounds.y() + bounds.height() / 2, |
| 188 new ClickTask(button, state, task)); |
| 154 } | 189 } |
| 155 | 190 |
| 156 } // namespace ui_controls | 191 } // namespace ui_controls |
| OLD | NEW |