diff --git a/src/native/configure.in b/src/native/configure.in index 502c2b59..f4134966 100644 --- a/src/native/configure.in +++ b/src/native/configure.in @@ -30,7 +30,7 @@ AC_CANONICAL_HOST case "$host_os" in darwin*) _BUILD_FLAGS="-D_AGL -fpascal-strings" - LDFLAGS="-Xlinker -framework -Xlinker Carbon -Xlinker -framework -Xlinker JavaVM" + LDFLAGS="-Xlinker -framework -Xlinker Carbon -Xlinker -framework -Xlinker QuickTime -Xlinker -framework -Xlinker JavaVM" NATIVE_BUILD_DIR=macosx CXXFLAGS="$CXXFLAGS $DEBUG_FLAGS -Wall $_BUILD_FLAGS" CFLAGS="$CFLAGS $DEBUG_FLAGS -Wall $_BUILD_FLAGS" diff --git a/src/native/macosx/Makefile.am b/src/native/macosx/Makefile.am index aa1cfc62..b54a4ed1 100644 --- a/src/native/macosx/Makefile.am +++ b/src/native/macosx/Makefile.am @@ -9,6 +9,7 @@ NATIVE = \ # org_lwjgl_input_Controller.cpp \ org_lwjgl_input_Keyboard.cpp \ org_lwjgl_opengl_MacOSX.cpp \ + tools.cpp \ # org_lwjgl_input_Mouse.cpp \ # org_lwjgl_input_Cursor.cpp \ org_lwjgl_opengl_Window.cpp diff --git a/src/native/macosx/Window.h b/src/native/macosx/Window.h index a44c41ca..60ec0f4c 100644 --- a/src/native/macosx/Window.h +++ b/src/native/macosx/Window.h @@ -43,6 +43,8 @@ #define _LWJGL_WINDOW_H_INCLUDED_ #include + #include extern void setQuitRequested(void); + extern bool registerKeyboardHandler(JNIEnv* env, WindowRef win_ref); #endif /* _LWJGL_WINDOW_H_INCLUDED_ */ diff --git a/src/native/macosx/org_lwjgl_input_Keyboard.cpp b/src/native/macosx/org_lwjgl_input_Keyboard.cpp index a8c7143a..e79e8b29 100644 --- a/src/native/macosx/org_lwjgl_input_Keyboard.cpp +++ b/src/native/macosx/org_lwjgl_input_Keyboard.cpp @@ -39,10 +39,7 @@ * @version $Revision$ */ -#include -#include -#include -#include +#include "Window.h" #include "tools.h" #include "org_lwjgl_input_Keyboard.h" @@ -50,6 +47,55 @@ #define KEYBOARD_SIZE 256 #define KEY_EVENT_BACKLOG 40 +static pascal OSStatus doKeyDown(EventHandlerCallRef next_handler, EventRef event, void *user_data) { + UInt32 key_code; + OSStatus err = GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(key_code), NULL, &key_code); + if (err != noErr) { +#ifdef _DEBUG + printf("Could not get event key code\n"); +#endif + return eventNotHandledErr; + } +printf("key down, key %d\n", key_code); + return noErr; +} + +static pascal OSStatus doKeyUp(EventHandlerCallRef next_handler, EventRef event, void *user_data) { + UInt32 key_code; + OSStatus err = GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(key_code), NULL, &key_code); + if (err != noErr) { +#ifdef _DEBUG + printf("Could not get event key code\n"); +#endif + return eventNotHandledErr; + } +printf("key up, key %d\n", key_code); + return noErr; +} + +bool registerKeyboardHandler(JNIEnv* env, WindowRef win_ref) { + EventTypeSpec event_types[1]; + EventHandlerUPP handler_upp = NewEventHandlerUPP(doKeyUp); + event_types[0].eventClass = kEventClassKeyboard; + event_types[0].eventKind = kEventRawKeyUp; + OSStatus err = InstallWindowEventHandler(win_ref, handler_upp, 1, event_types, NULL, NULL); + DisposeEventHandlerUPP(handler_upp); + if (noErr != err) { + throwException(env, "Could not register window event handler"); + return false; + } + handler_upp = NewEventHandlerUPP(doKeyDown); + event_types[0].eventClass = kEventClassKeyboard; + event_types[0].eventKind = kEventRawKeyDown; + err = InstallWindowEventHandler(win_ref, handler_upp, 1, event_types, NULL, NULL); + DisposeEventHandlerUPP(handler_upp); + if (noErr != err) { + throwException(env, "Could not register window event handler"); + return false; + } + return true; +} + /* * Class: org_lwjgl_input_Keyboard * Method: initIDs @@ -60,36 +106,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_initIDs { } -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 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("\n"); - } -} - /* * Class: org_lwjgl_input_Keyboard * Method: nCreate @@ -98,31 +114,6 @@ static void printProperty(CFDictionaryRef dict, CFStringRef key) { JNIEXPORT void JNICALL Java_org_lwjgl_input_Keyboard_nCreate (JNIEnv * env, jclass clazz) { - io_iterator_t device_iterator; - io_object_t hid_device; - kern_return_t kern_err; - CFMutableDictionaryRef dev_props; - CFMutableDictionaryRef matching_dic = IOServiceMatching(kIOHIDDeviceKey); - IOReturn err = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dic, &device_iterator); - if (err != kIOReturnSuccess) { - throwException(env, "Could not find matching devices"); - return; - } - while ((hid_device = IOIteratorNext(device_iterator)) != NULL) { - kern_err = IORegistryEntryCreateCFProperties(hid_device, &dev_props, kCFAllocatorDefault, kNilOptions); - IOObjectRelease(hid_device); - if (kern_err == KERN_SUCCESS && dev_props != NULL) { - printf("Device found: "); - printProperty(dev_props, CFSTR(kIOHIDProductKey)); - printf(" usage "); - printProperty(dev_props, CFSTR(kIOHIDPrimaryUsageKey)); - printf(" usage page "); - printProperty(dev_props, CFSTR(kIOHIDPrimaryUsagePageKey)); - printf("\n"); - CFRelease(dev_props); - } - } - IOObjectRelease(device_iterator); } /* diff --git a/src/native/macosx/org_lwjgl_opengl_Window.cpp b/src/native/macosx/org_lwjgl_opengl_Window.cpp index 3b728090..50e6a5f1 100644 --- a/src/native/macosx/org_lwjgl_opengl_Window.cpp +++ b/src/native/macosx/org_lwjgl_opengl_Window.cpp @@ -39,7 +39,8 @@ * @version $Revision$ */ -#include +#include "Window.h" +#include #include "org_lwjgl_opengl_Window.h" #include "extgl.h" #include "tools.h" @@ -47,6 +48,10 @@ static WindowRef win_ref; static AGLContext context; static bool close_requested; +static Ptr fullscreen_ptr; +static bool current_fullscreen; +static bool miniaturized; +static bool activated; static void setWindowTitle(JNIEnv *env, jstring title_obj) { const char* title = env->GetStringUTFChars(title_obj, NULL); @@ -63,7 +68,38 @@ static void setWindowTitle(JNIEnv *env, jstring title_obj) { } void setQuitRequested(void) { + lock(); close_requested = true; + unlock(); +} + +static pascal OSStatus doMiniaturized(EventHandlerCallRef next_handler, EventRef event, void *user_data) { + lock(); + miniaturized = true; + unlock(); + return noErr; +} + +static pascal OSStatus doMaximize(EventHandlerCallRef next_handler, EventRef event, void *user_data) { + lock(); + miniaturized = false; + unlock(); + return noErr; +} + +static pascal OSStatus doActivate(EventHandlerCallRef next_handler, EventRef event, void *user_data) { + lock(); + miniaturized = false; + activated = true; + unlock(); + return noErr; +} + +static pascal OSStatus doDeactivate(EventHandlerCallRef next_handler, EventRef event, void *user_data) { + lock(); + activated = false; + unlock(); + return noErr; } static pascal OSStatus doQuit(EventHandlerCallRef next_handler, EventRef event, void *user_data) { @@ -71,24 +107,46 @@ static pascal OSStatus doQuit(EventHandlerCallRef next_handler, EventRef event, return noErr; } -static void registerEventHandlers(JNIEnv *env) { - EventTypeSpec event_types[2]; +static bool registerWindowHandler(JNIEnv* env, EventHandlerProcPtr func, UInt32 event_kind) { + EventTypeSpec event_type; OSStatus err; - EventHandlerUPP handler_upp = NewEventHandlerUPP(doQuit); - event_types[0].eventClass = kEventClassWindow; - event_types[0].eventKind = kEventWindowClose; - err = InstallWindowEventHandler(win_ref, handler_upp, 1, event_types, NULL, NULL); + EventHandlerUPP handler_upp = NewEventHandlerUPP(func); + event_type.eventClass = kEventClassWindow; + event_type.eventKind = event_kind; + err = InstallWindowEventHandler(win_ref, handler_upp, 1, &event_type, NULL, NULL); DisposeEventHandlerUPP(handler_upp); if (noErr != err) { throwException(env, "Could not register window event handler"); - return; + return true; } + return false; +} + +static bool registerEventHandlers(JNIEnv *env) { + bool error; + error = registerWindowHandler(env, doQuit, kEventWindowClose); + error = error || registerWindowHandler(env, doActivate, kEventWindowActivated); + error = error || registerWindowHandler(env, doDeactivate, kEventWindowDeactivated); + error = error || registerWindowHandler(env, doMiniaturized, kEventWindowCollapsed); + error = error || registerWindowHandler(env, doMaximize, kEventWindowExpanded); + if (error) + return false; + else + return registerKeyboardHandler(env, win_ref); +} + +static void destroyWindow(void) { + if (current_fullscreen) + EndFullScreen(fullscreen_ptr, 0); + else + DisposeWindow(win_ref); } static void destroy(void) { + destroyLock(); aglSetCurrentContext(NULL); aglDestroyContext(context); - DisposeWindow(win_ref); + destroyWindow(); extgl_Close(); } @@ -98,7 +156,6 @@ static bool createContext(JNIEnv *env, jint bpp, jint alpha, jint depth, jint st GLint attrib[] = {AGL_RGBA, AGL_DOUBLEBUFFER, AGL_ACCELERATED, - //AGL_FULLSCREEN, AGL_NO_RECOVERY, AGL_MINIMUM_POLICY, AGL_PIXEL_SIZE, bpp, @@ -131,8 +188,10 @@ static bool createContext(JNIEnv *env, jint bpp, jint alpha, jint depth, jint st } JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Window_nIsCloseRequested(JNIEnv *, jclass) { + lock(); const bool saved = close_requested; close_requested = false; + unlock(); return saved; } @@ -143,6 +202,9 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate(JNIEnv *env, jclass kWindowCollapseBoxAttribute| kWindowStandardHandlerAttribute; SetRect(&rect, x, y, x + width, y + height); + current_fullscreen = fullscreen == JNI_TRUE; + miniaturized = false; + activated = true; close_requested = false; if (!extgl_Open()) { throwException(env, "Could not load gl library"); @@ -152,17 +214,31 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate(JNIEnv *env, jclass throwException(env, "Could not load agl symbols"); return; } - status = CreateNewWindow(kDocumentWindowClass, window_attr, &rect, &win_ref); + if (current_fullscreen) + status = BeginFullScreen(&fullscreen_ptr, NULL, 0, 0, &win_ref, NULL, 0); + else + status = CreateNewWindow(kDocumentWindowClass, window_attr, &rect, &win_ref); if (noErr != status) { + extgl_Close(); throwException(env, "Could not create window"); return; } - registerEventHandlers(env); + if (!registerEventHandlers(env)) { + destroyWindow(); + extgl_Close(); + return; + } + if (!initLock(env)) { + destroyWindow(); + extgl_Close(); + return; + } setWindowTitle(env, title); - const RGBColor background_color = { 0, 0, 0 }; + const RGBColor background_color = {0, 0, 0}; SetWindowContentColor(win_ref, &background_color); if (!createContext(env, bpp, alpha, depth, stencil)) { - DisposeWindow(win_ref); + destroyLock(); + destroyWindow(); extgl_Close(); return; } @@ -175,19 +251,41 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate(JNIEnv *env, jclass SelectWindow(win_ref); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_update - (JNIEnv *env, jclass clazz) -{ +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nSetTitle(JNIEnv * env, jclass clazz, jstring title_obj) { + setWindowTitle(env, title_obj); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_swapBuffers(JNIEnv * env, jclass clazz) -{ +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_update(JNIEnv *env, jclass clazz) { +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_swapBuffers(JNIEnv * env, jclass clazz) { aglSwapBuffers(context); } +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_minimize(JNIEnv *env, jclass clazz) { +} -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nDestroy - (JNIEnv *env, jclass clazz) -{ +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_restore(JNIEnv *env, jclass clazz) { +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nDestroy(JNIEnv *env, jclass clazz) { destroy(); } + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Window_nIsFocused(JNIEnv *env, jclass clazz) { + lock(); + bool result = activated; + unlock(); + return result; +} + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Window_nIsDirty(JNIEnv *env, jclass clazz) { + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_Window_nIsMinimized(JNIEnv *env, jclass clazz) { + lock(); + bool result = miniaturized; + unlock(); + return result; +} diff --git a/src/native/macosx/tools.cpp b/src/native/macosx/tools.cpp index 0b0ba376..b11cd656 100644 --- a/src/native/macosx/tools.cpp +++ b/src/native/macosx/tools.cpp @@ -1,7 +1,45 @@ #include "tools.h" +#include + +MPCriticalRegionID critical_region; void throwException(JNIEnv* env, const char* msg) { jclass cls = env->FindClass("java/lang/Exception"); - env->ThrowNew(cls, err); - env->DeleteLocalRef(cls); + env->ThrowNew(cls, msg); +} + +bool initLock(JNIEnv* env) { + OSStatus err = MPCreateCriticalRegion(&critical_region); + if (err != noErr) { + throwException(env, "Could not init lock"); + return false; + } + return true; +} + +void destroyLock(void) { + OSStatus err = MPDeleteCriticalRegion(critical_region); + if (err != noErr) { +#ifdef _DEBUG + printf("Could not delete lock\n"); +#endif + } +} + +void lock(void) { + OSStatus err = MPEnterCriticalRegion(critical_region, kDurationForever); + if (err != noErr) { +#ifdef _DEBUG + printf("Could not lock\n"); +#endif + } +} + +void unlock(void) { + OSStatus err = MPExitCriticalRegion(critical_region); + if (err != noErr) { +#ifdef _DEBUG + printf("Could not unlock\n"); +#endif + } } diff --git a/src/native/macosx/tools.h b/src/native/macosx/tools.h index 0ea1b091..f90659a4 100644 --- a/src/native/macosx/tools.h +++ b/src/native/macosx/tools.h @@ -4,5 +4,9 @@ #include extern void throwException(JNIEnv* env, const char* msg); +extern bool initLock(JNIEnv* env); +extern void destroyLock(void); +extern void lock(void); +extern void unlock(void); #endif