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

Side by Side Diff: ui/base/test/ui_controls_gtk.cc

Issue 231733005: Delete the GTK+ port of Chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remerge to ToT Created 6 years, 8 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
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/base/test/ui_controls.h"
6
7 #include <gdk/gdkkeysyms.h>
8 #include <gtk/gtk.h>
9
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "ui/base/gtk/event_synthesis_gtk.h"
14 #include "ui/base/gtk/gtk_screen_util.h"
15 #include "ui/gfx/rect.h"
16
17 namespace {
18 bool g_ui_controls_enabled = false;
19
20 // static
21 guint32 XTimeNow() {
22 struct timespec ts;
23 clock_gettime(CLOCK_MONOTONIC, &ts);
24 return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
25 }
26
27 class EventWaiter : public base::MessageLoopForUI::Observer {
28 public:
29 EventWaiter(const base::Closure& task, GdkEventType type, int count)
30 : task_(task),
31 type_(type),
32 count_(count) {
33 base::MessageLoopForUI::current()->AddObserver(this);
34 }
35
36 virtual ~EventWaiter() {
37 base::MessageLoopForUI::current()->RemoveObserver(this);
38 }
39
40 // MessageLoop::Observer implementation:
41 virtual void WillProcessEvent(GdkEvent* event) OVERRIDE {
42 if ((event->type == type_) && (--count_ == 0)) {
43 // At the time we're invoked the event has not actually been processed.
44 // Use PostTask to make sure the event has been processed before
45 // notifying.
46 // NOTE: if processing a message results in running a nested message
47 // loop, then DidProcessEvent isn't immediately sent. As such, we do
48 // the processing in WillProcessEvent rather than DidProcessEvent.
49 base::MessageLoop::current()->PostTask(FROM_HERE, task_);
50 delete this;
51 }
52 }
53
54 virtual void DidProcessEvent(GdkEvent* event) OVERRIDE {
55 // No-op.
56 }
57
58 private:
59 base::Closure task_;
60 GdkEventType type_;
61 // The number of events of this type to wait for.
62 int count_;
63 };
64
65 void FakeAMouseMotionEvent(gint x, gint y) {
66 GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY);
67
68 event->motion.send_event = false;
69 event->motion.time = XTimeNow();
70
71 GtkWidget* grab_widget = gtk_grab_get_current();
72 if (grab_widget) {
73 // If there is a grab, we need to target all events at it regardless of
74 // what widget the mouse is over.
75 event->motion.window = gtk_widget_get_window(grab_widget);
76 } else {
77 event->motion.window = gdk_window_at_pointer(&x, &y);
78 }
79 g_object_ref(event->motion.window);
80 gint window_x, window_y;
81 gdk_window_get_origin(event->motion.window, &window_x, &window_y);
82 event->motion.x = x - window_x;
83 event->motion.y = y - window_y;
84 event->motion.x_root = x;
85 event->motion.y_root = y;
86
87 event->motion.device = gdk_device_get_core_pointer();
88 event->type = GDK_MOTION_NOTIFY;
89
90 gdk_event_put(event);
91 gdk_event_free(event);
92 }
93
94 } // namespace
95
96 namespace ui_controls {
97
98 void EnableUIControls() {
99 g_ui_controls_enabled = true;
100 }
101
102 bool SendKeyPress(gfx::NativeWindow window,
103 ui::KeyboardCode key,
104 bool control,
105 bool shift,
106 bool alt,
107 bool command) {
108 CHECK(g_ui_controls_enabled);
109 DCHECK(!command); // No command key on Linux
110 GdkWindow* event_window = NULL;
111 GtkWidget* grab_widget = gtk_grab_get_current();
112 if (grab_widget) {
113 // If there is a grab, send all events to the grabbed widget.
114 event_window = gtk_widget_get_window(grab_widget);
115 } else if (window) {
116 event_window = gtk_widget_get_window(GTK_WIDGET(window));
117 } else {
118 // No target was specified. Send the events to the active toplevel.
119 GList* windows = gtk_window_list_toplevels();
120 for (GList* element = windows; element; element = g_list_next(element)) {
121 GtkWindow* this_window = GTK_WINDOW(element->data);
122 if (gtk_window_is_active(this_window)) {
123 event_window = gtk_widget_get_window(GTK_WIDGET(this_window));
124 break;
125 }
126 }
127 g_list_free(windows);
128 }
129 if (!event_window) {
130 NOTREACHED() << "Window not specified and none is active";
131 return false;
132 }
133
134 std::vector<GdkEvent*> events;
135 ui::SynthesizeKeyPressEvents(event_window, key, control, shift, alt, &events);
136 for (std::vector<GdkEvent*>::iterator iter = events.begin();
137 iter != events.end(); ++iter) {
138 gdk_event_put(*iter);
139 // gdk_event_put appends a copy of the event.
140 gdk_event_free(*iter);
141 }
142
143 return true;
144 }
145
146 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window,
147 ui::KeyboardCode key,
148 bool control,
149 bool shift,
150 bool alt,
151 bool command,
152 const base::Closure& task) {
153 CHECK(g_ui_controls_enabled);
154 DCHECK(!command); // No command key on Linux
155 int release_count = 1;
156 if (control)
157 release_count++;
158 if (shift)
159 release_count++;
160 if (alt)
161 release_count++;
162 // This object will delete itself after running |task|.
163 new EventWaiter(task, GDK_KEY_RELEASE, release_count);
164 return SendKeyPress(window, key, control, shift, alt, command);
165 }
166
167 bool SendMouseMove(long x, long y) {
168 CHECK(g_ui_controls_enabled);
169 gdk_display_warp_pointer(gdk_display_get_default(), gdk_screen_get_default(),
170 x, y);
171 // Sometimes gdk_display_warp_pointer fails to send back any indication of
172 // the move, even though it succesfully moves the server cursor. We fake it in
173 // order to get drags to work.
174 FakeAMouseMotionEvent(x, y);
175 return true;
176 }
177
178 bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) {
179 CHECK(g_ui_controls_enabled);
180 bool rv = SendMouseMove(x, y);
181 new EventWaiter(task, GDK_MOTION_NOTIFY, 1);
182 return rv;
183 }
184
185 bool SendMouseEvents(MouseButton type, int state) {
186 CHECK(g_ui_controls_enabled);
187 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
188
189 event->button.send_event = false;
190 event->button.time = XTimeNow();
191
192 gint x, y;
193 GtkWidget* grab_widget = gtk_grab_get_current();
194 if (grab_widget) {
195 // If there is a grab, we need to target all events at it regardless of
196 // what widget the mouse is over.
197 event->button.window = gtk_widget_get_window(grab_widget);
198 gdk_window_get_pointer(event->button.window, &x, &y, NULL);
199 } else {
200 event->button.window = gdk_window_at_pointer(&x, &y);
201 CHECK(event->button.window);
202 }
203
204 g_object_ref(event->button.window);
205 event->button.x = x;
206 event->button.y = y;
207 gint origin_x, origin_y;
208 gdk_window_get_origin(event->button.window, &origin_x, &origin_y);
209 event->button.x_root = x + origin_x;
210 event->button.y_root = y + origin_y;
211
212 event->button.axes = NULL;
213 GdkModifierType modifier;
214 gdk_window_get_pointer(event->button.window, NULL, NULL, &modifier);
215 event->button.state = modifier;
216 event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3);
217 event->button.device = gdk_device_get_core_pointer();
218
219 event->button.type = GDK_BUTTON_PRESS;
220 if (state & DOWN)
221 gdk_event_put(event);
222
223 // Also send a release event.
224 GdkEvent* release_event = gdk_event_copy(event);
225 release_event->button.type = GDK_BUTTON_RELEASE;
226 release_event->button.time++;
227 if (state & UP)
228 gdk_event_put(release_event);
229
230 gdk_event_free(event);
231 gdk_event_free(release_event);
232
233 return false;
234 }
235
236 bool SendMouseEventsNotifyWhenDone(MouseButton type,
237 int state,
238 const base::Closure& task) {
239 CHECK(g_ui_controls_enabled);
240 bool rv = SendMouseEvents(type, state);
241 GdkEventType wait_type;
242 if (state & UP) {
243 wait_type = GDK_BUTTON_RELEASE;
244 } else {
245 if (type == LEFT)
246 wait_type = GDK_BUTTON_PRESS;
247 else if (type == MIDDLE)
248 wait_type = GDK_2BUTTON_PRESS;
249 else
250 wait_type = GDK_3BUTTON_PRESS;
251 }
252 new EventWaiter(task, wait_type, 1);
253 return rv;
254 }
255
256 bool SendMouseClick(MouseButton type) {
257 CHECK(g_ui_controls_enabled);
258 return SendMouseEvents(type, UP | DOWN);
259 }
260
261 } // namespace ui_controls
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698