Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/ui_controls/ui_controls.h" | 5 #include "ui/ui_controls/ui_controls.h" |
| 6 | 6 |
| 7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
| 8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 event->type = GDK_MOTION_NOTIFY; | 87 event->type = GDK_MOTION_NOTIFY; |
| 88 | 88 |
| 89 gdk_event_put(event); | 89 gdk_event_put(event); |
| 90 gdk_event_free(event); | 90 gdk_event_free(event); |
| 91 } | 91 } |
| 92 | 92 |
| 93 } // namespace | 93 } // namespace |
| 94 | 94 |
| 95 namespace ui_controls { | 95 namespace ui_controls { |
| 96 | 96 |
| 97 bool SendKeyPress(gfx::NativeWindow window, | 97 namespace { |
| 98 ui::KeyboardCode key, | 98 |
| 99 bool control, | 99 class UIControlsGtk : public UIControls { |
| 100 bool shift, | 100 public: |
| 101 bool alt, | 101 UIControlsGtk() {} |
|
oshima
2012/11/16 20:41:39
virtual ~UIControlsGtk() {}
scottmg
2012/11/16 22:34:06
Done.
| |
| 102 bool command) { | 102 |
| 103 DCHECK(!command); // No command key on Linux | 103 bool SendKeyPress(gfx::NativeWindow window, |
| 104 GdkWindow* event_window = NULL; | 104 ui::KeyboardCode key, |
| 105 GtkWidget* grab_widget = gtk_grab_get_current(); | 105 bool control, |
| 106 if (grab_widget) { | 106 bool shift, |
| 107 // If there is a grab, send all events to the grabbed widget. | 107 bool alt, |
| 108 event_window = gtk_widget_get_window(grab_widget); | 108 bool command) OVERRIDE { |
| 109 } else if (window) { | 109 DCHECK(!command); // No command key on Linux |
| 110 event_window = gtk_widget_get_window(GTK_WIDGET(window)); | 110 GdkWindow* event_window = NULL; |
| 111 } else { | 111 GtkWidget* grab_widget = gtk_grab_get_current(); |
| 112 // No target was specified. Send the events to the active toplevel. | 112 if (grab_widget) { |
| 113 GList* windows = gtk_window_list_toplevels(); | 113 // If there is a grab, send all events to the grabbed widget. |
| 114 for (GList* element = windows; element; element = g_list_next(element)) { | 114 event_window = gtk_widget_get_window(grab_widget); |
| 115 GtkWindow* this_window = GTK_WINDOW(element->data); | 115 } else if (window) { |
| 116 if (gtk_window_is_active(this_window)) { | 116 event_window = gtk_widget_get_window(GTK_WIDGET(window)); |
| 117 event_window = gtk_widget_get_window(GTK_WIDGET(this_window)); | 117 } else { |
| 118 break; | 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 } | |
| 119 } | 126 } |
| 127 g_list_free(windows); | |
| 120 } | 128 } |
| 121 g_list_free(windows); | 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( | |
| 136 event_window, key, control, shift, alt, &events); | |
| 137 for (std::vector<GdkEvent*>::iterator iter = events.begin(); | |
| 138 iter != events.end(); ++iter) { | |
| 139 gdk_event_put(*iter); | |
| 140 // gdk_event_put appends a copy of the event. | |
| 141 gdk_event_free(*iter); | |
| 142 } | |
| 143 | |
| 144 return true; | |
| 122 } | 145 } |
| 123 if (!event_window) { | 146 |
| 124 NOTREACHED() << "Window not specified and none is active"; | 147 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, |
| 148 ui::KeyboardCode key, | |
| 149 bool control, | |
| 150 bool shift, | |
| 151 bool alt, | |
| 152 bool command, | |
| 153 const base::Closure& task) OVERRIDE { | |
| 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) OVERRIDE { | |
| 168 gdk_display_warp_pointer( | |
| 169 gdk_display_get_default(), gdk_screen_get_default(), x, y); | |
| 170 // Sometimes gdk_display_warp_pointer fails to send back any indication of | |
| 171 // the move, even though it succesfully moves the server cursor. We fake | |
| 172 // it in order to get drags to work. | |
| 173 FakeAMouseMotionEvent(x, y); | |
| 174 return true; | |
| 175 } | |
| 176 | |
| 177 bool SendMouseMoveNotifyWhenDone( | |
| 178 long x, long y, const base::Closure& task) OVERRIDE { | |
| 179 bool rv = SendMouseMove(x, y); | |
| 180 new EventWaiter(task, GDK_MOTION_NOTIFY, 1); | |
| 181 return rv; | |
| 182 } | |
| 183 | |
| 184 bool SendMouseEvents(MouseButton type, int state) OVERRIDE { | |
| 185 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); | |
| 186 | |
| 187 event->button.send_event = false; | |
| 188 event->button.time = XTimeNow(); | |
| 189 | |
| 190 gint x, y; | |
| 191 GtkWidget* grab_widget = gtk_grab_get_current(); | |
| 192 if (grab_widget) { | |
| 193 // If there is a grab, we need to target all events at it regardless of | |
| 194 // what widget the mouse is over. | |
| 195 event->button.window = gtk_widget_get_window(grab_widget); | |
| 196 gdk_window_get_pointer(event->button.window, &x, &y, NULL); | |
| 197 } else { | |
| 198 event->button.window = gdk_window_at_pointer(&x, &y); | |
| 199 CHECK(event->button.window); | |
| 200 } | |
| 201 | |
| 202 g_object_ref(event->button.window); | |
| 203 event->button.x = x; | |
| 204 event->button.y = y; | |
| 205 gint origin_x, origin_y; | |
| 206 gdk_window_get_origin(event->button.window, &origin_x, &origin_y); | |
| 207 event->button.x_root = x + origin_x; | |
| 208 event->button.y_root = y + origin_y; | |
| 209 | |
| 210 event->button.axes = NULL; | |
| 211 GdkModifierType modifier; | |
| 212 gdk_window_get_pointer(event->button.window, NULL, NULL, &modifier); | |
| 213 event->button.state = modifier; | |
| 214 event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3); | |
| 215 event->button.device = gdk_device_get_core_pointer(); | |
| 216 | |
| 217 event->button.type = GDK_BUTTON_PRESS; | |
| 218 if (state & DOWN) | |
| 219 gdk_event_put(event); | |
| 220 | |
| 221 // Also send a release event. | |
| 222 GdkEvent* release_event = gdk_event_copy(event); | |
| 223 release_event->button.type = GDK_BUTTON_RELEASE; | |
| 224 release_event->button.time++; | |
| 225 if (state & UP) | |
| 226 gdk_event_put(release_event); | |
| 227 | |
| 228 gdk_event_free(event); | |
| 229 gdk_event_free(release_event); | |
| 230 | |
| 125 return false; | 231 return false; |
| 126 } | 232 } |
| 127 | 233 |
| 128 std::vector<GdkEvent*> events; | 234 bool SendMouseEventsNotifyWhenDone(MouseButton type, |
| 129 ui::SynthesizeKeyPressEvents(event_window, key, control, shift, alt, &events); | 235 int state, |
| 130 for (std::vector<GdkEvent*>::iterator iter = events.begin(); | 236 const base::Closure& task) OVERRIDE { |
| 131 iter != events.end(); ++iter) { | 237 bool rv = SendMouseEvents(type, state); |
| 132 gdk_event_put(*iter); | 238 GdkEventType wait_type; |
| 133 // gdk_event_put appends a copy of the event. | 239 if (state & UP) { |
| 134 gdk_event_free(*iter); | 240 wait_type = GDK_BUTTON_RELEASE; |
| 241 } else { | |
| 242 if (type == LEFT) | |
| 243 wait_type = GDK_BUTTON_PRESS; | |
| 244 else if (type == MIDDLE) | |
| 245 wait_type = GDK_2BUTTON_PRESS; | |
| 246 else | |
| 247 wait_type = GDK_3BUTTON_PRESS; | |
| 248 } | |
| 249 new EventWaiter(task, wait_type, 1); | |
| 250 return rv; | |
| 135 } | 251 } |
| 136 | 252 |
| 137 return true; | 253 bool SendMouseClick(MouseButton type) { |
| 138 } | 254 return SendMouseEvents(type, UP | DOWN); |
| 139 | |
| 140 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, | |
| 141 ui::KeyboardCode key, | |
| 142 bool control, | |
| 143 bool shift, | |
| 144 bool alt, | |
| 145 bool command, | |
| 146 const base::Closure& task) { | |
| 147 DCHECK(!command); // No command key on Linux | |
| 148 int release_count = 1; | |
| 149 if (control) | |
| 150 release_count++; | |
| 151 if (shift) | |
| 152 release_count++; | |
| 153 if (alt) | |
| 154 release_count++; | |
| 155 // This object will delete itself after running |task|. | |
| 156 new EventWaiter(task, GDK_KEY_RELEASE, release_count); | |
| 157 return SendKeyPress(window, key, control, shift, alt, command); | |
| 158 } | |
| 159 | |
| 160 bool SendMouseMove(long x, long y) { | |
| 161 gdk_display_warp_pointer(gdk_display_get_default(), gdk_screen_get_default(), | |
| 162 x, y); | |
| 163 // Sometimes gdk_display_warp_pointer fails to send back any indication of | |
| 164 // the move, even though it succesfully moves the server cursor. We fake it in | |
| 165 // order to get drags to work. | |
| 166 FakeAMouseMotionEvent(x, y); | |
| 167 return true; | |
| 168 } | |
| 169 | |
| 170 bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) { | |
| 171 bool rv = SendMouseMove(x, y); | |
| 172 new EventWaiter(task, GDK_MOTION_NOTIFY, 1); | |
| 173 return rv; | |
| 174 } | |
| 175 | |
| 176 bool SendMouseEvents(MouseButton type, int state) { | |
| 177 GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); | |
| 178 | |
| 179 event->button.send_event = false; | |
| 180 event->button.time = XTimeNow(); | |
| 181 | |
| 182 gint x, y; | |
| 183 GtkWidget* grab_widget = gtk_grab_get_current(); | |
| 184 if (grab_widget) { | |
| 185 // If there is a grab, we need to target all events at it regardless of | |
| 186 // what widget the mouse is over. | |
| 187 event->button.window = gtk_widget_get_window(grab_widget); | |
| 188 gdk_window_get_pointer(event->button.window, &x, &y, NULL); | |
| 189 } else { | |
| 190 event->button.window = gdk_window_at_pointer(&x, &y); | |
| 191 CHECK(event->button.window); | |
| 192 } | 255 } |
| 193 | 256 |
| 194 g_object_ref(event->button.window); | 257 private: |
| 195 event->button.x = x; | 258 DISALLOW_COPY_AND_ASSIGN(UIControlsGtk); |
| 196 event->button.y = y; | 259 }; |
| 197 gint origin_x, origin_y; | |
| 198 gdk_window_get_origin(event->button.window, &origin_x, &origin_y); | |
| 199 event->button.x_root = x + origin_x; | |
| 200 event->button.y_root = y + origin_y; | |
| 201 | 260 |
| 202 event->button.axes = NULL; | 261 } // namespace |
| 203 GdkModifierType modifier; | |
| 204 gdk_window_get_pointer(event->button.window, NULL, NULL, &modifier); | |
| 205 event->button.state = modifier; | |
| 206 event->button.button = type == LEFT ? 1 : (type == MIDDLE ? 2 : 3); | |
| 207 event->button.device = gdk_device_get_core_pointer(); | |
| 208 | 262 |
| 209 event->button.type = GDK_BUTTON_PRESS; | 263 UIControls* CreateNativeUIControls() { |
| 210 if (state & DOWN) | 264 return new UIControlsGtk; |
| 211 gdk_event_put(event); | |
| 212 | |
| 213 // Also send a release event. | |
| 214 GdkEvent* release_event = gdk_event_copy(event); | |
| 215 release_event->button.type = GDK_BUTTON_RELEASE; | |
| 216 release_event->button.time++; | |
| 217 if (state & UP) | |
| 218 gdk_event_put(release_event); | |
| 219 | |
| 220 gdk_event_free(event); | |
| 221 gdk_event_free(release_event); | |
| 222 | |
| 223 return false; | |
| 224 } | |
| 225 | |
| 226 bool SendMouseEventsNotifyWhenDone(MouseButton type, | |
| 227 int state, | |
| 228 const base::Closure& task) { | |
| 229 bool rv = SendMouseEvents(type, state); | |
| 230 GdkEventType wait_type; | |
| 231 if (state & UP) { | |
| 232 wait_type = GDK_BUTTON_RELEASE; | |
| 233 } else { | |
| 234 if (type == LEFT) | |
| 235 wait_type = GDK_BUTTON_PRESS; | |
| 236 else if (type == MIDDLE) | |
| 237 wait_type = GDK_2BUTTON_PRESS; | |
| 238 else | |
| 239 wait_type = GDK_3BUTTON_PRESS; | |
| 240 } | |
| 241 new EventWaiter(task, wait_type, 1); | |
| 242 return rv; | |
| 243 } | |
| 244 | |
| 245 bool SendMouseClick(MouseButton type) { | |
| 246 return SendMouseEvents(type, UP | DOWN); | |
| 247 } | 265 } |
| 248 | 266 |
| 249 } // namespace ui_controls | 267 } // namespace ui_controls |
| OLD | NEW |