From 57b4c7af3ef2007942886f60a128a872d9bcee63 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Fri, 29 Nov 2019 19:18:35 +0100
Subject: Bug 1156: LinuxKeyEventTracker: Add '/dev/input/by-path/*-event-kbd'
and more documentation
---
.../newt/driver/linux/LinuxKeyEventTracker.java | 117 +++++++++++++--------
1 file changed, 75 insertions(+), 42 deletions(-)
diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxKeyEventTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxKeyEventTracker.java
index 6328e9020..402ad0051 100644
--- a/src/newt/classes/jogamp/newt/driver/linux/LinuxKeyEventTracker.java
+++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxKeyEventTracker.java
@@ -55,14 +55,29 @@ import com.jogamp.newt.event.WindowUpdateEvent;
import com.jogamp.newt.event.KeyEvent;
/**
- * Experimental native key event tracker thread for GNU/Linux
- * just reading /dev/input/by-id/*-event-kbd
if available
- * or /dev/input/event*
within it's own polling thread.
+ * Experimental native key event tracker thread for GNU/Linux.
+ *
+ * Implementation attempts to read one of the following input event files
+ *
+ * - try /dev/input/by-path/*-event-kbd
+ * - try /dev/input/by-id/*-event-kbd
+ * - try /dev/input/event* (Warning: Unreliable due to fiddling with all native input events !)
+ *
+ *
+ *
+ * The first two input event file mappings allow for only utilizing
+ * the actual event-kbd
keyboard events.
+ *
+ *
+ * The last method is used if all former methods fails and it brute
+ * force uses all first 32 event files, which can cause overall stability issues!
+ *
*/
public class LinuxKeyEventTracker implements WindowListener, KeyTracker {
private static final String linuxDevInputByEventXRoot = "/dev/input/";
private static final String linuxDevInputByIDRoot = "/dev/input/by-id/";
+ private static final String linuxDevInputByPathRoot = "/dev/input/by-path/";
private static final LinuxKeyEventTracker ledt;
@@ -80,20 +95,15 @@ public class LinuxKeyEventTracker implements WindowListener, KeyTracker {
private WindowImpl focusedWindow = null;
private final EventDeviceManager eventDeviceManager = new EventDeviceManager();
- /*
- The devices are in /dev/input:
-
- crw-r--r-- 1 root root 13, 64 Apr 1 10:49 event0
- crw-r--r-- 1 root root 13, 65 Apr 1 10:50 event1
- crw-r--r-- 1 root root 13, 66 Apr 1 10:50 event2
- crw-r--r-- 1 root root 13, 67 Apr 1 10:50 event3
- ...
-
- And so on up to event31.
-
- ..
-
- Or preferable under /dev/input/by-id/ using names like 'usb-Vendor_Product-event-kbd'
+ /**
+ * Mapping of input event basename file to spawn of EventDevicePoller.
+ *
+ * String key is the base filename one of either (in that order):
+ *
+ * - try /dev/input/by-path/*-event-kbd
+ * - try /dev/input/by-id/*-event-kbd
+ * - try /dev/input/event* (Warning: Unreliable due to fiddling with all native input events !)
+ *
*/
private final Map edpMap = new HashMap();
@@ -150,36 +160,59 @@ public class LinuxKeyEventTracker implements WindowListener, KeyTracker {
private volatile boolean stop = false;
+ private void managePaths(final String rootPath, final String suffix, final String[] subPaths) {
+ for(final String path : subPaths ) {
+ if( path.endsWith(suffix) ) {
+ final EventDevicePoller edpOld = edpMap.get(path);
+ if( null == edpOld ) {
+ final EventDevicePoller edpNew = new EventDevicePoller( rootPath + path );
+ edpMap.put(path, edpNew);
+ final Thread t = new InterruptSource.Thread(null, edpNew, "NEWT-KeyEventTracker-"+path);
+ t.setDaemon(true);
+ t.start();
+ } else if( edpOld.stop ) {
+ // clear stopped entry, will restart after sleep
+ edpMap.put(path, null);
+ }
+ }
+ }
+ try {
+ Thread.sleep(2000);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
@Override
public void run() {
- final File devInputByID = new File(linuxDevInputByIDRoot);
- final String[] devInputIDs = devInputByID.list();
- final boolean useDevInputByID = null != devInputIDs && 0 < devInputIDs.length && devInputByID.exists() && devInputByID.isDirectory();
-
- if( useDevInputByID ) {
- while(!stop){
- for(final String path : devInputIDs ) {
- if( path.endsWith("-event-kbd") ) {
- final EventDevicePoller edpOld = edpMap.get(path);
- if( null == edpOld ) {
- final EventDevicePoller edpNew = new EventDevicePoller( linuxDevInputByIDRoot + path );
- edpMap.put(path, edpNew);
- final Thread t = new InterruptSource.Thread(null, edpNew, "NEWT-KeyEventTracker-"+path);
- t.setDaemon(true);
- t.start();
- } else if( edpOld.stop ) {
- // clear stopped entry, will restart after sleep
- edpMap.put(path, null);
- }
- }
+ // 1) try /dev/input/by-path/*-event-kbd
+ {
+ final File devInputByPath = new File(linuxDevInputByPathRoot);
+ final String[] devInputPaths = devInputByPath.list();
+ final boolean useDevInputByPath = null != devInputPaths && 0 < devInputPaths.length && devInputByPath.exists() && devInputByPath.isDirectory();
+ if( useDevInputByPath ) {
+ while(!stop){
+ managePaths(linuxDevInputByPathRoot, "-event-kbd", devInputPaths);
}
- try {
- Thread.sleep(2000);
- } catch (final InterruptedException e) {
- e.printStackTrace();
+ return;
+ }
+ }
+
+ // 2) try /dev/input/by-id/*-event-kbd
+ {
+ final File devInputByID = new File(linuxDevInputByIDRoot);
+ final String[] devInputIDs = devInputByID.list();
+ final boolean useDevInputByID = null != devInputIDs && 0 < devInputIDs.length && devInputByID.exists() && devInputByID.isDirectory();
+ if( useDevInputByID ) {
+ while(!stop){
+ managePaths(linuxDevInputByIDRoot, "-event-kbd", devInputIDs);
}
+ return;
}
- } else {
+ }
+
+ // 3) try /dev/input/event* (Warning: Unreliable due to fiddling with all native input events !)
+ {
final File devInputByEventX = new File(linuxDevInputByEventXRoot);
while(!stop){
for( final String path : devInputByEventX.list() ) {
--
cgit v1.2.3