Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXi Yan2018-08-02 13:08:25 -0400
committerAlexander Kurtakov2018-08-04 08:04:31 -0400
commite7d5fd30562726d69d90d36803450f0de3d59c4e (patch)
tree3bc336a2f9ec83ad979a8676d6e03d5a52ccff23
parent35c14d6152ad0f9431f998d2f1b3849f4eb258bb (diff)
downloadeclipse.platform.swt-e7d5fd30562726d69d90d36803450f0de3d59c4e.tar.gz
eclipse.platform.swt-e7d5fd30562726d69d90d36803450f0de3d59c4e.tar.xz
eclipse.platform.swt-e7d5fd30562726d69d90d36803450f0de3d59c4e.zip
Bug 537025 - SWT + GTK3 + Sending key events programmatically
Fixed regression from Bug 302171 where sending modifier as a separate key event does not work. Sending GDK_KEY_PRESS event using gdk_test_simulate_key will not hold key down infinitely until a GDK_KEY_RELEASE event is sent. The modifier is cached in case modifiers are sent in separate event to Display.post(). Tested using attached snippet and Snippet146. Change-Id: I2c9b617345b3f92c3a32299e64ce7f1ce5ef7992 Signed-off-by: Xi Yan <xixiyan@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java31
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug537025_SendKeyEvent.java231
2 files changed, 256 insertions, 6 deletions
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 68b5de99d6..9353253272 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
@@ -443,6 +443,9 @@ public class Display extends Device {
};
+ /* Cache pressed modifier. See Bug 537025. */
+ int cachedModifier = 0;
+
/* Latin layout key group */
private int latinKeyGroup;
@@ -4421,6 +4424,22 @@ public boolean post (Event event) {
switch (type) {
case SWT.KeyDown:
case SWT.KeyUp: {
+ int pressedModifier = 0;
+ switch (event.keyCode) {
+ case SWT.SHIFT: pressedModifier = GDK.GDK_SHIFT_MASK; break;
+ case SWT.ALT: pressedModifier = GDK.GDK_MOD1_MASK; break;
+ case SWT.CONTROL: pressedModifier = GDK.GDK_CONTROL_MASK; break;
+ case SWT.ALT_GR: pressedModifier = GDK.GDK_MOD5_MASK; break;
+ default:
+ pressedModifier = 0;
+ }
+ if (pressedModifier != 0) {
+ if (type == SWT.KeyDown) {
+ cachedModifier |= pressedModifier;
+ } else {
+ cachedModifier &= ~pressedModifier;
+ }
+ }
int keysym = untranslateKey (event.keyCode);
if (keysym == 0) {
char key = event.character;
@@ -4436,14 +4455,14 @@ public boolean post (Event event) {
}
if (keysym == 0) return false;
}
- int modifier = 0;
+ int modifier = cachedModifier;
switch (event.stateMask) {
- case SWT.SHIFT: modifier = GDK.GDK_SHIFT_MASK; break;
- case SWT.ALT: modifier = GDK.GDK_MOD1_MASK; break;
- case SWT.CONTROL: modifier = GDK.GDK_CONTROL_MASK; break;
- case SWT.ALT_GR: modifier = GDK.GDK_MOD5_MASK; break;
+ case SWT.SHIFT: modifier = cachedModifier | GDK.GDK_SHIFT_MASK; break;
+ case SWT.ALT: modifier = cachedModifier | GDK.GDK_MOD1_MASK; break;
+ case SWT.CONTROL: modifier = cachedModifier | GDK.GDK_CONTROL_MASK; break;
+ case SWT.ALT_GR: modifier = cachedModifier | GDK.GDK_MOD5_MASK; break;
default:
- modifier = 0;
+ modifier = cachedModifier;
}
GDK.gdk_test_simulate_key(gdkWindow, x[0], y[0], keysym, modifier, type == SWT.KeyDown ? GDK.GDK_KEY_PRESS: GDK.GDK_KEY_RELEASE);
return true;
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug537025_SendKeyEvent.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug537025_SendKeyEvent.java
new file mode 100644
index 0000000000..4d164c05f7
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug537025_SendKeyEvent.java
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Red Hat and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+
+public class Bug537025_SendKeyEvent {
+
+ protected static final String SHELL_TITLE = "Keyboard testing shell";
+ private Text text;
+ private final Display display;
+ private final Shell shell;
+
+ public Bug537025_SendKeyEvent() {
+ display = Display.getDefault();
+ shell = new Shell(display, SWT.CLOSE);
+ createShell();
+
+ shell.addListener(SWT.CLOSE, arg0 -> {
+ System.out.println("Main Shell handling Close event, about to dipose the main Display");
+ display.dispose();
+ });
+
+ addClearButton();
+ addTestButtons();
+ addLeftButton();
+ addNoModButton();
+
+ while (!display.isDisposed()) {
+ try {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ System.out.println("Test finished");
+ }
+
+ public void addNoModButton() {
+ Button noMod = new Button(shell, SWT.PUSH);
+ noMod.setText("Press 'a' with no Shift");
+ noMod.setBounds(10, 150, 150, 30);
+ noMod.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ testNoMod();
+
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ testNoMod();
+
+ }
+
+ });
+ }
+
+ public void addLeftButton() {
+ Button left = new Button(shell, SWT.PUSH);
+ left.setText("To the Left");
+ left.setBounds(10, 120, 150, 30);
+ left.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ testTypeLeft();
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ widgetDefaultSelected(e);
+ }
+
+ });
+ }
+
+ public void addClearButton() {
+ Button spawn = new Button(shell, SWT.PUSH);
+ spawn.setText("Clear text");
+ spawn.setBounds(10, 30, 150, 30);
+ spawn.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent arg0) {
+ text.setText("");
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ widgetDefaultSelected(arg0);
+ }
+
+ });
+ }
+
+ public void addTestButtons() {
+ Button spawn = new Button(shell, SWT.PUSH);
+ spawn.setText("Test type one by one");
+ spawn.setBounds(10, 60, 150, 30);
+ spawn.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent arg0) {
+ testTypeOneByOne();
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ widgetDefaultSelected(arg0);
+ }
+ });
+
+ Button spawn2 = new Button(shell, SWT.PUSH);
+ spawn2.setText("Test type with mask");
+ spawn2.setBounds(10, 90, 150, 30);
+ spawn2.addSelectionListener(new SelectionListener() {
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent arg0) {
+ testTypeWithMask();
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ widgetDefaultSelected(arg0);
+ }
+ });
+ }
+
+ public void createShell() {
+ shell.setText(SHELL_TITLE);
+ shell.setLayout(new RowLayout(SWT.VERTICAL));
+ shell.setSize(500, 500);
+ shell.open();
+ shell.setFocus();
+ text = new Text(shell, SWT.NONE);
+ text.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
+ shell.layout();
+ }
+
+ public void testTypeOneByOne() {
+ text.setFocus();
+ Event shiftDown = keyDown(SWT.SHIFT);
+ Event shiftUp = keyUp(SWT.SHIFT);
+ Event a = keyDown('a');
+ Event aUp = keyUp('a');
+
+ postEvent(shiftDown);
+ postEvent(a);
+ postEvent(aUp);
+ postEvent(shiftUp);
+ }
+
+ public void testTypeLeft() {
+ text.setFocus();
+ Event leftDown = keyDown(SWT.ARROW_LEFT);
+ Event leftUp = keyUp(SWT.ARROW_LEFT);
+ postEvent(leftDown);
+ postEvent(leftUp);
+ }
+
+ public void testNoMod() {
+ text.setFocus();
+ Event aDown = keyDown('a');
+ Event aUp = keyUp('a');
+ postEvent(aDown);
+ postEvent(aUp);
+ }
+
+ public void testTypeWithMask() {
+ text.setFocus();
+ Event a = keyDown('a');
+ a.stateMask = SWT.SHIFT;
+ Event aUp = keyUp('a');
+ postEvent(a);
+ postEvent(aUp);
+ }
+
+ public Event keyDown(final int key) {
+ return keyEvent(key, SWT.KeyDown, getFocusControl());
+ }
+
+ public Event keyUp(final int key) {
+ return keyEvent(key, SWT.KeyUp, getFocusControl());
+ }
+
+ public void postEvent(Event e) {
+ org.eclipse.swt.widgets.Display.getDefault().post(e);
+ }
+
+ public Control getFocusControl() {
+ return org.eclipse.swt.widgets.Display.getDefault().getFocusControl();
+ }
+
+ public Event keyEvent(int key, int type, Widget w) {
+ Event e = new Event();
+ e.keyCode = key;
+ e.character = (char) key;
+ e.type = type;
+ e.widget = w;
+ return e;
+ }
+
+ public static void main(String[] args) {
+ new Bug537025_SendKeyEvent();
+ System.exit(0);
+ }
+
+} \ No newline at end of file

Back to the top