diff options
Diffstat (limited to 'plugins/windows')
42 files changed, 5897 insertions, 0 deletions
diff --git a/plugins/windows/README.txt b/plugins/windows/README.txt new file mode 100644 index 0000000..12cd468 --- /dev/null +++ b/plugins/windows/README.txt @@ -0,0 +1,46 @@ +This file modified last on 06/06/2003 by Jeff Kesselman + +This is the source tree for the core input API. + +Directory Organization: + +The root contains a master ANT build.xml. +After a successful build you will have the following sub directories: + -- apidocs Where the javadocs get built to + -- lib Where dependant libraries are kept. + -- bin Where the plugin dll and jar files ar built to. + -- src The source files. + + +Build instructions: + +To clean: ant clean +To build: ant all (or just ant) +To build docs: ant javadoc +To test: + This build will install the plug-in into the coreAPI's test + directories. + Use the tests in the coreAPI build.xml to test. + +Release Info: + Initial Release: This release contains an implementation of the input + API designed by Mike Martak of Sun and Thomas (?) of Sony CEA for + the WIn32 platform. All the code in src/input is cross platform. The + Win32 code is segregated to the DirectX plugin (src/DXplugin) which + depends on DirectInput from DX7 (or later). + + 05/09/2003: A number of bugs and problems with the DXPlugin are fixed in this + release. This release also brings the code up to date using the DI8 + interface. This thus is the first release that requries Peter Puck's + DX8 bindings to compile with MinGW. + + 05/09/2003 (second update): + This version adds a new standard value type to the API. + Axis.POV holds standard definitions for values for POV (hat) switches + -- Axis.POV.CENTER and Axis.POV.OFF are synonmous and are + the center position. + -- Axis.POV.UP, Axis.POV.DOWN, Axis.POV.LEFT and Axis.POV.RIGHT + should be self explainatory. + Any hat that claims to be "normalized" will return these values. (It is + recommended that all hats be normalized by the systemn specific plugins.) + diff --git a/plugins/windows/build.xml b/plugins/windows/build.xml new file mode 100644 index 0000000..a10d7cb --- /dev/null +++ b/plugins/windows/build.xml @@ -0,0 +1,86 @@ +<?xml version="1.0"?> +<project name="Direct Input Plugin" basedir="." default="all"> + <target name="init"> + <mkdir dir="classes"/> + <mkdir dir="bin"/> + <condition property="dx8" > + <os family="Windows" /> + </condition> + </target> + + <target name="compile" depends="init"> + <javac srcdir="src/java" destdir="classes" debug="true" deprecation="true" source="1.4" target="1.4"> + <!-- To add something to the classpath: --> + <classpath> + <pathelement location="../../coreAPI/bin/jinput-core.jar"/> + <pathelement location="../../lib/jutils.jar"/> + </classpath> + </javac> + </target> + + <target depends="init,compile" name="create_jniheaders"> + <javah destdir="src/native/dx8"> + <classpath> + <pathelement path="classes"/> + <pathelement location="../../coreAPI/classes"/> + </classpath> + <class name="net.java.games.input.IDirectInput"/> + <class name="net.java.games.input.IDirectInputDevice"/> + <class name="net.java.games.input.IDirectInputEffect"/> + </javah> + <javah destdir="src/native"> + <classpath> + <pathelement path="classes"/> + <pathelement location="../../coreAPI/classes"/> + </classpath> + <class name="net.java.games.input.DummyWindow"/> + </javah> + <javah destdir="src/native/raw"> + <classpath> + <pathelement path="classes"/> + <pathelement location="../../coreAPI/bin/jinput-core.jar"/> + </classpath> + <class name="net.java.games.input.RawInputEnvironmentPlugin"/> + <class name="net.java.games.input.RawInputEventQueue"/> + <class name="net.java.games.input.RawDevice"/> + </javah> + </target> + + <target name="compile_native" depends="init,create_jniheaders" if="dx8"> + <ant dir="src/native" target="compile"/> + <copy todir="bin"> + <fileset dir="src/native" includes="*.dll"/> + </copy> + </target> + + <target name="jar" depends="init,compile"> + <jar jarfile="bin/dxinput.jar" compress="true" basedir="classes"> + <include name="**/*.class"/> + </jar> + </target> + + <target name="all" depends="compile,compile_native,jar" description="Build everything."> + </target> + + <target name="javadoc" depends="init" description="Javadoc for my API."> + <mkdir dir="apidocs"/> + <javadoc packagenames="net.*" + destdir="apidocs" + additionalparam="-source 1.4"> + <sourcepath> + <pathelement location="src/java"/> + </sourcepath> + <classpath> + <pathelement location="../../bin/jinput-core.jar"/> + <pathelement location="../../lib/jutils.jar"/> + </classpath> + </javadoc> + </target> + + <target name="clean" depends="init" description="Clean all build products."> + <delete dir="classes" failonerror="no"/> + <delete dir="bin" failonerror="no"/> + <delete dir="apidocs" failonerror="no"/> + <ant inheritAll="false" antfile="src/native/build.xml" target="clean"/> + </target> +</project> diff --git a/plugins/windows/src/java/net/java/games/input/DIAbstractController.java b/plugins/windows/src/java/net/java/games/input/DIAbstractController.java new file mode 100644 index 0000000..ef75400 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIAbstractController.java @@ -0,0 +1,72 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** +* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* - Redistribution of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* - Redistribution in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materails provided with the distribution. +* +* Neither the name Sun Microsystems, Inc. or the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* This software is provided "AS IS," without a warranty of any kind. +* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING +* ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR +* NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND +* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS +* A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS +* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST +* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, +* INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY +* OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, +* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* +* You acknowledge that this software is not designed or intended for us in +* the design, construction, operation or maintenance of any nuclear facility +* +*****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** +* @author elias +* @version 1.0 +*/ +final class DIAbstractController extends AbstractController { + private final IDirectInputDevice device; + private final Controller.Type type; + + protected DIAbstractController(IDirectInputDevice device, Component[] components, Controller[] children, Rumbler[] rumblers, Controller.Type type) { + super(device.getProductName(), components, children, rumblers); + this.device = device; + this.type = type; + } + + public final void pollDevice() throws IOException { + device.pollAll(); + } + + protected final boolean getNextDeviceEvent(Event event) throws IOException { + return DIControllers.getNextDeviceEvent(event, device); + } + + protected final void setDeviceEventQueueSize(int size) throws IOException { + device.setBufferSize(size); + } + + public final Controller.Type getType() { + return type; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/DIComponent.java b/plugins/windows/src/java/net/java/games/input/DIComponent.java new file mode 100644 index 0000000..715c7fb --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIComponent.java @@ -0,0 +1,74 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** +* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* - Redistribution of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* - Redistribution in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materails provided with the distribution. +* +* Neither the name Sun Microsystems, Inc. or the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* This software is provided "AS IS," without a warranty of any kind. +* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING +* ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR +* NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND +* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS +* A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS +* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST +* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, +* INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY +* OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, +* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* +* You acknowledge that this software is not designed or intended for us in +* the design, construction, operation or maintenance of any nuclear facility +* +*****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** +* @author elias +* @version 1.0 +*/ +final class DIComponent extends AbstractComponent { + private final DIDeviceObject object; + + public DIComponent(Component.Identifier identifier, DIDeviceObject object) { + super(object.getName(), identifier); + this.object = object; + } + + public final boolean isRelative() { + return object.isRelative(); + } + + public final boolean isAnalog() { + return object.isAnalog(); + } + + public final float getDeadZone() { + return object.getDeadzone(); + } + + public final DIDeviceObject getDeviceObject() { + return object; + } + + protected final float poll() throws IOException { + return DIControllers.poll(this, object); + } +} diff --git a/plugins/windows/src/java/net/java/games/input/DIControllers.java b/plugins/windows/src/java/net/java/games/input/DIControllers.java new file mode 100644 index 0000000..0d7f01f --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIControllers.java @@ -0,0 +1,76 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** +* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* - Redistribution of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* - Redistribution in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materails provided with the distribution. +* +* Neither the name Sun Microsystems, Inc. or the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* This software is provided "AS IS," without a warranty of any kind. +* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING +* ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR +* NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND +* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS +* A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS +* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST +* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, +* INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY +* OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, +* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* +* You acknowledge that this software is not designed or intended for us in +* the design, construction, operation or maintenance of any nuclear facility +* +*****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** +* @author elias +* @version 1.0 +*/ +final class DIControllers { + private final static DIDeviceObjectData di_event = new DIDeviceObjectData(); + + /* synchronized to protect di_event */ + public final static synchronized boolean getNextDeviceEvent(Event event, IDirectInputDevice device) throws IOException { + if (!device.getNextEvent(di_event)) + return false; + DIDeviceObject object = device.mapEvent(di_event); + int event_value; + if (object.isRelative()) { + event_value = object.getRelativeEventValue(di_event.getData()); + } else { + event_value = di_event.getData(); + } + DIComponent component = device.mapObject(object); + event.set(component, component.getDeviceObject().convertValue(event_value), di_event.getNanos()); + return true; + } + + public final static float poll(Component component, DIDeviceObject object) throws IOException { + int poll_data = object.getDevice().getPollData(object); + float result; + if (object.isRelative()) { + result = object.getRelativePollValue(poll_data); + } else { + result = poll_data; + } + return object.convertValue(result); + } +} diff --git a/plugins/windows/src/java/net/java/games/input/DIDeviceObject.java b/plugins/windows/src/java/net/java/games/input/DIDeviceObject.java new file mode 100644 index 0000000..a7c43c8 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIDeviceObject.java @@ -0,0 +1,207 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper for DIDEVICEOBJECTINSTANCE + * @author elias + * @version 1.0 + */ +final class DIDeviceObject { + //DirectInput scales wheel deltas by 120 + private final static int WHEEL_SCALE = 120; + + private final IDirectInputDevice device; + private final byte[] guid; + private final int identifier; + private final int type; + private final int instance; + private final int guid_type; + private final int flags; + private final String name; + private final Component.Identifier id; + private final int format_offset; + private final long min; + private final long max; + private final int deadzone; + + /* These are used for emulating relative axes */ + private int last_poll_value; + private int last_event_value; + + public DIDeviceObject(IDirectInputDevice device, Component.Identifier id, byte[] guid, int guid_type, int identifier, int type, int instance, int flags, String name, int format_offset) throws IOException { + this.device = device; + this.id = id; + this.guid = guid; + this.identifier = identifier; + this.type = type; + this.instance = instance; + this.guid_type = guid_type; + this.flags = flags; + this.name = name; + this.format_offset = format_offset; + if (isAxis() && !isRelative()) { + long[] range = device.getRangeProperty(identifier); + this.min = range[0]; + this.max = range[1]; + this.deadzone = device.getDeadzoneProperty(identifier); + } else { + this.min = IDirectInputDevice.DIPROPRANGE_NOMIN; + this.max = IDirectInputDevice.DIPROPRANGE_NOMAX; + this.deadzone = 0; + } + } + + public final synchronized int getRelativePollValue(int current_abs_value) { + int rel_value = current_abs_value - last_poll_value; + last_poll_value = current_abs_value; + return rel_value; + } + + public final synchronized int getRelativeEventValue(int current_abs_value) { + int rel_value = current_abs_value - last_event_value; + last_event_value = current_abs_value; + return rel_value; + } + + public final int getGUIDType() { + return guid_type; + } + + public final int getFormatOffset() { + return format_offset; + } + + public final IDirectInputDevice getDevice() { + return device; + } + + public final int getDIIdentifier() { + return identifier; + } + + public final Component.Identifier getIdentifier() { + return id; + } + + public final String getName() { + return name; + } + + public final int getInstance() { + return instance; + } + + public final int getType() { + return type; + } + + public final byte[] getGUID() { + return guid; + } + + public final int getFlags() { + return flags; + } + + public final long getMin() { + return min; + } + + public final long getMax() { + return max; + } + + public final float getDeadzone() { + return deadzone; + } + + public final boolean isButton() { + return (type & IDirectInputDevice.DIDFT_BUTTON) != 0; + } + + private final boolean isAxis() { + return (type & IDirectInputDevice.DIDFT_AXIS) != 0; + } + + public final boolean isRelative() { + return isAxis() && (type & IDirectInputDevice.DIDFT_RELAXIS) != 0; + } + + public final boolean isAnalog() { + return isAxis() && id != Component.Identifier.Axis.POV; + } + + public final float convertValue(float value) { + if (getDevice().getType() == IDirectInputDevice.DI8DEVTYPE_MOUSE && id == Component.Identifier.Axis.Z) { + return value/WHEEL_SCALE; + } else if (isButton()) { + return (((int)value) & 0x80) != 0 ? 1 : 0; + } else if (id == Component.Identifier.Axis.POV) { + int int_value = (int)value; + if ((int_value & 0xFFFF) == 0xFFFF) + return Component.POV.OFF; + // DirectInput returns POV directions in hundredths of degree clockwise from north + int slice = 360*100/16; + if (int_value >= 0 && int_value < slice) + return Component.POV.UP; + else if (int_value < 3*slice) + return Component.POV.UP_RIGHT; + else if (int_value < 5*slice) + return Component.POV.RIGHT; + else if (int_value < 7*slice) + return Component.POV.DOWN_RIGHT; + else if (int_value < 9*slice) + return Component.POV.DOWN; + else if (int_value < 11*slice) + return Component.POV.DOWN_LEFT; + else if (int_value < 13*slice) + return Component.POV.LEFT; + else if (int_value < 15*slice) + return Component.POV.UP_LEFT; + else + return Component.POV.UP; + } else if (isAxis() && !isRelative()) { + return 2*(value - min)/(float)(max - min) - 1; + } else + return value; + } + +} diff --git a/plugins/windows/src/java/net/java/games/input/DIDeviceObjectData.java b/plugins/windows/src/java/net/java/games/input/DIDeviceObjectData.java new file mode 100644 index 0000000..fa84a9d --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIDeviceObjectData.java @@ -0,0 +1,73 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** Java wrapper for DIDEVICEOBJECTDATA + * @author elias + * @version 1.0 + */ +final class DIDeviceObjectData { + private int format_offset; + private int data; + private int millis; + private int sequence; + + public final void set(int format_offset, int data, int millis, int sequence) { + this.format_offset = format_offset; + this.data = data; + this.millis = millis; + this.sequence = sequence; + } + + public final void set(DIDeviceObjectData other) { + set(other.format_offset, other.data, other.millis, other.sequence); + } + + public final int getData() { + return data; + } + + public final int getFormatOffset() { + return format_offset; + } + + public final long getNanos() { + return millis*1000000L; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/DIEffectInfo.java b/plugins/windows/src/java/net/java/games/input/DIEffectInfo.java new file mode 100644 index 0000000..5ece8a3 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIEffectInfo.java @@ -0,0 +1,83 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** Java wrapper for DIEFFECTINFO + * @author elias + * @version 1.0 + */ +final class DIEffectInfo { + private final IDirectInputDevice device; + private final byte[] guid; + private final int guid_id; + private final int effect_type; + private final int static_params; + private final int dynamic_params; + private final String name; + + public DIEffectInfo(IDirectInputDevice device, byte[] guid, int guid_id, int effect_type, int static_params, int dynamic_params, String name) { + this.device = device; + this.guid = guid; + this.guid_id = guid_id; + this.effect_type = effect_type; + this.static_params = static_params; + this.dynamic_params = dynamic_params; + this.name = name; + } + + public final byte[] getGUID() { + return guid; + } + + public final int getGUIDId() { + return guid_id; + } + + public final int getDynamicParams() { + return dynamic_params; + } + + public final int getEffectType() { + return effect_type; + } + + public final String getName() { + return name; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/DIIdentifierMap.java b/plugins/windows/src/java/net/java/games/input/DIIdentifierMap.java new file mode 100644 index 0000000..f9c06a8 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIIdentifierMap.java @@ -0,0 +1,544 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * @author elias + * @version 1.0 + */ +final class DIIdentifierMap { + public final static int DIK_ESCAPE = 0x01; + public final static int DIK_1 = 0x02; + public final static int DIK_2 = 0x03; + public final static int DIK_3 = 0x04; + public final static int DIK_4 = 0x05; + public final static int DIK_5 = 0x06; + public final static int DIK_6 = 0x07; + public final static int DIK_7 = 0x08; + public final static int DIK_8 = 0x09; + public final static int DIK_9 = 0x0A; + public final static int DIK_0 = 0x0B; + public final static int DIK_MINUS = 0x0C; /* - on main keyboard */ + public final static int DIK_EQUALS = 0x0D; + public final static int DIK_BACK = 0x0E; /* backspace */ + public final static int DIK_TAB = 0x0F; + public final static int DIK_Q = 0x10; + public final static int DIK_W = 0x11; + public final static int DIK_E = 0x12; + public final static int DIK_R = 0x13; + public final static int DIK_T = 0x14; + public final static int DIK_Y = 0x15; + public final static int DIK_U = 0x16; + public final static int DIK_I = 0x17; + public final static int DIK_O = 0x18; + public final static int DIK_P = 0x19; + public final static int DIK_LBRACKET = 0x1A; + public final static int DIK_RBRACKET = 0x1B; + public final static int DIK_RETURN = 0x1C; /* Enter on main keyboard */ + public final static int DIK_LCONTROL = 0x1D; + public final static int DIK_A = 0x1E; + public final static int DIK_S = 0x1F; + public final static int DIK_D = 0x20; + public final static int DIK_F = 0x21; + public final static int DIK_G = 0x22; + public final static int DIK_H = 0x23; + public final static int DIK_J = 0x24; + public final static int DIK_K = 0x25; + public final static int DIK_L = 0x26; + public final static int DIK_SEMICOLON = 0x27; + public final static int DIK_APOSTROPHE = 0x28; + public final static int DIK_GRAVE = 0x29; /* accent grave */ + public final static int DIK_LSHIFT = 0x2A; + public final static int DIK_BACKSLASH = 0x2B; + public final static int DIK_Z = 0x2C; + public final static int DIK_X = 0x2D; + public final static int DIK_C = 0x2E; + public final static int DIK_V = 0x2F; + public final static int DIK_B = 0x30; + public final static int DIK_N = 0x31; + public final static int DIK_M = 0x32; + public final static int DIK_COMMA = 0x33; + public final static int DIK_PERIOD = 0x34; /* . on main keyboard */ + public final static int DIK_SLASH = 0x35; /* / on main keyboard */ + public final static int DIK_RSHIFT = 0x36; + public final static int DIK_MULTIPLY = 0x37; /* * on numeric keypad */ + public final static int DIK_LMENU = 0x38; /* left Alt */ + public final static int DIK_SPACE = 0x39; + public final static int DIK_CAPITAL = 0x3A; + public final static int DIK_F1 = 0x3B; + public final static int DIK_F2 = 0x3C; + public final static int DIK_F3 = 0x3D; + public final static int DIK_F4 = 0x3E; + public final static int DIK_F5 = 0x3F; + public final static int DIK_F6 = 0x40; + public final static int DIK_F7 = 0x41; + public final static int DIK_F8 = 0x42; + public final static int DIK_F9 = 0x43; + public final static int DIK_F10 = 0x44; + public final static int DIK_NUMLOCK = 0x45; + public final static int DIK_SCROLL = 0x46; /* Scroll Lock */ + public final static int DIK_NUMPAD7 = 0x47; + public final static int DIK_NUMPAD8 = 0x48; + public final static int DIK_NUMPAD9 = 0x49; + public final static int DIK_SUBTRACT = 0x4A; /* - on numeric keypad */ + public final static int DIK_NUMPAD4 = 0x4B; + public final static int DIK_NUMPAD5 = 0x4C; + public final static int DIK_NUMPAD6 = 0x4D; + public final static int DIK_ADD = 0x4E; /* + on numeric keypad */ + public final static int DIK_NUMPAD1 = 0x4F; + public final static int DIK_NUMPAD2 = 0x50; + public final static int DIK_NUMPAD3 = 0x51; + public final static int DIK_NUMPAD0 = 0x52; + public final static int DIK_DECIMAL = 0x53; /* . on numeric keypad */ + public final static int DIK_OEM_102 = 0x56; /* <> or \| on RT 102-key keyboard (Non-U.S.) */ + public final static int DIK_F11 = 0x57; + public final static int DIK_F12 = 0x58; + public final static int DIK_F13 = 0x64; /* (NEC PC98) */ + public final static int DIK_F14 = 0x65; /* (NEC PC98) */ + public final static int DIK_F15 = 0x66; /* (NEC PC98) */ + public final static int DIK_KANA = 0x70; /* (Japanese keyboard) */ + public final static int DIK_ABNT_C1 = 0x73; /* /? on Brazilian keyboard */ + public final static int DIK_CONVERT = 0x79; /* (Japanese keyboard) */ + public final static int DIK_NOCONVERT = 0x7B; /* (Japanese keyboard) */ + public final static int DIK_YEN = 0x7D; /* (Japanese keyboard) */ + public final static int DIK_ABNT_C2 = 0x7E; /* Numpad . on Brazilian keyboard */ + public final static int DIK_NUMPADEQUALS = 0x8D; /* = on numeric keypad (NEC PC98) */ + public final static int DIK_PREVTRACK = 0x90; /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */ + public final static int DIK_AT = 0x91; /* (NEC PC98) */ + public final static int DIK_COLON = 0x92; /* (NEC PC98) */ + public final static int DIK_UNDERLINE = 0x93; /* (NEC PC98) */ + public final static int DIK_KANJI = 0x94; /* (Japanese keyboard) */ + public final static int DIK_STOP = 0x95; /* (NEC PC98) */ + public final static int DIK_AX = 0x96; /* (Japan AX) */ + public final static int DIK_UNLABELED = 0x97; /* (J3100) */ + public final static int DIK_NEXTTRACK = 0x99; /* Next Track */ + public final static int DIK_NUMPADENTER = 0x9C; /* Enter on numeric keypad */ + public final static int DIK_RCONTROL = 0x9D; + public final static int DIK_MUTE = 0xA0; /* Mute */ + public final static int DIK_CALCULATOR = 0xA1; /* Calculator */ + public final static int DIK_PLAYPAUSE = 0xA2; /* Play / Pause */ + public final static int DIK_MEDIASTOP = 0xA4; /* Media Stop */ + public final static int DIK_VOLUMEDOWN = 0xAE; /* Volume - */ + public final static int DIK_VOLUMEUP = 0xB0; /* Volume + */ + public final static int DIK_WEBHOME = 0xB2; /* Web home */ + public final static int DIK_NUMPADCOMMA = 0xB3; /* , on numeric keypad (NEC PC98) */ + public final static int DIK_DIVIDE = 0xB5; /* / on numeric keypad */ + public final static int DIK_SYSRQ = 0xB7; + public final static int DIK_RMENU = 0xB8; /* right Alt */ + public final static int DIK_PAUSE = 0xC5; /* Pause */ + public final static int DIK_HOME = 0xC7; /* Home on arrow keypad */ + public final static int DIK_UP = 0xC8; /* UpArrow on arrow keypad */ + public final static int DIK_PRIOR = 0xC9; /* PgUp on arrow keypad */ + public final static int DIK_LEFT = 0xCB; /* LeftArrow on arrow keypad */ + public final static int DIK_RIGHT = 0xCD; /* RightArrow on arrow keypad */ + public final static int DIK_END = 0xCF; /* End on arrow keypad */ + public final static int DIK_DOWN = 0xD0; /* DownArrow on arrow keypad */ + public final static int DIK_NEXT = 0xD1; /* PgDn on arrow keypad */ + public final static int DIK_INSERT = 0xD2; /* Insert on arrow keypad */ + public final static int DIK_DELETE = 0xD3; /* Delete on arrow keypad */ + public final static int DIK_LWIN = 0xDB; /* Left Windows key */ + public final static int DIK_RWIN = 0xDC; /* Right Windows key */ + public final static int DIK_APPS = 0xDD; /* AppMenu key */ + public final static int DIK_POWER = 0xDE; /* System Power */ + public final static int DIK_SLEEP = 0xDF; /* System Sleep */ + public final static int DIK_WAKE = 0xE3; /* System Wake */ + public final static int DIK_WEBSEARCH = 0xE5; /* Web Search */ + public final static int DIK_WEBFAVORITES = 0xE6; /* Web Favorites */ + public final static int DIK_WEBREFRESH = 0xE7; /* Web Refresh */ + public final static int DIK_WEBSTOP = 0xE8; /* Web Stop */ + public final static int DIK_WEBFORWARD = 0xE9; /* Web Forward */ + public final static int DIK_WEBBACK = 0xEA; /* Web Back */ + public final static int DIK_MYCOMPUTER = 0xEB; /* My Computer */ + public final static int DIK_MAIL = 0xEC; /* Mail */ + public final static int DIK_MEDIASELECT = 0xED; /* Media Select */ + + public final static Component.Identifier.Key getKeyIdentifier(int key_code) { + switch (key_code) { + case DIK_ESCAPE: + return Component.Identifier.Key.ESCAPE; + case DIK_1: + return Component.Identifier.Key._1; + case DIK_2: + return Component.Identifier.Key._2; + case DIK_3: + return Component.Identifier.Key._3; + case DIK_4: + return Component.Identifier.Key._4; + case DIK_5: + return Component.Identifier.Key._5; + case DIK_6: + return Component.Identifier.Key._6; + case DIK_7: + return Component.Identifier.Key._7; + case DIK_8: + return Component.Identifier.Key._8; + case DIK_9: + return Component.Identifier.Key._9; + case DIK_0: + return Component.Identifier.Key._0; + case DIK_MINUS: + return Component.Identifier.Key.MINUS; + case DIK_EQUALS: + return Component.Identifier.Key.EQUALS; + case DIK_BACK: + return Component.Identifier.Key.BACK; + case DIK_TAB: + return Component.Identifier.Key.TAB; + case DIK_Q: + return Component.Identifier.Key.Q; + case DIK_W: + return Component.Identifier.Key.W; + case DIK_E: + return Component.Identifier.Key.E; + case DIK_R: + return Component.Identifier.Key.R; + case DIK_T: + return Component.Identifier.Key.T; + case DIK_Y: + return Component.Identifier.Key.Y; + case DIK_U: + return Component.Identifier.Key.U; + case DIK_I: + return Component.Identifier.Key.I; + case DIK_O: + return Component.Identifier.Key.O; + case DIK_P: + return Component.Identifier.Key.P; + case DIK_LBRACKET: + return Component.Identifier.Key.LBRACKET; + case DIK_RBRACKET: + return Component.Identifier.Key.RBRACKET; + case DIK_RETURN: + return Component.Identifier.Key.RETURN; + case DIK_LCONTROL: + return Component.Identifier.Key.LCONTROL; + case DIK_A: + return Component.Identifier.Key.A; + case DIK_S: + return Component.Identifier.Key.S; + case DIK_D: + return Component.Identifier.Key.D; + case DIK_F: + return Component.Identifier.Key.F; + case DIK_G: + return Component.Identifier.Key.G; + case DIK_H: + return Component.Identifier.Key.H; + case DIK_J: + return Component.Identifier.Key.J; + case DIK_K: + return Component.Identifier.Key.K; + case DIK_L: + return Component.Identifier.Key.L; + case DIK_SEMICOLON: + return Component.Identifier.Key.SEMICOLON; + case DIK_APOSTROPHE: + return Component.Identifier.Key.APOSTROPHE; + case DIK_GRAVE: + return Component.Identifier.Key.GRAVE; + case DIK_LSHIFT: + return Component.Identifier.Key.LSHIFT; + case DIK_BACKSLASH: + return Component.Identifier.Key.BACKSLASH; + case DIK_Z: + return Component.Identifier.Key.Z; + case DIK_X: + return Component.Identifier.Key.X; + case DIK_C: + return Component.Identifier.Key.C; + case DIK_V: + return Component.Identifier.Key.V; + case DIK_B: + return Component.Identifier.Key.B; + case DIK_N: + return Component.Identifier.Key.N; + case DIK_M: + return Component.Identifier.Key.M; + case DIK_COMMA: + return Component.Identifier.Key.COMMA; + case DIK_PERIOD: + return Component.Identifier.Key.PERIOD; + case DIK_SLASH: + return Component.Identifier.Key.SLASH; + case DIK_RSHIFT: + return Component.Identifier.Key.RSHIFT; + case DIK_MULTIPLY: + return Component.Identifier.Key.MULTIPLY; + case DIK_LMENU: + return Component.Identifier.Key.LALT; + case DIK_SPACE: + return Component.Identifier.Key.SPACE; + case DIK_CAPITAL: + return Component.Identifier.Key.CAPITAL; + case DIK_F1: + return Component.Identifier.Key.F1; + case DIK_F2: + return Component.Identifier.Key.F2; + case DIK_F3: + return Component.Identifier.Key.F3; + case DIK_F4: + return Component.Identifier.Key.F4; + case DIK_F5: + return Component.Identifier.Key.F5; + case DIK_F6: + return Component.Identifier.Key.F6; + case DIK_F7: + return Component.Identifier.Key.F7; + case DIK_F8: + return Component.Identifier.Key.F8; + case DIK_F9: + return Component.Identifier.Key.F9; + case DIK_F10: + return Component.Identifier.Key.F10; + case DIK_NUMLOCK: + return Component.Identifier.Key.NUMLOCK; + case DIK_SCROLL: + return Component.Identifier.Key.SCROLL; + case DIK_NUMPAD7: + return Component.Identifier.Key.NUMPAD7; + case DIK_NUMPAD8: + return Component.Identifier.Key.NUMPAD8; + case DIK_NUMPAD9: + return Component.Identifier.Key.NUMPAD9; + case DIK_SUBTRACT: + return Component.Identifier.Key.SUBTRACT; + case DIK_NUMPAD4: + return Component.Identifier.Key.NUMPAD4; + case DIK_NUMPAD5: + return Component.Identifier.Key.NUMPAD5; + case DIK_NUMPAD6: + return Component.Identifier.Key.NUMPAD6; + case DIK_ADD: + return Component.Identifier.Key.ADD; + case DIK_NUMPAD1: + return Component.Identifier.Key.NUMPAD1; + case DIK_NUMPAD2: + return Component.Identifier.Key.NUMPAD2; + case DIK_NUMPAD3: + return Component.Identifier.Key.NUMPAD3; + case DIK_NUMPAD0: + return Component.Identifier.Key.NUMPAD0; + case DIK_DECIMAL: + return Component.Identifier.Key.DECIMAL; + case DIK_F11: + return Component.Identifier.Key.F11; + case DIK_F12: + return Component.Identifier.Key.F12; + case DIK_F13: + return Component.Identifier.Key.F13; + case DIK_F14: + return Component.Identifier.Key.F14; + case DIK_F15: + return Component.Identifier.Key.F15; + case DIK_KANA: + return Component.Identifier.Key.KANA; + case DIK_CONVERT: + return Component.Identifier.Key.CONVERT; + case DIK_NOCONVERT: + return Component.Identifier.Key.NOCONVERT; + case DIK_YEN: + return Component.Identifier.Key.YEN; + case DIK_NUMPADEQUALS: + return Component.Identifier.Key.NUMPADEQUAL; + case DIK_AT: + return Component.Identifier.Key.AT; + case DIK_COLON: + return Component.Identifier.Key.COLON; + case DIK_UNDERLINE: + return Component.Identifier.Key.UNDERLINE; + case DIK_KANJI: + return Component.Identifier.Key.KANJI; + case DIK_STOP: + return Component.Identifier.Key.STOP; + case DIK_AX: + return Component.Identifier.Key.AX; + case DIK_UNLABELED: + return Component.Identifier.Key.UNLABELED; + case DIK_NUMPADENTER: + return Component.Identifier.Key.NUMPADENTER; + case DIK_RCONTROL: + return Component.Identifier.Key.RCONTROL; + case DIK_NUMPADCOMMA: + return Component.Identifier.Key.NUMPADCOMMA; + case DIK_DIVIDE: + return Component.Identifier.Key.DIVIDE; + case DIK_SYSRQ: + return Component.Identifier.Key.SYSRQ; + case DIK_RMENU: + return Component.Identifier.Key.RALT; + case DIK_PAUSE: + return Component.Identifier.Key.PAUSE; + case DIK_HOME: + return Component.Identifier.Key.HOME; + case DIK_UP: + return Component.Identifier.Key.UP; + case DIK_PRIOR: + return Component.Identifier.Key.PAGEUP; + case DIK_LEFT: + return Component.Identifier.Key.LEFT; + case DIK_RIGHT: + return Component.Identifier.Key.RIGHT; + case DIK_END: + return Component.Identifier.Key.END; + case DIK_DOWN: + return Component.Identifier.Key.DOWN; + case DIK_NEXT: + return Component.Identifier.Key.PAGEDOWN; + case DIK_INSERT: + return Component.Identifier.Key.INSERT; + case DIK_DELETE: + return Component.Identifier.Key.DELETE; + case DIK_LWIN: + return Component.Identifier.Key.LWIN; + case DIK_RWIN: + return Component.Identifier.Key.RWIN; + case DIK_APPS: + return Component.Identifier.Key.APPS; + case DIK_POWER: + return Component.Identifier.Key.POWER; + case DIK_SLEEP: + return Component.Identifier.Key.SLEEP; + /* Unassigned keys */ + case DIK_ABNT_C1: + case DIK_ABNT_C2: + case DIK_PREVTRACK: + case DIK_PLAYPAUSE: + case DIK_NEXTTRACK: + case DIK_MUTE: + case DIK_CALCULATOR: + case DIK_MEDIASTOP: + case DIK_VOLUMEDOWN: + case DIK_VOLUMEUP: + case DIK_WEBHOME: + case DIK_WAKE: + case DIK_WEBSEARCH: + case DIK_WEBFAVORITES: + case DIK_WEBREFRESH: + case DIK_WEBSTOP: + case DIK_WEBFORWARD: + case DIK_WEBBACK: + case DIK_MYCOMPUTER: + case DIK_MAIL: + case DIK_MEDIASELECT: + case DIK_OEM_102: + default: + return Component.Identifier.Key.UNKNOWN; + } + } + + public final static Component.Identifier.Button getButtonIdentifier(int id) { + switch (id) { + case 0: + return Component.Identifier.Button._0; + case 1: + return Component.Identifier.Button._1; + case 2: + return Component.Identifier.Button._2; + case 3: + return Component.Identifier.Button._3; + case 4: + return Component.Identifier.Button._4; + case 5: + return Component.Identifier.Button._5; + case 6: + return Component.Identifier.Button._6; + case 7: + return Component.Identifier.Button._7; + case 8: + return Component.Identifier.Button._8; + case 9: + return Component.Identifier.Button._9; + case 10: + return Component.Identifier.Button._10; + case 11: + return Component.Identifier.Button._11; + case 12: + return Component.Identifier.Button._12; + case 13: + return Component.Identifier.Button._13; + case 14: + return Component.Identifier.Button._14; + case 15: + return Component.Identifier.Button._15; + case 16: + return Component.Identifier.Button._16; + case 17: + return Component.Identifier.Button._17; + case 18: + return Component.Identifier.Button._18; + case 19: + return Component.Identifier.Button._19; + case 20: + return Component.Identifier.Button._20; + case 21: + return Component.Identifier.Button._21; + case 22: + return Component.Identifier.Button._23; + case 23: + return Component.Identifier.Button._24; + case 24: + return Component.Identifier.Button._25; + case 25: + return Component.Identifier.Button._26; + case 26: + return Component.Identifier.Button._27; + case 27: + return Component.Identifier.Button._28; + case 28: + return Component.Identifier.Button._29; + case 29: + return Component.Identifier.Button._30; + case 30: + return Component.Identifier.Button._31; + default: + return null; + } + } + + public final static Component.Identifier.Button mapMouseButtonIdentifier(Component.Identifier.Button button_id) { + if (button_id == Component.Identifier.Button._0) { + return Component.Identifier.Button.LEFT; + } else if (button_id == Component.Identifier.Button._1) { + return Component.Identifier.Button.RIGHT; + } else if (button_id == Component.Identifier.Button._2) { + return Component.Identifier.Button.MIDDLE; + } else + return button_id; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/DIKeyboard.java b/plugins/windows/src/java/net/java/games/input/DIKeyboard.java new file mode 100644 index 0000000..6eec1b7 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIKeyboard.java @@ -0,0 +1,66 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** +* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* - Redistribution of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* - Redistribution in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materails provided with the distribution. +* +* Neither the name Sun Microsystems, Inc. or the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* This software is provided "AS IS," without a warranty of any kind. +* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING +* ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR +* NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND +* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS +* A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS +* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST +* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, +* INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY +* OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, +* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* +* You acknowledge that this software is not designed or intended for us in +* the design, construction, operation or maintenance of any nuclear facility +* +*****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** +* @author elias +* @version 1.0 +*/ +final class DIKeyboard extends Keyboard { + private final IDirectInputDevice device; + + protected DIKeyboard(IDirectInputDevice device, Component[] components, Controller[] children, Rumbler[] rumblers) { + super(device.getProductName(), components, children, rumblers); + this.device = device; + } + + protected final boolean getNextDeviceEvent(Event event) throws IOException { + return DIControllers.getNextDeviceEvent(event, device); + } + + public final void pollDevice() throws IOException { + device.pollAll(); + } + + protected final void setDeviceEventQueueSize(int size) throws IOException { + device.setBufferSize(size); + } +} diff --git a/plugins/windows/src/java/net/java/games/input/DIMouse.java b/plugins/windows/src/java/net/java/games/input/DIMouse.java new file mode 100644 index 0000000..e24ff77 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DIMouse.java @@ -0,0 +1,67 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** +* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* - Redistribution of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* - Redistribution in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materails provided with the distribution. +* +* Neither the name Sun Microsystems, Inc. or the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* This software is provided "AS IS," without a warranty of any kind. +* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING +* ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR +* NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND +* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS +* A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS +* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST +* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, +* INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY +* OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, +* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* +* You acknowledge that this software is not designed or intended for us in +* the design, construction, operation or maintenance of any nuclear facility +* +*****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** +* @author elias +* @version 1.0 +*/ +final class DIMouse extends Mouse { + private final IDirectInputDevice device; + + protected DIMouse(IDirectInputDevice device, Component[] components, Controller[] children, Rumbler[] rumblers) { + super(device.getProductName(), components, children, rumblers); + this.device = device; + } + + public final void pollDevice() throws IOException { + device.pollAll(); + } + + protected final boolean getNextDeviceEvent(Event event) throws IOException { + return DIControllers.getNextDeviceEvent(event, device); + } + + protected final void setDeviceEventQueueSize(int size) throws IOException { + device.setBufferSize(size); + } + +} diff --git a/plugins/windows/src/java/net/java/games/input/DataQueue.java b/plugins/windows/src/java/net/java/games/input/DataQueue.java new file mode 100644 index 0000000..8151d3f --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DataQueue.java @@ -0,0 +1,125 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * @author elias + * @version 1.0 + */ +final class DataQueue { + private final Object[] elements; + private int position; + private int limit; + + public DataQueue(int size, Class element_type) { + this.elements= new Object[size]; + for (int i = 0; i < elements.length; i++) { + try { + elements[i] = element_type.newInstance(); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + clear(); + } + + public final void clear() { + position = 0; + limit = elements.length; + } + + public final int position() { + return position; + } + + public final int limit() { + return limit; + } + + public final Object get(int index) { + assert index < limit; + return elements[index]; + } + + public final Object get() { + if (!hasRemaining()) + return null; + return get(position++); + } + + public final void compact() { + int index = 0; + while (hasRemaining()) { + swap(position, index); + position++; + index++; + } + position = index; + limit = elements.length; + } + + private final void swap(int index1, int index2) { + Object temp = elements[index1]; + elements[index1] = elements[index2]; + elements[index2] = temp; + } + + public final void flip() { + limit = position; + position = 0; + } + + public final boolean hasRemaining() { + return remaining() > 0; + } + + public final int remaining() { + return limit - position; + } + + public final void position(int position) { + this.position = position; + } + + public final Object[] getElements() { + return elements; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java b/plugins/windows/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java new file mode 100644 index 0000000..46c9b7d --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DirectInputEnvironmentPlugin.java @@ -0,0 +1,186 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.ArrayList; +import java.io.IOException; + +import net.java.games.util.plugins.Plugin; + +/** DirectInput implementation of controller environment + * @author martak + * @author elias + * @version 1.0 + */ +public final class DirectInputEnvironmentPlugin extends ControllerEnvironment implements Plugin { + static { + AccessController.doPrivileged( + new PrivilegedAction() { + public final Object run() { + System.loadLibrary("jinput-dx8"); + return null; + } + }); + } + + private final Controller[] controllers; + private final List active_devices = new ArrayList(); + private final DummyWindow window; + + /** Creates new DirectInputEnvironment */ + public DirectInputEnvironmentPlugin() { + DummyWindow window = null; + Controller[] controllers = new Controller[]{}; + try { + window = new DummyWindow(); + try { + controllers = enumControllers(window); + } catch (IOException e) { + window.destroy(); + throw e; + } + } catch (IOException e) { + ControllerEnvironment.logln("Failed to enumerate devices: " + e.getMessage()); + } + this.window = window; + this.controllers = controllers; + AccessController.doPrivileged( + new PrivilegedAction() { + public final Object run() { + Runtime.getRuntime().addShutdownHook(new ShutdownHook()); + return null; + } + }); + } + + public final Controller[] getControllers() { + return controllers; + } + + private final Component[] createComponents(IDirectInputDevice device, boolean map_mouse_buttons) { + List device_objects = device.getObjects(); + List controller_components = new ArrayList(); + for (int i = 0; i < device_objects.size(); i++) { + DIDeviceObject device_object = (DIDeviceObject)device_objects.get(i); + Component.Identifier identifier = device_object.getIdentifier(); + if (map_mouse_buttons && identifier instanceof Component.Identifier.Button) { + identifier = DIIdentifierMap.mapMouseButtonIdentifier((Component.Identifier.Button)identifier); + } + DIComponent component = new DIComponent(identifier, device_object); + controller_components.add(component); + device.registerComponent(device_object, component); + } + Component[] components = new Component[controller_components.size()]; + controller_components.toArray(components); + return components; + } + + private final Mouse createMouseFromDevice(IDirectInputDevice device) { + Component[] components = createComponents(device, true); + Mouse mouse = new DIMouse(device, components, new Controller[]{}, device.getRumblers()); + if (mouse.getX() != null && mouse.getY() != null && mouse.getLeft() != null) + return mouse; + else + return null; + } + + private final AbstractController createControllerFromDevice(IDirectInputDevice device, Controller.Type type) { + Component[] components = createComponents(device, false); + AbstractController controller = new DIAbstractController(device, components, new Controller[]{}, device.getRumblers(), type); + return controller; + } + + private final Keyboard createKeyboardFromDevice(IDirectInputDevice device) { + Component[] components = createComponents(device, false); + return new DIKeyboard(device, components, new Controller[]{}, device.getRumblers()); + } + + private final Controller createControllerFromDevice(IDirectInputDevice device) { + switch (device.getType()) { + case IDirectInputDevice.DI8DEVTYPE_MOUSE: + return createMouseFromDevice(device); + case IDirectInputDevice.DI8DEVTYPE_KEYBOARD: + return createKeyboardFromDevice(device); + case IDirectInputDevice.DI8DEVTYPE_JOYSTICK: + return createControllerFromDevice(device, Controller.Type.STICK); + case IDirectInputDevice.DI8DEVTYPE_GAMEPAD: + return createControllerFromDevice(device, Controller.Type.GAMEPAD); + default: + return null; + } + } + + private final Controller[] enumControllers(DummyWindow window) throws IOException { + List controllers = new ArrayList(); + IDirectInput dinput = new IDirectInput(window); + try { + List devices = dinput.getDevices(); + for (int i = 0; i < devices.size(); i++) { + IDirectInputDevice device = (IDirectInputDevice)devices.get(i); + Controller controller = createControllerFromDevice(device); + if (controller != null) { + controllers.add(controller); + active_devices.add(device); + } else + device.release(); + } + } finally { + dinput.release(); + } + Controller[] controllers_array = new Controller[controllers.size()]; + controllers.toArray(controllers_array); + return controllers_array; + } + + private final class ShutdownHook extends Thread { + public final void run() { + /* Release the devices to kill off active force feedback effects */ + for (int i = 0; i < active_devices.size(); i++) { + IDirectInputDevice device = (IDirectInputDevice)active_devices.get(i); + device.release(); + } + /* We won't release the window since it is + * owned by the thread that created the environment. + */ + } + } +} // class DirectInputEnvironment diff --git a/plugins/windows/src/java/net/java/games/input/DummyWindow.java b/plugins/windows/src/java/net/java/games/input/DummyWindow.java new file mode 100644 index 0000000..5c66d9a --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/DummyWindow.java @@ -0,0 +1,64 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper for a (dummy) window + * @author martak + * @author elias + * @version 1.0 + */ +final class DummyWindow { + private final long hwnd_address; + + public DummyWindow() throws IOException { + this.hwnd_address = createWindow(); + } + private final static native long createWindow() throws IOException; + + public final void destroy() throws IOException { + nDestroy(hwnd_address); + } + private final static native void nDestroy(long hwnd_address) throws IOException; + + public final long getHwnd() { + return hwnd_address; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/IDirectInput.java b/plugins/windows/src/java/net/java/games/input/IDirectInput.java new file mode 100644 index 0000000..8cef150 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/IDirectInput.java @@ -0,0 +1,95 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; + +/** Java wrapper for IDirectInput + * @author martak + * @author elias + * @version 1.0 + */ +final class IDirectInput { + private final List devices = new ArrayList(); + private final long idirectinput_address; + private final DummyWindow window; + + public IDirectInput(DummyWindow window) throws IOException { + this.window = window; + this.idirectinput_address = createIDirectInput(); + try { + enumDevices(); + } catch (IOException e) { + releaseDevices(); + release(); + throw e; + } + } + private final static native long createIDirectInput() throws IOException; + + public final List getDevices() { + return devices; + } + + private final void enumDevices() throws IOException { + nEnumDevices(idirectinput_address); + } + private final native void nEnumDevices(long addr) throws IOException; + + /* This method is called from native code in nEnumDevices + * native side will clean up in case of an exception + */ + private final void addDevice(long address, byte[] instance_guid, byte[] product_guid, int dev_type, int dev_subtype, String instance_name, String product_name) throws IOException { + devices.add(new IDirectInputDevice(window, address, instance_guid, product_guid, dev_type, dev_subtype, instance_name, product_name)); + } + + public final void releaseDevices() { + for (int i = 0; i < devices.size(); i++) { + IDirectInputDevice device = (IDirectInputDevice)devices.get(i); + device.release(); + } + } + + public final void release() { + nRelease(idirectinput_address); + } + private final static native void nRelease(long address); +} diff --git a/plugins/windows/src/java/net/java/games/input/IDirectInputDevice.java b/plugins/windows/src/java/net/java/games/input/IDirectInputDevice.java new file mode 100644 index 0000000..ef061cd --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/IDirectInputDevice.java @@ -0,0 +1,519 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Arrays; + +/** Java wrapper for IDirectInputDevice + * @author martak + * @author elias + * @version 1.0 + */ +final class IDirectInputDevice { + public final static int GUID_XAxis = 1; + public final static int GUID_YAxis = 2; + public final static int GUID_ZAxis = 3; + public final static int GUID_RxAxis = 4; + public final static int GUID_RyAxis = 5; + public final static int GUID_RzAxis = 6; + public final static int GUID_Slider = 7; + public final static int GUID_Button = 8; + public final static int GUID_Key = 9; + public final static int GUID_POV = 10; + public final static int GUID_Unknown = 11; + + public final static int GUID_ConstantForce = 12; + public final static int GUID_RampForce = 13; + public final static int GUID_Square = 14; + public final static int GUID_Sine = 15; + public final static int GUID_Triangle = 16; + public final static int GUID_SawtoothUp = 17; + public final static int GUID_SawtoothDown = 18; + public final static int GUID_Spring = 19; + public final static int GUID_Damper = 20; + public final static int GUID_Inertia = 21; + public final static int GUID_Friction = 22; + public final static int GUID_CustomForce = 23; + + public final static int DI8DEVTYPE_DEVICE = 0x11; + public final static int DI8DEVTYPE_MOUSE = 0x12; + public final static int DI8DEVTYPE_KEYBOARD = 0x13; + public final static int DI8DEVTYPE_JOYSTICK = 0x14; + public final static int DI8DEVTYPE_GAMEPAD = 0x15; + public final static int DI8DEVTYPE_DRIVING = 0x16; + public final static int DI8DEVTYPE_FLIGHT = 0x17; + public final static int DI8DEVTYPE_1STPERSON = 0x18; + public final static int DI8DEVTYPE_DEVICECTRL = 0x19; + public final static int DI8DEVTYPE_SCREENPOINTER = 0x1A; + public final static int DI8DEVTYPE_REMOTE = 0x1B; + public final static int DI8DEVTYPE_SUPPLEMENTAL = 0x1C; + + public final static int DISCL_EXCLUSIVE = 0x00000001; + public final static int DISCL_NONEXCLUSIVE = 0x00000002; + public final static int DISCL_FOREGROUND = 0x00000004; + public final static int DISCL_BACKGROUND = 0x00000008; + public final static int DISCL_NOWINKEY = 0x00000010; + + public final static int DIDFT_ALL = 0x00000000; + + public final static int DIDFT_RELAXIS = 0x00000001; + public final static int DIDFT_ABSAXIS = 0x00000002; + public final static int DIDFT_AXIS = 0x00000003; + + public final static int DIDFT_PSHBUTTON = 0x00000004; + public final static int DIDFT_TGLBUTTON = 0x00000008; + public final static int DIDFT_BUTTON = 0x0000000C; + + public final static int DIDFT_POV = 0x00000010; + public final static int DIDFT_COLLECTION = 0x00000040; + public final static int DIDFT_NODATA = 0x00000080; + + public final static int DIDFT_FFACTUATOR = 0x01000000; + public final static int DIDFT_FFEFFECTTRIGGER = 0x02000000; + public final static int DIDFT_OUTPUT = 0x10000000; + public final static int DIDFT_VENDORDEFINED = 0x04000000; + public final static int DIDFT_ALIAS = 0x08000000; + public final static int DIDFT_OPTIONAL = 0x80000000; + + public final static int DIDFT_NOCOLLECTION = 0x00FFFF00; + + public final static int DIDF_ABSAXIS = 0x00000001; + public final static int DIDF_RELAXIS = 0x00000002; + + public final static int DI_OK = 0x00000000; + public final static int DI_NOEFFECT = 0x00000001; + public final static int DI_PROPNOEFFECT = 0x00000001; + + public final static int DI_DOWNLOADSKIPPED = 0x00000003; + public final static int DI_EFFECTRESTARTED = 0x00000004; + public final static int DI_TRUNCATED = 0x00000008; + public final static int DI_SETTINGSNOTSAVED = 0x0000000B; + public final static int DI_TRUNCATEDANDRESTARTED = 0x0000000C; + + public final static int DI_BUFFEROVERFLOW = 0x00000001; + public final static int DIERR_INPUTLOST = 0x8007001E; + public final static int DIERR_NOTACQUIRED = 0x8007001C; + public final static int DIERR_OTHERAPPHASPRIO = 0x80070005; + + public final static int DIDOI_FFACTUATOR = 0x00000001; + public final static int DIDOI_FFEFFECTTRIGGER = 0x00000002; + public final static int DIDOI_POLLED = 0x00008000; + public final static int DIDOI_ASPECTPOSITION = 0x00000100; + public final static int DIDOI_ASPECTVELOCITY = 0x00000200; + public final static int DIDOI_ASPECTACCEL = 0x00000300; + public final static int DIDOI_ASPECTFORCE = 0x00000400; + public final static int DIDOI_ASPECTMASK = 0x00000F00; + public final static int DIDOI_GUIDISUSAGE = 0x00010000; + + public final static int DIEFT_ALL = 0x00000000; + + public final static int DIEFT_CONSTANTFORCE = 0x00000001; + public final static int DIEFT_RAMPFORCE = 0x00000002; + public final static int DIEFT_PERIODIC = 0x00000003; + public final static int DIEFT_CONDITION = 0x00000004; + public final static int DIEFT_CUSTOMFORCE = 0x00000005; + public final static int DIEFT_HARDWARE = 0x000000FF; + public final static int DIEFT_FFATTACK = 0x00000200; + public final static int DIEFT_FFFADE = 0x00000400; + public final static int DIEFT_SATURATION = 0x00000800; + public final static int DIEFT_POSNEGCOEFFICIENTS = 0x00001000; + public final static int DIEFT_POSNEGSATURATION = 0x00002000; + public final static int DIEFT_DEADBAND = 0x00004000; + public final static int DIEFT_STARTDELAY = 0x00008000; + + public final static int DIEFF_OBJECTIDS = 0x00000001; + public final static int DIEFF_OBJECTOFFSETS = 0x00000002; + public final static int DIEFF_CARTESIAN = 0x00000010; + public final static int DIEFF_POLAR = 0x00000020; + public final static int DIEFF_SPHERICAL = 0x00000040; + + public final static int DIEP_DURATION = 0x00000001; + public final static int DIEP_SAMPLEPERIOD = 0x00000002; + public final static int DIEP_GAIN = 0x00000004; + public final static int DIEP_TRIGGERBUTTON = 0x00000008; + public final static int DIEP_TRIGGERREPEATINTERVAL = 0x00000010; + public final static int DIEP_AXES = 0x00000020; + public final static int DIEP_DIRECTION = 0x00000040; + public final static int DIEP_ENVELOPE = 0x00000080; + public final static int DIEP_TYPESPECIFICPARAMS = 0x00000100; + public final static int DIEP_STARTDELAY = 0x00000200; + public final static int DIEP_ALLPARAMS_DX5 = 0x000001FF; + public final static int DIEP_ALLPARAMS = 0x000003FF; + public final static int DIEP_START = 0x20000000; + public final static int DIEP_NORESTART = 0x40000000; + public final static int DIEP_NODOWNLOAD = 0x80000000; + public final static int DIEB_NOTRIGGER = 0xFFFFFFFF; + + public final static int INFINITE = 0xFFFFFFFF; + + public final static int DI_DEGREES = 100; + public final static int DI_FFNOMINALMAX = 10000; + public final static int DI_SECONDS = 1000000; + + public final static int DIPROPRANGE_NOMIN = 0x80000000; + public final static int DIPROPRANGE_NOMAX = 0x7FFFFFFF; + + private final DummyWindow window; + private final long address; + private final int dev_type; + private final int dev_subtype; + private final String instance_name; + private final String product_name; + private final List objects = new ArrayList(); + private final List effects = new ArrayList(); + private final List rumblers = new ArrayList(); + private final int[] device_state; + private final Map object_to_component = new HashMap(); + private boolean released; + private DataQueue queue; + + private int button_counter; + private int current_format_offset; + + public IDirectInputDevice(DummyWindow window, long address, byte[] instance_guid, byte[] product_guid, int dev_type, int dev_subtype, String instance_name, String product_name) throws IOException { + this.window = window; + this.address = address; + this.product_name = product_name; + this.instance_name = instance_name; + this.dev_type = dev_type; + this.dev_subtype = dev_subtype; + // Assume that the caller (native side) releases the device if setup fails + enumObjects(); + try { + enumEffects(); + createRumblers(); + } catch (IOException e) { + ControllerEnvironment.logln("Failed to create rumblers: " + e.getMessage()); + } + /* Some DirectInput lamer-designer made the device state + * axis mode be per-device not per-axis, so I'll just + * get all axes as absolute and compensate for relative axes + */ + setDataFormat(DIDF_ABSAXIS); + if (rumblers.size() > 0) { + try { + setCooperativeLevel(DISCL_BACKGROUND | DISCL_EXCLUSIVE); + } catch (IOException e) { + setCooperativeLevel(DISCL_BACKGROUND | DISCL_NONEXCLUSIVE); + } + } else + setCooperativeLevel(DISCL_BACKGROUND | DISCL_NONEXCLUSIVE); + setBufferSize(AbstractController.EVENT_QUEUE_DEPTH); + acquire(); + this.device_state = new int[objects.size()]; + } + + public final Rumbler[] getRumblers() { + return (Rumbler[])rumblers.toArray(new Rumbler[]{}); + } + + private final List createRumblers() throws IOException { + DIDeviceObject x_axis = lookupObjectByGUID(GUID_XAxis); + DIDeviceObject y_axis = lookupObjectByGUID(GUID_YAxis); + if(x_axis == null || y_axis == null) + return rumblers; + DIDeviceObject[] axes = {x_axis, y_axis}; + long[] directions = {0, 0}; + for (int i = 0; i < effects.size(); i++) { + DIEffectInfo info = (DIEffectInfo)effects.get(i); + if ((info.getEffectType() & 0xff) == DIEFT_PERIODIC && + (info.getDynamicParams() & DIEP_GAIN) != 0) { + rumblers.add(createPeriodicRumbler(axes, directions, info)); + } + } + return rumblers; + } + + private final Rumbler createPeriodicRumbler(DIDeviceObject[] axes, long[] directions, DIEffectInfo info) throws IOException { + int[] axis_ids = new int[axes.length]; + for (int i = 0; i < axis_ids.length; i++) { + axis_ids[i] = axes[i].getDIIdentifier(); + } + long effect_address = nCreatePeriodicEffect(address, info.getGUID(), DIEFF_CARTESIAN | DIEFF_OBJECTIDS, INFINITE, 0, 0, DIEB_NOTRIGGER, 0, axis_ids, directions, 0, 0, 0, 0, DI_FFNOMINALMAX, 0, 0, 50000, 0); + return new IDirectInputEffect(effect_address, info); + } + private final static native long nCreatePeriodicEffect(long address, byte[] effect_guid, int flags, int duration, int sample_period, int gain, int trigger_button, int trigger_repeat_interval, int[] axis_ids, long[] directions, int envelope_attack_level, int envelope_attack_time, int envelope_fade_level, int envelope_fade_time, int periodic_magnitude, int periodic_offset, int periodic_phase, int periodic_period, int start_delay) throws IOException; + + private final DIDeviceObject lookupObjectByGUID(int guid_id) { + for (int i = 0; i < objects.size(); i++) { + DIDeviceObject object = (DIDeviceObject)objects.get(i); + if (guid_id == object.getGUIDType()) + return object; + } + return null; + } + + public final int getPollData(DIDeviceObject object) { + return device_state[object.getFormatOffset()]; + } + + public final DIDeviceObject mapEvent(DIDeviceObjectData event) { + /* Raw event format offsets (dwOfs member) is in bytes, + * but we're indexing into ints so we have to compensate + * for the int size (4 bytes) + */ + int format_offset = event.getFormatOffset()/4; + return (DIDeviceObject)objects.get(format_offset); + } + + public final DIComponent mapObject(DIDeviceObject object) { + return (DIComponent)object_to_component.get(object); + } + + public final void registerComponent(DIDeviceObject object, DIComponent component) { + object_to_component.put(object, component); + } + + public final synchronized void pollAll() throws IOException { + checkReleased(); + poll(); + getDeviceState(device_state); + queue.compact(); + getDeviceData(queue); + queue.flip(); + } + + public synchronized final boolean getNextEvent(DIDeviceObjectData data) { + DIDeviceObjectData next_event = (DIDeviceObjectData)queue.get(); + if (next_event == null) + return false; + data.set(next_event); + return true; + } + + private final void poll() throws IOException { + int res = nPoll(address); + if (res != DI_OK && res != DI_NOEFFECT) { + if (res == DIERR_NOTACQUIRED) { + acquire(); + return; + } + throw new IOException("Failed to poll device (" + Integer.toHexString(res) + ")"); + } + } + private final static native int nPoll(long address) throws IOException; + + private final void acquire() throws IOException { + int res = nAcquire(address); + if (res != DI_OK && res != DIERR_OTHERAPPHASPRIO && res != DI_NOEFFECT) + throw new IOException("Failed to acquire device (" + Integer.toHexString(res) + ")"); + } + private final static native int nAcquire(long address); + + private final void unacquire() throws IOException { + int res = nUnacquire(address); + if (res != DI_OK && res != DI_NOEFFECT) + throw new IOException("Failed to unAcquire device (" + Integer.toHexString(res) + ")"); + } + private final static native int nUnacquire(long address); + + private final boolean getDeviceData(DataQueue queue) throws IOException { + int res = nGetDeviceData(address, 0, queue, queue.getElements(), queue.position(), queue.remaining()); + if (res != DI_OK && res != DI_BUFFEROVERFLOW) { + if (res == DIERR_NOTACQUIRED) { + acquire(); + return false; + } + throw new IOException("Failed to get device data (" + Integer.toHexString(res) + ")"); + } + return true; + } + private final static native int nGetDeviceData(long address, int flags, DataQueue queue, Object[] queue_elements, int position, int remaining); + + private final void getDeviceState(int[] device_state) throws IOException { + int res = nGetDeviceState(address, device_state); + if (res != DI_OK) { + if (res == DIERR_NOTACQUIRED) { + Arrays.fill(device_state, 0); + acquire(); + return; + } + throw new IOException("Failed to get device state (" + Integer.toHexString(res) + ")"); + } + } + private final static native int nGetDeviceState(long address, int[] device_state); + + /* Set a custom data format that maps each object's data into an int[] + array with the same index as in the objects List */ + private final void setDataFormat(int flags) throws IOException { + DIDeviceObject[] device_objects = new DIDeviceObject[objects.size()]; + objects.toArray(device_objects); + int res = nSetDataFormat(address, flags, device_objects); + if (res != DI_OK) + throw new IOException("Failed to set data format (" + Integer.toHexString(res) + ")"); + } + private final static native int nSetDataFormat(long address, int flags, DIDeviceObject[] device_objects); + + public final String getProductName() { + return product_name; + } + + public final int getType() { + return dev_type; + } + + public final List getObjects() { + return objects; + } + + private final void enumEffects() throws IOException { + int res = nEnumEffects(address, DIEFT_ALL); + if (res != DI_OK) + throw new IOException("Failed to enumerate effects (" + Integer.toHexString(res) + ")"); + } + private final native int nEnumEffects(long address, int flags); + + /* Called from native side from nEnumEffects */ + private final void addEffect(byte[] guid, int guid_id, int effect_type, int static_params, int dynamic_params, String name) { + effects.add(new DIEffectInfo(this, guid, guid_id, effect_type, static_params, dynamic_params, name)); + } + + private final void enumObjects() throws IOException { + int res = nEnumObjects(address, DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV); + if (res != DI_OK) + throw new IOException("Failed to enumerate objects (" + Integer.toHexString(res) + ")"); + } + private final native int nEnumObjects(long address, int flags); + + public final synchronized long[] getRangeProperty(int object_identifier) throws IOException { + checkReleased(); + long[] range = new long[2]; + int res = nGetRangeProperty(address, object_identifier, range); + if (res != DI_OK) + throw new IOException("Failed to get object range (" + res + ")"); + return range; + } + private final static native int nGetRangeProperty(long address, int object_id, long[] range); + + public final synchronized int getDeadzoneProperty(int object_identifier) throws IOException { + checkReleased(); + return nGetDeadzoneProperty(address, object_identifier); + } + private final static native int nGetDeadzoneProperty(long address, int object_id) throws IOException; + + /* Called from native side from nEnumObjects */ + private final void addObject(byte[] guid, int guid_type, int identifier, int type, int instance, int flags, String name) throws IOException { + Component.Identifier id = getIdentifier(guid_type, type, instance); + int format_offset = current_format_offset++; + DIDeviceObject obj = new DIDeviceObject(this, id, guid, guid_type, identifier, type, instance, flags, name, format_offset); + objects.add(obj); + } + + private final static Component.Identifier.Key getKeyIdentifier(int key_instance) { + return DIIdentifierMap.getKeyIdentifier(key_instance); + } + + private final Component.Identifier.Button getNextButtonIdentifier() { + int button_id = button_counter++; + return DIIdentifierMap.getButtonIdentifier(button_id); + } + + private final Component.Identifier getIdentifier(int guid_type, int type, int instance) { + switch (guid_type) { + case IDirectInputDevice.GUID_XAxis: + return Component.Identifier.Axis.X; + case IDirectInputDevice.GUID_YAxis: + return Component.Identifier.Axis.Y; + case IDirectInputDevice.GUID_ZAxis: + return Component.Identifier.Axis.Z; + case IDirectInputDevice.GUID_RxAxis: + return Component.Identifier.Axis.RX; + case IDirectInputDevice.GUID_RyAxis: + return Component.Identifier.Axis.RY; + case IDirectInputDevice.GUID_RzAxis: + return Component.Identifier.Axis.RZ; + case IDirectInputDevice.GUID_Slider: + return Component.Identifier.Axis.SLIDER; + case IDirectInputDevice.GUID_POV: + return Component.Identifier.Axis.POV; + case IDirectInputDevice.GUID_Key: + return getKeyIdentifier(instance); + case IDirectInputDevice.GUID_Button: + return getNextButtonIdentifier(); + default: + return null; + } + } + + public final synchronized void setBufferSize(int size) throws IOException { + checkReleased(); + unacquire(); + int res = nSetBufferSize(address, size); + if (res != DI_OK && res != DI_PROPNOEFFECT) + throw new IOException("Failed to set buffer size (" + Integer.toHexString(res) + ")"); + queue = new DataQueue(size, DIDeviceObjectData.class); + queue.position(queue.limit()); + acquire(); + } + private final static native int nSetBufferSize(long address, int size); + + public final synchronized void setCooperativeLevel(int flags) throws IOException { + checkReleased(); + int res = nSetCooperativeLevel(address, window.getHwnd(), flags); + if (res != DI_OK) + throw new IOException("Failed to set cooperative level (" + Integer.toHexString(res) + ")"); + } + private final static native int nSetCooperativeLevel(long address, long hwnd_address, int flags); + + public synchronized final void release() { + if (!released) { + released = true; + for (int i = 0; i < rumblers.size(); i++) { + IDirectInputEffect effect = (IDirectInputEffect)rumblers.get(i); + effect.release(); + } + nRelease(address); + } + } + private final static native void nRelease(long address); + + private final void checkReleased() throws IOException { + if (released) + throw new IOException("Device is released"); + } + + protected void finalize() { + release(); + } +} diff --git a/plugins/windows/src/java/net/java/games/input/IDirectInputEffect.java b/plugins/windows/src/java/net/java/games/input/IDirectInputEffect.java new file mode 100644 index 0000000..5cb372f --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/IDirectInputEffect.java @@ -0,0 +1,121 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper for IDirectInputEffect + * @author elias + * @version 1.0 + */ +final class IDirectInputEffect implements Rumbler { + private final long address; + private final DIEffectInfo info; + private boolean released; + + public IDirectInputEffect(long address, DIEffectInfo info) { + this.address = address; + this.info = info; + } + + public final synchronized void rumble(float intensity) { + try { + checkReleased(); + if (intensity > 0) { + int int_gain = (int)Math.round(intensity*IDirectInputDevice.DI_FFNOMINALMAX); + setGain(int_gain); + start(1, 0); + } else + stop(); + } catch (IOException e) { + ControllerEnvironment.logln("Failed to set rumbler gain: " + e.getMessage()); + } + } + + public final Component.Identifier getAxisIdentifier() { + return null; + } + + public final String getAxisName() { + return null; + } + + public final synchronized void release() { + if (!released) { + released = true; + nRelease(address); + } + } + private final static native void nRelease(long address); + + private final void checkReleased() throws IOException { + if (released) + throw new IOException(); + } + + private final void setGain(int gain) throws IOException { + int res = nSetGain(address, gain); + if (res != IDirectInputDevice.DI_DOWNLOADSKIPPED && + res != IDirectInputDevice.DI_EFFECTRESTARTED && + res != IDirectInputDevice.DI_OK && + res != IDirectInputDevice.DI_TRUNCATED && + res != IDirectInputDevice.DI_TRUNCATEDANDRESTARTED) { + throw new IOException("Failed to set effect gain (0x" + Integer.toHexString(res) + ")"); + } + } + private final static native int nSetGain(long address, int gain); + + private final void start(int iterations, int flags) throws IOException { + int res = nStart(address, iterations, flags); + if (res != IDirectInputDevice.DI_OK) + throw new IOException("Failed to start effect (0x" + Integer.toHexString(res) + ")"); + } + private final static native int nStart(long address, int iterations, int flags); + + private final void stop() throws IOException { + int res = nStop(address); + if (res != IDirectInputDevice.DI_OK) + throw new IOException("Failed to stop effect (0x" + Integer.toHexString(res) + ")"); + } + private final static native int nStop(long address); + + protected void finalize() { + release(); + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawDevice.java b/plugins/windows/src/java/net/java/games/input/RawDevice.java new file mode 100644 index 0000000..4841234 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawDevice.java @@ -0,0 +1,310 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper of RAWDEVICELIST + * @author elias + * @version 1.0 + */ +final class RawDevice { + public final static int RI_MOUSE_LEFT_BUTTON_DOWN = 0x0001; // Left Button changed to down. + public final static int RI_MOUSE_LEFT_BUTTON_UP = 0x0002; // Left Button changed to up. + public final static int RI_MOUSE_RIGHT_BUTTON_DOWN = 0x0004; // Right Button changed to down. + public final static int RI_MOUSE_RIGHT_BUTTON_UP = 0x0008; // Right Button changed to up. + public final static int RI_MOUSE_MIDDLE_BUTTON_DOWN = 0x0010; // Middle Button changed to down. + public final static int RI_MOUSE_MIDDLE_BUTTON_UP = 0x0020; // Middle Button changed to up. + + public final static int RI_MOUSE_BUTTON_1_DOWN = RI_MOUSE_LEFT_BUTTON_DOWN; + public final static int RI_MOUSE_BUTTON_1_UP = RI_MOUSE_LEFT_BUTTON_UP; + public final static int RI_MOUSE_BUTTON_2_DOWN = RI_MOUSE_RIGHT_BUTTON_DOWN; + public final static int RI_MOUSE_BUTTON_2_UP = RI_MOUSE_RIGHT_BUTTON_UP; + public final static int RI_MOUSE_BUTTON_3_DOWN = RI_MOUSE_MIDDLE_BUTTON_DOWN; + public final static int RI_MOUSE_BUTTON_3_UP = RI_MOUSE_MIDDLE_BUTTON_UP; + + public final static int RI_MOUSE_BUTTON_4_DOWN = 0x0040; + public final static int RI_MOUSE_BUTTON_4_UP = 0x0080; + public final static int RI_MOUSE_BUTTON_5_DOWN = 0x0100; + public final static int RI_MOUSE_BUTTON_5_UP = 0x0200; + + /* + * If usButtonFlags has RI_MOUSE_WHEEL, the wheel delta is stored in usButtonData. + * Take it as a signed value. + */ + public final static int RI_MOUSE_WHEEL = 0x0400; + + public final static int MOUSE_MOVE_RELATIVE = 0; + public final static int MOUSE_MOVE_ABSOLUTE = 1; + public final static int MOUSE_VIRTUAL_DESKTOP = 0x02; // the coordinates are mapped to the virtual desktop + public final static int MOUSE_ATTRIBUTES_CHANGED = 0x04; // requery for mouse attributes + + public final static int RIM_TYPEHID = 2; + public final static int RIM_TYPEKEYBOARD = 1; + public final static int RIM_TYPEMOUSE = 0; + + public final static int WM_KEYDOWN = 0x0100; + public final static int WM_KEYUP = 0x0101; + public final static int WM_SYSKEYDOWN = 0x0104; + public final static int WM_SYSKEYUP = 0x0105; + + private final RawInputEventQueue queue; + private final long handle; + private final int type; + + /* Events from the event queue thread end here */ + private DataQueue keyboard_events; + private DataQueue mouse_events; + + /* After processing in poll*(), the events are placed here */ + private DataQueue processed_keyboard_events; + private DataQueue processed_mouse_events; + + /* mouse state */ + private final boolean[] button_states = new boolean[5]; + private int wheel; + private int relative_x; + private int relative_y; + private int last_x; + private int last_y; + + // Last x, y for converting absolute events to relative + private int event_relative_x; + private int event_relative_y; + private int event_last_x; + private int event_last_y; + + /* keyboard state */ + private final boolean[] key_states = new boolean[0xFF]; + + public RawDevice(RawInputEventQueue queue, long handle, int type) { + this.queue = queue; + this.handle = handle; + this.type = type; + setBufferSize(AbstractController.EVENT_QUEUE_DEPTH); + } + + /* Careful, this is called from the event queue thread */ + public final synchronized void addMouseEvent(long millis, int flags, int button_flags, int button_data, long raw_buttons, long last_x, long last_y, long extra_information) { + if (mouse_events.hasRemaining()) { + RawMouseEvent event = (RawMouseEvent)mouse_events.get(); + event.set(millis, flags, button_flags, button_data, raw_buttons, last_x, last_y, extra_information); + } + } + + /* Careful, this is called from the event queue thread */ + public final synchronized void addKeyboardEvent(long millis, int make_code, int flags, int vkey, int message, long extra_information) { + if (keyboard_events.hasRemaining()) { + RawKeyboardEvent event = (RawKeyboardEvent)keyboard_events.get(); + event.set(millis, make_code, flags, vkey, message, extra_information); + } + } + + public final synchronized void pollMouse() { + relative_x = relative_y = wheel = 0; + mouse_events.flip(); + while (mouse_events.hasRemaining()) { + RawMouseEvent event = (RawMouseEvent)mouse_events.get(); + boolean has_update = processMouseEvent(event); + if (has_update && processed_mouse_events.hasRemaining()) { + RawMouseEvent processed_event = (RawMouseEvent)processed_mouse_events.get(); + processed_event.set(event); + } + } + mouse_events.compact(); + } + + public final synchronized void pollKeyboard() { + keyboard_events.flip(); + while (keyboard_events.hasRemaining()) { + RawKeyboardEvent event = (RawKeyboardEvent)keyboard_events.get(); + boolean has_update = processKeyboardEvent(event); + if (has_update && processed_keyboard_events.hasRemaining()) { + RawKeyboardEvent processed_event = (RawKeyboardEvent)processed_keyboard_events.get(); + processed_event.set(event); + } + } + keyboard_events.compact(); + } + + private final boolean updateButtonState(int button_id, int button_flags, int down_flag, int up_flag) { + if (button_id >= button_states.length) + return false; + if ((button_flags & down_flag) != 0) { + button_states[button_id] = true; + return true; + } else if ((button_flags & up_flag) != 0) { + button_states[button_id] = false; + return true; + } else + return false; + } + + private final boolean processKeyboardEvent(RawKeyboardEvent event) { + int message = event.getMessage(); + int vkey = event.getVKey(); + if (vkey >= key_states.length) + return false; + if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN) { + key_states[vkey] = true; + return true; + } else if (message == WM_KEYUP || message == WM_SYSKEYUP) { + key_states[vkey] = false; + return true; + } else + return false; + } + + public final boolean isKeyDown(int vkey) { + return key_states[vkey]; + } + + private final boolean processMouseEvent(RawMouseEvent event) { + boolean has_update = false; + int button_flags = event.getButtonFlags(); + has_update = updateButtonState(0, button_flags, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP) || has_update; + has_update = updateButtonState(1, button_flags, RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP) || has_update; + has_update = updateButtonState(2, button_flags, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP) || has_update; + has_update = updateButtonState(3, button_flags, RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP) || has_update; + has_update = updateButtonState(4, button_flags, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP) || has_update; + int dx; + int dy; + if ((event.getFlags() & MOUSE_MOVE_ABSOLUTE) != 0) { + dx = event.getLastX() - last_x; + dy = event.getLastY() - last_y; + last_x = event.getLastX(); + last_y = event.getLastY(); + } else { + dx = event.getLastX(); + dy = event.getLastY(); + } + int dwheel = 0; + if ((button_flags & RI_MOUSE_WHEEL) != 0) + dwheel = event.getWheelDelta(); + relative_x += dx; + relative_y += dy; + wheel += dwheel; + has_update = dx != 0 || dy != 0 || dwheel != 0 || has_update; + return has_update; + } + + public final int getWheel() { + return wheel; + } + + public final int getEventRelativeX() { + return event_relative_x; + } + + public final int getEventRelativeY() { + return event_relative_y; + } + + public final int getRelativeX() { + return relative_x; + } + + public final int getRelativeY() { + return relative_y; + } + + public final synchronized boolean getNextKeyboardEvent(RawKeyboardEvent event) { + processed_keyboard_events.flip(); + if (!processed_keyboard_events.hasRemaining()) { + processed_keyboard_events.compact(); + return false; + } + RawKeyboardEvent next_event = (RawKeyboardEvent)processed_keyboard_events.get(); + event.set(next_event); + processed_keyboard_events.compact(); + return true; + } + + public final synchronized boolean getNextMouseEvent(RawMouseEvent event) { + processed_mouse_events.flip(); + if (!processed_mouse_events.hasRemaining()) { + processed_mouse_events.compact(); + return false; + } + RawMouseEvent next_event = (RawMouseEvent)processed_mouse_events.get(); + if ((next_event.getFlags() & MOUSE_MOVE_ABSOLUTE) != 0) { + event_relative_x = next_event.getLastX() - event_last_x; + event_relative_y = next_event.getLastY() - event_last_y; + event_last_x = next_event.getLastX(); + event_last_y = next_event.getLastY(); + } else { + event_relative_x = next_event.getLastX(); + event_relative_y = next_event.getLastY(); + } + event.set(next_event); + processed_mouse_events.compact(); + return true; + } + + public final boolean getButtonState(int button_id) { + if (button_id >= button_states.length) + return false; + return button_states[button_id]; + } + + public final void setBufferSize(int size) { + keyboard_events = new DataQueue(size, RawKeyboardEvent.class); + mouse_events = new DataQueue(size, RawMouseEvent.class); + processed_keyboard_events = new DataQueue(size, RawKeyboardEvent.class); + processed_mouse_events = new DataQueue(size, RawMouseEvent.class); + } + + public final int getType() { + return type; + } + + public final long getHandle() { + return handle; + } + + public final String getName() throws IOException { + return nGetName(handle); + } + private final static native String nGetName(long handle) throws IOException; + + public final RawDeviceInfo getInfo() throws IOException { + return nGetInfo(this, handle); + } + private final static native RawDeviceInfo nGetInfo(RawDevice device, long handle) throws IOException; +} diff --git a/plugins/windows/src/java/net/java/games/input/RawDeviceInfo.java b/plugins/windows/src/java/net/java/games/input/RawDeviceInfo.java new file mode 100644 index 0000000..7e6228f --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawDeviceInfo.java @@ -0,0 +1,67 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper of RID_DEVICE_INFO + * @author elias + * @version 1.0 + */ +abstract class RawDeviceInfo { + public abstract Controller createControllerFromDevice(RawDevice device, SetupAPIDevice setupapi_device) throws IOException; + + public abstract int getUsage(); + + public abstract int getUsagePage(); + + public abstract long getHandle(); + + public final boolean equals(Object other) { + if (!(other instanceof RawDeviceInfo)) + return false; + RawDeviceInfo other_info = (RawDeviceInfo)other; + return other_info.getUsage() == getUsage() && + other_info.getUsagePage() == getUsagePage(); + } + + public final int hashCode() { + return getUsage() ^ getUsagePage(); + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawHIDInfo.java b/plugins/windows/src/java/net/java/games/input/RawHIDInfo.java new file mode 100644 index 0000000..6465bb4 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawHIDInfo.java @@ -0,0 +1,80 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper of RID_DEVICE_INFO_HID + * @author elias + * @version 1.0 + */ +class RawHIDInfo extends RawDeviceInfo { + private final RawDevice device; + + private final int vendor_id; + private final int product_id; + private final int version; + private final int page; + private final int usage; + + public RawHIDInfo(RawDevice device, int vendor_id, int product_id, int version, int page, int usage) { + this.device = device; + this.vendor_id = vendor_id; + this.product_id = product_id; + this.version = version; + this.page = page; + this.usage = usage; + } + + public final int getUsage() { + return usage; + } + + public final int getUsagePage() { + return page; + } + + public final long getHandle() { + return device.getHandle(); + } + + public final Controller createControllerFromDevice(RawDevice device, SetupAPIDevice setupapi_device) throws IOException { + return null; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawIdentifierMap.java b/plugins/windows/src/java/net/java/games/input/RawIdentifierMap.java new file mode 100644 index 0000000..662a183 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawIdentifierMap.java @@ -0,0 +1,553 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +/** + * @author elias + * @version 1.0 + */ +final class RawIdentifierMap { + public final static int VK_LBUTTON = 0x01; + public final static int VK_RBUTTON = 0x02; + public final static int VK_CANCEL = 0x03; + public final static int VK_MBUTTON = 0x04; /* NOT contiguous with L & RBUTTON */ + + public final static int VK_XBUTTON1 = 0x05; /* NOT contiguous with L & RBUTTON */ + public final static int VK_XBUTTON2 = 0x06; /* NOT contiguous with L & RBUTTON */ + +/* + * 0x07 : unassigned + */ + + public final static int VK_BACK = 0x08; + public final static int VK_TAB = 0x09; + +/* + * 0x0A - 0x0B : reserved + */ + + public final static int VK_CLEAR = 0x0C; + public final static int VK_RETURN = 0x0D; + + public final static int VK_SHIFT = 0x10; + public final static int VK_CONTROL = 0x11; + public final static int VK_MENU = 0x12; + public final static int VK_PAUSE = 0x13; + public final static int VK_CAPITAL = 0x14; + + public final static int VK_KANA = 0x15; + public final static int VK_HANGEUL = 0x15; /* old name - should be here for compatibility */ + public final static int VK_HANGUL = 0x15; + public final static int VK_JUNJA = 0x17; + public final static int VK_FINAL = 0x18; + public final static int VK_HANJA = 0x19; + public final static int VK_KANJI = 0x19; + + public final static int VK_ESCAPE = 0x1B; + + public final static int VK_CONVERT = 0x1C; + public final static int VK_NONCONVERT = 0x1D; + public final static int VK_ACCEPT = 0x1E; + public final static int VK_MODECHANGE = 0x1F; + + public final static int VK_SPACE = 0x20; + public final static int VK_PRIOR = 0x21; + public final static int VK_NEXT = 0x22; + public final static int VK_END = 0x23; + public final static int VK_HOME = 0x24; + public final static int VK_LEFT = 0x25; + public final static int VK_UP = 0x26; + public final static int VK_RIGHT = 0x27; + public final static int VK_DOWN = 0x28; + public final static int VK_SELECT = 0x29; + public final static int VK_PRINT = 0x2A; + public final static int VK_EXECUTE = 0x2B; + public final static int VK_SNAPSHOT = 0x2C; + public final static int VK_INSERT = 0x2D; + public final static int VK_DELETE = 0x2E; + public final static int VK_HELP = 0x2F; +/* + * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39) + * 0x40 : unassigned + * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A) + */ + public final static int VK_0 = 0x30; + public final static int VK_1 = 0x31; + public final static int VK_2 = 0x32; + public final static int VK_3 = 0x33; + public final static int VK_4 = 0x34; + public final static int VK_5 = 0x35; + public final static int VK_6 = 0x36; + public final static int VK_7 = 0x37; + public final static int VK_8 = 0x38; + public final static int VK_9 = 0x39; + + public final static int VK_A = 0x41; + public final static int VK_B = 0x42; + public final static int VK_C = 0x43; + public final static int VK_D = 0x44; + public final static int VK_E = 0x45; + public final static int VK_F = 0x46; + public final static int VK_G = 0x47; + public final static int VK_H = 0x48; + public final static int VK_I = 0x49; + public final static int VK_J = 0x4A; + public final static int VK_K = 0x4B; + public final static int VK_L = 0x4C; + public final static int VK_M = 0x4D; + public final static int VK_N = 0x4E; + public final static int VK_O = 0x4F; + public final static int VK_P = 0x50; + public final static int VK_Q = 0x51; + public final static int VK_R = 0x52; + public final static int VK_S = 0x53; + public final static int VK_T = 0x54; + public final static int VK_U = 0x55; + public final static int VK_V = 0x56; + public final static int VK_W = 0x57; + public final static int VK_X = 0x58; + public final static int VK_Y = 0x59; + public final static int VK_Z = 0x5A; + + public final static int VK_LWIN = 0x5B; + public final static int VK_RWIN = 0x5C; + public final static int VK_APPS = 0x5D; +/* + * 0x5E : reserved; + */ + + public final static int VK_SLEEP = 0x5F; + + public final static int VK_NUMPAD0 = 0x60; + public final static int VK_NUMPAD1 = 0x61; + public final static int VK_NUMPAD2 = 0x62; + public final static int VK_NUMPAD3 = 0x63; + public final static int VK_NUMPAD4 = 0x64; + public final static int VK_NUMPAD5 = 0x65; + public final static int VK_NUMPAD6 = 0x66; + public final static int VK_NUMPAD7 = 0x67; + public final static int VK_NUMPAD8 = 0x68; + public final static int VK_NUMPAD9 = 0x69; + public final static int VK_MULTIPLY = 0x6A; + public final static int VK_ADD = 0x6B; + public final static int VK_SEPARATOR = 0x6C; + public final static int VK_SUBTRACT = 0x6D; + public final static int VK_DECIMAL = 0x6E; + public final static int VK_DIVIDE = 0x6F; + public final static int VK_F1 = 0x70; + public final static int VK_F2 = 0x71; + public final static int VK_F3 = 0x72; + public final static int VK_F4 = 0x73; + public final static int VK_F5 = 0x74; + public final static int VK_F6 = 0x75; + public final static int VK_F7 = 0x76; + public final static int VK_F8 = 0x77; + public final static int VK_F9 = 0x78; + public final static int VK_F10 = 0x79; + public final static int VK_F11 = 0x7A; + public final static int VK_F12 = 0x7B; + public final static int VK_F13 = 0x7C; + public final static int VK_F14 = 0x7D; + public final static int VK_F15 = 0x7E; + public final static int VK_F16 = 0x7F; + public final static int VK_F17 = 0x80; + public final static int VK_F18 = 0x81; + public final static int VK_F19 = 0x82; + public final static int VK_F20 = 0x83; + public final static int VK_F21 = 0x84; + public final static int VK_F22 = 0x85; + public final static int VK_F23 = 0x86; + public final static int VK_F24 = 0x87; + +/* + * 0x88 - 0x8F : unassigned; + */ + + public final static int VK_NUMLOCK = 0x90; + public final static int VK_SCROLL = 0x91; + +/* + * NEC PC-9800 kbd definitions + */ + public final static int VK_OEM_NEC_EQUAL = 0x92; // '=' key on numpad +/* + * Fujitsu/OASYS kbd definitions + */ + public final static int VK_OEM_FJ_JISHO = 0x92; // 'Dictionary' key + public final static int VK_OEM_FJ_MASSHOU = 0x93; // 'Unregister word' key + public final static int VK_OEM_FJ_TOUROKU = 0x94; // 'Register word' key + public final static int VK_OEM_FJ_LOYA = 0x95; // 'Left OYAYUBI' key + public final static int VK_OEM_FJ_ROYA = 0x96; // 'Right OYAYUBI' key + +/* + * 0x97 - 0x9F : unassigned + */ + +/* + * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys. + * Used only as parameters to GetAsyncKeyState() and GetKeyState(). + * No other API or message will distinguish left and right keys in this way. + */ + public final static int VK_LSHIFT = 0xA0; + public final static int VK_RSHIFT = 0xA1; + public final static int VK_LCONTROL = 0xA2; + public final static int VK_RCONTROL = 0xA3; + public final static int VK_LMENU = 0xA4; + public final static int VK_RMENU = 0xA5; + + public final static int VK_BROWSER_BACK = 0xA6; + public final static int VK_BROWSER_FORWARD = 0xA7; + public final static int VK_BROWSER_REFRESH = 0xA8; + public final static int VK_BROWSER_STOP = 0xA9; + public final static int VK_BROWSER_SEARCH = 0xAA; + public final static int VK_BROWSER_FAVORITES = 0xAB; + public final static int VK_BROWSER_HOME = 0xAC; + + public final static int VK_VOLUME_MUTE = 0xAD; + public final static int VK_VOLUME_DOWN = 0xAE; + public final static int VK_VOLUME_UP = 0xAF; + public final static int VK_MEDIA_NEXT_TRACK = 0xB0; + public final static int VK_MEDIA_PREV_TRACK = 0xB1; + public final static int VK_MEDIA_STOP = 0xB2; + public final static int VK_MEDIA_PLAY_PAUSE = 0xB3; + public final static int VK_LAUNCH_MAIL = 0xB4; + public final static int VK_LAUNCH_MEDIA_SELECT = 0xB5; + public final static int VK_LAUNCH_APP1 = 0xB6; + public final static int VK_LAUNCH_APP2 = 0xB7; + +/* + * 0xB8 - 0xB9 : reserved + */ + + public final static int VK_OEM_1 = 0xBA; // ';:' for US + public final static int VK_OEM_PLUS = 0xBB; // '+' any country + public final static int VK_OEM_COMMA = 0xBC; // ',' any country + public final static int VK_OEM_MINUS = 0xBD; // '-' any country + public final static int VK_OEM_PERIOD = 0xBE; // '.' any country + public final static int VK_OEM_2 = 0xBF; // '/?' for US + public final static int VK_OEM_3 = 0xC0; // '`~' for US + +/* + * 0xC1 - 0xD7 : reserved + */ + +/* + * 0xD8 - 0xDA : unassigned + */ + + public final static int VK_OEM_4 = 0xDB; // '[{' for US + public final static int VK_OEM_5 = 0xDC; // '\|' for US + public final static int VK_OEM_6 = 0xDD; // ']}' for US + public final static int VK_OEM_7 = 0xDE; // ''"' for US + public final static int VK_OEM_8 = 0xDF; + +/* + * 0xE0 : reserved + */ + +/* + * Various extended or enhanced keyboards + */ + public final static int VK_OEM_AX = 0xE1; // 'AX' key on Japanese AX kbd + public final static int VK_OEM_102 = 0xE2; // "<>" or "\|" on RT 102-key kbd. + public final static int VK_ICO_HELP = 0xE3; // Help key on ICO + public final static int VK_ICO_00 = 0xE4; // 00 key on ICO + + public final static int VK_PROCESSKEY = 0xE5; + + public final static int VK_ICO_CLEAR = 0xE6; + + + public final static int VK_PACKET = 0xE7; + +/* + * 0xE8 : unassigned + */ + +/* + * Nokia/Ericsson definitions + */ + public final static int VK_OEM_RESET = 0xE9; + public final static int VK_OEM_JUMP = 0xEA; + public final static int VK_OEM_PA1 = 0xEB; + public final static int VK_OEM_PA2 = 0xEC; + public final static int VK_OEM_PA3 = 0xED; + public final static int VK_OEM_WSCTRL = 0xEE; + public final static int VK_OEM_CUSEL = 0xEF; + public final static int VK_OEM_ATTN = 0xF0; + public final static int VK_OEM_FINISH = 0xF1; + public final static int VK_OEM_COPY = 0xF2; + public final static int VK_OEM_AUTO = 0xF3; + public final static int VK_OEM_ENLW = 0xF4; + public final static int VK_OEM_BACKTAB = 0xF5; + + public final static int VK_ATTN = 0xF6; + public final static int VK_CRSEL = 0xF7; + public final static int VK_EXSEL = 0xF8; + public final static int VK_EREOF = 0xF9; + public final static int VK_PLAY = 0xFA; + public final static int VK_ZOOM = 0xFB; + public final static int VK_NONAME = 0xFC; + public final static int VK_PA1 = 0xFD; + public final static int VK_OEM_CLEAR = 0xFE; + + public final static Component.Identifier.Key mapVKey(int vkey) { + switch (vkey) { + case VK_ESCAPE: + return Component.Identifier.Key.ESCAPE; + case VK_1: + return Component.Identifier.Key._1; + case VK_2: + return Component.Identifier.Key._2; + case VK_3: + return Component.Identifier.Key._3; + case VK_4: + return Component.Identifier.Key._4; + case VK_5: + return Component.Identifier.Key._5; + case VK_6: + return Component.Identifier.Key._6; + case VK_7: + return Component.Identifier.Key._7; + case VK_8: + return Component.Identifier.Key._8; + case VK_9: + return Component.Identifier.Key._9; + case VK_0: + return Component.Identifier.Key._0; + case VK_OEM_NEC_EQUAL: + return Component.Identifier.Key.NUMPADEQUAL; + case VK_BACK: + return Component.Identifier.Key.BACK; + case VK_TAB: + return Component.Identifier.Key.TAB; + case VK_Q: + return Component.Identifier.Key.Q; + case VK_W: + return Component.Identifier.Key.W; + case VK_E: + return Component.Identifier.Key.E; + case VK_R: + return Component.Identifier.Key.R; + case VK_T: + return Component.Identifier.Key.T; + case VK_Y: + return Component.Identifier.Key.Y; + case VK_U: + return Component.Identifier.Key.U; + case VK_I: + return Component.Identifier.Key.I; + case VK_O: + return Component.Identifier.Key.O; + case VK_P: + return Component.Identifier.Key.P; + case VK_OEM_4: + return Component.Identifier.Key.LBRACKET; + case VK_OEM_6: + return Component.Identifier.Key.RBRACKET; + case VK_RETURN: + return Component.Identifier.Key.RETURN; + case VK_CONTROL: + case VK_LCONTROL: + return Component.Identifier.Key.LCONTROL; + case VK_A: + return Component.Identifier.Key.A; + case VK_S: + return Component.Identifier.Key.S; + case VK_D: + return Component.Identifier.Key.D; + case VK_F: + return Component.Identifier.Key.F; + case VK_G: + return Component.Identifier.Key.G; + case VK_H: + return Component.Identifier.Key.H; + case VK_J: + return Component.Identifier.Key.J; + case VK_K: + return Component.Identifier.Key.K; + case VK_L: + return Component.Identifier.Key.L; + case VK_OEM_3: + return Component.Identifier.Key.GRAVE; + case VK_SHIFT: + case VK_LSHIFT: + return Component.Identifier.Key.LSHIFT; + case VK_Z: + return Component.Identifier.Key.Z; + case VK_X: + return Component.Identifier.Key.X; + case VK_C: + return Component.Identifier.Key.C; + case VK_V: + return Component.Identifier.Key.V; + case VK_B: + return Component.Identifier.Key.B; + case VK_N: + return Component.Identifier.Key.N; + case VK_M: + return Component.Identifier.Key.M; + case VK_OEM_COMMA: + return Component.Identifier.Key.COMMA; + case VK_OEM_PERIOD: + return Component.Identifier.Key.PERIOD; + case VK_RSHIFT: + return Component.Identifier.Key.RSHIFT; + case VK_MULTIPLY: + return Component.Identifier.Key.MULTIPLY; + case VK_MENU: + case VK_LMENU: + return Component.Identifier.Key.LALT; + case VK_SPACE: + return Component.Identifier.Key.SPACE; + case VK_CAPITAL: + return Component.Identifier.Key.CAPITAL; + case VK_F1: + return Component.Identifier.Key.F1; + case VK_F2: + return Component.Identifier.Key.F2; + case VK_F3: + return Component.Identifier.Key.F3; + case VK_F4: + return Component.Identifier.Key.F4; + case VK_F5: + return Component.Identifier.Key.F5; + case VK_F6: + return Component.Identifier.Key.F6; + case VK_F7: + return Component.Identifier.Key.F7; + case VK_F8: + return Component.Identifier.Key.F8; + case VK_F9: + return Component.Identifier.Key.F9; + case VK_F10: + return Component.Identifier.Key.F10; + case VK_NUMLOCK: + return Component.Identifier.Key.NUMLOCK; + case VK_SCROLL: + return Component.Identifier.Key.SCROLL; + case VK_NUMPAD7: + return Component.Identifier.Key.NUMPAD7; + case VK_NUMPAD8: + return Component.Identifier.Key.NUMPAD8; + case VK_NUMPAD9: + return Component.Identifier.Key.NUMPAD9; + case VK_SUBTRACT: + return Component.Identifier.Key.SUBTRACT; + case VK_NUMPAD4: + return Component.Identifier.Key.NUMPAD4; + case VK_NUMPAD5: + return Component.Identifier.Key.NUMPAD5; + case VK_NUMPAD6: + return Component.Identifier.Key.NUMPAD6; + case VK_ADD: + return Component.Identifier.Key.ADD; + case VK_NUMPAD1: + return Component.Identifier.Key.NUMPAD1; + case VK_NUMPAD2: + return Component.Identifier.Key.NUMPAD2; + case VK_NUMPAD3: + return Component.Identifier.Key.NUMPAD3; + case VK_NUMPAD0: + return Component.Identifier.Key.NUMPAD0; + case VK_DECIMAL: + return Component.Identifier.Key.DECIMAL; + case VK_F11: + return Component.Identifier.Key.F11; + case VK_F12: + return Component.Identifier.Key.F12; + case VK_F13: + return Component.Identifier.Key.F13; + case VK_F14: + return Component.Identifier.Key.F14; + case VK_F15: + return Component.Identifier.Key.F15; + case VK_KANA: + return Component.Identifier.Key.KANA; + case VK_CONVERT: + return Component.Identifier.Key.CONVERT; + case VK_KANJI: + return Component.Identifier.Key.KANJI; + case VK_OEM_AX: + return Component.Identifier.Key.AX; + case VK_RCONTROL: + return Component.Identifier.Key.RCONTROL; + case VK_SEPARATOR: + return Component.Identifier.Key.NUMPADCOMMA; + case VK_DIVIDE: + return Component.Identifier.Key.DIVIDE; + case VK_SNAPSHOT: + return Component.Identifier.Key.SYSRQ; + case VK_RMENU: + return Component.Identifier.Key.RALT; + case VK_PAUSE: + return Component.Identifier.Key.PAUSE; + case VK_HOME: + return Component.Identifier.Key.HOME; + case VK_UP: + return Component.Identifier.Key.UP; + case VK_PRIOR: + return Component.Identifier.Key.PAGEUP; + case VK_LEFT: + return Component.Identifier.Key.LEFT; + case VK_RIGHT: + return Component.Identifier.Key.RIGHT; + case VK_END: + return Component.Identifier.Key.END; + case VK_DOWN: + return Component.Identifier.Key.DOWN; + case VK_NEXT: + return Component.Identifier.Key.PAGEDOWN; + case VK_INSERT: + return Component.Identifier.Key.INSERT; + case VK_DELETE: + return Component.Identifier.Key.DELETE; + case VK_LWIN: + return Component.Identifier.Key.LWIN; + case VK_RWIN: + return Component.Identifier.Key.RWIN; + case VK_APPS: + return Component.Identifier.Key.APPS; + case VK_SLEEP: + return Component.Identifier.Key.SLEEP; + default: + return Component.Identifier.Key.UNKNOWN; + } + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawInputEnvironmentPlugin.java b/plugins/windows/src/java/net/java/games/input/RawInputEnvironmentPlugin.java new file mode 100644 index 0000000..304ff13 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawInputEnvironmentPlugin.java @@ -0,0 +1,160 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.ArrayList; +import java.io.IOException; + +import net.java.games.util.plugins.Plugin; + +/** DirectInput implementation of controller environment + * @author martak + * @author elias + * @version 1.0 + */ +public final class RawInputEnvironmentPlugin extends ControllerEnvironment implements Plugin { + static { + AccessController.doPrivileged( + new PrivilegedAction() { + public final Object run() { + System.loadLibrary("jinput-raw"); + return null; + } + }); + } + + private final Controller[] controllers; + + /** Creates new DirectInputEnvironment */ + public RawInputEnvironmentPlugin() { + RawInputEventQueue queue; + Controller[] controllers = new Controller[]{}; + try { + queue = new RawInputEventQueue(); + controllers = enumControllers(queue); + } catch (IOException e) { + ControllerEnvironment.logln("Failed to enumerate devices: " + e.getMessage()); + } + this.controllers = controllers; + } + + public final Controller[] getControllers() { + return controllers; + } + + private final static SetupAPIDevice lookupSetupAPIDevice(String device_name, List setupapi_devices) { + /* First, replace # with / in the device name, since that + * seems to be the format in raw input device name + */ + device_name = device_name.replaceAll("#", "\\\\").toUpperCase(); + for (int i = 0; i < setupapi_devices.size(); i++) { + SetupAPIDevice device = (SetupAPIDevice)setupapi_devices.get(i); + if (device_name.indexOf(device.getInstanceId().toUpperCase()) != -1) + return device; + } + return null; + } + + private final static void createControllersFromDevices(RawInputEventQueue queue, List controllers, List devices, List setupapi_devices) throws IOException { + List active_devices = new ArrayList(); + for (int i = 0; i < devices.size(); i++) { + RawDevice device = (RawDevice)devices.get(i); + SetupAPIDevice setupapi_device = lookupSetupAPIDevice(device.getName(), setupapi_devices); + if (setupapi_device == null) { + /* Either the device is an RDP or we failed to locate the + * SetupAPI device that matches + */ + continue; + } + RawDeviceInfo info = device.getInfo(); + Controller controller = info.createControllerFromDevice(device, setupapi_device); + if (controller != null) { + controllers.add(controller); + active_devices.add(device); + } + } + queue.start(active_devices); + } + + private final static native void enumerateDevices(RawInputEventQueue queue, List devices) throws IOException; + + private final Controller[] enumControllers(RawInputEventQueue queue) throws IOException { + List controllers = new ArrayList(); + List devices = new ArrayList(); + enumerateDevices(queue, devices); + List setupapi_devices = enumSetupAPIDevices(); + createControllersFromDevices(queue, controllers, devices, setupapi_devices); + Controller[] controllers_array = new Controller[controllers.size()]; + controllers.toArray(controllers_array); + return controllers_array; + } + + /* + * The raw input API, while being able to access + * multiple mice and keyboards, is a bit raw (hah) + * since it lacks some important features: + * + * 1. The list of keyboards and the list of mice + * both include useless Terminal Server + * devices (RDP_MOU and RDP_KEY) that we'd + * like to skip. + * 2. The device names returned by GetRawInputDeviceInfo() + * are not for display, but instead synthesized + * from a combination of a device instance id + * and a GUID. + * + * A solution to both problems is the SetupAPI that allows + * us to enumerate all keyboard and mouse devices and fetch their + * descriptive names and at the same time filter out the unwanted + * RDP devices. + */ + private final static List enumSetupAPIDevices() throws IOException { + List devices = new ArrayList(); + nEnumSetupAPIDevices(getKeyboardClassGUID(), devices); + nEnumSetupAPIDevices(getMouseClassGUID(), devices); + return devices; + } + private final static native void nEnumSetupAPIDevices(byte[] guid, List devices) throws IOException; + + private final static native byte[] getKeyboardClassGUID(); + private final static native byte[] getMouseClassGUID(); +} // class DirectInputEnvironment diff --git a/plugins/windows/src/java/net/java/games/input/RawInputEventQueue.java b/plugins/windows/src/java/net/java/games/input/RawInputEventQueue.java new file mode 100644 index 0000000..99f486d --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawInputEventQueue.java @@ -0,0 +1,157 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; +import java.util.Set; +import java.util.HashSet; + +/** Java wrapper of RAWDEVICELIST + * @author elias + * @version 1.0 + */ +final class RawInputEventQueue { + private final Object monitor = new Object(); + + private List devices; + + public final void start(List devices) throws IOException { + this.devices = devices; + QueueThread queue = new QueueThread(); + synchronized (monitor) { + queue.start(); + // wait for initialization + while (!queue.isInitialized()) { + try { + monitor.wait(); + } catch (InterruptedException e) {} + } + } + if (queue.getException() != null) + throw queue.getException(); + } + + private final RawDevice lookupDevice(long handle) { + for (int i = 0; i < devices.size(); i++) { + RawDevice device = (RawDevice)devices.get(i); + if (device.getHandle() == handle) + return device; + } + return null; + } + + /* Event methods called back from native code in nPoll() */ + private final void addMouseEvent(long handle, long millis, int flags, int button_flags, int button_data, long raw_buttons, long last_x, long last_y, long extra_information) { + RawDevice device = lookupDevice(handle); + if (device == null) + return; + device.addMouseEvent(millis, flags, button_flags, button_data, raw_buttons, last_x, last_y, extra_information); + } + + private final void addKeyboardEvent(long handle, long millis, int make_code, int flags, int vkey, int message, long extra_information) { + RawDevice device = lookupDevice(handle); + if (device == null) + return; + device.addKeyboardEvent(millis, make_code, flags, vkey, message, extra_information); + } + + private final void poll(DummyWindow window) throws IOException { + nPoll(window.getHwnd()); + } + private final native void nPoll(long hwnd_handle) throws IOException; + + private final static void registerDevices(DummyWindow window, RawDeviceInfo[] devices) throws IOException { + nRegisterDevices(0, window.getHwnd(), devices); + } + private final static native void nRegisterDevices(int flags, long hwnd_addr, RawDeviceInfo[] devices) throws IOException; + + private final class QueueThread extends Thread { + private boolean initialized; + private DummyWindow window; + private IOException exception; + + public QueueThread() { + setDaemon(true); + } + + public final boolean isInitialized() { + return initialized; + } + + public final IOException getException() { + return exception; + } + + public final void run() { + // We have to create the window in the (private) queue thread + try { + window = new DummyWindow(); + } catch (IOException e) { + exception = e; + } + initialized = true; + synchronized (monitor) { + monitor.notify(); + } + if (exception != null) + return; + Set active_infos = new HashSet(); + try { + for (int i = 0; i < devices.size(); i++) { + RawDevice device = (RawDevice)devices.get(i); + active_infos.add(device.getInfo()); + } + RawDeviceInfo[] active_infos_array = new RawDeviceInfo[active_infos.size()]; + active_infos.toArray(active_infos_array); + try { + registerDevices(window, active_infos_array); + while (!isInterrupted()) { + poll(window); + } + } finally { + window.destroy(); + } + } catch (IOException e) { + exception = e; + } + } + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawKeyboard.java b/plugins/windows/src/java/net/java/games/input/RawKeyboard.java new file mode 100644 index 0000000..728284f --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawKeyboard.java @@ -0,0 +1,130 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** +* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* - Redistribution of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* - Redistribution in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materails provided with the distribution. +* +* Neither the name Sun Microsystems, Inc. or the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* This software is provided "AS IS," without a warranty of any kind. +* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING +* ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR +* NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND +* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS +* A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS +* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST +* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, +* INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY +* OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, +* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* +* You acknowledge that this software is not designed or intended for us in +* the design, construction, operation or maintenance of any nuclear facility +* +*****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** +* @author elias +* @version 1.0 +*/ +final class RawKeyboard extends Keyboard { + private final RawKeyboardEvent raw_event = new RawKeyboardEvent(); + private final RawDevice device; + + protected RawKeyboard(String name, RawDevice device, Controller[] children, Rumbler[] rumblers) throws IOException { + super(name, createKeyboardComponents(device), children, rumblers); + this.device = device; + } + + private final static Component[] createKeyboardComponents(RawDevice device) { + List components = new ArrayList(); + Field[] vkey_fields = RawIdentifierMap.class.getFields(); + for (int i = 0; i < vkey_fields.length; i++) { + Field vkey_field = vkey_fields[i]; + try { + if (Modifier.isStatic(vkey_field.getModifiers()) && vkey_field.getType() == int.class) { + int vkey_code = vkey_field.getInt(null); + Component.Identifier.Key key_id = RawIdentifierMap.mapVKey(vkey_code); + if (key_id != Component.Identifier.Key.UNKNOWN) + components.add(new Key(device, vkey_code, key_id)); + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + return (Component[])components.toArray(new Component[]{}); + } + + protected final synchronized boolean getNextDeviceEvent(Event event) throws IOException { + while (true) { + if (!device.getNextKeyboardEvent(raw_event)) + return false; + int vkey = raw_event.getVKey(); + Component.Identifier.Key key_id = RawIdentifierMap.mapVKey(vkey); + Component key = getComponent(key_id); + if (key == null) + continue; + int message = raw_event.getMessage(); + if (message == RawDevice.WM_KEYDOWN || message == RawDevice.WM_SYSKEYDOWN) { + event.set(key, 1, raw_event.getNanos()); + return true; + } else if (message == RawDevice.WM_KEYUP || message == RawDevice.WM_SYSKEYUP) { + event.set(key, 0, raw_event.getNanos()); + return true; + } + } + } + + public final void pollDevice() throws IOException { + device.pollKeyboard(); + } + + protected final void setDeviceEventQueueSize(int size) throws IOException { + device.setBufferSize(size); + } + + final static class Key extends AbstractComponent { + private final RawDevice device; + private final int vkey_code; + + public Key(RawDevice device, int vkey_code, Component.Identifier.Key key_id) { + super(key_id.getName(), key_id); + this.device = device; + this.vkey_code = vkey_code; + } + + protected final float poll() throws IOException { + return device.isKeyDown(vkey_code) ? 1f : 0f; + } + + public final boolean isAnalog() { + return false; + } + + public final boolean isRelative() { + return false; + } + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawKeyboardEvent.java b/plugins/windows/src/java/net/java/games/input/RawKeyboardEvent.java new file mode 100644 index 0000000..753baa9 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawKeyboardEvent.java @@ -0,0 +1,79 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper of RAWKEYBOARD + * @author elias + * @version 1.0 + */ +final class RawKeyboardEvent { + private long millis; + private int make_code; + private int flags; + private int vkey; + private int message; + private long extra_information; + + public final void set(long millis, int make_code, int flags, int vkey, int message, long extra_information) { + this.millis = millis; + this.make_code = make_code; + this.flags = flags; + this.vkey = vkey; + this.message = message; + this.extra_information = extra_information; + } + + public final void set(RawKeyboardEvent event) { + set(event.millis, event.make_code, event.flags, event.vkey, event.message, event.extra_information); + } + + public final int getVKey() { + return vkey; + } + + public final int getMessage() { + return message; + } + + public final long getNanos() { + return millis*1000000L; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawKeyboardInfo.java b/plugins/windows/src/java/net/java/games/input/RawKeyboardInfo.java new file mode 100644 index 0000000..3b4add3 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawKeyboardInfo.java @@ -0,0 +1,81 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper of RID_DEVICE_INFO_KEYBOARD + * @author elias + * @version 1.0 + */ +class RawKeyboardInfo extends RawDeviceInfo { + private final RawDevice device; + private final int type; + private final int sub_type; + private final int keyboard_mode; + private final int num_function_keys; + private final int num_indicators; + private final int num_keys_total; + + public RawKeyboardInfo(RawDevice device, int type, int sub_type, int keyboard_mode, int num_function_keys, int num_indicators, int num_keys_total) { + this.device = device; + this.type = type; + this.sub_type = sub_type; + this.keyboard_mode = keyboard_mode; + this.num_function_keys = num_function_keys; + this.num_indicators = num_indicators; + this.num_keys_total = num_keys_total; + } + + public final int getUsage() { + return 6; + } + + public final int getUsagePage() { + return 1; + } + + public final long getHandle() { + return device.getHandle(); + } + + public final Controller createControllerFromDevice(RawDevice device, SetupAPIDevice setupapi_device) throws IOException { + return new RawKeyboard(setupapi_device.getName(), device, new Controller[]{}, new Rumbler[]{}); + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawMouse.java b/plugins/windows/src/java/net/java/games/input/RawMouse.java new file mode 100644 index 0000000..597085f --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawMouse.java @@ -0,0 +1,214 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** +* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* - Redistribution of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* - Redistribution in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materails provided with the distribution. +* +* Neither the name Sun Microsystems, Inc. or the names of the contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* This software is provided "AS IS," without a warranty of any kind. +* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING +* ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR +* NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND +* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS +* A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS +* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST +* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, +* INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY +* OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, +* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +* +* You acknowledge that this software is not designed or intended for us in +* the design, construction, operation or maintenance of any nuclear facility +* +*****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** +* @author elias +* @version 1.0 +*/ +final class RawMouse extends Mouse { + /* Because one raw event can contain multiple + * changes, we'll make a simple state machine + * to keep track of which change to report next + */ + + // Another event should be read + private final static int EVENT_DONE = 1; + // The X axis should be reported next + private final static int EVENT_X = 2; + // The Y axis should be reported next + private final static int EVENT_Y = 3; + // The Z axis should be reported next + private final static int EVENT_Z = 4; + // Button 0 should be reported next + private final static int EVENT_BUTTON_0 = 5; + // Button 1 should be reported next + private final static int EVENT_BUTTON_1 = 6; + // Button 2 should be reported next + private final static int EVENT_BUTTON_2 = 7; + // Button 3 should be reported next + private final static int EVENT_BUTTON_3 = 8; + // Button 4 should be reported next + private final static int EVENT_BUTTON_4 = 9; + + private final RawDevice device; + + private final RawMouseEvent current_event = new RawMouseEvent(); + private int event_state = EVENT_DONE; + + protected RawMouse(String name, RawDevice device, Component[] components, Controller[] children, Rumbler[] rumblers) throws IOException { + super(name, components, children, rumblers); + this.device = device; + } + + public final void pollDevice() throws IOException { + device.pollMouse(); + } + + private final static boolean makeButtonEvent(RawMouseEvent mouse_event, Event event, Component button_component, int down_flag, int up_flag) { + if ((mouse_event.getButtonFlags() & down_flag) != 0) { + event.set(button_component, 1, mouse_event.getNanos()); + return true; + } else if ((mouse_event.getButtonFlags() & up_flag) != 0) { + event.set(button_component, 0, mouse_event.getNanos()); + return true; + } else + return false; + } + + protected final synchronized boolean getNextDeviceEvent(Event event) throws IOException { + while (true) { + switch (event_state) { + case EVENT_DONE: + if (!device.getNextMouseEvent(current_event)) + return false; + event_state = EVENT_X; + break; + case EVENT_X: + int rel_x = device.getEventRelativeX(); + event_state = EVENT_Y; + if (rel_x != 0) { + event.set(getX(), rel_x, current_event.getNanos()); + return true; + } + break; + case EVENT_Y: + int rel_y = device.getEventRelativeY(); + event_state = EVENT_Z; + if (rel_y != 0) { + event.set(getY(), rel_y, current_event.getNanos()); + return true; + } + break; + case EVENT_Z: + int wheel = current_event.getWheelDelta(); + event_state = EVENT_BUTTON_0; + if (wheel != 0) { + event.set(getWheel(), wheel, current_event.getNanos()); + return true; + } + break; + case EVENT_BUTTON_0: + event_state = EVENT_BUTTON_1; + if (makeButtonEvent(current_event, event, getLeft(), RawDevice.RI_MOUSE_BUTTON_1_DOWN, RawDevice.RI_MOUSE_BUTTON_1_UP)) + return true; + break; + case EVENT_BUTTON_1: + event_state = EVENT_BUTTON_2; + if (makeButtonEvent(current_event, event, getLeft(), RawDevice.RI_MOUSE_BUTTON_2_DOWN, RawDevice.RI_MOUSE_BUTTON_2_UP)) + return true; + break; + case EVENT_BUTTON_2: + event_state = EVENT_BUTTON_3; + if (makeButtonEvent(current_event, event, getLeft(), RawDevice.RI_MOUSE_BUTTON_3_DOWN, RawDevice.RI_MOUSE_BUTTON_3_UP)) + return true; + break; + case EVENT_BUTTON_3: + event_state = EVENT_BUTTON_4; + if (makeButtonEvent(current_event, event, getLeft(), RawDevice.RI_MOUSE_BUTTON_4_DOWN, RawDevice.RI_MOUSE_BUTTON_4_UP)) + return true; + break; + case EVENT_BUTTON_4: + event_state = EVENT_DONE; + if (makeButtonEvent(current_event, event, getLeft(), RawDevice.RI_MOUSE_BUTTON_5_DOWN, RawDevice.RI_MOUSE_BUTTON_5_UP)) + return true; + break; + default: + throw new RuntimeException("Unknown event state: " + event_state); + } + } + } + + protected final void setDeviceEventQueueSize(int size) throws IOException { + device.setBufferSize(size); + } + + final static class Axis extends AbstractComponent { + private final RawDevice device; + + public Axis(RawDevice device, Component.Identifier.Axis axis) { + super(axis.getName(), axis); + this.device = device; + } + + public final boolean isRelative() { + return true; + } + + public final boolean isAnalog() { + return true; + } + + protected final float poll() throws IOException { + if (getIdentifier() == Component.Identifier.Axis.X) { + return device.getRelativeX(); + } else if (getIdentifier() == Component.Identifier.Axis.Y) { + return device.getRelativeY(); + } else if (getIdentifier() == Component.Identifier.Axis.Z) { + return device.getWheel(); + } else + throw new RuntimeException("Unknown raw axis: " + getIdentifier()); + } + } + + final static class Button extends AbstractComponent { + private final RawDevice device; + private final int button_id; + + public Button(RawDevice device, Component.Identifier.Button id, int button_id) { + super(id.getName(), id); + this.device = device; + this.button_id = button_id; + } + + protected final float poll() throws IOException { + return device.getButtonState(button_id) ? 1 : 0; + } + + public final boolean isAnalog() { + return false; + } + + public final boolean isRelative() { + return false; + } + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawMouseEvent.java b/plugins/windows/src/java/net/java/games/input/RawMouseEvent.java new file mode 100644 index 0000000..1cc8fce --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawMouseEvent.java @@ -0,0 +1,108 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper of RAWMOUSE + * @author elias + * @version 1.0 + */ +final class RawMouseEvent { + /* It seems that raw input scales wheel + * the same way as direcinput + */ + private final static int WHEEL_SCALE = 120; + + private long millis; + private int flags; + private int button_flags; + private int button_data; + private long raw_buttons; + private long last_x; + private long last_y; + private long extra_information; + + public final void set(long millis, int flags, int button_flags, int button_data, long raw_buttons, long last_x, long last_y, long extra_information) { + this.millis = millis; + this.flags = flags; + this.button_flags = button_flags; + this.button_data = button_data; + this.raw_buttons = raw_buttons; + this.last_x = last_x; + this.last_y = last_y; + this.extra_information = extra_information; + } + + public final void set(RawMouseEvent event) { + set(event.millis, event.flags, event.button_flags, event.button_data, event.raw_buttons, event.last_x, event.last_y, event.extra_information); + } + + public final int getWheelDelta() { + return button_data/WHEEL_SCALE; + } + + private final int getButtonData() { + return button_data; + } + + public final int getFlags() { + return flags; + } + + public final int getButtonFlags() { + return button_flags; + } + + public final int getLastX() { + return (int)last_x; + } + + public final int getLastY() { + return (int)last_y; + } + + public final long getRawButtons() { + return raw_buttons; + } + + public final long getNanos() { + return millis*1000000L; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/RawMouseInfo.java b/plugins/windows/src/java/net/java/games/input/RawMouseInfo.java new file mode 100644 index 0000000..aa89e94 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/RawMouseInfo.java @@ -0,0 +1,88 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper of RID_DEVICE_INFO_MOUSE + * @author elias + * @version 1.0 + */ +class RawMouseInfo extends RawDeviceInfo { + private final RawDevice device; + private final int id; + private final int num_buttons; + private final int sample_rate; + + public RawMouseInfo(RawDevice device, int id, int num_buttons, int sample_rate) { + this.device = device; + this.id = id; + this.num_buttons = num_buttons; + this.sample_rate = sample_rate; + } + + public final int getUsage() { + return 2; + } + + public final int getUsagePage() { + return 1; + } + + public final long getHandle() { + return device.getHandle(); + } + + public final Controller createControllerFromDevice(RawDevice device, SetupAPIDevice setupapi_device) throws IOException { + if (num_buttons == 0) + return null; + // A raw mouse contains the x and y and z axis and the buttons + Component[] components = new Component[3 + num_buttons]; + int index = 0; + components[index++] = new RawMouse.Axis(device, Component.Identifier.Axis.X); + components[index++] = new RawMouse.Axis(device, Component.Identifier.Axis.Y); + components[index++] = new RawMouse.Axis(device, Component.Identifier.Axis.Z); + for (int i = 0; i < num_buttons; i++) { + Component.Identifier.Button id = DIIdentifierMap.mapMouseButtonIdentifier(DIIdentifierMap.getButtonIdentifier(i)); + components[index++] = new RawMouse.Button(device, id, i); + } + Controller mouse = new RawMouse(setupapi_device.getName(), device, components, new Controller[]{}, new Rumbler[]{}); + return mouse; + } +} diff --git a/plugins/windows/src/java/net/java/games/input/SetupAPIDevice.java b/plugins/windows/src/java/net/java/games/input/SetupAPIDevice.java new file mode 100644 index 0000000..1c84545 --- /dev/null +++ b/plugins/windows/src/java/net/java/games/input/SetupAPIDevice.java @@ -0,0 +1,63 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ +/***************************************************************************** + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materails provided with the distribution. + * + * Neither the name Sun Microsystems, Inc. or the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANT OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMEN, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND + * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS + * A RESULT OF USING, MODIFYING OR DESTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES. HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OUR INABILITY TO USE THIS SOFTWARE, + * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for us in + * the design, construction, operation or maintenance of any nuclear facility + * + *****************************************************************************/ +package net.java.games.input; + +import java.io.IOException; + +/** Java wrapper of a SetupAPI device + * @author elias + * @version 1.0 + */ +final class SetupAPIDevice { + private final String device_instance_id; + private final String device_name; + + public SetupAPIDevice(String device_instance_id, String device_name) { + this.device_instance_id = device_instance_id; + this.device_name = device_name; + } + + public final String getName() { + return device_name; + } + + public final String getInstanceId() { + return device_instance_id; + } +} diff --git a/plugins/windows/src/native/build.xml b/plugins/windows/src/native/build.xml new file mode 100644 index 0000000..02225a7 --- /dev/null +++ b/plugins/windows/src/native/build.xml @@ -0,0 +1,87 @@ +<?xml version="1.0"?> + +<project name="JInput dx8 port, Native code" basedir="." default="compile"> + <target name="init"> + </target> + + <target name="compile_dir" depends="init"> + <echo message="${compiledir}"/> + <apply dir="${compiledir}" failonerror="true" executable="cl" dest="${compiledir}" skipemptyfilesets="true"> + <arg line="/Ox /Wp64 /W2 /nologo /c"/> + <arg value="/I${toolkithome}\include"/> + <arg value="/I${sdkhome}\include"/> + <arg value="/I${dxhome}\include"/> + <arg value="/I${java.home}\..\include"/> + <arg value="/I${java.home}\..\include\win32"/> + <arg value="/I${commonhome}/src/native"/> + <arg value="/I.."/> + <srcfile/> + <fileset dir="${compiledir}" includes="*.c"/> + <mapper type="glob" from="*.c" to="*.obj"/> + </apply> + </target> + + <!-- <target name="link" unless="nolink">--> + <target name="link"> + <apply dir="." parallel="true" executable="cl" failonerror="true"> + <arg line="/LD /nologo"/> + <srcfile/> + <arg line="/Fe${dllname} /link"/> + <arg value="/LIBPATH:${java.home}\lib"/> + <arg value="/LIBPATH:${dxhome}\lib\x86"/> + <arg value="/LIBPATH:${sdkhome}\lib"/> + <arg value="/LIBPATH:${toolkithome}\lib"/> + <arg line="/DLL ${libs}"/> + <fileset dir="${commonhome}/src/native" includes="*.obj"/> + <fileset dir="." includes="*.obj"/> + <fileset dir="${objdir}" includes="*.obj"/> + </apply> + </target> + + <target name="clean"> + <delete> + <fileset dir="." includes="*.obj"/> + <fileset dir="raw" includes="*.obj"/> + <fileset dir="dx8" includes="*.obj"/> + <fileset dir="." includes="*.dll"/> + </delete> + </target> + + <target name="compile" depends="init"> + <property name="program_files" location="c:\Program Files"/> + <property name="dxhome" location="${program_files}\Microsoft DirectX SDK (February 2006)"/> + <property name="toolkithome" location="${program_files}\Microsoft Visual C++ Toolkit 2003"/> + <property name="rawlibs" value="Kernel32.lib User32.lib Setupapi.lib"/> + <property name="dx8libs" value="Kernel32.lib dinput8.lib dxguid.lib User32.lib"/> + <property name="sdkhome" location="${program_files}\Microsoft Platform SDK"/> + <property name="commonhome" location="../../../common"/> + <property name="dx8dllname" value="jinput-dx8.dll"/> + <property name="rawdllname" value="jinput-raw.dll"/> + <antcall target="compile_dir"> + <param name="compiledir" location="${commonhome}/src/native"/> + </antcall> + <antcall target="compile_dir"> + <param name="compiledir" location="."/> + </antcall> + <antcall target="compile_dir"> + <param name="compiledir" location="raw"/> + </antcall> + <antcall target="compile_dir"> + <param name="compiledir" location="dx8"/> + </antcall> + <!-- <uptodate property="nolink" targetfile="${dllname}"> + <srcfiles dir="." includes="*.obj"/> + </uptodate>--> + <antcall target="link"> + <param name="dllname" value="${dx8dllname}"/> + <param name="libs" value="${dx8libs}"/> + <param name="objdir" location="dx8"/> + </antcall> + <antcall target="link"> + <param name="dllname" value="${rawdllname}"/> + <param name="libs" value="${rawlibs}"/> + <param name="objdir" location="raw"/> + </antcall> + </target> +</project> + diff --git a/plugins/windows/src/native/dx8/dxversion.h b/plugins/windows/src/native/dx8/dxversion.h new file mode 100644 index 0000000..396c7f7 --- /dev/null +++ b/plugins/windows/src/native/dx8/dxversion.h @@ -0,0 +1,13 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#ifndef DXVERSION_H +#define DXVERSION_H + +#define DIRECTINPUT_VERSION 0x0800 + +#endif diff --git a/plugins/windows/src/native/dx8/net_java_games_input_IDirectInput.c b/plugins/windows/src/native/dx8/net_java_games_input_IDirectInput.c new file mode 100644 index 0000000..ae7b0ca --- /dev/null +++ b/plugins/windows/src/native/dx8/net_java_games_input_IDirectInput.c @@ -0,0 +1,103 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include <windows.h> +#include <jni.h> +#include "dxversion.h" +#include <dinput.h> +#include "net_java_games_input_IDirectInput.h" +#include "util.h" +#include "winutil.h" + +typedef struct { + LPDIRECTINPUT8 lpDirectInput; + JNIEnv *env; + jobject obj; +} enum_context_t; + +JNIEXPORT jlong JNICALL Java_net_java_games_input_IDirectInput_createIDirectInput(JNIEnv *env, jclass unused) { + LPDIRECTINPUT8 lpDirectInput; + HRESULT res = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, + &IID_IDirectInput8,(VOID **)&lpDirectInput, NULL); + if (FAILED(res)) { + throwIOException(env, "Failed to create IDirectInput8 (%d)\n", res); + return 0; + } + return (jlong)(INT_PTR)lpDirectInput; +} + +static BOOL CALLBACK enumerateDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID context) { + enum_context_t *enum_context = (enum_context_t *)context; +// LPCDIDATAFORMAT lpDataFormat; + LPDIRECTINPUTDEVICE8 lpDevice; + DWORD device_type; + DWORD device_subtype; + HRESULT res; + jclass obj_class; + jmethodID IDirectInput_addDevice; + jstring instance_name; + jstring product_name; + jbyteArray instance_guid; + jbyteArray product_guid; + + instance_guid = wrapGUID(enum_context->env, &(lpddi->guidInstance)); + if (instance_guid == NULL) + return DIENUM_STOP; + product_guid = wrapGUID(enum_context->env, &(lpddi->guidProduct)); + if (product_guid == NULL) + return DIENUM_STOP; + instance_name = (*enum_context->env)->NewStringUTF(enum_context->env, lpddi->tszInstanceName); + if (instance_name == NULL) + return DIENUM_STOP; + product_name = (*enum_context->env)->NewStringUTF(enum_context->env, lpddi->tszProductName); + if (product_name == NULL) + return DIENUM_STOP; + + obj_class = (*enum_context->env)->GetObjectClass(enum_context->env, enum_context->obj); + if (obj_class == NULL) + return DIENUM_STOP; + + IDirectInput_addDevice = (*enum_context->env)->GetMethodID(enum_context->env, obj_class, "addDevice", "(J[B[BIILjava/lang/String;Ljava/lang/String;)V"); + if (IDirectInput_addDevice == NULL) + return DIENUM_STOP; + + res = IDirectInput8_CreateDevice(enum_context->lpDirectInput, &(lpddi->guidInstance), &lpDevice, NULL); + if (FAILED(res)) { + throwIOException(enum_context->env, "Failed to create device (%d)\n", res); + return DIENUM_STOP; + } + + device_type = GET_DIDEVICE_TYPE(lpddi->dwDevType); + device_subtype = GET_DIDEVICE_SUBTYPE(lpddi->dwDevType); + + (*enum_context->env)->CallVoidMethod(enum_context->env, enum_context->obj, IDirectInput_addDevice, (jlong)(INT_PTR)lpDevice, instance_guid, product_guid, (jint)device_type, (jint)device_subtype, instance_name, product_name); + if ((*enum_context->env)->ExceptionOccurred(enum_context->env) != NULL) { + IDirectInputDevice8_Release(lpDevice); + return DIENUM_STOP; + } + + return DIENUM_CONTINUE; +} + +JNIEXPORT void JNICALL Java_net_java_games_input_IDirectInput_nEnumDevices(JNIEnv *env, jobject obj, jlong address) { + LPDIRECTINPUT8 lpDirectInput = (LPDIRECTINPUT8)(INT_PTR)address; + HRESULT res; + + enum_context_t enum_context; + enum_context.lpDirectInput = lpDirectInput; + enum_context.env = env; + enum_context.obj = obj; + res = IDirectInput8_EnumDevices(lpDirectInput, DI8DEVCLASS_ALL, enumerateDevicesCallback, &enum_context, DIEDFL_ATTACHEDONLY); + if (FAILED(res)) { + throwIOException(env, "Failed to enumerate devices (%d)\n", res); + } +} + +JNIEXPORT void JNICALL Java_net_java_games_input_IDirectInput_nRelease(JNIEnv *env, jclass unused, jlong address) { + LPDIRECTINPUT8 lpDirectInput = (LPDIRECTINPUT8)(INT_PTR)address; + IDirectInput8_Release(lpDirectInput); +} diff --git a/plugins/windows/src/native/dx8/net_java_games_input_IDirectInputDevice.c b/plugins/windows/src/native/dx8/net_java_games_input_IDirectInputDevice.c new file mode 100644 index 0000000..d4561b3 --- /dev/null +++ b/plugins/windows/src/native/dx8/net_java_games_input_IDirectInputDevice.c @@ -0,0 +1,532 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include <windows.h> +#include "dxversion.h" +#include <jni.h> +#include <dinput.h> +#include "net_java_games_input_IDirectInputDevice.h" +#include "util.h" +#include "winutil.h" + +typedef struct { + JNIEnv *env; + jobject device_obj; +} enum_context_t; + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nSetBufferSize(JNIEnv *env, jclass unused, jlong address, jint size) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + DIPROPDWORD dipropdw; + HRESULT res; + + dipropdw.diph.dwSize = sizeof(DIPROPDWORD); + dipropdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipropdw.diph.dwObj = 0; + dipropdw.diph.dwHow = DIPH_DEVICE; + dipropdw.dwData = size; + res = IDirectInputDevice8_SetProperty(lpDevice, DIPROP_BUFFERSIZE, &dipropdw.diph); + return res; +} + +static const GUID *mapGUIDId(const jint guid_id) { + switch (guid_id) { + case net_java_games_input_IDirectInputDevice_GUID_XAxis: + return &GUID_XAxis; + case net_java_games_input_IDirectInputDevice_GUID_YAxis: + return &GUID_YAxis; + case net_java_games_input_IDirectInputDevice_GUID_ZAxis: + return &GUID_ZAxis; + case net_java_games_input_IDirectInputDevice_GUID_RxAxis: + return &GUID_RxAxis; + case net_java_games_input_IDirectInputDevice_GUID_RyAxis: + return &GUID_RyAxis; + case net_java_games_input_IDirectInputDevice_GUID_RzAxis: + return &GUID_RzAxis; + case net_java_games_input_IDirectInputDevice_GUID_Slider: + return &GUID_Slider; + case net_java_games_input_IDirectInputDevice_GUID_Button: + return &GUID_Button; + case net_java_games_input_IDirectInputDevice_GUID_Key: + return &GUID_Key; + case net_java_games_input_IDirectInputDevice_GUID_POV: + return &GUID_POV; + case net_java_games_input_IDirectInputDevice_GUID_Unknown: + default: + return NULL; + } +} + +static jint mapGUIDType(const GUID *guid) { + if (IsEqualGUID(guid, &GUID_XAxis)) { + return net_java_games_input_IDirectInputDevice_GUID_XAxis; + } else if (IsEqualGUID(guid, &GUID_YAxis)) { + return net_java_games_input_IDirectInputDevice_GUID_YAxis; + } else if (IsEqualGUID(guid, &GUID_ZAxis)) { + return net_java_games_input_IDirectInputDevice_GUID_ZAxis; + } else if (IsEqualGUID(guid, &GUID_RxAxis)) { + return net_java_games_input_IDirectInputDevice_GUID_RxAxis; + } else if (IsEqualGUID(guid, &GUID_RyAxis)) { + return net_java_games_input_IDirectInputDevice_GUID_RyAxis; + } else if (IsEqualGUID(guid, &GUID_RzAxis)) { + return net_java_games_input_IDirectInputDevice_GUID_RzAxis; + } else if (IsEqualGUID(guid, &GUID_Slider)) { + return net_java_games_input_IDirectInputDevice_GUID_Slider; + } else if (IsEqualGUID(guid, &GUID_Button)) { + return net_java_games_input_IDirectInputDevice_GUID_Button; + } else if (IsEqualGUID(guid, &GUID_Key)) { + return net_java_games_input_IDirectInputDevice_GUID_Key; + } else if (IsEqualGUID(guid, &GUID_POV)) { + return net_java_games_input_IDirectInputDevice_GUID_POV; + } else if (IsEqualGUID(guid, &GUID_ConstantForce)) { + return net_java_games_input_IDirectInputDevice_GUID_ConstantForce; + } else if (IsEqualGUID(guid, &GUID_RampForce)) { + return net_java_games_input_IDirectInputDevice_GUID_RampForce; + } else if (IsEqualGUID(guid, &GUID_Square)) { + return net_java_games_input_IDirectInputDevice_GUID_Square; + } else if (IsEqualGUID(guid, &GUID_Sine)) { + return net_java_games_input_IDirectInputDevice_GUID_Sine; + } else if (IsEqualGUID(guid, &GUID_Triangle)) { + return net_java_games_input_IDirectInputDevice_GUID_Triangle; + } else if (IsEqualGUID(guid, &GUID_SawtoothUp)) { + return net_java_games_input_IDirectInputDevice_GUID_SawtoothUp; + } else if (IsEqualGUID(guid, &GUID_SawtoothDown)) { + return net_java_games_input_IDirectInputDevice_GUID_SawtoothDown; + } else if (IsEqualGUID(guid, &GUID_Spring)) { + return net_java_games_input_IDirectInputDevice_GUID_Spring; + } else if (IsEqualGUID(guid, &GUID_Damper)) { + return net_java_games_input_IDirectInputDevice_GUID_Damper; + } else if (IsEqualGUID(guid, &GUID_Inertia)) { + return net_java_games_input_IDirectInputDevice_GUID_Inertia; + } else if (IsEqualGUID(guid, &GUID_Friction)) { + return net_java_games_input_IDirectInputDevice_GUID_Friction; + } else if (IsEqualGUID(guid, &GUID_CustomForce)) { + return net_java_games_input_IDirectInputDevice_GUID_CustomForce; + } else + return net_java_games_input_IDirectInputDevice_GUID_Unknown; +} + +static BOOL CALLBACK enumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef) { + enum_context_t *enum_context = (enum_context_t *)pvRef; + jmethodID add_method; + jstring name; + DWORD instance; + DWORD type; + jint guid_type; + jbyteArray guid; + JNIEnv *env = enum_context->env; + jobject device_obj = enum_context->device_obj; + jint guid_id; + jclass obj_class = (*env)->GetObjectClass(env, device_obj); + + + if (obj_class == NULL) + return DIENUM_STOP; + guid = wrapGUID(env, &(pdei->guid)); + if (guid == NULL) + return DIENUM_STOP; + add_method = (*env)->GetMethodID(env, obj_class, "addEffect", "([BIIIILjava/lang/String;)V"); + if (add_method == NULL) + return DIENUM_STOP; + name = (*env)->NewStringUTF(env, pdei->tszName); + if (name == NULL) + return DIENUM_STOP; + guid_id = mapGUIDType(&(pdei->guid)); + (*env)->CallBooleanMethod(env, device_obj, add_method, guid, guid_id, (jint)pdei->dwEffType, (jint)pdei->dwStaticParams, (jint)pdei->dwDynamicParams, name); + if ((*env)->ExceptionOccurred(env)) { + return DIENUM_STOP; + } + return DIENUM_CONTINUE; +} + +static BOOL CALLBACK enumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) { + enum_context_t *enum_context = (enum_context_t *)pvRef; + jmethodID add_method; + jstring name; + DWORD instance; + DWORD type; + jint guid_type; + jbyteArray guid; + JNIEnv *env = enum_context->env; + jobject device_obj = enum_context->device_obj; + jclass obj_class = (*env)->GetObjectClass(env, device_obj); + + if (obj_class == NULL) + return DIENUM_STOP; + guid = wrapGUID(env, &(lpddoi->guidType)); + if (guid == NULL) + return DIENUM_STOP; + add_method = (*env)->GetMethodID(env, obj_class, "addObject", "([BIIIIILjava/lang/String;)V"); + if (add_method == NULL) + return DIENUM_STOP; + name = (*env)->NewStringUTF(env, lpddoi->tszName); + if (name == NULL) + return DIENUM_STOP; + instance = DIDFT_GETINSTANCE(lpddoi->dwType); + type = DIDFT_GETTYPE(lpddoi->dwType); + guid_type = mapGUIDType(&(lpddoi->guidType)); +//printfJava(env, "name %s guid_type %d id %d\n", lpddoi->tszName, guid_type, lpddoi->dwType); + (*env)->CallBooleanMethod(env, device_obj, add_method, guid, (jint)guid_type, (jint)lpddoi->dwType, (jint)type, (jint)instance, (jint)lpddoi->dwFlags, name); + if ((*env)->ExceptionOccurred(env)) { + return DIENUM_STOP; + } + return DIENUM_CONTINUE; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nGetRangeProperty(JNIEnv *env, jclass unused, jlong address, jint object_id, jlongArray range_array_obj) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + DIPROPRANGE range; + HRESULT res; + jlong range_array[2]; + + range.diph.dwSize = sizeof(DIPROPRANGE); + range.diph.dwHeaderSize = sizeof(DIPROPHEADER); + range.diph.dwObj = object_id; + range.diph.dwHow = DIPH_BYID; + res = IDirectInputDevice8_GetProperty(lpDevice, DIPROP_RANGE, &(range.diph)); + range_array[0] = range.lMin; + range_array[1] = range.lMax; + (*env)->SetLongArrayRegion(env, range_array_obj, 0, 2, range_array); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nGetDeadzoneProperty(JNIEnv *env, jclass unused, jlong address, jint object_id) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + DIPROPDWORD deadzone; + HRESULT res; + + deadzone.diph.dwSize = sizeof(deadzone); + deadzone.diph.dwHeaderSize = sizeof(DIPROPHEADER); + deadzone.diph.dwObj = object_id; + deadzone.diph.dwHow = DIPH_BYID; + res = IDirectInputDevice8_GetProperty(lpDevice, DIPROP_DEADZONE, &(deadzone.diph)); + if (res != DI_OK && res != S_FALSE) + throwIOException(env, "Failed to get deadzone property (%x)\n", res); + return deadzone.dwData; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nSetDataFormat(JNIEnv *env, jclass unused, jlong address, jint flags, jobjectArray objects) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + DIDATAFORMAT data_format; + jsize num_objects = (*env)->GetArrayLength(env, objects); + /* + * Data size must be a multiple of 4, but since sizeof(jint) is + * 4, we're safe + */ + DWORD data_size = num_objects*sizeof(jint); + GUID *guids; + DIOBJECTDATAFORMAT *object_formats; + int i; + HRESULT res; + jclass clazz; + jmethodID getGUID_method; + jmethodID getFlags_method; + jmethodID getType_method; + jmethodID getInstance_method; + jobject object; + jint type; + jint guid_id; + jint object_flags; + jint instance; + jobject guid_array; + DWORD composite_type; + DWORD flags_masked; + LPDIOBJECTDATAFORMAT object_format; + + data_format.dwSize = sizeof(DIDATAFORMAT); + data_format.dwObjSize = sizeof(DIOBJECTDATAFORMAT); + data_format.dwFlags = flags; + data_format.dwDataSize = data_size; + data_format.dwNumObjs = num_objects; + + clazz = (*env)->FindClass(env, "net/java/games/input/DIDeviceObject"); + if (clazz == NULL) + return -1; + getGUID_method = (*env)->GetMethodID(env, clazz, "getGUID", "()[B"); + if (getGUID_method == NULL) + return -1; + getFlags_method = (*env)->GetMethodID(env, clazz, "getFlags", "()I"); + if (getFlags_method == NULL) + return -1; + getType_method = (*env)->GetMethodID(env, clazz, "getType", "()I"); + if (getType_method == NULL) + return -1; + getInstance_method = (*env)->GetMethodID(env, clazz, "getInstance", "()I"); + if (getInstance_method == NULL) + return -1; + + guids = (GUID *)malloc(num_objects*sizeof(GUID)); + if (guids == NULL) { + throwIOException(env, "Failed to allocate GUIDs"); + return -1; + } + object_formats = (DIOBJECTDATAFORMAT *)malloc(num_objects*sizeof(DIOBJECTDATAFORMAT)); + if (object_formats == NULL) { + free(guids); + throwIOException(env, "Failed to allocate data format"); + return -1; + } + for (i = 0; i < num_objects; i++) { + object = (*env)->GetObjectArrayElement(env, objects, i); + if ((*env)->ExceptionOccurred(env)) { + free(guids); + free(object_formats); + return -1; + } + guid_array = (*env)->CallObjectMethod(env, object, getGUID_method); + if ((*env)->ExceptionOccurred(env)) { + free(guids); + free(object_formats); + return -1; + } + unwrapGUID(env, guid_array, guids + i); + if ((*env)->ExceptionOccurred(env)) { + free(guids); + free(object_formats); + return -1; + } + type = (*env)->CallIntMethod(env, object, getType_method); + if ((*env)->ExceptionOccurred(env)) { + free(guids); + free(object_formats); + return -1; + } + object_flags = (*env)->CallIntMethod(env, object, getFlags_method); + if ((*env)->ExceptionOccurred(env)) { + free(guids); + free(object_formats); + return -1; + } + instance = (*env)->CallIntMethod(env, object, getInstance_method); + if ((*env)->ExceptionOccurred(env)) { + free(guids); + free(object_formats); + return -1; + } + (*env)->DeleteLocalRef(env, object); + composite_type = type | DIDFT_MAKEINSTANCE(instance); + flags_masked = flags & (DIDOI_ASPECTACCEL | DIDOI_ASPECTFORCE | DIDOI_ASPECTPOSITION | DIDOI_ASPECTVELOCITY); + object_format = object_formats + i; + object_format->pguid = guids + i; + object_format->dwType = composite_type; + object_format->dwFlags = flags_masked; + // dwOfs must be multiple of 4, but sizeof(jint) is 4, so we're safe + object_format->dwOfs = i*sizeof(jint); + } + data_format.rgodf = object_formats; + res = IDirectInputDevice8_SetDataFormat(lpDevice, &data_format); + free(guids); + free(object_formats); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nAcquire(JNIEnv *env, jclass unused, jlong address) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + + HRESULT res = IDirectInputDevice8_Acquire(lpDevice); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nUnacquire(JNIEnv *env, jclass unused, jlong address) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + + HRESULT res = IDirectInputDevice8_Unacquire(lpDevice); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nPoll(JNIEnv *env, jclass unused, jlong address) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + + HRESULT res = IDirectInputDevice8_Poll(lpDevice); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nGetDeviceState(JNIEnv *env, jclass unused, jlong address, jintArray device_state_array) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + jsize state_length = (*env)->GetArrayLength(env, device_state_array); + DWORD state_size = state_length*sizeof(jint); + HRESULT res; + jint *device_state = (*env)->GetIntArrayElements(env, device_state_array, NULL); + if (device_state == NULL) + return -1; + + res = IDirectInputDevice8_GetDeviceState(lpDevice, state_size, device_state); + (*env)->ReleaseIntArrayElements(env, device_state_array, device_state, 0); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nGetDeviceData(JNIEnv *env, jclass unused, jlong address, jint flags, jobject queue, jobject queue_array, jint position, jint remaining) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + DWORD num_events = remaining; + DIDEVICEOBJECTDATA *data; + DIDEVICEOBJECTDATA *data_element; + jmethodID set_method; + HRESULT res; + int i; + jclass data_class; + jclass queue_class; + jmethodID position_method; + + data_class = (*env)->FindClass(env, "net/java/games/input/DIDeviceObjectData"); + if (data_class == NULL) + return -1; + set_method = (*env)->GetMethodID(env, data_class, "set", "(IIII)V"); + if (set_method == NULL) + return -1; + queue_class = (*env)->GetObjectClass(env, queue); + if (queue_class == NULL) + return -1; + position_method = (*env)->GetMethodID(env, queue_class, "position", "(I)V"); + if (position_method == NULL) + return -1; + + data = (DIDEVICEOBJECTDATA *)malloc(num_events*sizeof(DIDEVICEOBJECTDATA)); + + res = IDirectInputDevice8_GetDeviceData(lpDevice, sizeof(DIDEVICEOBJECTDATA), data, &num_events, flags); + if (res == DI_OK || res == DI_BUFFEROVERFLOW) { + for (i = 0; i < num_events; i++) { + jobject queue_element = (*env)->GetObjectArrayElement(env, queue_array, position + i); + if (queue_element == NULL) { + free(data); + return -1; + } + data_element = data + i; + (*env)->CallVoidMethod(env, queue_element, set_method, (jint)data_element->dwOfs, (jint)data_element->dwData, (jint)data_element->dwTimeStamp, (jint)data_element->dwSequence); + if ((*env)->ExceptionOccurred(env)) { + free(data); + return -1; + } + } + (*env)->CallVoidMethod(env, queue, position_method, position + num_events); + } + free(data); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nEnumEffects(JNIEnv *env, jobject device_obj, jlong address, jint flags) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + HRESULT res; + enum_context_t enum_context; + + enum_context.env = env; + enum_context.device_obj = device_obj; + res = IDirectInputDevice8_EnumEffects(lpDevice, enumEffectsCallback, &enum_context, flags); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nEnumObjects(JNIEnv *env, jobject device_obj, jlong address, jint flags) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + HRESULT res; + enum_context_t enum_context; + + enum_context.env = env; + enum_context.device_obj = device_obj; + res = IDirectInputDevice8_EnumObjects(lpDevice, enumObjectsCallback, &enum_context, flags); + return res; +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputDevice_nSetCooperativeLevel(JNIEnv *env, jclass unused, jlong address, jlong hwnd_address, jint flags) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + HWND hwnd = (HWND)(INT_PTR)hwnd_address; + + HRESULT res = IDirectInputDevice8_SetCooperativeLevel(lpDevice, hwnd, flags); + return res; +} + +JNIEXPORT void JNICALL Java_net_java_games_input_IDirectInputDevice_nRelease(JNIEnv *env, jclass unused, jlong address) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + + IDirectInputDevice8_Release(lpDevice); +} + +JNIEXPORT jlong JNICALL Java_net_java_games_input_IDirectInputDevice_nCreatePeriodicEffect(JNIEnv *env, jclass unused, jlong address, jbyteArray effect_guid_array, jint flags, jint duration, jint sample_period, jint gain, jint trigger_button, jint trigger_repeat_interval, jintArray axis_ids_array, jlongArray directions_array, jint envelope_attack_level, jint envelope_attack_time, jint envelope_fade_level, jint envelope_fade_time, jint periodic_magnitude, jint periodic_offset, jint periodic_phase, jint periodic_period, jint start_delay) { + LPDIRECTINPUTDEVICE8 lpDevice = (LPDIRECTINPUTDEVICE8)(INT_PTR)address; + LPDIRECTINPUTEFFECT lpdiEffect; + DIEFFECT effect; + GUID effect_guid; + jint *axis_ids; + jlong *directions; + jsize num_axes; + jsize num_directions; + LONG *directions_long; + DWORD *axis_ids_dword; + HRESULT res; + DIPERIODIC periodic; + DIENVELOPE envelope; + int i; + + num_axes = (*env)->GetArrayLength(env, axis_ids_array); + num_directions = (*env)->GetArrayLength(env, directions_array); + + if (num_axes != num_directions) { + throwIOException(env, "axis_ids.length != directions.length\n"); + return 0; + } + + unwrapGUID(env, effect_guid_array, &effect_guid); + if ((*env)->ExceptionOccurred(env)) + return 0; + axis_ids = (*env)->GetIntArrayElements(env, axis_ids_array, NULL); + if (axis_ids == NULL) + return 0; + directions = (*env)->GetLongArrayElements(env, directions_array, NULL); + if (axis_ids == NULL) + return 0; + axis_ids_dword = (DWORD *)malloc(sizeof(DWORD)*num_axes); + if (axis_ids_dword == NULL) { + throwIOException(env, "Failed to allocate axes array\n"); + return 0; + } + directions_long = (LONG *)malloc(sizeof(LONG)*num_directions); + if (directions_long == NULL) { + free(axis_ids_dword); + throwIOException(env, "Failed to allocate directions array\n"); + return 0; + } + for (i = 0; i < num_axes; i++) { + axis_ids_dword[i] = axis_ids[i]; + } + for (i = 0; i < num_directions; i++) { + directions_long[i] = directions[i]; + } + + envelope.dwSize = sizeof(DIENVELOPE); + envelope.dwAttackLevel = envelope_attack_level; + envelope.dwAttackTime = envelope_attack_time; + envelope.dwFadeLevel = envelope_fade_level; + envelope.dwFadeTime = envelope_fade_time; + + periodic.dwMagnitude = periodic_magnitude; + periodic.lOffset = periodic_offset; + periodic.dwPhase = periodic_phase; + periodic.dwPeriod = periodic_period; + + effect.dwSize = sizeof(DIEFFECT); + effect.dwFlags = flags; + effect.dwDuration = duration; + effect.dwSamplePeriod = sample_period; + effect.dwGain = gain; + effect.dwTriggerButton = trigger_button; + effect.dwTriggerRepeatInterval = trigger_repeat_interval; + effect.cAxes = num_axes; + effect.rgdwAxes = axis_ids_dword; + effect.rglDirection = directions_long; + effect.lpEnvelope = &envelope; + effect.cbTypeSpecificParams = sizeof(periodic); + effect.lpvTypeSpecificParams = &periodic; + effect.dwStartDelay = start_delay; + + res = IDirectInputDevice8_CreateEffect(lpDevice, &effect_guid, &effect, &lpdiEffect, NULL); + (*env)->ReleaseIntArrayElements(env, axis_ids_array, axis_ids, 0); + (*env)->ReleaseLongArrayElements(env, directions_array, directions, 0); + free(axis_ids_dword); + free(directions_long); + if (res != DI_OK) { + throwIOException(env, "Failed to create effect (0x%x)\n", res); + return 0; + } + return (jlong)(INT_PTR)lpdiEffect; +} diff --git a/plugins/windows/src/native/dx8/net_java_games_input_IDirectInputEffect.c b/plugins/windows/src/native/dx8/net_java_games_input_IDirectInputEffect.c new file mode 100644 index 0000000..4553817 --- /dev/null +++ b/plugins/windows/src/native/dx8/net_java_games_input_IDirectInputEffect.c @@ -0,0 +1,42 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include <windows.h> +#include "dxversion.h" +#include <jni.h> +#include <dinput.h> +#include "net_java_games_input_IDirectInputEffect.h" +#include "util.h" + +JNIEXPORT void JNICALL Java_net_java_games_input_IDirectInputEffect_nRelease(JNIEnv *env, jclass unused, jlong address) { + LPDIRECTINPUTEFFECT ppdeff = (LPDIRECTINPUTEFFECT)(INT_PTR)address; + + IDirectInputEffect_Release(ppdeff); +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputEffect_nSetGain(JNIEnv *env, jclass unused, jlong address, jint gain) { + LPDIRECTINPUTEFFECT ppdeff = (LPDIRECTINPUTEFFECT)(INT_PTR)address; + DIEFFECT params; + + ZeroMemory(¶ms, sizeof(params)); + params.dwSize = sizeof(params); + params.dwGain = gain; + + return IDirectInputEffect_SetParameters(ppdeff, ¶ms, DIEP_GAIN); +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputEffect_nStart(JNIEnv *env, jclass unused, jlong address, jint iterations, jint flags) { + LPDIRECTINPUTEFFECT ppdeff = (LPDIRECTINPUTEFFECT)(INT_PTR)address; + + return IDirectInputEffect_Start(ppdeff, iterations, flags); +} + +JNIEXPORT jint JNICALL Java_net_java_games_input_IDirectInputEffect_nStop(JNIEnv *env, jclass unused, jlong address) { + LPDIRECTINPUTEFFECT ppdeff = (LPDIRECTINPUTEFFECT)(INT_PTR)address; + + return IDirectInputEffect_Stop(ppdeff); +} diff --git a/plugins/windows/src/native/net_java_games_input_DummyWindow.c b/plugins/windows/src/native/net_java_games_input_DummyWindow.c new file mode 100644 index 0000000..539e45c --- /dev/null +++ b/plugins/windows/src/native/net_java_games_input_DummyWindow.c @@ -0,0 +1,71 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include <windows.h> +#include <jni.h> +#include "net_java_games_input_DummyWindow.h" +#include "util.h" + +static const TCHAR* DUMMY_WINDOW_NAME = "JInputControllerWindow"; + +static LRESULT CALLBACK DummyWndProc( + HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + return DefWindowProc(hWnd, message, wParam, lParam); +} + +static BOOL RegisterDummyWindow(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)DummyWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = NULL; + wcex.hCursor = NULL; + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = (LPCSTR)NULL; + wcex.lpszClassName = DUMMY_WINDOW_NAME; + wcex.hIconSm = NULL; + return RegisterClassEx(&wcex); +} + +JNIEXPORT jlong JNICALL Java_net_java_games_input_DummyWindow_createWindow(JNIEnv *env, jclass unused) { + HINSTANCE hInst = GetModuleHandle(NULL); + HWND hwndDummy; + WNDCLASSEX class_info; + class_info.cbSize = sizeof(WNDCLASSEX); + class_info.cbClsExtra = 0; + class_info.cbWndExtra = 0; + + if (!GetClassInfoEx(hInst, DUMMY_WINDOW_NAME, &class_info)) { + // Register the dummy input window + if (!RegisterDummyWindow(hInst)) { + throwIOException(env, "Failed to register window class (%d)\n", GetLastError()); + return 0; + } + } + + // Create the dummy input window + hwndDummy = CreateWindow(DUMMY_WINDOW_NAME, NULL, + WS_POPUP | WS_ICONIC, + 0, 0, 0, 0, NULL, NULL, hInst, NULL); + if (hwndDummy == NULL) { + throwIOException(env, "Failed to create window (%d)\n", GetLastError()); + return 0; + } + return (jlong)hwndDummy; +} + +JNIEXPORT void JNICALL Java_net_java_games_input_DummyWindow_nDestroy(JNIEnv *env, jclass unused, jlong hwnd_address) { + HWND hwndDummy = (HWND)(INT_PTR)hwnd_address; + BOOL result = DestroyWindow(hwndDummy); + if (!result) { + throwIOException(env, "Failed to destroy window (%d)\n", GetLastError()); + } +} diff --git a/plugins/windows/src/native/raw/net_java_games_input_RawDevice.c b/plugins/windows/src/native/raw/net_java_games_input_RawDevice.c new file mode 100644 index 0000000..3730a6c --- /dev/null +++ b/plugins/windows/src/native/raw/net_java_games_input_RawDevice.c @@ -0,0 +1,69 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include "rawwinver.h" +#include <windows.h> +#include <jni.h> +#include "net_java_games_input_RawDevice.h" +#include "util.h" + +JNIEXPORT jstring JNICALL Java_net_java_games_input_RawDevice_nGetName(JNIEnv *env, jclass unused, jlong handle_addr) { + HANDLE handle = (HANDLE)(INT_PTR)handle_addr; + UINT res; + UINT name_length; + char *name; + jstring name_str; + + res = GetRawInputDeviceInfo(handle, RIDI_DEVICENAME, NULL, &name_length); + name = (char *)malloc(name_length*sizeof(char)); + res = GetRawInputDeviceInfo(handle, RIDI_DEVICENAME, name, &name_length); + if ((UINT)-1 == res) { + free(name); + throwIOException(env, "Failed to get device name (%d)\n", GetLastError()); + return NULL; + } + name_str = (*env)->NewStringUTF(env, name); + free(name); + return name_str; +} + +static jobject createKeyboardInfo(JNIEnv *env, jobject device_obj, RID_DEVICE_INFO_KEYBOARD *device_info) { + return newJObject(env, "net/java/games/input/RawKeyboardInfo", "(Lnet/java/games/input/RawDevice;IIIIII)V", device_obj, (jint)device_info->dwType, (jint)device_info->dwSubType, (jint)device_info->dwKeyboardMode, (jint)device_info->dwNumberOfFunctionKeys, (jint)device_info->dwNumberOfIndicators, (jint)device_info->dwNumberOfKeysTotal); +} + +static jobject createMouseInfo(JNIEnv *env, jobject device_obj, RID_DEVICE_INFO_MOUSE *device_info) { + return newJObject(env, "net/java/games/input/RawMouseInfo", "(Lnet/java/games/input/RawDevice;III)V", device_obj, (jint)device_info->dwId, (jint)device_info->dwNumberOfButtons, (jint)device_info->dwSampleRate); +} + +static jobject createHIDInfo(JNIEnv *env, jobject device_obj, RID_DEVICE_INFO_HID *device_info) { + return newJObject(env, "net/java/games/input/RawHIDInfo", "(Lnet/java/games/input/RawDevice;IIIII)V", device_obj, (jint)device_info->dwVendorId, (jint)device_info->dwProductId, (jint)device_info->dwVersionNumber, (jint)device_info->usUsagePage, (jint)device_info->usUsage); +} + +JNIEXPORT jobject JNICALL Java_net_java_games_input_RawDevice_nGetInfo(JNIEnv *env, jclass unused, jobject device_obj, jlong handle_addr) { + HANDLE handle = (HANDLE)(INT_PTR)handle_addr; + RID_DEVICE_INFO device_info; + UINT size = sizeof(RID_DEVICE_INFO); + UINT res; + + device_info.cbSize = sizeof(RID_DEVICE_INFO); + res = GetRawInputDeviceInfo(handle, RIDI_DEVICEINFO, &device_info, &size); + if ((UINT)-1 == res) { + throwIOException(env, "Failed to get device info (%d)\n", GetLastError()); + return NULL; + } + switch (device_info.dwType) { + case RIM_TYPEHID: + return createHIDInfo(env, device_obj,&(device_info.hid)); + case RIM_TYPEKEYBOARD: + return createKeyboardInfo(env, device_obj, &(device_info.keyboard)); + case RIM_TYPEMOUSE: + return createMouseInfo(env, device_obj, &(device_info.mouse)); + default: + throwIOException(env, "Unknown device type: %d\n", device_info.dwType); + return NULL; + } +} diff --git a/plugins/windows/src/native/raw/net_java_games_input_RawInputEnvironmentPlugin.c b/plugins/windows/src/native/raw/net_java_games_input_RawInputEnvironmentPlugin.c new file mode 100644 index 0000000..9814b7d --- /dev/null +++ b/plugins/windows/src/native/raw/net_java_games_input_RawInputEnvironmentPlugin.c @@ -0,0 +1,166 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include "rawwinver.h" +#include <windows.h> +#include <setupapi.h> +#include <devguid.h> +#include <regstr.h> +#include <jni.h> +#include "net_java_games_input_RawInputEnvironmentPlugin.h" +#include "util.h" +#include "winutil.h" + +JNIEXPORT jbyteArray JNICALL Java_net_java_games_input_RawInputEnvironmentPlugin_getKeyboardClassGUID(JNIEnv *env, jclass unused) { + return wrapGUID(env, &GUID_DEVCLASS_KEYBOARD); +} + +JNIEXPORT jbyteArray JNICALL Java_net_java_games_input_RawInputEnvironmentPlugin_getMouseClassGUID(JNIEnv *env, jclass unused) { + return wrapGUID(env, &GUID_DEVCLASS_MOUSE); +} + +JNIEXPORT void JNICALL Java_net_java_games_input_RawInputEnvironmentPlugin_nEnumSetupAPIDevices(JNIEnv *env, jclass unused, jbyteArray guid_array, jobject device_list) { + jclass list_class; + jmethodID add_method; + HDEVINFO hDevInfo; + SP_DEVINFO_DATA DeviceInfoData; + int i; + GUID setup_class_guid; + jstring device_name; + jstring device_instance_id; + jobject setup_api_device; + + list_class = (*env)->GetObjectClass(env, device_list); + if (list_class == NULL) + return; + add_method = (*env)->GetMethodID(env, list_class, "add", "(Ljava/lang/Object;)Z"); + if (add_method == NULL) + return; + unwrapGUID(env, guid_array, &setup_class_guid); + if ((*env)->ExceptionOccurred(env)) + return; + + hDevInfo = SetupDiGetClassDevs(&setup_class_guid, + NULL, + NULL, + DIGCF_PRESENT); + + if (hDevInfo == INVALID_HANDLE_VALUE) { + throwIOException(env, "Failed to create device enumerator (%d)\n", GetLastError()); + return; + } + + + DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++) { + DWORD DataT; + LPTSTR buffer = NULL; + DWORD buffersize = 0; + + + while (!SetupDiGetDeviceRegistryProperty( + hDevInfo, + &DeviceInfoData, + SPDRP_DEVICEDESC, + &DataT, + (PBYTE)buffer, + buffersize, + &buffersize)) { + if (buffer != NULL) + free(buffer); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + buffer = malloc(buffersize); + } else { + throwIOException(env, "Failed to get device description (%x)\n", GetLastError()); + SetupDiDestroyDeviceInfoList(hDevInfo); + return; + } + } + + device_name = (*env)->NewStringUTF(env, buffer); + if (device_name == NULL) { + free(buffer); + SetupDiDestroyDeviceInfoList(hDevInfo); + return; + } + + while (!SetupDiGetDeviceInstanceId( + hDevInfo, + &DeviceInfoData, + buffer, + buffersize, + &buffersize)) + { + if (buffer != NULL) + free(buffer); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + buffer = malloc(buffersize); + } else { + throwIOException(env, "Failed to get device instance id (%x)\n", GetLastError()); + SetupDiDestroyDeviceInfoList(hDevInfo); + return; + } + } + + device_instance_id = (*env)->NewStringUTF(env, buffer); + if (buffer != NULL) + free(buffer); + if (device_instance_id == NULL) { + SetupDiDestroyDeviceInfoList(hDevInfo); + return; + } + setup_api_device = newJObject(env, "net/java/games/input/SetupAPIDevice", "(Ljava/lang/String;Ljava/lang/String;)V", device_instance_id, device_name); + if (setup_api_device == NULL) { + SetupDiDestroyDeviceInfoList(hDevInfo); + return; + } + (*env)->CallBooleanMethod(env, device_list, add_method, setup_api_device); + if ((*env)->ExceptionOccurred(env)) { + SetupDiDestroyDeviceInfoList(hDevInfo); + return; + } + } + SetupDiDestroyDeviceInfoList(hDevInfo); +} + +JNIEXPORT void JNICALL Java_net_java_games_input_RawInputEnvironmentPlugin_enumerateDevices(JNIEnv *env, jclass unused, jobject queue, jobject device_list) { + UINT num_devices; + UINT res; + RAWINPUTDEVICELIST *devices; + RAWINPUTDEVICELIST *device; + jobject device_object; + jclass list_class; + jmethodID add_method; + int i; + + list_class = (*env)->GetObjectClass(env, device_list); + if (list_class == NULL) + return; + add_method = (*env)->GetMethodID(env, list_class, "add", "(Ljava/lang/Object;)Z"); + if (add_method == NULL) + return; + + res = GetRawInputDeviceList(NULL, &num_devices, sizeof(RAWINPUTDEVICELIST)); + if ((UINT)-1 == res) { + throwIOException(env, "Failed to get number of devices (%d)\n", GetLastError()); + return; + } + devices = (RAWINPUTDEVICELIST *)malloc(num_devices*sizeof(RAWINPUTDEVICELIST)); + GetRawInputDeviceList(devices, &num_devices, sizeof(RAWINPUTDEVICELIST)); + for (i = 0; i < num_devices; i++) { + device = devices + i; + device_object = newJObject(env, "net/java/games/input/RawDevice", "(Lnet/java/games/input/RawInputEventQueue;JI)V", queue, (jlong)(INT_PTR)device->hDevice, (jint)device->dwType); + if (device_object == NULL) { + free(devices); + return; + } + (*env)->CallBooleanMethod(env, device_list, add_method, device_object); + (*env)->DeleteLocalRef(env, device_object); + } + free(devices); +} + diff --git a/plugins/windows/src/native/raw/net_java_games_input_RawInputEventQueue.c b/plugins/windows/src/native/raw/net_java_games_input_RawInputEventQueue.c new file mode 100644 index 0000000..130430f --- /dev/null +++ b/plugins/windows/src/native/raw/net_java_games_input_RawInputEventQueue.c @@ -0,0 +1,168 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include "rawwinver.h" +#include <windows.h> +#include <jni.h> +#include "net_java_games_input_RawInputEventQueue.h" +#include "util.h" + +static void handleMouseEvent(JNIEnv *env, jobject self, jmethodID add_method, LONG time, RAWINPUT *data) { + (*env)->CallVoidMethod(env, self, add_method, + (jlong)(INT_PTR)data->header.hDevice, + (jlong)time, + (jint)data->data.mouse.usFlags, + (jint)data->data.mouse.usButtonFlags, + /* + * The Raw Input spec says that the usButtonData + * is a signed value, if RI_MOUSE_WHEEL + * is set in usFlags. However, usButtonData + * is an unsigned value, for unknown reasons, + * and since its only known use is the wheel + * delta, we'll convert it to a signed value here + */ + (jint)(SHORT)data->data.mouse.usButtonData, + (jlong)data->data.mouse.ulRawButtons, + (jlong)data->data.mouse.lLastX, + (jlong)data->data.mouse.lLastY, + (jlong)data->data.mouse.ulExtraInformation + ); +} + +static void handleKeyboardEvent(JNIEnv *env, jobject self, jmethodID add_method, LONG time, RAWINPUT *data) { + (*env)->CallVoidMethod(env, self, add_method, + (jlong)(INT_PTR)data->header.hDevice, + (jlong)time, + (jint)data->data.keyboard.MakeCode, + (jint)data->data.keyboard.Flags, + (jint)data->data.keyboard.VKey, + (jint)data->data.keyboard.Message, + (jlong)data->data.keyboard.ExtraInformation + ); +} + +JNIEXPORT void JNICALL Java_net_java_games_input_RawInputEventQueue_nRegisterDevices(JNIEnv *env, jclass unused, jint flags, jlong hwnd_addr, jobjectArray device_infos) { + BOOL res; + jclass device_info_class; + jmethodID getUsage_method; + jmethodID getUsagePage_method; + RAWINPUTDEVICE *devices; + RAWINPUTDEVICE *device; + jsize num_devices = (*env)->GetArrayLength(env, device_infos); + USHORT usage; + USHORT usage_page; + int i; + HWND hwnd = (HWND)(INT_PTR)hwnd_addr; + + device_info_class = (*env)->FindClass(env, "net/java/games/input/RawDeviceInfo"); + if (device_info_class == NULL) + return; + getUsage_method = (*env)->GetMethodID(env, device_info_class, "getUsage", "()I"); + if (getUsage_method == NULL) + return; + getUsagePage_method = (*env)->GetMethodID(env, device_info_class, "getUsagePage", "()I"); + if (getUsagePage_method == NULL) + return; + devices = (RAWINPUTDEVICE *)malloc(num_devices*sizeof(RAWINPUTDEVICE)); + if (devices == NULL) { + throwIOException(env, "Failed to allocate device structs\n"); + return; + } + for (i = 0; i < num_devices; i++) { + jobject device_obj = (*env)->GetObjectArrayElement(env, device_infos, i); + if (device_obj == NULL) { + free(devices); + return; + } + usage = (*env)->CallIntMethod(env, device_obj, getUsage_method); + if ((*env)->ExceptionOccurred(env)) { + free(devices); + return; + } + usage_page = (*env)->CallIntMethod(env, device_obj, getUsagePage_method); + if ((*env)->ExceptionOccurred(env)) { + free(devices); + return; + } + device = devices + i; + device->usUsagePage = usage_page; + device->usUsage = usage; + device->dwFlags = flags; + device->hwndTarget = hwnd; + } + res = RegisterRawInputDevices(devices, num_devices, sizeof(RAWINPUTDEVICE)); + free(devices); + if (!res) + throwIOException(env, "Failed to register raw devices (%d)\n", GetLastError()); + +/* + + + + res = GetRegisteredRawInputDevices(NULL, &num_devices, sizeof(RAWINPUTDEVICE)); + devices = (RAWINPUTDEVICE *)malloc(num_devices*sizeof(RAWINPUTDEVICE)); + res = GetRegisteredRawInputDevices(devices, &num_devices, sizeof(RAWINPUTDEVICE)); + if (res == -1) { + throwIOException(env, "Failed to get registered raw devices (%d)\n", GetLastError()); + return; + } + for (i = 0; i < num_devices; i++) { +printfJava(env, "from windows: registered: %d %d %p (of %d)\n", devices[i].usUsagePage, devices[i].usUsage, devices[i].hwndTarget, num_devices); + } + free(devices);*/ +} + +JNIEXPORT void JNICALL Java_net_java_games_input_RawInputEventQueue_nPoll(JNIEnv *env, jobject self, jlong hwnd_handle) { + MSG msg; + HWND hwnd = (HWND)(INT_PTR)hwnd_handle; + jmethodID addMouseEvent_method; + jmethodID addKeyboardEvent_method; + UINT input_size; + RAWINPUT *input_data; + LONG time; + jclass self_class = (*env)->GetObjectClass(env, self); + + if (self_class == NULL) + return; + addMouseEvent_method = (*env)->GetMethodID(env, self_class, "addMouseEvent", "(JJIIIJJJJ)V"); + if (addMouseEvent_method == NULL) + return; + addKeyboardEvent_method = (*env)->GetMethodID(env, self_class, "addKeyboardEvent", "(JJIIIIJ)V"); + if (addKeyboardEvent_method == NULL) + return; + if (GetMessage(&msg, hwnd, 0, 0) != 0) { + if (msg.message != WM_INPUT) + return; // ignore it + time = GetMessageTime(); + if (GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, NULL, &input_size, sizeof(RAWINPUTHEADER)) == (UINT)-1) { + throwIOException(env, "Failed to get raw input data size (%d)\n", GetLastError()); + return; + } + input_data = (RAWINPUT *)malloc(input_size); + if (input_data == NULL) { + throwIOException(env, "Failed to allocate input data buffer\n"); + return; + } + if (GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, input_data, &input_size, sizeof(RAWINPUTHEADER)) == (UINT)-1) { + free(input_data); + throwIOException(env, "Failed to get raw input data (%d)\n", GetLastError()); + return; + } + switch (input_data->header.dwType) { + case RIM_TYPEMOUSE: + handleMouseEvent(env, self, addMouseEvent_method, time, input_data); + break; + case RIM_TYPEKEYBOARD: + handleKeyboardEvent(env, self, addKeyboardEvent_method, time, input_data); + break; + default: + /* ignore other types of message */ + break; + } + free(input_data); + } +} diff --git a/plugins/windows/src/native/raw/rawwinver.h b/plugins/windows/src/native/raw/rawwinver.h new file mode 100644 index 0000000..882341a --- /dev/null +++ b/plugins/windows/src/native/raw/rawwinver.h @@ -0,0 +1,14 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#ifndef RAWWINVER_H +#define RAWWINVER_H + +#define _WIN32_WINNT 0x0501 +#define WINVER 0x0501 + +#endif diff --git a/plugins/windows/src/native/winutil.c b/plugins/windows/src/native/winutil.c new file mode 100644 index 0000000..93606dd --- /dev/null +++ b/plugins/windows/src/native/winutil.c @@ -0,0 +1,21 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#include "winutil.h" + +jbyteArray wrapGUID(JNIEnv *env, const GUID *guid) { + jbyteArray guid_array = (*env)->NewByteArray(env, sizeof(GUID)); + if (guid_array == NULL) + return NULL; + (*env)->SetByteArrayRegion(env, guid_array, 0, sizeof(GUID), (jbyte *)guid); + return guid_array; +} + +void unwrapGUID(JNIEnv *env, const jobjectArray byte_array, GUID *guid) { + (*env)->GetByteArrayRegion(env, byte_array, 0, sizeof(GUID), (jbyte *)guid); +} + diff --git a/plugins/windows/src/native/winutil.h b/plugins/windows/src/native/winutil.h new file mode 100644 index 0000000..169280e --- /dev/null +++ b/plugins/windows/src/native/winutil.h @@ -0,0 +1,17 @@ +/* + * %W% %E% + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +#ifndef _WINUTIL_H +#define _WINUTIL_H + +#include <windows.h> +#include <jni.h> + +extern jbyteArray wrapGUID(JNIEnv *env, const GUID *guid); +extern void unwrapGUID(JNIEnv *env, const jobjectArray byte_array, GUID *guid); + +#endif |