Index: chrome/browser/ui/libgtk2ui/gtk2_event_loop.cc |
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_event_loop.cc b/chrome/browser/ui/libgtk2ui/gtk2_event_loop.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fe32abd3dc7bd7c1a2812df1d4fcc45177d04964 |
--- /dev/null |
+++ b/chrome/browser/ui/libgtk2ui/gtk2_event_loop.cc |
@@ -0,0 +1,80 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/ui/libgtk2ui/gtk2_event_loop.h" |
+ |
+#include <gdk/gdk.h> |
+#include <gdk/gdkx.h> |
+#include <gtk/gtk.h> |
+#include <X11/X.h> |
+ |
+#include "base/memory/singleton.h" |
+#include "base/message_loop/message_pump_x11.h" |
+ |
+namespace libgtk2ui { |
+ |
+// static |
+Gtk2EventLoop* Gtk2EventLoop::GetInstance() { |
+ return Singleton<Gtk2EventLoop>::get(); |
+} |
+ |
+Gtk2EventLoop::Gtk2EventLoop() { |
+ gdk_event_handler_set(GdkEventTrampoline, this, NULL); |
+} |
+ |
+Gtk2EventLoop::~Gtk2EventLoop() { |
+ gdk_event_handler_set(reinterpret_cast<GdkEventFunc>(gtk_main_do_event), |
+ NULL, NULL); |
+} |
+ |
+// static |
+void Gtk2EventLoop::GdkEventTrampoline(GdkEvent* event, gpointer data) { |
+ Gtk2EventLoop* loop = reinterpret_cast<Gtk2EventLoop*>(data); |
+ loop->DispatchGdkEvent(event); |
+} |
+ |
+void Gtk2EventLoop::DispatchGdkEvent(GdkEvent* gdk_event) { |
+ switch (gdk_event->type) { |
+ case GDK_KEY_PRESS: |
+ case GDK_KEY_RELEASE: |
+ ProcessGdkEventKey(gdk_event->key); |
+ break; |
+ default: |
+ break; // Do nothing. |
+ } |
+ |
+ gtk_main_do_event(gdk_event); |
+} |
+ |
+void Gtk2EventLoop::ProcessGdkEventKey(const GdkEventKey& gdk_event_key) { |
+ // This function translates GdkEventKeys into XKeyEvents and puts them to |
+ // the X event queue. |
+ // |
+ // base::MessagePumpX11 is using the X11 event queue and all key events should |
+ // be processed there. However, there are cases(*1) that GdkEventKeys are |
+ // created instead of XKeyEvents. In these cases, we have to translate |
+ // GdkEventKeys to XKeyEvents and puts them to the X event queue so our main |
+ // event loop can handle those key events. |
+ // |
+ // (*1) At least ibus-gtk in async mode creates a copy of user's key event and |
+ // pushes it back to the GDK event queue. In this case, there is no |
+ // corresponding key event in the X event queue. So we have to handle this |
+ // case. ibus-gtk is used through gtk-immodule to support IMEs. |
+ |
+ XEvent x_event = {0}; |
+ x_event.xkey.type = |
+ gdk_event_key.type == GDK_KEY_PRESS ? KeyPress : KeyRelease; |
+ x_event.xkey.send_event = gdk_event_key.send_event; |
+ x_event.xkey.display = base::MessagePumpX11::GetDefaultXDisplay(); |
+ x_event.xkey.window = GDK_WINDOW_XID(gdk_event_key.window); |
+ x_event.xkey.root = DefaultRootWindow(x_event.xkey.display); |
+ x_event.xkey.time = gdk_event_key.time; |
+ x_event.xkey.state = gdk_event_key.state; |
+ x_event.xkey.keycode = gdk_event_key.hardware_keycode; |
+ x_event.xkey.same_screen = true; |
+ |
+ XPutBackEvent(x_event.xkey.display, &x_event); |
+} |
+ |
+} // namespace libgtk2ui |