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 |