1 /* 2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.glass.ui.monocle.linux; 27 28 import com.sun.glass.ui.monocle.input.InputDeviceRegistry; 29 30 import java.io.File; 31 import java.io.IOException; 32 import java.security.AllPermission; 33 import java.util.BitSet; 34 import java.util.HashMap; 35 import java.util.Map; 36 37 public class LinuxInputDeviceRegistry extends InputDeviceRegistry { 38 39 public LinuxInputDeviceRegistry(boolean headless) { 40 if (headless) { 41 // Keep the registry but do not bind it to udev. 42 return; 43 } 44 Map<File, LinuxInputDevice> deviceMap = new HashMap<>(); 45 UdevListener udevListener = new UdevListener() { 46 @Override 47 public void udevEvent(String action, Map<String, String> event) { 48 String subsystem = event.get("SUBSYSTEM"); 49 String devPath = event.get("DEVPATH"); 50 String devName = event.get("DEVNAME"); 51 if (subsystem != null && subsystem.equals("input") 52 && devPath != null && devName != null) { 53 try { 54 File sysPath = new File("/sys", devPath); 55 if (action.equals("add") 56 || (action.equals("change") 57 && !deviceMap.containsKey(sysPath))) { 58 File devNode = new File(devName); 59 LinuxInputDevice device = createDevice( 60 devNode, sysPath, event); 61 if (device != null) { 62 deviceMap.put(sysPath, device); 63 } 64 } else if (action.equals("remove")) { 65 LinuxInputDevice device = deviceMap.get(sysPath); 66 deviceMap.remove(sysPath); 67 if (device != null) { 68 devices.remove(device); 69 } 70 } 71 } catch (IOException e) { 72 e.printStackTrace(); 73 } 74 } 75 } 76 }; 77 Udev.getInstance().addListener(udevListener); 78 // Request updates for existing devices 79 SysFS.triggerUdevNotification("input"); 80 } 81 82 private LinuxInputDevice createDevice(File devNode, 83 File sysPath, 84 Map<String, String> udevManifest) 85 throws IOException { 86 LinuxInputDevice device = new LinuxInputDevice( 87 devNode, sysPath, udevManifest); 88 return addDeviceInternal(device, "Linux input: " + devNode.toString()); 89 } 90 91 public LinuxInputDevice addDevice(LinuxInputDevice device, String name) { 92 SecurityManager security = System.getSecurityManager(); 93 if (security != null) { 94 security.checkPermission(new AllPermission()); 95 } 96 return addDeviceInternal(device, name); 97 } 98 99 private LinuxInputDevice addDeviceInternal(LinuxInputDevice device, String name) { 100 LinuxInputProcessor processor = createInputProcessor(device); 101 if (processor == null) { 102 return null; 103 } else { 104 device.setInputProcessor(createInputProcessor(device)); 105 Thread thread = new Thread(device); 106 thread.setName(name); 107 thread.setDaemon(true); 108 thread.start(); 109 devices.add(device); 110 return device; 111 } 112 } 113 114 public void removeDevice(LinuxInputDevice device) { 115 SecurityManager security = System.getSecurityManager(); 116 if (security != null) { 117 security.checkPermission(new AllPermission()); 118 } 119 devices.remove(device); 120 } 121 122 private LinuxInputProcessor createInputProcessor(LinuxInputDevice device) { 123 if (device.isTouch()) { 124 BitSet absCaps = device.getCapability("abs"); 125 boolean isMT = absCaps.get(Input.ABS_MT_POSITION_X) 126 && absCaps.get(Input.ABS_MT_POSITION_Y); 127 if (isMT) { 128 if (absCaps.get(Input.ABS_MT_TRACKING_ID)) { 129 return new LinuxStatefulMultiTouchProcessor(device); 130 } else { 131 return new LinuxStatelessMultiTouchProcessor(device); 132 } 133 } else { 134 return new LinuxSimpleTouchProcessor(device); 135 } 136 } else if (device.isRelative()) { 137 return new LinuxMouseProcessor(); 138 } else { 139 BitSet keyCaps = device.getCapability("key"); 140 if (keyCaps != null && !keyCaps.isEmpty()) { 141 return new LinuxKeyProcessor(); 142 } else { 143 return null; 144 } 145 } 146 } 147 148 }