From 95e0cb1ec0942a6f24e42af56a2cb1c308d6d9b8 Mon Sep 17 00:00:00 2001 From: Xi Yan Date: Mon, 17 Sep 2018 16:57:49 -0400 Subject: Bug 533395 - [Gtk][Regression] Keyboard shortcuts are taken from first item in "Input Source" instead of currently active input, thus breaking custom layouts (e.g Dvorak/Colemak/AZERTY) if it's not default layout. Previous patch to bug 61190 forces every keyboard layout to use any Latin layout group (depending on order of Map). For custom layouts that is a Latin layout group (i.e. contains alphabets a-z), there is no need to force an arbitrary Latin layout group for them as it might default to another layout if there are multiple input sources. Take the current active input layout if it is Latin group, otherwise take the default Latin group to prevent shortcuts not working for non-English keyboard. The patch applies to X11 only. On Wayland, GdkEventKey.group always defaults to the primary layout. Tested with attached snippet: Ctrl+i/Ctrl+. should copy/paste in both StyledText and Text in Dvorak. In child Eclipse: Ctrl+i/Ctrl+. copy/paste text in Dvorak, shortcuts should work under Russian keyboard. Change-Id: Iab4ee98060b3062bad1c5952436f2bed27225d07 Signed-off-by: Xi Yan --- .../gtk/org/eclipse/swt/widgets/Display.java | 17 +++++++-- .../gtk/org/eclipse/swt/widgets/Widget.java | 11 +++++- .../gtk/snippets/Bug533395_KeyboardShortcut.java | 43 ++++++++++++++++++++++ 3 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533395_KeyboardShortcut.java 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 782537482b..dfa7ec5da7 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 @@ -440,6 +440,9 @@ public class Display extends Device { /* Latin layout key group */ private int latinKeyGroup; + /* Mapping from layout key group to number of Latin alphabet keys. See Bug 533395, Bug 61190. */ + Map groupKeysCount; + /* Keymap "keys-changed" callback */ long /*int*/ keysChangedProc; Callback keysChangedCallback; @@ -1125,13 +1128,14 @@ void createDisplay (DeviceData data) { } /** - * Determine key group of Latin layout. + * Determine key group of Latin layout, and update the layout group to key count map. + * If there are multiple Latin keyboard layout group, return the first one. * - * @return the most Latin keyboard layout group + * @return the most Latin keyboard layout group (i.e. group holding the max number of Latin alphabet keys) */ private int findLatinKeyGroup () { int result = 0; - Map groupKeysCount = new HashMap<> (); + groupKeysCount = new HashMap<> (); long /*int*/ keymap = GDK.gdk_keymap_get_default (); // count all key groups for Latin alphabet @@ -1176,6 +1180,13 @@ int getLatinKeyGroup () { return latinKeyGroup; } +/** + * Return a mapping from layout group to the number of Latin alphabet (a-z) in each group + */ +Map getGroupKeysCount () { + return groupKeysCount; +} + /** * 'keys-changed' event handler. * Updates the most Latin keyboard layout group field. 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 74e6d50ddb..fe6648b75b 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 @@ -14,6 +14,8 @@ package org.eclipse.swt.widgets; +import java.util.*; + import org.eclipse.swt.*; import org.eclipse.swt.events.*; import org.eclipse.swt.internal.*; @@ -1662,7 +1664,14 @@ boolean setKeyState (Event event, GdkEventKey keyEvent) { if (event.keyCode == 0) { long [] keyval = new long [1]; int [] effective_group = new int [1], level = new int [1], consumed_modifiers = new int [1]; - if (OS.gdk_keymap_translate_keyboard_state (GDK.gdk_keymap_get_default (), keyEvent.hardware_keycode, 0, display.getLatinKeyGroup(), keyval, effective_group, level, consumed_modifiers)) { + /* If current group is not a Latin layout, get the most Latin Layout group from input source. */ + Map groupLatinKeysCount = display.getGroupKeysCount(); + int keyLayoutGroup = keyEvent.group; + if (!groupLatinKeysCount.containsKey(keyLayoutGroup)) { + keyLayoutGroup = display.getLatinKeyGroup(); + } + if (OS.gdk_keymap_translate_keyboard_state (GDK.gdk_keymap_get_default (), keyEvent.hardware_keycode, + 0, keyLayoutGroup, keyval, effective_group, level, consumed_modifiers)) { event.keyCode = (int) GDK.gdk_keyval_to_unicode (keyval [0]); } } diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533395_KeyboardShortcut.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533395_KeyboardShortcut.java new file mode 100644 index 0000000000..ec2ad7bfbf --- /dev/null +++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533395_KeyboardShortcut.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2018 Red Hat and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.tests.gtk.snippets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +public class Bug533395_KeyboardShortcut { + public static void main (String [] args) { + Display display = new Display (); + Shell shell = new Shell(display); + + shell.setLayout(new FillLayout()); + + StyledText styledText = new StyledText(shell, SWT.BORDER); + styledText.setText("StyledText"); + + Text text = new Text(shell, SWT.BORDER); + text.setText("Text"); + + shell.open (); + while (!shell.isDisposed ()) { + if (!display.readAndDispatch ()) display.sleep (); + } + display.dispose (); + } + +} -- cgit v1.2.3