diff options
author | Xerxes Rånby <[email protected]> | 2013-01-17 16:35:01 +0100 |
---|---|---|
committer | Xerxes Rånby <[email protected]> | 2013-01-30 21:57:20 +0100 |
commit | 1f7b17a93aa2cf21bc943b54d764d6f283c808de (patch) | |
tree | 042468edea0684b5254dc252e4ac9b85f6d016bb | |
parent | cedbdb09c00bb2a32cc065cb75590f3571bb7aa1 (diff) |
Add LinuxEventDeviceTracker used by RaspPi newt/driver/bcm/vc/iv/WindowDriver
Signed-off-by: Xerxes Rånby <[email protected]>
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java | 3 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java | 406 |
2 files changed, 409 insertions, 0 deletions
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java index 21fbea9ac..bdef8e6cd 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java @@ -37,6 +37,7 @@ import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import jogamp.newt.WindowImpl; +import jogamp.newt.driver.linux.LinuxEventDeviceTracker; import jogamp.newt.driver.linux.LinuxMouseTracker; public class WindowDriver extends WindowImpl { @@ -76,11 +77,13 @@ public class WindowDriver extends WindowImpl { } windowHandleClose = nativeWindowHandle; addWindowListener(LinuxMouseTracker.getSingleton()); + addWindowListener(LinuxEventDeviceTracker.getSingleton()); focusChanged(false, true); } protected void closeNativeImpl() { removeWindowListener(LinuxMouseTracker.getSingleton()); + removeWindowListener(LinuxEventDeviceTracker.getSingleton()); if(0!=windowHandleClose) { CloseWindow(windowHandleClose, windowUserData); diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java new file mode 100644 index 000000000..9fcb40e67 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java @@ -0,0 +1,406 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.newt.driver.linux; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; + +import jogamp.newt.WindowImpl; + +import com.jogamp.common.nio.StructAccessor; +import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowListener; +import com.jogamp.newt.event.WindowUpdateEvent; +import com.jogamp.newt.event.KeyEvent; + +/** + * Experimental native event device tracker thread for GNU/Linux + * just reading <code>/dev/input/event*</code> + * within it's own polling thread. + */ + +public class LinuxEventDeviceTracker implements WindowListener { + + private static final LinuxEventDeviceTracker ledt; + + + static { + ledt = new LinuxEventDeviceTracker(); + final Thread t = new Thread(ledt.eventDevicePoller, "NEWT-LinuxEventDeviceTracker"); + t.setDaemon(true); + t.start(); + } + + public static LinuxEventDeviceTracker getSingleton() { + return ledt; + } + + private volatile boolean stop = false; + private WindowImpl focusedWindow = null; + private EventDevicePoller eventDevicePoller = new EventDevicePoller(); + + @Override + public void windowResized(WindowEvent e) { } + + @Override + public void windowMoved(WindowEvent e) { } + + @Override + public void windowDestroyNotify(WindowEvent e) { + Object s = e.getSource(); + if(focusedWindow == s) { + focusedWindow = null; + } + } + + @Override + public void windowDestroyed(WindowEvent e) { } + + @Override + public void windowGainedFocus(WindowEvent e) { + Object s = e.getSource(); + if(s instanceof WindowImpl) { + focusedWindow = (WindowImpl) s; + } + } + + @Override + public void windowLostFocus(WindowEvent e) { + Object s = e.getSource(); + if(focusedWindow == s) { + focusedWindow = null; + } + } + + public static void main(String[] args ){ + LinuxEventDeviceTracker.getSingleton(); + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Override + public void windowRepaint(WindowUpdateEvent e) { } + + class EventDevicePoller implements Runnable { + @Override + public void run() { + final byte[] b = new byte[16]; + /** + * The Linux input event interface. + * http://www.kernel.org/doc/Documentation/input/input.txt + * + * struct input_event { + * struct timeval time; + * unsigned short type; + * unsigned short code; + * unsigned int value; + * }; + */ + ByteBuffer bb = ByteBuffer.wrap(b); + StructAccessor s = new StructAccessor(bb); + final File f = new File("/dev/input/event2"); + f.setReadOnly(); + InputStream fis; + try { + fis = new FileInputStream(f); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + + int timeSeconds; + int timeSecondFraction; + short type; + short code; + int value; + + int keyCode=KeyEvent.VK_UNDEFINED; + char keyChar=' '; + int eventType=0; + int modifiers=0; + + while(!stop) { + int remaining=16; + while(remaining>0) { + int read = 0; + try { + read = fis.read(b, 0, remaining); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if(read<0) { + stop = true; // EOF of event device file !? + } else { + remaining -= read; + } + } + + timeSeconds = s.getIntAt(0); + timeSecondFraction = s.getShortAt(4); + type = s.getShortAt(8); + code = s.getShortAt(10); + value = s.getIntAt(12); + + if(null != focusedWindow) { + /* + * Linux sends Keyboard events in the following order: + * EV_MSC (optional, contains scancode) + * EV_KEY + * SYN_REPORT (sent before next key) + */ + + switch(type) { + case 0: // SYN_REPORT + // Clear + eventType = 0; + keyCode = KeyEvent.VK_UNDEFINED; + keyChar = 0; // Print null for unprintable char. + modifiers = 0; + break; + case 1: // EV_KEY + keyCode = LinuxEVKey2NewtVKey(code); // The device independent code. + keyChar = LinuxEVKey2Unicode(code); // The printable character w/o key modifiers. + switch(value) { + case 0: + modifiers=0; + eventType=KeyEvent.EVENT_KEY_RELEASED; + focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyChar); + //Send syntetic typed + focusedWindow.sendKeyEvent(KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, (char) keyChar); + break; + case 1: + eventType=KeyEvent.EVENT_KEY_PRESSED; + focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyChar); + break; + case 2: + eventType=KeyEvent.EVENT_KEY_PRESSED; + modifiers=InputEvent.AUTOREPEAT_MASK; + + //Send syntetic autorepeat release + focusedWindow.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyChar); + //Send syntetic typed + focusedWindow.sendKeyEvent(KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar); + + focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyChar); + break; + } + break; + case 4: // EV_MSC + if(code==4) { // MSC_SCAN + // scancode ignore, linux kernel specific + // keyCode = value; + } + break; + // TODO: handle joystick events + // TODO: handle mouse events + // TODO: handle headphone/hdmi connector events + } + + //System.out.println("[time "+timeSeconds+":"+timeSecondFraction+"] type "+type+" / code "+code+" = value "+value); + + } else { + //if(Window.DEBUG_KEY_EVENT) + System.out.println("[time "+timeSeconds+":"+timeSecondFraction+"] type "+type+" / code "+code+" = value "+value); + } + } + if(null != fis) { + try { + fis.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + private char LinuxEVKey2Unicode(short EVKey) { + // This is the stuff normally mapped by a system keymap + + switch(EVKey){ + case 17: // w + return 'w'; + case 31: // s + return 's'; + case 30: // a + return 'a'; + case 32: // d + return 'd'; + case 1: // ESC + return 27; + case 28: // Enter + case 96: // Keypad Enter + return '\n'; + case 57: // Space + return ' '; + case 11: // 0 + case 82: // Numpad 0 + return '0'; + case 2: // 1 + case 79: // Numpad 1 + return '1'; + case 3: // 2 + case 80: // Numpad 1 + return '2'; + case 4: // 3 + case 81: // Numpad 3 + return '3'; + case 5: // 4 + case 75: // Numpad 4 + return '4'; + case 6: // 5 + case 76: // Numpad 5 + return '5'; + case 7: // 6 + case 77: // Numpad 6 + return '6'; + case 8: // 7 + case 71: // Numpad 7 + return '7'; + case 9: // 8 + case 72: // Numpad 8 + return '8'; + case 10: // 9 + case 73: // Numpad 9 + return '9'; + + default: + } + + return 0; + } + + static final short KEY_F1 = 59; + static final short KEY_F10 = 68; + static final short KEY_1 = 2; + static final short KEY_0 = 1; + + private int LinuxEVKey2NewtVKey(short EVKey) { + char vkCode = KeyEvent.VK_UNDEFINED; + + // F1 - F10 + if(isLinuxEVKeyWithin(EVKey, KEY_F1, KEY_F10)) + return (EVKey-KEY_F1)+KeyEvent.VK_F1; + + switch(EVKey){ + case 103: // KEY_UP + return KeyEvent.VK_UP; + case 105: // KEY_LEFT + return KeyEvent.VK_LEFT; + case 106: // KEY_RIGHT + return KeyEvent.VK_RIGHT; + case 108: // KEY_DOWN + return KeyEvent.VK_DOWN; + + case 14: // Backspace + return KeyEvent.VK_BACK_SPACE; + case 111: // del + return KeyEvent.VK_DELETE; + + case 17: // w + return KeyEvent.VK_W; + case 31: // s + return KeyEvent.VK_S; + case 30: // a + return KeyEvent.VK_A; + case 32: // d + return KeyEvent.VK_D; + case 1: // ESC + return KeyEvent.VK_ESCAPE; + case 28: // Enter + case 96: // Keypad Enter + return KeyEvent.VK_ENTER; + case 57: // Space + return KeyEvent.VK_SPACE; + case 11: // 0 + return KeyEvent.VK_0; + case 82: // Numpad 0 + return KeyEvent.VK_NUMPAD0; + case 2: // 1 + return KeyEvent.VK_1; + case 79: // Numpad 1 + return KeyEvent.VK_NUMPAD1; + case 3: // 2 + return KeyEvent.VK_2; + case 80: // Numpad 2 + return KeyEvent.VK_NUMPAD2; + case 4: // 3 + return KeyEvent.VK_3; + case 81: // Numpad 3 + return KeyEvent.VK_NUMPAD3; + case 5: // 4 + return KeyEvent.VK_4; + case 75: // Numpad 4 + return KeyEvent.VK_NUMPAD4; + case 6: // 5 + return KeyEvent.VK_5; + case 76: // Numpad 5 + return KeyEvent.VK_NUMPAD5; + case 7: // 6 + return KeyEvent.VK_6; + case 77: // Numpad 6 + return KeyEvent.VK_NUMPAD6; + case 8: // 7 + return KeyEvent.VK_7; + case 71: // Numpad 7 + return KeyEvent.VK_NUMPAD7; + case 9: // 8 + return KeyEvent.VK_8; + case 72: // Numpad 8 + return KeyEvent.VK_NUMPAD8; + case 10: // 9 + return KeyEvent.VK_9; + case 73: // Numpad 9 + return KeyEvent.VK_NUMPAD9; + + default: + //System.out.println("LinuxEVKey2NewtVKey: Unmapped EVKey "+EVKey); + } + + return vkCode; + } + + private boolean isLinuxEVKeyWithin(short eVKey, short min, + short max) { + if((eVKey>=min) && (eVKey<=max)) + return true; + return false; + } + } +} |