Bug 1511973 - [Wayland] Listen for keyboard layout changes on wl_seat again, r=jhorak
authorMartin Stransky <stransky@redhat.com>
Wed, 05 Dec 2018 19:57:04 +0000
changeset 505935 d932537fec3b
parent 505934 c1f4c5673aae
child 505936 5ca5e911d32f
child 505943 92080f90bad8
push id10301
push userarchaeopteryx@coole-files.de
push dateThu, 06 Dec 2018 16:36:14 +0000
treeherdermozilla-beta@7d2f3c71997c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjhorak
bugs1511973
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1511973 - [Wayland] Listen for keyboard layout changes on wl_seat again, r=jhorak We can't listen on GdkDeviceManager as we need to track device changes here. Rvert back the old working setup based on wl_seat listeners. Also check if the keyboard is already present (before it's created here) to avoid memory leaks. Differential Revision: https://phabricator.services.mozilla.com/D13727
widget/gtk/nsGtkKeyUtils.cpp
--- a/widget/gtk/nsGtkKeyUtils.cpp
+++ b/widget/gtk/nsGtkKeyUtils.cpp
@@ -538,64 +538,74 @@ static void keyboard_handle_keymap(void*
   static auto sXkbContextUnref =
       (void (*)(struct xkb_context*))dlsym(RTLD_DEFAULT, "xkb_context_unref");
   sXkbContextUnref(xkb_context);
 }
 
 static void keyboard_handle_enter(void* data, struct wl_keyboard* keyboard,
                                   uint32_t serial, struct wl_surface* surface,
                                   struct wl_array* keys) {}
-
 static void keyboard_handle_leave(void* data, struct wl_keyboard* keyboard,
                                   uint32_t serial, struct wl_surface* surface) {
 }
-
 static void keyboard_handle_key(void* data, struct wl_keyboard* keyboard,
                                 uint32_t serial, uint32_t time, uint32_t key,
                                 uint32_t state) {}
-
 static void keyboard_handle_modifiers(void* data, struct wl_keyboard* keyboard,
                                       uint32_t serial, uint32_t mods_depressed,
                                       uint32_t mods_latched,
                                       uint32_t mods_locked, uint32_t group) {}
 
 static const struct wl_keyboard_listener keyboard_listener = {
     keyboard_handle_keymap, keyboard_handle_enter,     keyboard_handle_leave,
     keyboard_handle_key,    keyboard_handle_modifiers,
 };
 
-void KeymapWrapper::InitBySystemSettingsWayland() {
-  GdkDeviceManager* manager =
-      gdk_display_get_device_manager(gdk_display_get_default());
-  GList* devices =
-      gdk_device_manager_list_devices(manager, GDK_DEVICE_TYPE_MASTER);
-  GdkDevice* device = nullptr;
+static void seat_handle_capabilities(void* data, struct wl_seat* seat,
+                                     unsigned int caps) {
+  static wl_keyboard* keyboard = nullptr;
 
-  GList* list = devices;
-  while (devices) {
-    device = static_cast<GdkDevice*>(devices->data);
-    if (gdk_device_get_source(device) == GDK_SOURCE_KEYBOARD) {
-      break;
-    }
-    devices = devices->next;
+  if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !keyboard) {
+    keyboard = wl_seat_get_keyboard(seat);
+    wl_keyboard_add_listener(keyboard, &keyboard_listener, nullptr);
+  } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && keyboard) {
+    wl_keyboard_destroy(keyboard);
+    keyboard = nullptr;
   }
+}
 
-  if (list) {
-    g_list_free(list);
+static const struct wl_seat_listener seat_listener = {
+    seat_handle_capabilities,
+};
+
+static void gdk_registry_handle_global(void* data, struct wl_registry* registry,
+                                       uint32_t id, const char* interface,
+                                       uint32_t version) {
+  if (strcmp(interface, "wl_seat") == 0) {
+    wl_seat* seat =
+        (wl_seat*)wl_registry_bind(registry, id, &wl_seat_interface, 1);
+    wl_seat_add_listener(seat, &seat_listener, data);
   }
+}
 
-  if (device) {
-    // Present in Gtk+ 3.10
-    static auto sGdkWaylandDeviceGetWlKeyboard =
-        (struct wl_keyboard * (*)(GdkDevice * device))
-            dlsym(RTLD_DEFAULT, "gdk_wayland_device_get_wl_keyboard");
+static void gdk_registry_handle_global_remove(void* data,
+                                              struct wl_registry* registry,
+                                              uint32_t id) {}
+
+static const struct wl_registry_listener keyboard_registry_listener = {
+    gdk_registry_handle_global, gdk_registry_handle_global_remove};
 
-    wl_keyboard_add_listener(sGdkWaylandDeviceGetWlKeyboard(device),
-                             &keyboard_listener, nullptr);
-  }
+void KeymapWrapper::InitBySystemSettingsWayland() {
+  // Available as of GTK 3.8+
+  static auto sGdkWaylandDisplayGetWlDisplay = (wl_display * (*)(GdkDisplay*))
+      dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
+  wl_display* display =
+      sGdkWaylandDisplayGetWlDisplay(gdk_display_get_default());
+  wl_registry_add_listener(wl_display_get_registry(display),
+                           &keyboard_registry_listener, this);
 }
 #endif
 
 KeymapWrapper::~KeymapWrapper() {
   gdk_window_remove_filter(nullptr, FilterEvents, this);
   g_signal_handlers_disconnect_by_func(mGdkKeymap,
                                        FuncToGpointer(OnKeysChanged), this);
   g_signal_handlers_disconnect_by_func(