/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.driver.input;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.ByteChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import javax.naming.NameNotFoundException;
import org.jnode.driver.Device;
import org.jnode.driver.DriverException;
import org.jnode.naming.InitialNaming;
import org.jnode.util.SystemInputStream;
/**
* @author epr
*/
public abstract class AbstractKeyboardDriver extends AbstractInputDriver<KeyboardEvent> implements
KeyboardAPI, SystemTriggerAPI {
ByteChannel channel;
KeyboardInterpreter kbInterpreter;
private InputStream kis;
private final ArrayList<SystemTriggerListener> stListeners = new ArrayList<SystemTriggerListener>();
public final void addKeyboardListener(KeyboardListener l) {
super.addListener(l);
}
public final void removeKeyboardListener(KeyboardListener l) {
super.removeListener(l);
}
/**
* Claim to be the preferred listener.
* The given listener must have been added by addKeyboardListener.
* If there is a security manager, this method will call
* <code>checkPermission(new DriverPermission("setPreferredListener"))</code>.
*
* @param l
*/
public synchronized void setPreferredListener(KeyboardListener l) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SET_PREFERRED_LISTENER_PERMISSION);
}
super.setPreferredListener(l);
}
/**
* Add a listener
*
* @param l
*/
public void addSystemTriggerListener(SystemTriggerListener l) {
stListeners.add(l);
}
/**
* Remove a listener
*
* @param l
*/
public void removeSystemTriggerListener(SystemTriggerListener l) {
stListeners.remove(l);
}
/**
* Start the keyboard device.
*/
protected synchronized void startDevice() throws DriverException {
this.channel = getChannel();
try {
KeyboardLayoutManager mgr = InitialNaming.lookup(KeyboardLayoutManager.NAME);
this.kbInterpreter = mgr.createDefaultKeyboardInterpreter();
} catch (NameNotFoundException ex) {
throw new DriverException("Cannot find the keyboard layout manager", ex);
} catch (KeyboardInterpreterException ex) {
throw new DriverException();
}
final Device dev = getDevice();
final String id = dev.getId();
startDispatcher(id);
dev.registerAPI(KeyboardAPI.class, this);
dev.registerAPI(SystemTriggerAPI.class, this);
// // If no inputstream has been defined, create and set one.
// kis = null;
// if (channel != null) {
// kis = new KeyboardInputStream(this);
// }
// final InputStream systemIn = kis;
// AccessController.doPrivileged(new PrivilegedAction() {
// public Object run() {
// SystemInputStream.getInstance().initialize(systemIn);
// return null;
// }
// });
}
/**
* Gets the byte channel. This is implementation specific
*
* @return The byte channel
*/
protected abstract ByteChannel getChannel();
/**
* Stop the keyboard device.
*/
protected synchronized void stopDevice() throws DriverException {
final Device dev = getDevice();
dev.unregisterAPI(KeyboardAPI.class);
dev.unregisterAPI(SystemTriggerAPI.class);
if (System.in == kis) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
SystemInputStream.getInstance().releaseSystemIn();
return null;
}
});
}
stopDispatcher();
try {
channel.close();
} catch (IOException ex) {
System.err.println("Error closing Keyboard channel: "
+ ex.toString());
}
}
/**
* Send a given keyboard event to the given listener.
*
* @param l
* @param event
*/
@Override
protected void sendEvent(SystemListener<KeyboardEvent> l, KeyboardEvent event) {
KeyboardListener kl = (KeyboardListener) l;
if (event.isKeyPressed()) {
kl.keyPressed(event);
} else if (event.isKeyReleased()) {
kl.keyReleased(event);
}
}
/**
* Dispatch a given event to all known system trigger listeners.
*
* @param event
*/
protected void dispatchSystemTriggerEvent(KeyboardEvent event) {
//Syslog.debug("Dispatching event to " + listeners.size());
for (SystemTriggerListener l : stListeners) {
l.systemTrigger(event);
}
}
protected KeyboardEvent handleScancode(byte scancode) {
KeyboardEvent event = kbInterpreter.interpretScancode(scancode & 0xff);
if (event != null) {
if ((event.getKeyCode() == KeyEvent.VK_PRINTSCREEN) &&
event.isControlDown() &&
event.isShiftDown() &&
event.isKeyPressed()) {
dispatchSystemTriggerEvent(event);
}
}
return event;
}
/**
* @return KeyboardInterpreter
*/
public KeyboardInterpreter getKbInterpreter() {
return kbInterpreter;
}
/**
* Sets the kbInterpreter.
*
* @param kbInterpreter The kbInterpreter to set
*/
public void setKbInterpreter(KeyboardInterpreter kbInterpreter) {
if (kbInterpreter == null) {
throw new IllegalArgumentException(
"kbInterpreter==null");
}
this.kbInterpreter = kbInterpreter;
}
}