Implemented Matzon's mac os x init through reflection

This commit is contained in:
Elias Naur 2003-10-13 11:54:45 +00:00
parent 963605989f
commit 36dbba4596
7 changed files with 273 additions and 92 deletions

View File

@ -32,24 +32,80 @@
package org.lwjgl.opengl;
import java.lang.reflect.*;
import org.lwjgl.Sys;
/**
* $Id$
*
* Mac OS X specific hacks
*
* @author elias_naur <elias_naur@users.sourceforge.net>
* @author Brian Matzon <brian@matzon.dk>
* @version $Revision$
*/
class MacOSX {
/**
* Initializes the Mac OS X specific hack
*/
public static void initMacOSX() {
java.awt.Toolkit.getDefaultToolkit();
new com.apple.eawt.Application().addApplicationListener(new com.apple.eawt.ApplicationAdapter() {
public void handleQuit(com.apple.eawt.ApplicationEvent e) {
e.setHandled(false);
setQuitRequested();
// Add ourselves to quit requested, using reflection to allow
// compiling on other platforms
try {
Class appClass = Class.forName("com.apple.eawt.Application");
Class listenerClass = Class.forName("com.apple.eawt.ApplicationListener");
Object appInstance = appClass.newInstance();
// create proxy for adapter
Object proxyInvoker = Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, new Invokee());
Method addApplicationListener = appClass.getMethod("addApplicationListener", new Class[]{listenerClass});
addApplicationListener.invoke(appInstance, new Object[]{proxyInvoker});
} catch (Exception e) {
// validate success
if (Sys.DEBUG) {
System.out.println("Unable to invoke 'addApplicationListener' method because of " + e);
}
});
}
}
/**
* Even more hackish proxy class for allowing mac os x to be compiled on all platforms
*
* @author Brian Matzon <brian@matzon.dk>
*/
static private class Invokee implements InvocationHandler {
/**
* Called when the actual method of the proxied class is called
*
* @param proxy Object being proxied
* @param method Method being invoked
* @param args Arguments for that specific method
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// Return if we were not called through handleQuit
Class applicationEventClass = Class.forName("com.apple.eawt.ApplicationEvent");
Class applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener");
Method handleQuitMethod = applicationListenerClass.getMethod("handleQuit", new Class[]{applicationEventClass});
if (!method.equals(handleQuitMethod))
return null;
// invoke setHandled(false);
Method setHandled = args[0].getClass().getMethod("setHandled", new Class[] {boolean.class});
setHandled.invoke(args[0], new Object[]{new Boolean(false)});
// just call setQuitRequested
setQuitRequested();
} catch (Exception e) {
if (Sys.DEBUG) {
System.out.println("Unable to invoke 'setHandled' because of " + e);
}
}
return null;
}
}
/** Notifies the native implementation that a quit event has been received */
private static native void setQuitRequested();
}

View File

@ -55,17 +55,7 @@ public final class Window {
*
*/
if (Display.getPlatform() == Display.PLATFORM_AGL)
initMacOSX();
}
private static void initMacOSX() {
try {
Class mac_class = Class.forName("org.lwjgl.opengl.MacOSX");
Method init_method = mac_class.getMethod("initMacOSX", null);
init_method.invoke(null, null);
} catch (Exception e) {
e.printStackTrace();
}
MacOSX.initMacOSX();
}
/** Whether the window is currently created, ie. has a native peer */

View File

@ -47,5 +47,6 @@
extern void setQuitRequested(void);
extern bool registerKeyboardHandler(JNIEnv* env, WindowRef win_ref);
extern bool registerMouseHandler(JNIEnv* env, WindowRef win_ref);
extern bool isMouseCreatedAndNotNativeCursor(void);
#endif /* _LWJGL_WINDOW_H_INCLUDED_ */

View File

@ -42,53 +42,24 @@
#include "Window.h"
#include "tools.h"
#include "org_lwjgl_input_Keyboard.h"
#include "common_tools.h"
#define EVENT_BUFFER_SIZE 100
#define KEYBOARD_SIZE 256
#define UNICODE_BUFFER_SIZE 10
static unsigned char key_buf[KEYBOARD_SIZE];
static unsigned char key_map[KEYBOARD_SIZE];
static unsigned char input_event_buffer[EVENT_BUFFER_SIZE];
static unsigned char output_event_buffer[EVENT_BUFFER_SIZE];
static int list_start = 0;
static int list_end = 0;
static bool buffer_enabled = false;
static bool translation_enabled = false;
static void putEventElement(unsigned char byte) {
int next_index = (list_end + 1)%EVENT_BUFFER_SIZE;
if (next_index == list_start) {
#ifdef _DEBUG
printf("Keyboard buffer overflow!\n");
#endif
return;
}
input_event_buffer[list_end] = byte;
list_end = next_index;
}
static bool hasMoreEvents(void) {
return list_start != list_end;
}
static void copyEvent(int event_size, int event_index) {
int output_index = event_index*event_size;
for (int i = 0; i < event_size; i++) {
output_event_buffer[output_index] = input_event_buffer[list_start];
list_start = (list_start + 1)%EVENT_BUFFER_SIZE;
output_index++;
}
}
static event_queue_t event_queue;
static bool handleMappedKey(unsigned char mapped_code, unsigned char state) {
unsigned char old_state = key_buf[mapped_code];
if (old_state != state) {
key_buf[mapped_code] = state;
if (buffer_enabled) {
putEventElement(mapped_code);
putEventElement(state);
putEventElement(&event_queue, mapped_code);
putEventElement(&event_queue, state);
return true;
}
}
@ -125,15 +96,15 @@ static bool writeChars(int num_chars, UniChar *buffer) {
return false;
unsigned char b0 = getFirstByte(buffer[0]);
unsigned char b1 = getSecondByte(buffer[0]);
putEventElement(b0);
putEventElement(b1);
putEventElement(&event_queue, b0);
putEventElement(&event_queue, b1);
for (int i = 1; i < num_chars; i++) {
putEventElement(0);
putEventElement(0);
putEventElement(&event_queue, 0);
putEventElement(&event_queue, 0);
b0 = getFirstByte(buffer[i]);
b1 = getSecondByte(buffer[i]);
putEventElement(b0);
putEventElement(b1);
putEventElement(&event_queue, b0);
putEventElement(&event_queue, b1);
}
return true;
}
@ -179,12 +150,12 @@ static pascal OSStatus doKeyDown(EventHandlerCallRef next_handler, EventRef even
if (handleKey(key_code, 1)) {
if (translation_enabled) {
if (!handleUnicode(event)) {
putEventElement(0);
putEventElement(0);
putEventElement(&event_queue, 0);
putEventElement(&event_queue, 0);
}
} else {
putEventElement(0);
putEventElement(0);
putEventElement(&event_queue, 0);
putEventElement(&event_queue, 0);
}
}
unlock();
@ -202,8 +173,8 @@ static pascal OSStatus doKeyUp(EventHandlerCallRef next_handler, EventRef event,
}
lock();
if (handleKey(key_code, 0)) {
putEventElement(0);
putEventElement(0);
putEventElement(&event_queue, 0);
putEventElement(&event_queue, 0);
}
unlock();
return noErr;
@ -213,8 +184,8 @@ static void handleModifier(UInt32 modifier_bit_mask, UInt32 modifier_bit, unsign
bool key_down = (modifier_bit_mask & modifier_bit) == modifier_bit;
unsigned char key_state = key_down ? 1 : 0;
if (handleMappedKey(key_code, key_state)) {
putEventElement(0);
putEventElement(0);
putEventElement(&event_queue, 0);
putEventElement(&event_queue, 0);
}
}
@ -346,8 +317,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_nCreate(JNIEnv * env, jclas
lock();
buffer_enabled = false;
translation_enabled = false;
list_end = 0;
list_start = 0;
initEventQueue(&event_queue);
memset(key_buf, 0, KEYBOARD_SIZE*sizeof(unsigned char));
setupMappings();
unlock();
@ -371,10 +341,7 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_input_Keyboard_nRead(JNIEnv * env, jclass
event_size = 4;
else
event_size = 2;
while (hasMoreEvents()) {
copyEvent(event_size, num_events);
num_events++;
}
num_events = copyEvents(&event_queue, event_size);
unlock();
return num_events;
}
@ -383,12 +350,10 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_nEnableTranslation(JNIEnv *
translation_enabled = true;
}
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Keyboard_nEnableBuffer(JNIEnv * env, jclass clazz) {
jfieldID fid_readBuffer = env->GetStaticFieldID(clazz, "readBuffer", "Ljava/nio/ByteBuffer;");
jobject new_buffer = env->NewDirectByteBuffer(&output_event_buffer, EVENT_BUFFER_SIZE);
env->SetStaticObjectField(clazz, fid_readBuffer, new_buffer);
JNIEXPORT jobject JNICALL Java_org_lwjgl_input_Keyboard_nEnableBuffer(JNIEnv * env, jclass clazz) {
jobject new_buffer = env->NewDirectByteBuffer(getOutputList(&event_queue), getEventBufferSize(&event_queue));
buffer_enabled = true;
return EVENT_BUFFER_SIZE/2;
return new_buffer;
}
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Keyboard_nisStateKeySet(JNIEnv *env, jclass clazz, jint key) {

View File

@ -39,6 +39,11 @@
* @version $Revision$
*/
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDUsageTables.h>
#include <IOKit/IOCFPlugIn.h>
#include "Window.h"
#include "tools.h"
#include "org_lwjgl_input_Mouse.h"
@ -54,6 +59,18 @@ static unsigned char button_state[NUM_BUTTONS];
static int last_x;
static int last_y;
static int wheel_dz;
static bool native_cursor;
static bool created;
static IOHIDDeviceInterface **device_interface;
/*static pascal OSStatus doMouseMoved(EventHandlerCallRef next_handler, EventRef event, void *user_data) {
printf("Mouse moved\n");
return eventNotHandledErr; // allow the event to propagate
}
*/
bool isMouseCreatedAndNotNativeCursor(void) {
return created && !native_cursor;
}
static pascal OSStatus doMouseDown(EventHandlerCallRef next_handler, EventRef event, void *user_data) {
printf("Mouse down\n");
@ -79,18 +96,132 @@ printf("Mouse wheel\n");
bool registerMouseHandler(JNIEnv* env, WindowRef win_ref) {
bool error = registerHandler(env, win_ref, doMouseDown, kEventClassMouse, kEventMouseDown);
error = error || registerHandler(env, win_ref, doMouseUp, kEventClassMouse, kEventMouseUp);
//error = error || registerHandler(env, win_ref, doMouseMoved, kEventClassMouse, kEventMouseMoved);
error = error || registerHandler(env, win_ref, doMouseWheel, kEventClassMouse, kEventMouseWheelMoved);
return !error;
}
static void printCFString(CFStringRef str) {
CFIndex buffer_size = CFStringGetLength(str) + 1;
char * buffer = (char *)malloc(buffer_size);
if (buffer != NULL) {
if (CFStringGetCString(str, buffer, buffer_size, CFStringGetSystemEncoding()))
printf("%s", buffer);
free(buffer);
}
}
static void printCFNumber(CFNumberRef num) {
long number;
if (CFNumberGetValue(num, kCFNumberLongType, &number))
printf("0x%lx (%ld)", number, number);
}
static bool getIntProperty(CFDictionaryRef dict, CFStringRef key, int *key_value) {
CFTypeRef val = CFDictionaryGetValue(dict, key);
if (val != NULL) {
CFTypeID type = CFGetTypeID(val);
if (type == CFNumberGetTypeID())
if (CFNumberGetValue((CFNumberRef)val, kCFNumberIntType, key_value))
return true;
}
return false;
}
static void printProperty(CFDictionaryRef dict, CFStringRef key) {
CFTypeRef val = CFDictionaryGetValue(dict, key);
if (val != NULL) {
CFTypeID type = CFGetTypeID(val);
if (type == CFArrayGetTypeID()) printf("array\n");
else if (type == CFBooleanGetTypeID()) printf("boolean\n");
else if (type == CFDictionaryGetTypeID()) printf("dictionary\n");
else if (type == CFNumberGetTypeID()) printCFNumber((CFNumberRef)val);
else if (type == CFStringGetTypeID()) printCFString((CFStringRef)val);
else printf("<unknown object type>\n");
}
}
static void releaseDevice(void) {
(*device_interface)->close(device_interface);
}
static bool initDevice(io_object_t hid_device) {
io_name_t class_name;
IOCFPlugInInterface **plugin_interface;
SInt32 score;
IOReturn io_err = IOObjectGetClass(hid_device, class_name);
if (io_err != kIOReturnSuccess)
return false;
printf("Found device type %s\n", class_name);
io_err = IOCreatePlugInInterfaceForService(hid_device, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugin_interface, &score);
if (io_err != kIOReturnSuccess)
return false;
HRESULT plugin_err = (*plugin_interface)->QueryInterface(plugin_interface,
CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
device_interface
);
(*plugin_interface)->Release(plugin_interface);
if (plugin_err != S_OK)
return false;
io_err = (*device_interface)->open(device_interface, 0);
if (io_err != kIOReturnSuccess) {
releaseDevice();
return false;
} else
return true;
}
static void findDevice(void) {
io_iterator_t device_iterator;
io_object_t hid_device;
kern_return_t kern_err;
bool success = false;
CFMutableDictionaryRef dev_props;
CFMutableDictionaryRef matching_dic = IOServiceMatching(kIOHIDDeviceKey);
IOReturn err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dic, &device_iterator);
if (err != kIOReturnSuccess) {
#ifdef _DEBUG
printf("Could not find matching devices\n");
#endif
return;
}
while (!success && (hid_device = IOIteratorNext(device_iterator)) != NULL) {
kern_err = IORegistryEntryCreateCFProperties(hid_device, &dev_props, kCFAllocatorDefault, kNilOptions);
if (kern_err == KERN_SUCCESS && dev_props != NULL) {
/*printf(" usage ");
printProperty(dev_props, CFSTR(kIOHIDPrimaryUsageKey));
printf(" usage page ");
printProperty(dev_props, CFSTR(kIOHIDPrimaryUsagePageKey));*/
int usage;
int usage_page;
if (getIntProperty(dev_props, CFSTR(kIOHIDPrimaryUsageKey), &usage) &&
getIntProperty(dev_props, CFSTR(kIOHIDPrimaryUsagePageKey), &usage_page) &&
usage_page == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Mouse) {
printProperty(dev_props, CFSTR(kIOHIDProductKey));
printf("\n");
success = initDevice(hid_device);
if (success)
printf("Device found: ");
}
CFRelease(dev_props);
}
IOObjectRelease(hid_device);
}
IOObjectRelease(device_iterator);
}
static void pollDevice(void) {
}
JNIEXPORT jboolean JNICALL Java_org_lwjgl_input_Mouse_nHasWheel(JNIEnv *, jclass) {
return JNI_TRUE;
}
JNIEXPORT jint JNICALL Java_org_lwjgl_input_Mouse_nGetButtonCount(JNIEnv *, jclass) {
return NUM_BUTTONS;
}
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_initIDs(JNIEnv * env, jclass clazz) {
fid_dx = env->GetStaticFieldID(clazz, "dx", "I");
fid_dy = env->GetStaticFieldID(clazz, "dy", "I");
@ -114,31 +245,39 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nCreate(JNIEnv * env, jclass c
last_x = 0;
last_y = 0;
wheel_dz = 0;
CGAssociateMouseAndMouseCursorPosition(FALSE);
native_cursor = false;
findDevice();
//CGAssociateMouseAndMouseCursorPosition(FALSE);
created = true;
}
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nDestroy(JNIEnv * env, jclass clazz) {
CGAssociateMouseAndMouseCursorPosition(TRUE);
if (!native_cursor)
CGAssociateMouseAndMouseCursorPosition(TRUE);
created = false;
}
JNIEXPORT void JNICALL Java_org_lwjgl_input_Mouse_nPoll(JNIEnv * env, jclass clazz) {
lock();
/*Point cursor_pos;
GetMouse(&cursor_pos);
int dx = cursor_pos.v - last_x;
int dy = cursor_pos.h - last_y;
last_x += dx;
last_y += dy;*/
CGMouseDelta dx, dy;
CGGetLastMouseDelta(&dx, &dy);
int dx;
int dy;
if (!native_cursor) {
pollDevice();
} else {
Point cursor_pos;
GetMouse(&cursor_pos);
dx = cursor_pos.v - last_x;
dy = cursor_pos.h - last_y;
last_x += dx;
last_y += dy;
}
env->SetStaticIntField(clazz, fid_dx, (jint)dx);
env->SetStaticIntField(clazz, fid_dy, (jint)dy);
env->SetStaticIntField(clazz, fid_dwheel, (jint)wheel_dz);
jbooleanArray buttons_array = (jbooleanArray)env->GetStaticObjectField(clazz, fid_buttons);
env->SetBooleanArrayRegion(buttons_array, 0, NUM_BUTTONS, button_state);
wheel_dz = 0;
unlock();
/*
if (dx != 0 || dy != 0)
/*if (dx != 0 || dy != 0)
printf("dx %d dy %d, lx %d ly %d\n", dx, dy, last_x, last_y);*/
unlock();
}

View File

@ -44,6 +44,7 @@
#include "org_lwjgl_opengl_Window.h"
#include "extgl.h"
#include "tools.h"
#include "common_tools.h"
static WindowRef win_ref;
static AGLContext context;
@ -52,6 +53,8 @@ static Ptr fullscreen_ptr;
static bool current_fullscreen;
static bool miniaturized;
static bool activated;
static int center_x;
static int center_y;
static void setWindowTitle(JNIEnv *env, jstring title_obj) {
const char* title = env->GetStringUTFChars(title_obj, NULL);
@ -87,10 +90,17 @@ static pascal OSStatus doMaximize(EventHandlerCallRef next_handler, EventRef eve
return eventNotHandledErr;
}
static void warpCursorToCenter(void) {
CGPoint p = {center_x, center_y};
CGWarpMouseCursorPosition(p);
}
static pascal OSStatus doActivate(EventHandlerCallRef next_handler, EventRef event, void *user_data) {
lock();
miniaturized = false;
activated = true;
if (isMouseCreatedAndNotNativeCursor())
warpCursorToCenter();
unlock();
return eventNotHandledErr;
}
@ -107,6 +117,22 @@ static pascal OSStatus doQuit(EventHandlerCallRef next_handler, EventRef event,
return noErr;
}
static pascal OSStatus doBoundsChanged(EventHandlerCallRef next_handler, EventRef event, void *user_data) {
Rect rect;
OSStatus err = GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(rect), NULL, &rect);
if (err != noErr) {
#ifdef _DEBUG
printf("Could not get bounds from bounds changed event\n");
#endif
return eventNotHandledErr;
}
lock();
center_x = (rect.left + rect.right)/2;
center_y = (rect.top + rect.bottom)/2;
unlock();
return noErr;
}
static bool registerEventHandlers(JNIEnv *env) {
bool error;
error = registerHandler(env, win_ref, doQuit, kEventClassWindow, kEventWindowClose);
@ -114,6 +140,7 @@ static bool registerEventHandlers(JNIEnv *env) {
error = error || registerHandler(env, win_ref, doDeactivate, kEventClassWindow, kEventWindowDeactivated);
error = error || registerHandler(env, win_ref, doMiniaturized, kEventClassWindow, kEventWindowCollapsed);
error = error || registerHandler(env, win_ref, doMaximize, kEventClassWindow, kEventWindowExpanded);
error = error || registerHandler(env, win_ref, doBoundsChanged, kEventClassWindow, kEventWindowBoundsChanged);
return !error && registerKeyboardHandler(env, win_ref) && registerMouseHandler(env, win_ref);
}
@ -185,6 +212,8 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate(JNIEnv *env, jclass
kWindowCollapseBoxAttribute|
kWindowStandardHandlerAttribute;
SetRect(&rect, x, y, x + width, y + height);
center_x = x + width/2;
center_y = y + height/2;
current_fullscreen = fullscreen == JNI_TRUE;
miniaturized = false;
activated = true;
@ -232,8 +261,8 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate(JNIEnv *env, jclass
}
ShowWindow(win_ref);
SelectWindow(win_ref);
CGPoint p = {x, y};
CGWarpMouseCursorPosition(p);
warpCursorToCenter();
CGPoint p = {center_x, center_y};
CGPostMouseEvent(p, FALSE, 1, TRUE);
CGPostMouseEvent(p, FALSE, 1, FALSE);
}

View File

@ -1,5 +1,6 @@
#include "tools.h"
#include <CoreServices/CoreServices.h>
#include "tools.h"
#include "common_tools.h"
MPCriticalRegionID critical_region;