mirror of
https://github.com/refactorinqq/SLC-1.8.9.git
synced 2024-11-10 07:11:31 +01:00
Better Cursors
This commit is contained in:
parent
c18c49d54a
commit
5713b06f6f
@ -1,5 +1,6 @@
|
||||
package net.silentclient.client.utils;
|
||||
|
||||
import net.silentclient.client.utils.cursors.SystemCursors;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.LWJGLException;
|
||||
@ -69,56 +70,75 @@ public class MouseCursorHandler {
|
||||
}
|
||||
|
||||
public boolean enableCursor(final CursorType cursorType) {
|
||||
if (this.customCursorDisabled) {
|
||||
return false;
|
||||
}
|
||||
if (this.currentCursor.equals(cursorType)) {
|
||||
if(SystemCursors.isSupported()) {
|
||||
SystemCursors.setCursor(cursorType.getCursor());
|
||||
return true;
|
||||
}
|
||||
if (cursorType.equals(CursorType.NORMAL)) {
|
||||
this.disableCursor();
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
final Cursor nativeCursor = this.cursors.get(cursorType);
|
||||
if (nativeCursor != null) {
|
||||
Mouse.setNativeCursor(nativeCursor);
|
||||
this.currentCursor = cursorType;
|
||||
} else {
|
||||
if (this.customCursorDisabled) {
|
||||
return false;
|
||||
}
|
||||
if (this.currentCursor.equals(cursorType)) {
|
||||
return true;
|
||||
}
|
||||
if (cursorType.equals(CursorType.NORMAL)) {
|
||||
this.disableCursor();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
LogManager.getLogger().catching((Throwable)ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void disableCursor() {
|
||||
if (this.customCursorDisabled) {
|
||||
return;
|
||||
}
|
||||
if (this.currentCursor != CursorType.NORMAL) {
|
||||
try {
|
||||
Mouse.setNativeCursor((Cursor)null);
|
||||
this.currentCursor = CursorType.NORMAL;
|
||||
final Cursor nativeCursor = this.cursors.get(cursorType);
|
||||
if (nativeCursor != null) {
|
||||
Mouse.setNativeCursor(nativeCursor);
|
||||
this.currentCursor = cursorType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
LogManager.getLogger().catching((Throwable)ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void disableCursor() {
|
||||
if(SystemCursors.isSupported()) {
|
||||
SystemCursors.setCursor(SystemCursors.ARROW);
|
||||
} else {
|
||||
if (this.customCursorDisabled) {
|
||||
return;
|
||||
}
|
||||
if (this.currentCursor != CursorType.NORMAL) {
|
||||
try {
|
||||
Mouse.setNativeCursor((Cursor)null);
|
||||
this.currentCursor = CursorType.NORMAL;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
LogManager.getLogger().catching((Throwable)ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CursorType getCurrentCursor() {
|
||||
return currentCursor;
|
||||
return CursorType.NORMAL;
|
||||
}
|
||||
|
||||
public enum CursorType
|
||||
{
|
||||
NORMAL,
|
||||
NESW_RESIZE,
|
||||
NWSE_RESIZE,
|
||||
MOVE,
|
||||
EDIT_TEXT,
|
||||
POINTER;
|
||||
NORMAL(SystemCursors.ARROW),
|
||||
NESW_RESIZE(SystemCursors.RESIZE_NESW),
|
||||
NWSE_RESIZE(SystemCursors.RESIZE_NWSE),
|
||||
MOVE(SystemCursors.CROSSHAIR),
|
||||
EDIT_TEXT(SystemCursors.IBEAM),
|
||||
POINTER(SystemCursors.POINTING_HAND);
|
||||
|
||||
private final byte cursor;
|
||||
|
||||
CursorType(byte cursor) {
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
public byte getCursor() {
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
package net.silentclient.client.utils.cursors;
|
||||
|
||||
import org.apache.logging.log4j.*;
|
||||
import org.lwjgl.LWJGLUtil;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
public class SystemCursors {
|
||||
public static final byte ARROW = 0;
|
||||
public static final byte IBEAM = 1;
|
||||
public static final byte CROSSHAIR = 2;
|
||||
public static final byte POINTING_HAND = 3;
|
||||
public static final byte RESIZE_EW = 4;
|
||||
public static final byte RESIZE_NS = 5;
|
||||
public static final byte RESIZE_NWSE = 6;
|
||||
public static final byte RESIZE_NESW = 7;
|
||||
public static final byte ALL_CURSOR = 8;
|
||||
public static final byte NOT_ALLOWED = 9;
|
||||
public static final byte SIZE = size();
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static boolean supported = true;
|
||||
|
||||
static void markUnsupported() {
|
||||
supported = false;
|
||||
}
|
||||
|
||||
public static void setCursor(byte cursor) {
|
||||
if (!supported)
|
||||
return;
|
||||
|
||||
try {
|
||||
if (cursor == ARROW) {
|
||||
Mouse.setNativeCursor(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor < 0 || cursor >= SIZE)
|
||||
throw new IllegalArgumentException(Byte.toString(cursor));
|
||||
|
||||
if (LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_LINUX || LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_MACOSX)
|
||||
X11SystemCursors.setCursor(cursor);
|
||||
else if (LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_WINDOWS)
|
||||
Win32SystemCursors.setCursor(cursor);
|
||||
} catch (Throwable error) {
|
||||
LOGGER.error("Error occured; not trying again", error);
|
||||
markUnsupported();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
return supported;
|
||||
}
|
||||
|
||||
private static byte size() {
|
||||
return NOT_ALLOWED + 1;
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package net.silentclient.client.utils.cursors;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.InputImplementation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Util {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static MethodHandle getInputImplementationMethod;
|
||||
private static MethodHandle getDisplayImplementationMethod;
|
||||
|
||||
static {
|
||||
try {
|
||||
Method getInputImplementation = Mouse.class.getDeclaredMethod("getImplementation");
|
||||
getInputImplementation.setAccessible(true);
|
||||
getInputImplementationMethod = MethodHandles.lookup().unreflect(getInputImplementation);
|
||||
|
||||
Method getDisplayImplementation = Display.class.getDeclaredMethod("getImplementation");
|
||||
getDisplayImplementation.setAccessible(true);
|
||||
getDisplayImplementationMethod = MethodHandles.lookup().unreflect(getDisplayImplementation);
|
||||
} catch (Throwable error) {
|
||||
LOGGER.error("Could not perform reflection", error);
|
||||
}
|
||||
}
|
||||
|
||||
public static RuntimeException sneakyThrow(Throwable error) {
|
||||
if (error instanceof Error)
|
||||
throw (Error) error;
|
||||
if (error instanceof RuntimeException)
|
||||
throw (RuntimeException) error;
|
||||
if (error instanceof IOException)
|
||||
throw new UncheckedIOException((IOException) error);
|
||||
|
||||
throw new IllegalStateException(error);
|
||||
}
|
||||
|
||||
public static boolean foundInputImplementationMethod() {
|
||||
return getInputImplementationMethod != null;
|
||||
}
|
||||
|
||||
public static InputImplementation getInputImplementation() {
|
||||
try {
|
||||
return (InputImplementation) getInputImplementationMethod.invokeExact();
|
||||
} catch (Throwable error) {
|
||||
throw sneakyThrow(error);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getDisplayImplementation() {
|
||||
try {
|
||||
return getDisplayImplementationMethod.invoke();
|
||||
} catch (Throwable error) {
|
||||
throw sneakyThrow(error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadLibrary(String name) throws IOException {
|
||||
String resourceName = System.mapLibraryName(name);
|
||||
File file = File.createTempFile(resourceName, "");
|
||||
file.deleteOnExit();
|
||||
try (InputStream in = Util.class.getResourceAsStream('/' + resourceName)) {
|
||||
FileUtils.copyInputStreamToFile(in, file);
|
||||
}
|
||||
System.load(file.getAbsolutePath());
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package net.silentclient.client.utils.cursors;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Win32SystemCursors {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Long[] CACHE = new Long[SystemCursors.SIZE];
|
||||
private static MethodHandle getHwndMethod;
|
||||
|
||||
static {
|
||||
if (Util.foundInputImplementationMethod()) {
|
||||
try {
|
||||
Class<?> windowsDisplay = Class.forName("org.lwjgl.opengl.WindowsDisplay");
|
||||
Method getHwnd = windowsDisplay.getDeclaredMethod("getHwnd");
|
||||
getHwnd.setAccessible(true);
|
||||
getHwndMethod = MethodHandles.lookup().unreflect(getHwnd);
|
||||
|
||||
Util.loadLibrary("lwjglLegacyCursorsWin32");
|
||||
} catch (Throwable error) {
|
||||
LOGGER.error("Could not perform reflection/load natives", error);
|
||||
SystemCursors.markUnsupported();
|
||||
}
|
||||
} else
|
||||
SystemCursors.markUnsupported();
|
||||
}
|
||||
|
||||
public static void setCursor(byte cursor) {
|
||||
nSetCursor(getHwnd(), getDefaultCursorHandle(cursor));
|
||||
}
|
||||
|
||||
private static long getDefaultCursorHandle(byte cursor) {
|
||||
if (CACHE[cursor] != null)
|
||||
return CACHE[cursor];
|
||||
|
||||
return CACHE[cursor] = nGetDefaultCursorHandle(cursor);
|
||||
}
|
||||
|
||||
private static long getHwnd() {
|
||||
try {
|
||||
return (long) getHwndMethod.invoke(Util.getDisplayImplementation());
|
||||
} catch (Throwable error) {
|
||||
throw Util.sneakyThrow(error);
|
||||
}
|
||||
}
|
||||
|
||||
private static native long nGetDefaultCursorHandle(byte cursor);
|
||||
|
||||
private static native void nSetCursor(long hwnd, long cursor);
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package net.silentclient.client.utils.cursors;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.LWJGLException;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class X11SystemCursors {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Long[] CACHE = new Long[SystemCursors.SIZE];
|
||||
private static MethodHandle getDisplayMethod;
|
||||
|
||||
static {
|
||||
if (Util.foundInputImplementationMethod()) {
|
||||
try {
|
||||
Class<?> linuxDisplay = Class.forName("org.lwjgl.opengl.LinuxDisplay");
|
||||
Method getDisplay = linuxDisplay.getDeclaredMethod("getDisplay");
|
||||
getDisplay.setAccessible(true);
|
||||
getDisplayMethod = MethodHandles.lookup().unreflect(getDisplay);
|
||||
|
||||
Util.loadLibrary("lwjglLegacyCursorsX11");
|
||||
} catch (Throwable error) {
|
||||
LOGGER.error("Could not perform reflection/load natives", error);
|
||||
SystemCursors.markUnsupported();
|
||||
}
|
||||
} else
|
||||
SystemCursors.markUnsupported();
|
||||
}
|
||||
|
||||
public static void setCursor(byte cursor) throws LWJGLException {
|
||||
Util.getInputImplementation().setNativeCursor(getDefaultCursorHandle(cursor));
|
||||
}
|
||||
|
||||
private static long getDefaultCursorHandle(byte cursor) {
|
||||
if (CACHE[cursor] != null)
|
||||
return CACHE[cursor];
|
||||
|
||||
return CACHE[cursor] = nGetDefaultCursorHandle(getDisplay(), cursor);
|
||||
}
|
||||
|
||||
private static long getDisplay() {
|
||||
try {
|
||||
return (long) getDisplayMethod.invokeExact();
|
||||
} catch (Throwable error) {
|
||||
throw Util.sneakyThrow(error);
|
||||
}
|
||||
}
|
||||
|
||||
private static native long nGetDefaultCursorHandle(long display, byte cursor);
|
||||
}
|
23
src/main/resources/liblwjglLegacyCursorsX11.c
Normal file
23
src/main/resources/liblwjglLegacyCursorsX11.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <Xcursor/Xcursor.h>
|
||||
#include <jni.h>
|
||||
|
||||
const char *LOOKUP[] = {
|
||||
"default",
|
||||
"text",
|
||||
"crosshair",
|
||||
"pointer",
|
||||
"ew-resize",
|
||||
"ns-resize",
|
||||
"nwse-resize",
|
||||
"nesw-resize",
|
||||
"all-scroll",
|
||||
"not-allowed"
|
||||
};
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_io_github_solclient_client_util_cursors_X11SystemCursors_nGetDefaultCursorHandle(
|
||||
JNIEnv *env, jclass unused, jlong display, jbyte cursor) {
|
||||
if (cursor < 0 || cursor >= sizeof(LOOKUP) / sizeof(*LOOKUP))
|
||||
cursor = 0;
|
||||
|
||||
return XcursorLibraryLoadCursor((Display *) display, LOOKUP[cursor]);
|
||||
}
|
BIN
src/main/resources/liblwjglLegacyCursorsX11.so
Normal file
BIN
src/main/resources/liblwjglLegacyCursorsX11.so
Normal file
Binary file not shown.
36
src/main/resources/lwjglLegacyCursorsWin32.c
Normal file
36
src/main/resources/lwjglLegacyCursorsWin32.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <windows.h>
|
||||
#include <winuser.h>
|
||||
#include <jni.h>
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_io_github_solclient_client_util_cursors_Win32SystemCursors_nGetDefaultCursorHandle(
|
||||
JNIEnv *env, jclass unused, jbyte cursor) {
|
||||
switch (cursor) {
|
||||
case 0:
|
||||
default:
|
||||
return (jlong) LoadCursor(NULL, IDC_ARROW);
|
||||
case 1:
|
||||
return (jlong) LoadCursor(NULL, IDC_IBEAM);
|
||||
case 2:
|
||||
return (jlong) LoadCursor(NULL, IDC_CROSS);
|
||||
case 3:
|
||||
return (jlong) LoadCursor(NULL, IDC_HAND);
|
||||
case 4:
|
||||
return (jlong) LoadCursor(NULL, IDC_SIZEWE);
|
||||
case 5:
|
||||
return (jlong) LoadCursor(NULL, IDC_SIZENS);
|
||||
case 6:
|
||||
return (jlong) LoadCursor(NULL, IDC_SIZENWSE);
|
||||
case 7:
|
||||
return (jlong) LoadCursor(NULL, IDC_SIZENESW);
|
||||
case 8:
|
||||
return (jlong) LoadCursor(NULL, IDC_SIZEALL);
|
||||
case 9:
|
||||
return (jlong) LoadCursor(NULL, IDC_NO);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_io_github_solclient_client_util_cursors_Win32SystemCursors_nSetCursor(
|
||||
JNIEnv *env, jclass unused, jlong hwnd, jlong cursor) {
|
||||
SetClassLongPtr((HWND) hwnd, GCLP_HCURSOR, NULL);
|
||||
SetCursor((HCURSOR) cursor);
|
||||
}
|
BIN
src/main/resources/lwjglLegacyCursorsWin32.dll
Normal file
BIN
src/main/resources/lwjglLegacyCursorsWin32.dll
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user