Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Side by Side Diff: chrome/browser/automation/ui_controls_linux.cc

Issue 173392: Couple of tweaks to ui_controls_linux:... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/automation/ui_controls.h ('k') | chrome/browser/browser_focus_uitest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/gfx/rect.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "chrome/common/gtk_util.h" 13 #include "chrome/common/gtk_util.h"
14 #include "chrome/test/automation/automation_constants.h" 14 #include "chrome/test/automation/automation_constants.h"
15 15
16 #if defined(TOOLKIT_VIEWS)
17 #include "views/view.h"
18 #include "views/widget/widget.h"
19 #endif
20
16 namespace { 21 namespace {
17 22
18 guint32 EventTimeNow() { 23 guint32 EventTimeNow() {
19 struct timespec ts; 24 struct timespec ts;
20 clock_gettime(CLOCK_MONOTONIC, &ts); 25 clock_gettime(CLOCK_MONOTONIC, &ts);
21 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; 26 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
22 } 27 }
23 28
24 class EventWaiter : public MessageLoopForUI::Observer { 29 class EventWaiter : public MessageLoopForUI::Observer {
25 public: 30 public:
26 EventWaiter(Task* task, GdkEventType type) : task_(task), type_(type) { 31 EventWaiter(Task* task, GdkEventType type) : task_(task), type_(type) {
27 MessageLoopForUI::current()->AddObserver(this); 32 MessageLoopForUI::current()->AddObserver(this);
28 } 33 }
29 34
30 virtual ~EventWaiter() { 35 virtual ~EventWaiter() {
31 MessageLoopForUI::current()->RemoveObserver(this); 36 MessageLoopForUI::current()->RemoveObserver(this);
32 } 37 }
33 38
34 // MessageLoop::Observer implementation: 39 // MessageLoop::Observer implementation:
35 virtual void WillProcessEvent(GdkEvent* event) { 40 virtual void WillProcessEvent(GdkEvent* event) {
36 // No-op. 41 if (event->type == type_) {
37 } 42 // At the time we're invoked the event has not actually been processed.
38 43 // Use PostTask to make sure the event has been processed before
39 virtual void DidProcessEvent(GdkEvent* event) { 44 // notifying.
40 if (event->any.type == type_) { 45 // NOTE: if processing a message results in running a nested message
41 task_->Run(); 46 // loop, then DidProcessEvent isn't immediately sent. As such, we do
47 // the processing in WillProcessEvent rather than DidProcessEvent.
48 MessageLoop::current()->PostTask(FROM_HERE, task_);
42 delete this; 49 delete this;
43 } 50 }
44 } 51 }
45 52
53 virtual void DidProcessEvent(GdkEvent* event) {
54 // No-op.
55 }
56
46 private: 57 private:
47 scoped_ptr<Task> task_; 58 // We pass ownership of task_ to MessageLoop when the corrent event is
59 // received.
60 Task *task_;
48 GdkEventType type_; 61 GdkEventType type_;
49 }; 62 };
50 63
51 class ClickTask : public Task { 64 class ClickTask : public Task {
52 public: 65 public:
53 ClickTask(ui_controls::MouseButton button, int state, Task* followup) 66 ClickTask(ui_controls::MouseButton button, int state, Task* followup)
54 : button_(button), state_(state), followup_(followup) { 67 : button_(button), state_(state), followup_(followup) {
55 } 68 }
56 69
57 virtual ~ClickTask() {} 70 virtual ~ClickTask() {}
58 71
59 virtual void Run() { 72 virtual void Run() {
60 ui_controls::SendMouseEventsNotifyWhenDone(button_, state_, followup_); 73 if (followup_)
74 ui_controls::SendMouseEventsNotifyWhenDone(button_, state_, followup_);
75 else
76 ui_controls::SendMouseEvents(button_, state_);
61 } 77 }
62 78
63 private: 79 private:
64 ui_controls::MouseButton button_; 80 ui_controls::MouseButton button_;
65 int state_; 81 int state_;
66 Task* followup_; 82 Task* followup_;
67 }; 83 };
68 84
69 } // namespace 85 } // namespace
70 86
71 namespace ui_controls { 87 namespace ui_controls {
72 88
73 bool SendKeyPress(gfx::NativeWindow window, 89 bool SendKeyPress(gfx::NativeWindow window,
74 wchar_t key, bool control, bool shift, bool alt) { 90 wchar_t key, bool control, bool shift, bool alt) {
75 // TODO(estade): send a release as well? 91 // TODO(estade): send a release as well?
76 GdkEvent* event = gdk_event_new(GDK_KEY_PRESS); 92 GdkEvent* event = gdk_event_new(GDK_KEY_PRESS);
77 93
78 event->key.type = GDK_KEY_PRESS; 94 event->key.type = GDK_KEY_PRESS;
79 event->key.window = GTK_WIDGET(window)->window; 95 GtkWidget* grab_widget = gtk_grab_get_current();
96 if (grab_widget) {
97 // If there is a grab, send all events to the grabbed widget.
98 event->key.window = grab_widget->window;
99 } else if (window) {
100 event->key.window = GTK_WIDGET(window)->window;
101 } else {
102 // No target was specified. Send the events to the focused window.
103 GList* windows = gtk_window_list_toplevels();
104 for (GList* element = windows; element; element = g_list_next(element)) {
105 GtkWindow* window = GTK_WINDOW(element->data);
106 if (gtk_window_is_active(window)) {
107 event->key.window = GTK_WIDGET(window)->window;
108 break;
109 }
110 }
111 g_list_free(windows);
112 }
113 DCHECK(event->key.window);
80 g_object_ref(event->key.window); 114 g_object_ref(event->key.window);
81 event->key.send_event = false; 115 event->key.send_event = false;
82 event->key.time = EventTimeNow(); 116 event->key.time = EventTimeNow();
83 117
84 // TODO(estade): handle other state flags besides control, shift, alt? 118 // TODO(estade): handle other state flags besides control, shift, alt?
85 // For example caps lock. 119 // For example caps lock.
86 event->key.state = (control ? GDK_CONTROL_MASK : 0) | 120 event->key.state = (control ? GDK_CONTROL_MASK : 0) |
87 (shift ? GDK_SHIFT_MASK : 0) | 121 (shift ? GDK_SHIFT_MASK : 0) |
88 (alt ? GDK_MOD1_MASK : 0); 122 (alt ? GDK_MOD1_MASK : 0);
89 event->key.keyval = key; 123 event->key.keyval = key;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 return rv; 163 return rv;
130 } 164 }
131 165
132 bool SendMouseEvents(MouseButton type, int state) { 166 bool SendMouseEvents(MouseButton type, int state) {
133 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); 167 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
134 168
135 event->button.send_event = false; 169 event->button.send_event = false;
136 event->button.time = EventTimeNow(); 170 event->button.time = EventTimeNow();
137 171
138 gint x, y; 172 gint x, y;
139 event->button.window = gdk_window_at_pointer(&x, &y); 173 GtkWidget* grab_widget = gtk_grab_get_current();
174 if (grab_widget) {
175 // If there is a grab, we need to target all events at it regardless of
176 // what widget the mouse is over.
177 event->button.window = grab_widget->window;
178 gdk_window_get_pointer(event->button.window, &x, &y, NULL);
179 } else {
180 event->button.window = gdk_window_at_pointer(&x, &y);
181 }
140 g_object_ref(event->button.window); 182 g_object_ref(event->button.window);
141 event->motion.x = x; 183 event->motion.x = x;
142 event->motion.y = y; 184 event->motion.y = y;
143 gint origin_x, origin_y; 185 gint origin_x, origin_y;
144 gdk_window_get_origin(event->button.window, &origin_x, &origin_y); 186 gdk_window_get_origin(event->button.window, &origin_x, &origin_y);
145 event->button.x_root = x + origin_x; 187 event->button.x_root = x + origin_x;
146 event->button.y_root = y + origin_y; 188 event->button.y_root = y + origin_y;
147 189
148 event->button.axes = NULL; 190 event->button.axes = NULL;
149 // TODO(estade): as above, we may want to pack this with the actual state. 191 // TODO(estade): as above, we may want to pack this with the actual state.
(...skipping 13 matching lines...) Expand all
163 gdk_event_put(release_event); 205 gdk_event_put(release_event);
164 206
165 gdk_event_free(event); 207 gdk_event_free(event);
166 gdk_event_free(release_event); 208 gdk_event_free(release_event);
167 209
168 return false; 210 return false;
169 } 211 }
170 212
171 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) { 213 bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, Task* task) {
172 bool rv = SendMouseEvents(type, state); 214 bool rv = SendMouseEvents(type, state);
173 MessageLoop::current()->PostTask(FROM_HERE, task); 215 GdkEventType wait_type;
216 if (state & UP) {
217 wait_type = GDK_BUTTON_RELEASE;
218 } else {
219 if (type == LEFT)
220 wait_type = GDK_BUTTON_PRESS;
221 else if (type == MIDDLE)
222 wait_type = GDK_2BUTTON_PRESS;
223 else
224 wait_type = GDK_3BUTTON_PRESS;
225 }
226 new EventWaiter(task, wait_type);
174 return rv; 227 return rv;
175 } 228 }
176 229
177 bool SendMouseClick(MouseButton type) { 230 bool SendMouseClick(MouseButton type) {
178 return SendMouseEvents(type, UP | DOWN); 231 return SendMouseEvents(type, UP | DOWN);
179 } 232 }
180 233
234 #if defined(TOOLKIT_VIEWS)
235 void MoveMouseToCenterAndPress(views::View* view, MouseButton button,
236 int state, Task* task) {
237 gfx::Point view_center(view->width() / 2, view->height() / 2);
238 views::View::ConvertPointToScreen(view, &view_center);
239 SendMouseMoveNotifyWhenDone(view_center.x(), view_center.y(),
240 new ClickTask(button, state, task));
241 }
242 #else
181 void MoveMouseToCenterAndPress(GtkWidget* widget, 243 void MoveMouseToCenterAndPress(GtkWidget* widget,
182 MouseButton button, 244 MouseButton button,
183 int state, 245 int state,
184 Task* task) { 246 Task* task) {
185 gfx::Rect bounds = gtk_util::GetWidgetScreenBounds(widget); 247 gfx::Rect bounds = gtk_util::GetWidgetScreenBounds(widget);
186 SendMouseMoveNotifyWhenDone(bounds.x() + bounds.width() / 2, 248 SendMouseMoveNotifyWhenDone(bounds.x() + bounds.width() / 2,
187 bounds.y() + bounds.height() / 2, 249 bounds.y() + bounds.height() / 2,
188 new ClickTask(button, state, task)); 250 new ClickTask(button, state, task));
189 } 251 }
252 #endif
190 253
191 } // namespace ui_controls 254 } // namespace ui_controls
OLDNEW
« no previous file with comments | « chrome/browser/automation/ui_controls.h ('k') | chrome/browser/browser_focus_uitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698