/* * Copyright (c) 2002-2004 Lightweight Java Game Library Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'Light Weight Java Game Library' nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.lwjgl.input; import java.util.HashMap; import java.util.Map; import java.nio.ByteBuffer; import java.nio.ByteOrder; import org.lwjgl.*; /** * $Id$ * * A raw Mouse interface. This can be used to poll the current state of the * mouse buttons, and determine the mouse movement delta since the last poll. * * n buttons supported, n being a native limit. A scrolly wheel is also * supported, if one such is available. All movement is reported as delta from * last position. * * @author cix_foo * @author elias_naur * @author Brian Matzon * @version $Revision$ */ public class Mouse { /** 1 bit transparency for native cursor */ public final static int CURSOR_ONE_BIT_TRANSPARENCY = 1; /** 8 bit alhpa native cursor */ public final static int CURSOR_8_BIT_ALPHA = 2; /** animation native cursor */ public final static int CURSOR_ANIMATION = 4; /** Has the mouse been created? */ private static boolean created; /** The mouse buttons status from the last poll */ private static byte[] buttons; /** Delta X */ private static int dx; /** Delta Y */ private static int dy; /** Delta Z */ private static int dwheel; /** Number of buttons supported by the mouse */ private static int buttonCount = -1; /** Does this mouse support a scroll wheel */ private static boolean hasWheel = false; /** The current native cursor, if any */ private static Cursor currentCursor; /** Button names. These are set upon create(), to names like BUTTON0, BUTTON1, etc. */ private static String[] buttonName; /** hashmap of button names, for fast lookup */ private static final Map buttonMap = new HashMap(16); /** Lazy initialization */ private static boolean initialized; /** The mouse button events from the last read */ private static ByteBuffer readBuffer = null; /** The current mouse event button being examined */ private static int eventButton; /** The current state of the button being examined in the event queue */ private static boolean eventState; /** * Mouse cannot be constructed. */ private Mouse() { } /** * Gets the currently bound native cursor, if any. * * @return the currently bound native cursor, if any. */ public static Cursor getNativeCursor() { return currentCursor; } /** * Get the capabilities of the native cursor. Return a bit mask of the native cursor capabilities. * The CURSOR_ONE_BIT_TRANSPARANCY indicates support for cursors with one bit transparancy, * the CURSOR_8_BIT_ALPHA indicates support for 8 bit alpha and CURSOR_ANIMATION indicates * support for cursor animations. * * @return A bit mask with native cursor capabilities. */ public static int getNativeCursorCaps() { return nGetNativeCursorCaps(); } /** * Native function to determine native cursor support */ private static native int nGetNativeCursorCaps(); /** * Binds a native cursor. If the cursor argument is null, the * native cursor is disabled, as if native cursors were not supported. * The Mouse must be created before a native cursor can be bound. * * NOTE: The native cursor is not constrained to the window, but * relative events will not be generated if the cursor is outside. * The initial position of the cursor is the middle of the window, * that is, {window_width/2, window_height/2}. * The cursor will be moved to this origin when a * native cursor is set and the previous cursor is null. * * @param cursor the native cursor object to bind. May be null. * @return The previous Cursor object set, or null. * @throws Exception if the cursor could not be set for any reason */ public static Cursor setNativeCursor(Cursor cursor) throws Exception { assert created && ((getNativeCursorCaps() | CURSOR_ONE_BIT_TRANSPARENCY) != 0); Cursor oldCursor = currentCursor; currentCursor = cursor; if (currentCursor != null) { nSetNativeCursor(currentCursor.getHandle()); } else { nSetNativeCursor(0); } return oldCursor; } /** Native method to set the native cursor */ private static native void nSetNativeCursor(long handle) throws Exception; /** * Gets the minimum size of a native cursor. Can only be called if * The Mouse is created and cursor caps includes at least * CURSOR_ONE_BIT_TRANSPARANCY. * * @return the maximum size of a native cursor */ public static int getMinCursorSize() { return nGetMinCursorSize(); } /** Native method returning the minimum cursor size */ private static native int nGetMinCursorSize(); /** * Gets the maximum size of a native cursor. Can only be called if * The Mouse is created and cursor caps includes at least * CURSOR_ONE_BIT_TRANSPARANCY. * * @return the maximum size of a native cursor */ public static int getMaxCursorSize() { return nGetMaxCursorSize(); } /** Native method returning the maximum cursor size */ private static native int nGetMaxCursorSize(); /** * Static initialization */ private static void initialize() { System.loadLibrary(Sys.getLibraryName()); initIDs(); // Assign names to all the buttons buttonName = new String[16]; for (int i = 0; i < 16; i ++) { buttonName[i] = "BUTTON" + i; buttonMap.put(buttonName[i], new Integer(i)); } initialized = true; } /** * Register fields with the native library */ private static native void initIDs(); /** * "Create" the mouse. The display must first have been created. * * @throws Exception if the mouse could not be created for any reason */ public static void create() throws Exception { if (!initialized) { initialize(); } if (created) { return; } nCreate(); hasWheel = nHasWheel(); created = true; currentCursor = null; // set mouse buttons buttonCount = nGetButtonCount(); buttons = new byte[buttonCount]; } /** Native query of wheel support */ private static native boolean nHasWheel(); /** Native query of button count */ private static native int nGetButtonCount(); /** * Native method to create the mouse. * * @return true if the mouse was created */ private static native void nCreate(); /** * @return true if the mouse has been created */ public static boolean isCreated() { return created; } /** * "Destroy" the mouse. Remember to reset the native cursor if * setNativeCursor() has been called with anything else than null. */ public static void destroy() { assert currentCursor == null; if (!created) return; created = false; buttons = null; currentCursor = null; nDestroy(); } /** * Native method the destroy the mouse */ private static native void nDestroy(); /** * Polls the mouse. */ public static void poll() { assert created : "The mouse has not been created."; nPoll(); } /** * Native method to poll the mouse */ private static native void nPoll(); /** * See if a particular mouse button is down. * * @param button The index of the button you wish to test (0..buttonCount-1) * @return true if the specified button is down */ public static boolean isButtonDown(int button) { assert created : "The mouse has not been created."; if (button >= buttonCount || button < 0) return false; else return buttons[button] == 1; } /** * Gets a button's name * @param button The button * @return a String with the button's human readable name in it or null if the button is unnamed */ public static String getButtonName(int button) { if (button >= buttonName.length || button < 0) return null; else return buttonName[button]; } /** * Get's a button's index. If the button is unrecognised then -1 is returned. * @param buttonName The button name */ public static int getButtonIndex(String buttonName) { Integer ret = (Integer) buttonMap.get(buttonName); if (ret == null) return -1; else return ret.intValue(); } /** * Enable mouse button buffering. Must be called after the mouse is created. * @return the size of the mouse buffer in events, or 0 if no buffering * can be enabled for any reason */ public static int enableBuffer() throws Exception { assert created : "The mouse has not been created."; readBuffer = nEnableBuffer(); if (readBuffer != null) readBuffer.order(ByteOrder.nativeOrder()); return readBuffer.capacity()/2; } /** * Native method to enable the buffer * @return the event buffer, * or null if no buffer can be allocated */ private static native ByteBuffer nEnableBuffer() throws Exception; /** * Reads the mouse buffer. */ public static void read() { assert created : "The mouse has not been created."; assert readBuffer != null : "Mouse buffering has not been enabled."; int numEvents = nRead(); readBuffer.clear(); readBuffer.limit(numEvents << 1); } /** * Native method to read the keyboard buffer * @return the total number of events read. */ private static native int nRead(); /** * Gets the next mouse event. This is stored in the publicly accessible * static fields button and state. * @return true if a mouse event was read, false otherwise */ public static boolean next() { assert created : "The mouse has not been created."; assert readBuffer != null : "Mouse buffering has not been enabled."; if (readBuffer.hasRemaining()) { eventButton = readBuffer.get() & 0xFF; eventState = readBuffer.get() != 0; return true; } else return false; } /** * @return Current events button */ public static int getEventButton() { return eventButton; } /** * @return Current events button state */ public static boolean getEventButtonState() { return eventState; } /** * @return Movement on the x axis since last poll */ public static int getDX() { return dx; } /** * @return Movement on the y axis since last poll */ public static int getDY() { return dy; } /** * @return Movement of the wheel since last poll */ public static int getDWheel() { return dwheel; } /** * @return Number of buttons on this mouse */ public static int getButtonCount() { return buttonCount; } /** * @return Whether or not this mouse has wheel support */ public static boolean hasWheel() { return hasWheel; } }