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

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

Issue 218017: GTK: First cut at tab dragging automation.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: comments Created 11 years, 3 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
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"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 MessageLoop::current()->PostTask(FROM_HERE, task_); 51 MessageLoop::current()->PostTask(FROM_HERE, task_);
52 delete this; 52 delete this;
53 } 53 }
54 } 54 }
55 55
56 virtual void DidProcessEvent(GdkEvent* event) { 56 virtual void DidProcessEvent(GdkEvent* event) {
57 // No-op. 57 // No-op.
58 } 58 }
59 59
60 private: 60 private:
61 // We pass ownership of task_ to MessageLoop when the corrent event is 61 // We pass ownership of task_ to MessageLoop when the current event is
62 // received. 62 // received.
63 Task *task_; 63 Task* task_;
64 GdkEventType type_; 64 GdkEventType type_;
65 // The number of events of this type to wait for. 65 // The number of events of this type to wait for.
66 int count_; 66 int count_;
67 }; 67 };
68 68
69 class ClickTask : public Task { 69 class ClickTask : public Task {
70 public: 70 public:
71 ClickTask(ui_controls::MouseButton button, int state, Task* followup) 71 ClickTask(ui_controls::MouseButton button, int state, Task* followup)
72 : button_(button), state_(state), followup_(followup) { 72 : button_(button), state_(state), followup_(followup) {
73 } 73 }
74 74
75 virtual ~ClickTask() {} 75 virtual ~ClickTask() {}
76 76
77 virtual void Run() { 77 virtual void Run() {
78 if (followup_) 78 if (followup_)
79 ui_controls::SendMouseEventsNotifyWhenDone(button_, state_, followup_); 79 ui_controls::SendMouseEventsNotifyWhenDone(button_, state_, followup_);
80 else 80 else
81 ui_controls::SendMouseEvents(button_, state_); 81 ui_controls::SendMouseEvents(button_, state_);
82 } 82 }
83 83
84 private: 84 private:
85 ui_controls::MouseButton button_; 85 ui_controls::MouseButton button_;
86 int state_; 86 int state_;
87 Task* followup_; 87 Task* followup_;
88 }; 88 };
89 89
90
91 bool SendKeyEvent(GdkWindow* window, bool press, guint key, guint state) { 90 bool SendKeyEvent(GdkWindow* window, bool press, guint key, guint state) {
92 GdkEvent* event = gdk_event_new(press ? GDK_KEY_PRESS : GDK_KEY_RELEASE); 91 GdkEvent* event = gdk_event_new(press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
93 92
94 event->key.type = press ? GDK_KEY_PRESS : GDK_KEY_RELEASE; 93 event->key.type = press ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
95 event->key.window = window; 94 event->key.window = window;
96 g_object_ref(event->key.window); 95 g_object_ref(event->key.window);
97 event->key.send_event = false; 96 event->key.send_event = false;
98 event->key.time = EventTimeNow(); 97 event->key.time = EventTimeNow();
99 98
100 event->key.state = state; 99 event->key.state = state;
101 event->key.keyval = key; 100 event->key.keyval = key;
102 101
103 GdkKeymapKey* keys; 102 GdkKeymapKey* keys;
104 gint n_keys; 103 gint n_keys;
105 if (!gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), 104 if (!gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(),
106 event->key.keyval, &keys, &n_keys)) { 105 event->key.keyval, &keys, &n_keys)) {
107 return false; 106 return false;
108 } 107 }
109 event->key.hardware_keycode = keys[0].keycode; 108 event->key.hardware_keycode = keys[0].keycode;
110 event->key.group = keys[0].group; 109 event->key.group = keys[0].group;
111 g_free(keys); 110 g_free(keys);
112 111
113 gdk_event_put(event); 112 gdk_event_put(event);
114 // gdk_event_put appends a copy of the event. 113 // gdk_event_put appends a copy of the event.
115 gdk_event_free(event); 114 gdk_event_free(event);
116 return true; 115 return true;
117 } 116 }
118 117
118 void FakeAMouseMotionEvent(gint x, gint y) {
119 GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY);
120
121 event->motion.send_event = false;
122 event->motion.time = EventTimeNow();
123
124 GtkWidget* grab_widget = gtk_grab_get_current();
125 if (grab_widget) {
126 // If there is a grab, we need to target all events at it regardless of
127 // what widget the mouse is over.
128 event->motion.window = grab_widget->window;
129 } else {
130 event->motion.window = gdk_window_at_pointer(&x, &y);
131 }
132 g_object_ref(event->motion.window);
133 event->motion.x = x;
134 event->motion.y = y;
135 gint origin_x, origin_y;
136 gdk_window_get_origin(event->motion.window, &origin_x, &origin_y);
137 event->motion.x_root = x + origin_x;
138 event->motion.y_root = y + origin_y;
139
140 event->motion.device = gdk_device_get_core_pointer();
141 event->type = GDK_MOTION_NOTIFY;
142
143 gdk_event_put(event);
144 gdk_event_free(event);
145 }
146
119 } // namespace 147 } // namespace
120 148
121 namespace ui_controls { 149 namespace ui_controls {
122 150
123 bool SendKeyPress(gfx::NativeWindow window, 151 bool SendKeyPress(gfx::NativeWindow window,
124 wchar_t key, bool control, bool shift, bool alt) { 152 wchar_t key, bool control, bool shift, bool alt) {
125 GdkWindow* event_window = NULL; 153 GdkWindow* event_window = NULL;
126 GtkWidget* grab_widget = gtk_grab_get_current(); 154 GtkWidget* grab_widget = gtk_grab_get_current();
127 if (grab_widget) { 155 if (grab_widget) {
128 // If there is a grab, send all events to the grabbed widget. 156 // If there is a grab, send all events to the grabbed widget.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 if (alt) 226 if (alt)
199 release_count++; 227 release_count++;
200 // This object will delete itself after running |task|. 228 // This object will delete itself after running |task|.
201 new EventWaiter(task, GDK_KEY_RELEASE, release_count); 229 new EventWaiter(task, GDK_KEY_RELEASE, release_count);
202 return SendKeyPress(window, key, control, shift, alt); 230 return SendKeyPress(window, key, control, shift, alt);
203 } 231 }
204 232
205 bool SendMouseMove(long x, long y) { 233 bool SendMouseMove(long x, long y) {
206 gdk_display_warp_pointer(gdk_display_get_default(), gdk_screen_get_default(), 234 gdk_display_warp_pointer(gdk_display_get_default(), gdk_screen_get_default(),
207 x, y); 235 x, y);
236 // Sometimes gdk_display_warp_pointer fails to send back any indication of
237 // the move, even though it succesfully moves the server cursor. We fake it in
238 // order to get drags to work.
239 FakeAMouseMotionEvent(x, y);
240
208 return true; 241 return true;
209 } 242 }
210 243
211 bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) { 244 bool SendMouseMoveNotifyWhenDone(long x, long y, Task* task) {
212 bool rv = SendMouseMove(x, y); 245 bool rv = SendMouseMove(x, y);
213 // We can't rely on any particular event signalling the completion of the 246 // We can't rely on any particular event signalling the completion of the
214 // mouse move. Posting the task to the message loop should gaurantee 247 // mouse move. Posting the task to the message loop hopefully guarantees
215 // the pointer has moved before task is run (although it may not run it as 248 // the pointer has moved before task is run (although it may not run it as
216 // soon as it could). 249 // soon as it could).
217 MessageLoop::current()->PostTask(FROM_HERE, task); 250 MessageLoop::current()->PostTask(FROM_HERE, task);
218 return rv; 251 return rv;
219 } 252 }
220 253
221 bool SendMouseEvents(MouseButton type, int state) { 254 bool SendMouseEvents(MouseButton type, int state) {
222 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); 255 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
223 256
224 event->button.send_event = false; 257 event->button.send_event = false;
225 event->button.time = EventTimeNow(); 258 event->button.time = EventTimeNow();
226 259
227 gint x, y; 260 gint x, y;
228 GtkWidget* grab_widget = gtk_grab_get_current(); 261 GtkWidget* grab_widget = gtk_grab_get_current();
229 if (grab_widget) { 262 if (grab_widget) {
230 // If there is a grab, we need to target all events at it regardless of 263 // If there is a grab, we need to target all events at it regardless of
231 // what widget the mouse is over. 264 // what widget the mouse is over.
232 event->button.window = grab_widget->window; 265 event->button.window = grab_widget->window;
233 gdk_window_get_pointer(event->button.window, &x, &y, NULL); 266 gdk_window_get_pointer(event->button.window, &x, &y, NULL);
234 } else { 267 } else {
235 event->button.window = gdk_window_at_pointer(&x, &y); 268 event->button.window = gdk_window_at_pointer(&x, &y);
236 } 269 }
270
237 g_object_ref(event->button.window); 271 g_object_ref(event->button.window);
238 event->motion.x = x; 272 event->button.x = x;
239 event->motion.y = y; 273 event->button.y = y;
240 gint origin_x, origin_y; 274 gint origin_x, origin_y;
241 gdk_window_get_origin(event->button.window, &origin_x, &origin_y); 275 gdk_window_get_origin(event->button.window, &origin_x, &origin_y);
242 event->button.x_root = x + origin_x; 276 event->button.x_root = x + origin_x;
243 event->button.y_root = y + origin_y; 277 event->button.y_root = y + origin_y;
244 278
245 event->button.axes = NULL; 279 event->button.axes = NULL;
246 // TODO(estade): as above, we may want to pack this with the actual state. 280 gdk_window_get_pointer(event->button.window, NULL, NULL,
247 event->button.state = 0; 281 reinterpret_cast<GdkModifierType*>(&event->button.state));
248 event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3); 282 event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3);
249 event->button.device = gdk_device_get_core_pointer(); 283 event->button.device = gdk_device_get_core_pointer();
250 284
251 event->button.type = GDK_BUTTON_PRESS; 285 event->button.type = GDK_BUTTON_PRESS;
252 if (state & DOWN) 286 if (state & DOWN)
253 gdk_event_put(event); 287 gdk_event_put(event);
254 288
255 // Also send a release event. 289 // Also send a release event.
256 GdkEvent* release_event = gdk_event_copy(event); 290 GdkEvent* release_event = gdk_event_copy(event);
257 release_event->button.type = GDK_BUTTON_RELEASE; 291 release_event->button.type = GDK_BUTTON_RELEASE;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 int state, 334 int state,
301 Task* task) { 335 Task* task) {
302 gfx::Rect bounds = gtk_util::GetWidgetScreenBounds(widget); 336 gfx::Rect bounds = gtk_util::GetWidgetScreenBounds(widget);
303 SendMouseMoveNotifyWhenDone(bounds.x() + bounds.width() / 2, 337 SendMouseMoveNotifyWhenDone(bounds.x() + bounds.width() / 2,
304 bounds.y() + bounds.height() / 2, 338 bounds.y() + bounds.height() / 2,
305 new ClickTask(button, state, task)); 339 new ClickTask(button, state, task));
306 } 340 }
307 #endif 341 #endif
308 342
309 } // namespace ui_controls 343 } // namespace ui_controls
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698