Bug 564799 - [GTK4] Adapt to GdkKeymap API changes

Suggestions from:
https://developer.gnome.org/gtk4/stable/ch40s02.html#id-1.7.4.4.12

- Added gdk_display_map_keyval as a replacement of
gdk_keymap_get_entries_for_keyval

- Removed gdk_display_get_keymap which doesn't exist in GTK4
	- Redirect keyChanged signal to keyboard device as suggested

- Gtk4 specific case in Display#findLatinKeygroup
- Gtk4 specific case in Display#post

Change-Id: Ibcb279449358e2a031825be6c0607953eadb26f9
Signed-off-by: Paul D'Pong <sdamrong@redhat.com>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
index c255b1f..420e93c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
@@ -580,18 +580,6 @@
 }
 #endif
 
-#ifndef NO_gdk_1display_1get_1keymap
-JNIEXPORT jlong JNICALL GDK_NATIVE(gdk_1display_1get_1keymap)
-	(JNIEnv *env, jclass that, jlong arg0)
-{
-	jlong rc = 0;
-	GDK_NATIVE_ENTER(env, that, gdk_1display_1get_1keymap_FUNC);
-	rc = (jlong)gdk_display_get_keymap((GdkDisplay *)arg0);
-	GDK_NATIVE_EXIT(env, that, gdk_1display_1get_1keymap_FUNC);
-	return rc;
-}
-#endif
-
 #ifndef NO_gdk_1display_1get_1monitor
 JNIEXPORT jlong JNICALL GDK_NATIVE(gdk_1display_1get_1monitor)
 	(JNIEnv *env, jclass that, jlong arg0, jint arg1)
@@ -728,6 +716,33 @@
 }
 #endif
 
+#ifndef NO_gdk_1display_1map_1keyval
+JNIEXPORT jboolean JNICALL GDK_NATIVE(gdk_1display_1map_1keyval)
+	(JNIEnv *env, jclass that, jlong arg0, jint arg1, jlongArray arg2, jintArray arg3)
+{
+	jlong *lparg2=NULL;
+	jint *lparg3=NULL;
+	jboolean rc = 0;
+	GDK_NATIVE_ENTER(env, that, gdk_1display_1map_1keyval_FUNC);
+	if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail;
+	if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+/*
+	rc = (jboolean)gdk_display_map_keyval((GdkDisplay *)arg0, (guint)arg1, (GdkKeymapKey**)lparg2, (gint*)lparg3);
+*/
+	{
+		GDK_LOAD_FUNCTION(fp, gdk_display_map_keyval)
+		if (fp) {
+			rc = (jboolean)((jboolean (CALLING_CONVENTION*)(GdkDisplay *, guint, GdkKeymapKey**, gint*))fp)((GdkDisplay *)arg0, (guint)arg1, (GdkKeymapKey**)lparg2, (gint*)lparg3);
+		}
+	}
+fail:
+	if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
+	if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0);
+	GDK_NATIVE_EXIT(env, that, gdk_1display_1map_1keyval_FUNC);
+	return rc;
+}
+#endif
+
 #ifndef NO_gdk_1display_1peek_1event
 JNIEXPORT jlong JNICALL GDK_NATIVE(gdk_1display_1peek_1event)
 	(JNIEnv *env, jclass that, jlong arg0)
@@ -1231,7 +1246,15 @@
 	GDK_NATIVE_ENTER(env, that, gdk_1keymap_1get_1entries_1for_1keyval_FUNC);
 	if (arg2) if ((lparg2 = (*env)->GetLongArrayElements(env, arg2, NULL)) == NULL) goto fail;
 	if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail;
+/*
 	rc = (jboolean)gdk_keymap_get_entries_for_keyval((GdkKeymap*)arg0, (guint)arg1, (GdkKeymapKey**)lparg2, (gint*)lparg3);
+*/
+	{
+		GDK_LOAD_FUNCTION(fp, gdk_keymap_get_entries_for_keyval)
+		if (fp) {
+			rc = (jboolean)((jboolean (CALLING_CONVENTION*)(GdkKeymap*, guint, GdkKeymapKey**, gint*))fp)((GdkKeymap*)arg0, (guint)arg1, (GdkKeymapKey**)lparg2, (gint*)lparg3);
+		}
+	}
 fail:
 	if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0);
 	if (arg2 && lparg2) (*env)->ReleaseLongArrayElements(env, arg2, lparg2, 0);
@@ -1274,7 +1297,15 @@
 	if (arg5) if ((lparg5 = (*env)->GetIntArrayElements(env, arg5, NULL)) == NULL) goto fail;
 	if (arg6) if ((lparg6 = (*env)->GetIntArrayElements(env, arg6, NULL)) == NULL) goto fail;
 	if (arg7) if ((lparg7 = (*env)->GetIntArrayElements(env, arg7, NULL)) == NULL) goto fail;
+/*
 	rc = (jboolean)gdk_keymap_translate_keyboard_state((GdkKeymap *)arg0, (guint)arg1, (GdkModifierType)arg2, (gint)arg3, (guint *)lparg4, (gint *)lparg5, (gint *)lparg6, (GdkModifierType *)lparg7);
+*/
+	{
+		GDK_LOAD_FUNCTION(fp, gdk_keymap_translate_keyboard_state)
+		if (fp) {
+			rc = (jboolean)((jboolean (CALLING_CONVENTION*)(GdkKeymap *, guint, GdkModifierType, gint, guint *, gint *, gint *, GdkModifierType *))fp)((GdkKeymap *)arg0, (guint)arg1, (GdkModifierType)arg2, (gint)arg3, (guint *)lparg4, (gint *)lparg5, (gint *)lparg6, (GdkModifierType *)lparg7);
+		}
+	}
 fail:
 	if (arg7 && lparg7) (*env)->ReleaseIntArrayElements(env, arg7, lparg7, 0);
 	if (arg6 && lparg6) (*env)->ReleaseIntArrayElements(env, arg6, lparg6, 0);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h
index 867aac7..0026439 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h
@@ -369,6 +369,10 @@
 #define NO_gdk_1display_1supports_1cursor_1color
 #define NO_gdk_1cursor_1new_1from_1name__JLjava_lang_String_2
 
+// GdkKeymap removals
+#define NO_gdk_1keymap_1translate_1keyboard_1state
+#define NO_gdk_1keymap_1get_1entries_1for_1keyval
+
 #else
 
 /**
@@ -435,7 +439,6 @@
 // Miscellaneous functions not present on GTK3
 #define NO_gdk_1device_1warp__III
 #define NO_gdk_1device_1warp__JII
-#define NO_gdk_1display_1get_1keymap
 #define NO_gtk_1widget_1measure
 #define NO_gtk_1style_1context_1add_1provider_1for_1display
 #define NO_gtk_1widget_1get_1first_1child
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
index 4980c75..ca23100 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
@@ -64,7 +64,6 @@
 	"gdk_1display_1get_1default",
 	"gdk_1display_1get_1default_1group",
 	"gdk_1display_1get_1default_1seat",
-	"gdk_1display_1get_1keymap",
 	"gdk_1display_1get_1monitor",
 	"gdk_1display_1get_1monitor_1at_1point",
 	"gdk_1display_1get_1monitor_1at_1surface",
@@ -73,6 +72,7 @@
 	"gdk_1display_1get_1primary_1clipboard",
 	"gdk_1display_1get_1primary_1monitor",
 	"gdk_1display_1is_1composited",
+	"gdk_1display_1map_1keyval",
 	"gdk_1display_1peek_1event",
 	"gdk_1display_1put_1event",
 	"gdk_1display_1supports_1cursor_1color",
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
index 7ddac47..33306da 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
@@ -74,7 +74,6 @@
 	gdk_1display_1get_1default_FUNC,
 	gdk_1display_1get_1default_1group_FUNC,
 	gdk_1display_1get_1default_1seat_FUNC,
-	gdk_1display_1get_1keymap_FUNC,
 	gdk_1display_1get_1monitor_FUNC,
 	gdk_1display_1get_1monitor_1at_1point_FUNC,
 	gdk_1display_1get_1monitor_1at_1surface_FUNC,
@@ -83,6 +82,7 @@
 	gdk_1display_1get_1primary_1clipboard_FUNC,
 	gdk_1display_1get_1primary_1monitor_FUNC,
 	gdk_1display_1is_1composited_FUNC,
+	gdk_1display_1map_1keyval_FUNC,
 	gdk_1display_1peek_1event_FUNC,
 	gdk_1display_1put_1event_FUNC,
 	gdk_1display_1supports_1cursor_1color_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java
index 1999f7e..b26bf6a 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java
@@ -630,11 +630,16 @@
 	/* [GTK3 only] */
 	public static final native long gdk_keymap_get_for_display(long display);
 	/**
+	 * @method flags=dynamic
 	 * @param display cast=(GdkDisplay *)
+	 * @param keyval cast=(guint)
+	 * @param keys cast=(GdkKeymapKey**)
+	 * @param n_keys cast=(gint*)
 	 */
 	/* [GTK4 only, if-def'd in os.h] */
-	public static final native long gdk_display_get_keymap(long display);
+	public static final native boolean gdk_display_map_keyval(long display, int keyval, long[] keys, int[] n_keys);
 	/**
+	 * @method flags=dynamic
 	 * @param keymap cast=(GdkKeymap *)
 	 * @param hardware_keycode cast=(guint)
 	 * @param state cast=(GdkModifierType)
@@ -644,13 +649,16 @@
 	 * @param level cast=(gint *)
 	 * @param consumed_modifiers cast=(GdkModifierType *)
 	 */
+	/* [GTK3 only] */
 	public static final native boolean gdk_keymap_translate_keyboard_state(long keymap, int hardware_keycode, int state, int group, int[] keyval, int[] effective_group, int[] level,  int[] consumed_modifiers);
 	/**
+	 * @method flags=dynamic
 	 * @param keymap cast=(GdkKeymap*)
 	 * @param keyval cast=(guint)
 	 * @param keys cast=(GdkKeymapKey**)
 	 * @param n_keys cast=(gint*)
 	 */
+	/* [GTK3 only] */
 	public static final native boolean gdk_keymap_get_entries_for_keyval(long keymap, int keyval, long [] keys, int[] n_keys);
 	public static final native long gdk_keyval_to_lower(long keyval);
 	public static final native long gdk_keyval_to_unicode(long keyval);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
index 14a973b..46ca33b 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
@@ -1234,11 +1234,12 @@
 	long keymap;
 	long display = GDK.gdk_display_get_default();
 	if (GTK.GTK4) {
-		keymap = GDK.gdk_display_get_keymap(display);
+		long keyboardDevice = GDK.gdk_seat_get_keyboard(GDK.gdk_display_get_default_seat(display));
+		OS.g_signal_connect (keyboardDevice, OS.changed, keysChangedProc, 0);
 	} else {
 		keymap = GDK.gdk_keymap_get_for_display(display);
+		OS.g_signal_connect (keymap, OS.keys_changed, keysChangedProc, 0);
 	}
-	OS.g_signal_connect (keymap, OS.keys_changed, keysChangedProc, 0);
 }
 
 /**
@@ -1250,20 +1251,22 @@
 private int findLatinKeyGroup () {
 	int result = 0;
 	groupKeysCount = new HashMap<> ();
-	long keymap;
 	long display = GDK.gdk_display_get_default();
-	if (GTK.GTK4) {
-		keymap = GDK.gdk_display_get_keymap(display);
-	} else {
-		keymap = GDK.gdk_keymap_get_for_display(display);
-	}
 
 	// count all key groups for Latin alphabet
 	for (int keyval = GDK.GDK_KEY_a; keyval <= GDK.GDK_KEY_z; keyval++) {
 		long [] keys = new long [1];
 		int [] n_keys = new int [1];
 
-		if (GDK.gdk_keymap_get_entries_for_keyval (keymap, keyval, keys, n_keys)) {
+		boolean foundKeys;
+		if (GTK.GTK4) {
+			foundKeys = GDK.gdk_display_map_keyval(display, keyval, keys, n_keys);
+		} else {
+			long keymap = GDK.gdk_keymap_get_for_display(display);
+			foundKeys = GDK.gdk_keymap_get_entries_for_keyval (keymap, keyval, keys, n_keys);
+		}
+
+		if (foundKeys) {
 			GdkKeymapKey key_entry = new GdkKeymapKey ();
 			for (int key = 0; key < n_keys [0]; key++) {
 				OS.memmove (key_entry, keys [0] + key * GdkKeymapKey.sizeof, GdkKeymapKey.sizeof);
@@ -4270,7 +4273,6 @@
 					cachedModifierState = 0;
 				}
 
-				long gdkKeymap = GDK.gdk_keymap_get_for_display(gdkDisplay);
 				int hardware_keycode = 0;
 				int raw_keyval = untranslateKey(event.keyCode);
 				if (raw_keyval == 0) raw_keyval = event.character;
@@ -4280,7 +4282,15 @@
 				int [] keyval = new int [1], effective_group = new int [1], level = new int [1], consumed_modifiers = new int[1];
 				int final_keyval = raw_keyval;
 
-				if (GDK.gdk_keymap_get_entries_for_keyval(gdkKeymap, raw_keyval, keys_list, n_keys)) {
+				boolean foundKeys;
+				if (GTK.GTK4) {
+					foundKeys = GDK.gdk_display_map_keyval(gdkDisplay, raw_keyval, keys_list, n_keys);
+				} else {
+					long keymap = GDK.gdk_keymap_get_for_display(gdkDisplay);
+					foundKeys = GDK.gdk_keymap_get_entries_for_keyval (keymap, raw_keyval, keys_list, n_keys);
+				}
+
+				if (foundKeys) {
 					GdkKeymapKey key_entry = new GdkKeymapKey ();
 					if (n_keys[0] > 0) {
 						OS.memmove(key_entry, keys_list[0], GdkKeymapKey.sizeof);
@@ -4288,7 +4298,8 @@
 					}
 					OS.g_free(keys_list[0]);
 
-					GDK.gdk_keymap_translate_keyboard_state(gdkKeymap, hardware_keycode, state, 0, keyval, effective_group, level, consumed_modifiers);
+					long keymap = GDK.gdk_keymap_get_for_display(gdkDisplay);
+					GDK.gdk_keymap_translate_keyboard_state(keymap, hardware_keycode, state, 0, keyval, effective_group, level, consumed_modifiers);
 					if (is_modifier == 1) final_keyval = keyval[0];
 				}
 
@@ -4308,8 +4319,7 @@
 				OS.memmove(eventPtr, newKeyEvent, GdkEventKey.sizeof);
 				GDK.gdk_event_set_device (eventPtr, gdkKeyboardDevice);
 				if (GTK.GTK4) {
-					long display = GDK.gdk_display_get_default();
-					GDK.gdk_display_put_event(display, eventPtr);
+					GDK.gdk_display_put_event(gdkDisplay, eventPtr);
 				} else {
 					GDK.gdk_event_put (eventPtr);
 				}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
index 4501887..ea39d1a 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
@@ -1776,23 +1776,13 @@
 		default: {
 			if (javaEvent.keyCode == 0) {
 				int [] keyval = new int [1];
-				int [] effective_group = new int [1], level = new int [1], consumed_modifiers = new int [1];
 				/* If current group is not a Latin layout, get the most Latin Layout group from input source. */
 				Map<Integer, Integer> groupLatinKeysCount = display.getGroupKeysCount();
 				if (!groupLatinKeysCount.containsKey(group)) {
 					group = display.getLatinKeyGroup();
 				}
-				long keymap = 0;
-				long display = GDK.gdk_display_get_default();
-				if (GTK.GTK4) {
-					keymap = GDK.gdk_display_get_keymap(display);
-				} else {
-					keymap = GDK.gdk_keymap_get_for_display(display);
-				}
-				short [] keyCode = new short [1];
-				GDK.gdk_event_get_keycode(event, keyCode);
-				if (GDK.gdk_keymap_translate_keyboard_state (keymap, keyCode[0],
-						0, group, keyval, effective_group, level, consumed_modifiers)) {
+
+				if (GDK.gdk_event_get_keyval(event, keyval)) {
 					javaEvent.keyCode = (int) GDK.gdk_keyval_to_unicode (keyval [0]);
 				}
 			}