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 + *

    + *
  1. try /dev/input/by-path/*-event-kbd
  2. + *
  3. try /dev/input/by-id/*-event-kbd
  4. + *
  5. try /dev/input/event* (Warning: Unreliable due to fiddling with all native input events !)
  6. + *
+ *

+ *

+ * 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): + *

    + *
  1. try /dev/input/by-path/*-event-kbd
  2. + *
  3. try /dev/input/by-id/*-event-kbd
  4. + *
  5. try /dev/input/event* (Warning: Unreliable due to fiddling with all native input events !)
  6. + *
*/ 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