diff options
author | Sven Gothel <[email protected]> | 2009-03-16 14:38:27 +0000 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2009-03-16 14:38:27 +0000 |
commit | 24fcece997ba911b0270033a357bbd83258d4f1a (patch) | |
tree | 4d01034154734897724d6a3b7738bf22693a8d36 /src/newt/native | |
parent | 9517d52c18bfa93d78e03f4c212757eda421afb6 (diff) |
JOGL refactoring:
Refactored JOGL into 3 independent components.
1 NWI - Native windowing interface
Abstracts the the general NativeWindow interface and it's factory,
incl the basic JAWT and Xlib toolkit.
The latter was motivated to clean up the JOGL workspace,
and to allow other to reuse this part.
The generic core is nwi.core.jar, the AWT add-on is nwi.awt.jar.
2 JOGL - The OpenGL mapping
Further cleanup of the SPEC.
All non OpenGL toolkits are relocated to NWI and NEWT.
There is still openmax and the windows audio layer ..
Another cleanup of the fixed function pipeline emulation.
Moved utilities and implementations where they belong ..
Removed GLUnsupportedException.
Misc .. changes
3 NEWT - The new windowing toolkit
The generic NEWT, newt.core.jar.
The JOGL and AWT modules are seperate, newt.ogl.jar newt.awt.jar.
Their build can be switched off.
The modules source and builds resides in their own directory.
Because of their nature, they share the stub_includes, etc.
Each module has it's own ant build script
- build-nwi.xml
- build-jogl.xml
- build-newt.xml
They can be build at once using build.xml as ususal,
which just invokes the seperate build tasks.
if rootrel.build=build, then the build location is
jogl/build-nwi
jogl/build-jogl
jogl/build-newt
and the sources are under
jogl/src/nwi
jogl/src/jogl
jogl/src/newt
Tested: jogl-demos, d4; Linux, MacOsX; Nvidia
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/branches/JOGL_2_SANDBOX@1868 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/newt/native')
-rw-r--r-- | src/newt/native/EventListener.h | 9 | ||||
-rw-r--r-- | src/newt/native/InputEvent.h | 43 | ||||
-rwxr-xr-x | src/newt/native/KDWindow.c | 328 | ||||
-rw-r--r-- | src/newt/native/KeyEvent.h | 207 | ||||
-rw-r--r-- | src/newt/native/MacWindow.m | 286 | ||||
-rw-r--r-- | src/newt/native/MouseEvent.h | 13 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.h | 53 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.m | 293 | ||||
-rwxr-xr-x | src/newt/native/WindowsWindow.c | 515 | ||||
-rwxr-xr-x | src/newt/native/X11Window.c | 618 |
10 files changed, 2365 insertions, 0 deletions
diff --git a/src/newt/native/EventListener.h b/src/newt/native/EventListener.h new file mode 100644 index 000000000..2e0e92323 --- /dev/null +++ b/src/newt/native/EventListener.h @@ -0,0 +1,9 @@ + +#ifndef _EVENT_LISTSENER_H +#define _EVENT_LISTSENER_H + +#define EVENT_WINDOW (1 << 0) +#define EVENT_MOUSE (1 << 1) +#define EVENT_KEY (1 << 2) + +#endif diff --git a/src/newt/native/InputEvent.h b/src/newt/native/InputEvent.h new file mode 100644 index 000000000..1284a8535 --- /dev/null +++ b/src/newt/native/InputEvent.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2009 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 materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, 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 + * DISTRIBUTING 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 OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef _INPUT_EVENT_H_ +#define _INPUT_EVENT_H_ + +#define EVENT_SHIFT_MASK 1 +#define EVENT_CTRL_MASK 2 +#define EVENT_META_MASK 4 +#define EVENT_ALT_MASK 8 +#define EVENT_ALT_GRAPH_MASK 32 + +#endif diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c new file mode 100755 index 000000000..8e4764c49 --- /dev/null +++ b/src/newt/native/KDWindow.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2008 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 materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, 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 + * DISTRIBUTING 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 OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifdef _WIN32 + #include <windows.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +/* This typedef is apparently needed for Microsoft compilers before VC8, + and on Windows CE */ +#if (_MSC_VER < 1400) || defined(UNDER_CE) + #ifdef _WIN64 + typedef long long intptr_t; + #else + typedef int intptr_t; + #endif +#else + #include <inttypes.h> +#endif + +#include <KD/kd.h> +#include <KD/NV_extwindowprops.h> + +#include "com_sun_javafx_newt_opengl_kd_KDWindow.h" + +#include "EventListener.h" +#include "MouseEvent.h" +#include "KeyEvent.h" + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + #define DBG_PRINT(...) fprintf(stdout, __VA_ARGS__) +#else + #define DBG_PRINT(...) +#endif + +#ifdef VERBOSE_ON + #ifdef _WIN32_WCE + #define STDOUT_FILE "\\Storage Card\\stdout.txt" + #define STDERR_FILE "\\Storage Card\\stderr.txt" + #endif +#endif + +/** + * Window + */ + +static jmethodID sizeChangedID = NULL; +static jmethodID windowDestroyNotifyID = NULL; +static jmethodID windowDestroyedID = NULL; +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; + +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_kd_KDWindow_initIDs + (JNIEnv *env, jclass clazz) +{ +#ifdef VERBOSE_ON + #ifdef _WIN32_WCE + _wfreopen(TEXT(STDOUT_FILE),L"w",stdout); + _wfreopen(TEXT(STDERR_FILE),L"w",stderr); + #endif +#endif + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + if (sizeChangedID == NULL || + windowDestroyNotifyID == NULL || + windowDestroyedID == NULL || + sendMouseEventID == NULL || + sendKeyEventID == NULL) { + DBG_PRINT( "initIDs failed\n" ); + return JNI_FALSE; + } + DBG_PRINT( "initIDs ok\n" ); + return JNI_TRUE; +} + +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_kd_KDWindow_CreateWindow + (JNIEnv *env, jobject obj, jint owner, jlong display, jintArray jAttrs) +{ + jint * attrs = NULL; + jsize attrsLen; + EGLDisplay dpy = (EGLDisplay)(intptr_t)display; + KDWindow *window = 0; + + DBG_PRINT( "[CreateWindow]: owner %d\n", owner); + + if(dpy==NULL) { + fprintf(stderr, "[CreateWindow] invalid display connection..\n"); + return 0; + } + + attrsLen = (*env)->GetArrayLength(env, jAttrs); + if(0==attrsLen) { + fprintf(stderr, "[CreateWindow] attribute array size 0..\n"); + return 0; + } + attrs = (*env)->GetIntArrayElements(env, jAttrs, 0); + if(NULL==attrs) { + fprintf(stderr, "[CreateWindow] attribute array NULL..\n"); + return 0; + } + + /* passing the KDWindow instance for the eventuserptr */ + window = kdCreateWindow(dpy, attrs, (void *)(intptr_t)owner); + + (*env)->ReleaseIntArrayElements(env, jAttrs, attrs, 0); + + if(NULL==window) { + fprintf(stderr, "[CreateWindow] failed: 0x%X\n", kdGetError()); + } + DBG_PRINT( "[CreateWindow] ok: %p, owner %d\n", window, (void *)(intptr_t)owner); + return (jlong) (intptr_t) window; +} + +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_kd_KDWindow_RealizeWindow + (JNIEnv *env, jobject obj, jlong window) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + EGLNativeWindowType nativeWindow=0; + + jint res = kdRealizeWindow(w, &nativeWindow); + if(res) { + fprintf(stderr, "[RealizeWindow] failed: 0x%X, 0x%X\n", res, kdGetError()); + nativeWindow = NULL; + } + DBG_PRINT( "[RealizeWindow] ok: %p\n", nativeWindow); + return (jlong) (intptr_t) nativeWindow; +} + +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_kd_KDWindow_CloseWindow + (JNIEnv *env, jobject obj, jlong window) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + int res = kdDestroyWindow(w); + + DBG_PRINT( "[CloseWindow] res: %d\n", res); + return res; +} + +/* + * Class: com_sun_javafx_newt_kd_KDWindow + * Method: setVisible0 + * Signature: (JJZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_setVisible0 + (JNIEnv *env, jobject obj, jlong window, jboolean visible) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + KDboolean v = (visible==JNI_TRUE)?KD_TRUE:KD_FALSE; + kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &v); + DBG_PRINT( "[setVisible] v=%d\n", visible); +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_DispatchMessages + (JNIEnv *env, jobject obj, jint owner, jlong window, jint eventMask) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + const KDEvent * evt; + + // Periodically take a break + while( NULL!=(evt=kdWaitEvent(0)) ) { + jint src_owner = (jint)(intptr_t)evt->userptr; + if(src_owner != owner) { + DBG_PRINT( "event unrelated: src: %d, caller: %d, evt type: 0x%X\n", src_owner, owner, evt->type); + continue; + } + DBG_PRINT( "[DispatchMessages]: caller %d, evt type: 0x%X\n", owner, evt->type); + + switch(evt->type) { + case KD_EVENT_INPUT_POINTER: + if( ! ( eventMask & EVENT_MOUSE ) ) { + DBG_PRINT( "event mouse ignored: src: %d\n", owner); + continue; + } + break; + /* + case KeyPress: + case KeyRelease: + if( ! ( eventMask & EVENT_KEY ) ) { + DBG_PRINT( "event key ignored: src: %d\n", owner); + continue; + } + break; + */ + case KD_EVENT_WINDOW_FOCUS: + case KD_EVENT_WINDOW_CLOSE: + case KD_EVENT_WINDOWPROPERTY_CHANGE: + case KD_EVENT_WINDOW_REDRAW: + if( ! ( eventMask & EVENT_WINDOW ) ) { + DBG_PRINT( "event window ignored: src: %d\n", owner); + continue; + } + break; + } + + // FIXME: support resize and window re-positioning events + + switch(evt->type) { + case KD_EVENT_WINDOW_FOCUS: + { + KDboolean hasFocus; + kdGetWindowPropertybv(w, KD_WINDOWPROPERTY_FOCUS, &hasFocus); + DBG_PRINT( "event window focus : src: %d\n", owner); + } + break; + case KD_EVENT_WINDOW_CLOSE: + { + DBG_PRINT( "event window close : src: %d\n", owner); + (*env)->CallVoidMethod(env, obj, windowDestroyNotifyID); + // Called by Window.java: DestroyWindow(wnd); + // (*env)->CallVoidMethod(env, obj, windowDestroyedID); + } + break; + case KD_EVENT_WINDOWPROPERTY_CHANGE: + { + const KDEventWindowProperty* prop = &evt->data.windowproperty; + switch (prop->pname) { + case KD_WINDOWPROPERTY_SIZE: + { + KDint32 v[2]; + if(!kdGetWindowPropertyiv(w, KD_WINDOWPROPERTY_SIZE, v)) { + DBG_PRINT( "event window size change : src: %d %dx%d\n", owner, v[0], v[1]); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) v[0], (jint) v[1]); + } else { + DBG_PRINT( "event window size change error: src: %d %dx%d\n", owner, v[0], v[1]); + } + } + break; + case KD_WINDOWPROPERTY_FOCUS: + DBG_PRINT( "event window focus: src: %d\n", owner); + break; + case KD_WINDOWPROPERTY_VISIBILITY: + { + KDboolean visible; + kdGetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &visible); + DBG_PRINT( "event window visibility: src: %d, v:%d\n", owner, visible); + } + break; + default: + break; + } + } + break; + case KD_EVENT_INPUT_POINTER: + { + const KDEventInputPointer* ptr = &(evt->data.inputpointer); + // button idx: evt->data.input.index + // pressed = ev->data.input.value.i + // time = ev->timestamp + if(KD_INPUT_POINTER_SELECT==ptr->index) { + DBG_PRINT( "event mouse click: src: %d, s:%d, (%d,%d)\n", owner, ptr->select, ptr->x, ptr->y); + (*env)->CallVoidMethod(env, obj, sendMouseEventID, + (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED, + (jint) 0, + (jint) ptr->x, (jint) ptr->y, 1); + } else { + DBG_PRINT( "event mouse: src: %d, s:%d, i:0x%X (%d,%d)\n", owner, ptr->select, ptr->index, ptr->x, ptr->y); + (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + 0, + (jint) ptr->x, (jint) ptr->y, 0); + } + } + break; + } + } +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_setFullScreen0 + (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + KDboolean v = fullscreen; + + int res = kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_FULLSCREEN_NV, &v); + DBG_PRINT( "[setFullScreen] v=%d, res=%d\n", fullscreen, res); + (void)res; +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_setSize0 + (JNIEnv *env, jobject obj, jlong window, jint width, jint height) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + KDint32 v[] = { width, height }; + + int res = kdSetWindowPropertyiv(w, KD_WINDOWPROPERTY_SIZE, v); + DBG_PRINT( "[setSize] v=%dx%d, res=%d\n", width, height, res); + (void)res; + + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h new file mode 100644 index 000000000..eb5547b21 --- /dev/null +++ b/src/newt/native/KeyEvent.h @@ -0,0 +1,207 @@ + +#ifndef _KEY_EVENT_H_ +#define _KEY_EVENT_H_ + +#define EVENT_KEY_PRESSED 300 +#define EVENT_KEY_RELEASED 301 +// Send by Java: EVENT_KEY_TYPED 302 + +#define VK_ENTER '\n' +#define VK_BACK_SPACE '\b' +#define VK_TAB '\t' +#define VK_CANCEL 0x03 +#define VK_CLEAR 0x0C +#define VK_SHIFT 0x10 +#define VK_CONTROL 0x11 +#define VK_ALT 0x12 +#define VK_PAUSE 0x13 +#define VK_CAPS_LOCK 0x14 +#define VK_ESCAPE 0x1B +#define VK_SPACE 0x20 +#define VK_PAGE_UP 0x21 +#define VK_PAGE_DOWN 0x22 +#define VK_END 0x23 +#define VK_HOME 0x24 + +#define VK_LEFT 0x25 + +#define VK_UP 0x26 + +#define VK_RIGHT 0x27 + +#define VK_DOWN 0x28 + +#define VK_COMMA 0x2C + +#define VK_MINUS 0x2D + +#define VK_PERIOD 0x2E + +#define VK_SLASH 0x2F + +#define VK_0 0x30 +#define VK_1 0x31 +#define VK_2 0x32 +#define VK_3 0x33 +#define VK_4 0x34 +#define VK_5 0x35 +#define VK_6 0x36 +#define VK_7 0x37 +#define VK_8 0x38 +#define VK_9 0x39 + +#define VK_SEMICOLON 0x3B + +#define VK_EQUALS 0x3D + +#define VK_A 0x41 +#define VK_B 0x42 +#define VK_C 0x43 +#define VK_D 0x44 +#define VK_E 0x45 +#define VK_F 0x46 +#define VK_G 0x47 +#define VK_H 0x48 +#define VK_I 0x49 +#define VK_J 0x4A +#define VK_K 0x4B +#define VK_L 0x4C +#define VK_M 0x4D +#define VK_N 0x4E +#define VK_O 0x4F +#define VK_P 0x50 +#define VK_Q 0x51 +#define VK_R 0x52 +#define VK_S 0x53 +#define VK_T 0x54 +#define VK_U 0x55 +#define VK_V 0x56 +#define VK_W 0x57 +#define VK_X 0x58 +#define VK_Y 0x59 +#define VK_Z 0x5A + +#define VK_OPEN_BRACKET 0x5B + +#define VK_BACK_SLASH 0x5C + +#define VK_CLOSE_BRACKET 0x5D + +#define VK_NUMPAD0 0x60 +#define VK_NUMPAD1 0x61 +#define VK_NUMPAD2 0x62 +#define VK_NUMPAD3 0x63 +#define VK_NUMPAD4 0x64 +#define VK_NUMPAD5 0x65 +#define VK_NUMPAD6 0x66 +#define VK_NUMPAD7 0x67 +#define VK_NUMPAD8 0x68 +#define VK_NUMPAD9 0x69 +#define VK_MULTIPLY 0x6A +#define VK_ADD 0x6B + +#define VK_SEPARATER 0x6C + +#define VK_SEPARATOR VK_SEPARATER + +#define VK_SUBTRACT 0x6D +#define VK_DECIMAL 0x6E +#define VK_DIVIDE 0x6F +#define VK_DELETE 0x7F; /* ASCII DEL */ +#define VK_NUM_LOCK 0x90 +#define VK_SCROLL_LOCK 0x91 + +#define VK_F1 0x70 + +#define VK_F2 0x71 + +#define VK_F3 0x72 + +#define VK_F4 0x73 + +#define VK_F5 0x74 + +#define VK_F6 0x75 + +#define VK_F7 0x76 + +#define VK_F8 0x77 + +#define VK_F9 0x78 + +#define VK_F10 0x79 + +#define VK_F11 0x7A + +#define VK_F12 0x7B + +#define VK_F13 0xF000 + +#define VK_F14 0xF001 + +#define VK_F15 0xF002 + +#define VK_F16 0xF003 + +#define VK_F17 0xF004 + +#define VK_F18 0xF005 + +#define VK_F19 0xF006 + +#define VK_F20 0xF007 + +#define VK_F21 0xF008 + +#define VK_F22 0xF009 + +#define VK_F23 0xF00A + +#define VK_F24 0xF00B + +#define VK_PRINTSCREEN 0x9A +#define VK_INSERT 0x9B +#define VK_HELP 0x9C +#define VK_META 0x9D + +#define VK_BACK_QUOTE 0xC0 +#define VK_QUOTE 0xDE + +#define VK_KP_UP 0xE0 + +#define VK_KP_DOWN 0xE1 + +#define VK_KP_LEFT 0xE2 + +#define VK_KP_RIGHT 0xE3 + +#define VK_AT 0x0200 + +#define VK_COLON 0x0201 + +#define VK_CIRCUMFLEX 0x0202 + +#define VK_DOLLAR 0x0203 + +#define VK_EURO_SIGN 0x0204 + +#define VK_EXCLAMATION_MARK 0x0205 + +#define VK_INVERTED_EXCLAMATION_MARK 0x0206 + +#define VK_LEFT_PARENTHESIS 0x0207 + +#define VK_NUMBER_SIGN 0x0208 + +#define VK_PLUS 0x0209 + +#define VK_RIGHT_PARENTHESIS 0x020A + +#define VK_UNDERSCORE 0x020B + +#define VK_WINDOWS 0x020C + +#define VK_CONTEXT_MENU 0x020D + +#endif + diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m new file mode 100644 index 000000000..701187b2a --- /dev/null +++ b/src/newt/native/MacWindow.m @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2009 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 materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, 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 + * DISTRIBUTING 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 OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#import <inttypes.h> + +#import "com_sun_javafx_newt_macosx_MacWindow.h" +#import "NewtMacWindow.h" + +#import "EventListener.h" +#import "MouseEvent.h" +#import "KeyEvent.h" + +#import <ApplicationServices/ApplicationServices.h> + +#import <stdio.h> + +// For some reason, rightMouseDown isn't automatically being passed +// from the NSView to the containing NSWindow + +@interface NewtView : NSView +{ +} + +@end + +@implementation NewtView +- (void) rightMouseDown: (NSEvent*) theEvent +{ + NSResponder* next = [self nextResponder]; + if (next != nil) { + [next rightMouseDown: theEvent]; + } +} +@end + +NSString* jstringToNSString(JNIEnv* env, jstring jstr) +{ + const jchar* jstrChars = (*env)->GetStringChars(env, jstr, NULL); + NSString* str = [[NSString alloc] initWithCharacters: jstrChars length: (*env)->GetStringLength(env, jstr)]; + (*env)->ReleaseStringChars(env, jstr, jstrChars); + return str; +} + +void setFrameTopLeftPoint(NSWindow* win, jint x, jint y) +{ + NSScreen* screen = [NSScreen mainScreen]; + NSRect visibleScreenRect = [screen visibleFrame]; + NSPoint pt; + + pt = NSMakePoint(x, visibleScreenRect.origin.y + visibleScreenRect.size.height - y); + [win setFrameTopLeftPoint: pt]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_initIDs + (JNIEnv *env, jclass clazz) +{ + // This little bit of magic is needed in order to receive mouse + // motion events and allow key focus to be properly transferred. + // FIXME: are these Carbon APIs? They come from the + // ApplicationServices.framework. + ProcessSerialNumber psn; + if (GetCurrentProcess(&psn) == noErr) { + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + SetFrontProcess(&psn); + } + + // Initialize the shared NSApplication instance + [NSApplication sharedApplication]; + + // Need this when debugging, as it is necessary to attach gdb to + // the running java process -- "gdb java" doesn't work + // printf("Going to sleep for 10 seconds\n"); + // sleep(10); + + return (jboolean) [NewtMacWindow initNatives: env forClass: clazz]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: createWindow + * Signature: (IIIIIIZ)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_createWindow + (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, jint styleMask, jint bufferingType, jboolean deferCreation) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSRect rect = NSMakeRect(x, y, w, h); + jobject windowObj = (*env)->NewGlobalRef(env, jthis); + + // Allocate the window + NSWindow* window = [[[NewtMacWindow alloc] initWithContentRect: rect + styleMask: (NSUInteger) styleMask + backing: (NSBackingStoreType) bufferingType + defer: YES + javaWindowObject: windowObj] retain]; + + // If the window is undecorated, assume we want the possibility of + // a shaped window, so make it non-opaque and the background color clear + if ((styleMask & NSTitledWindowMask) == 0) { + [window setOpaque: NO]; + [window setBackgroundColor: [NSColor clearColor]]; + } + + // Immediately re-position the window based on an upper-left coordinate system + setFrameTopLeftPoint(window, x, y); + + // Allocate an NSView + NSView* view = [[NewtView alloc] initWithFrame: rect]; + + // specify we want mouse-moved events + [window setAcceptsMouseMovedEvents:YES]; + + // Set the content view + [window setContentView: view]; + + // Set the next responder to be the window so that we can forward + // right mouse button down events + [view setNextResponder: window]; + + [pool release]; + + return (jlong) ((intptr_t) window); +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: makeKeyAndOrderFront + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_makeKeyAndOrderFront + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win makeKeyAndOrderFront: win]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: orderOut + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_orderOut + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win orderOut: win]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: close0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_close0 + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win close]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: setTitle0 + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setTitle0 + (JNIEnv *env, jobject unused, jlong window, jstring title) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + NSString* str = jstringToNSString(env, title); + [str autorelease]; + [win setTitle: str]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: dispatchMessages + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_dispatchMessages + (JNIEnv *env, jobject unused, jint eventMask) +{ + NSEvent* event = NULL; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + [NewtMacWindow setJNIEnv: env]; + do { + // FIXME: ignoring event mask for the time being + event = [NSApp nextEventMatchingMask: NSAnyEventMask + untilDate: [NSDate distantPast] + inMode: NSDefaultRunLoopMode + dequeue: YES]; + if (event != NULL) { + [NSApp sendEvent: event]; + } + } while (event != NULL); + [NewtMacWindow setJNIEnv: NULL]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: contentView + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_contentView + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + jlong res = (jlong) ((intptr_t) [win contentView]); + [pool release]; + return res; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: setContentSize + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setContentSize + (JNIEnv *env, jobject unused, jlong window, jint w, jint h) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + NSSize sz = NSMakeSize(w, h); + [win setContentSize: sz]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: setFrameTopLeftPoint + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setFrameTopLeftPoint + (JNIEnv *env, jobject unused, jlong window, jint x, jint y) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + setFrameTopLeftPoint(win, x, y); + [pool release]; +} diff --git a/src/newt/native/MouseEvent.h b/src/newt/native/MouseEvent.h new file mode 100644 index 000000000..37157808b --- /dev/null +++ b/src/newt/native/MouseEvent.h @@ -0,0 +1,13 @@ + +#ifndef _MOUSE_EVENT_H_ +#define _MOUSE_EVENT_H_ + +// Generated by Java: EVENT_MOUSE_CLICKED = 200; +#define EVENT_MOUSE_ENTERED 201 +#define EVENT_MOUSE_EXITED 202 +#define EVENT_MOUSE_PRESSED 203 +#define EVENT_MOUSE_RELEASED 204 +#define EVENT_MOUSE_MOVED 205 +// Generated by Java: EVENT_MOUSE_DRAGGED = 206; + +#endif diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h new file mode 100644 index 000000000..971661ebf --- /dev/null +++ b/src/newt/native/NewtMacWindow.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2009 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 materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, 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 + * DISTRIBUTING 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 OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#import <AppKit/AppKit.h> +#import "jni.h" + +@interface NewtMacWindow : NSWindow +{ + jobject javaWindowObject; +} + ++ (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz; + +/* Set and cleared during event dispatching cycle */ ++ (void) setJNIEnv: (JNIEnv*) env; + +- (id) initWithContentRect: (NSRect) contentRect + styleMask: (NSUInteger) windowStyle + backing: (NSBackingStoreType) bufferingType + defer: (BOOL) deferCreation + javaWindowObject: (jobject) javaWindowObj; + +@end diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m new file mode 100644 index 000000000..5809c16b0 --- /dev/null +++ b/src/newt/native/NewtMacWindow.m @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2009 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 materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, 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 + * DISTRIBUTING 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 OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#import "NewtMacWindow.h" +#import "InputEvent.h" +#import "KeyEvent.h" +#import "MouseEvent.h" + +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; +static jmethodID sizeChangedID = NULL; +static jmethodID positionChangedID = NULL; +static jmethodID windowClosedID = NULL; + +// This is set while messages are being dispatched and cleared afterward +static JNIEnv* env = NULL; + +@implementation NewtMacWindow + ++ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz +{ + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); + windowClosedID = (*env)->GetMethodID(env, clazz, "windowClosed", "()V"); + if (sendMouseEventID && sendKeyEventID && sizeChangedID && positionChangedID && windowClosedID) { + return YES; + } + return NO; +} + ++ (void) setJNIEnv: (JNIEnv*) theEnv +{ + env = theEnv; +} + +- (id) initWithContentRect: (NSRect) contentRect + styleMask: (NSUInteger) windowStyle + backing: (NSBackingStoreType) bufferingType + defer: (BOOL) deferCreation + javaWindowObject: (jobject) javaWindowObj +{ + id res = [super initWithContentRect: contentRect + styleMask: windowStyle + backing: bufferingType + defer: deferCreation]; + javaWindowObject = javaWindowObj; + // Why is this necessary? Without it we don't get any of the + // delegate methods like resizing and window movement. + [self setDelegate: self]; + return res; +} + +- (BOOL) canBecomeKeyWindow +{ + // Even if the window is borderless, we still want it to be able + // to become the key window to receive keyboard events + return YES; +} + +static jint mods2JavaMods(NSUInteger mods) +{ + int javaMods = 0; + if (mods & NSShiftKeyMask) { + javaMods |= EVENT_SHIFT_MASK; + } + if (mods & NSControlKeyMask) { + javaMods |= EVENT_CTRL_MASK; + } + if (mods & NSCommandKeyMask) { + javaMods |= EVENT_META_MASK; + } + if (mods & NSAlternateKeyMask) { + javaMods |= EVENT_ALT_MASK; + } + return javaMods; +} + +- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType +{ + int i; + jint keyCode = (jint) [event keyCode]; + NSString* chars = [event charactersIgnoringModifiers]; + int len = [chars length]; + jint javaMods = mods2JavaMods([event modifierFlags]); + + if (env == NULL) { + return; + } + + if (javaWindowObject == NULL) { + return; + } + + for (i = 0; i < len; i++) { + // Note: the key code in the NSEvent does not map to anything we can use + jchar keyChar = (jchar) [chars characterAtIndex: i]; + + (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID, + evType, javaMods, keyCode, keyChar); + } +} + +- (void) keyDown: (NSEvent*) theEvent +{ + [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED]; +} + +- (void) keyUp: (NSEvent*) theEvent +{ + [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED]; +} + +- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType +{ + jint javaMods = mods2JavaMods([event modifierFlags]); + NSRect frameRect = [self frame]; + NSRect contentRect = [self contentRectForFrameRect: frameRect]; + // NSPoint location = [event locationInWindow]; + // The following computation improves the behavior of mouse drag + // events when they also affect the location of the window, but it + // still isn't perfect + NSPoint curLocation = [NSEvent mouseLocation]; + NSPoint location = NSMakePoint(curLocation.x - frameRect.origin.x, + curLocation.y - frameRect.origin.y); + + if (env == NULL) { + return; + } + + if (javaWindowObject == NULL) { + return; + } + + // 1-base the button number + (*env)->CallVoidMethod(env, javaWindowObject, sendMouseEventID, + evType, javaMods, + (jint) location.x, + (jint) (contentRect.size.height - location.y), + (jint) (1 + [event buttonNumber])); +} + +- (void) mouseEntered: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED]; +} + +- (void) mouseExited: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED]; +} + +- (void) mouseMoved: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) mouseDown: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) mouseDragged: (NSEvent*) theEvent +{ + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) mouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void) rightMouseDown: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) rightMouseDragged: (NSEvent*) theEvent +{ + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) rightMouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void) otherMouseDown: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) otherMouseDragged: (NSEvent*) theEvent +{ + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) otherMouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void)windowDidResize: (NSNotification*) notification +{ + NSRect frameRect = [self frame]; + NSRect contentRect = [self contentRectForFrameRect: frameRect]; + + if (env == NULL) { + return; + } + + if (javaWindowObject == NULL) { + return; + } + + (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, + (jint) contentRect.size.width, + (jint) contentRect.size.height); +} + +- (void)windowDidMove: (NSNotification*) notification +{ + NSRect rect = [self frame]; + NSScreen* menuBarScreen = NULL; + NSScreen* screen = NULL; + NSRect screenRect; + NSPoint pt; + + if (env == NULL) { + return; + } + + if (javaWindowObject == NULL) { + return; + } + + // FIXME: unclear whether this works correctly in multiple monitor situations + screen = [self screen]; + screenRect = [screen visibleFrame]; + pt = NSMakePoint(rect.origin.x, screenRect.origin.y + screenRect.size.height - rect.origin.y - rect.size.height); + + (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, + (jint) pt.x, (jint) pt.y); +} + +- (void)windowWillClose: (NSNotification*) notification +{ + if (env == NULL) { + return; + } + + if (javaWindowObject == NULL) { + return; + } + + (*env)->CallVoidMethod(env, javaWindowObject, windowClosedID); +} + +@end diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c new file mode 100755 index 000000000..1e173372b --- /dev/null +++ b/src/newt/native/WindowsWindow.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2008 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 materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, 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 + * DISTRIBUTING 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 OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include <windows.h> +#include <tchar.h> +#include <stdlib.h> +// NOTE: it looks like SHFullScreen and/or aygshell.dll is not available on the APX 2500 any more +// #ifdef UNDER_CE +// #include "aygshell.h" +// #endif + +/* This typedef is apparently needed for Microsoft compilers before VC8, + and on Windows CE */ +#if (_MSC_VER < 1400) || defined(UNDER_CE) +#ifdef _WIN64 +typedef long long intptr_t; +#else +typedef int intptr_t; +#endif +#endif + +#include "com_sun_javafx_newt_windows_WindowsWindow.h" + +#include "EventListener.h" +#include "MouseEvent.h" +#include "KeyEvent.h" + +static jmethodID sizeChangedID = NULL; +static jmethodID positionChangedID = NULL; +static jmethodID windowClosedID = NULL; +static jmethodID windowDestroyedID = NULL; +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; + +// This is set by DispatchMessages, below, and cleared when it exits +static JNIEnv* env = NULL; + +// Really need to factor this out in to a separate run-time file +static jchar* GetNullTerminatedStringChars(JNIEnv* env, jstring str) +{ + jchar* strChars = NULL; + strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); + if (strChars != NULL) { + (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + } + return strChars; +} + +static LRESULT CALLBACK wndProc(HWND wnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + RECT rc; + int useDefWindowProc = 0; + jobject window = NULL; + BOOL isKeyDown = FALSE; + +#if defined(UNDER_CE) || _MSC_VER <= 1200 + window = (jobject) GetWindowLong(wnd, GWL_USERDATA); +#else + window = (jobject) GetWindowLongPtr(wnd, GWLP_USERDATA); +#endif + if (window == NULL || env == NULL) { + // Shouldn't happen + return DefWindowProc(wnd, message, wParam, lParam); + } + + switch (message) { + case WM_CLOSE: + (*env)->CallVoidMethod(env, window, windowClosedID); + DestroyWindow(wnd); + break; + + case WM_DESTROY: + (*env)->CallVoidMethod(env, window, windowDestroyedID); + break; + + // Windows does the translation between key codes and key chars by + // producing synthetic WM_CHAR messages in response to WM_KEYDOWN + // messages. The Java level contains the state machine to assemble + // these multiple events into a single event. + case WM_CHAR: + // NOTE that the (1 << 31) bit is meaningless regardless of + // what the docs for WM_CHAR say; we never receive a WM_CHAR + // message in response to translating a WM_KEYUP message + (*env)->CallVoidMethod(env, window, sendKeyEventID, + (jint) EVENT_KEY_PRESSED, + // FIXME: need to interpret the key events in order to compute the modifiers + (jint) 0, + (jint) -1, + (jchar) wParam); + useDefWindowProc = 1; + break; + + case WM_KEYDOWN: + // FIXME: need to interpret the key events in order to compute the modifiers + (*env)->CallVoidMethod(env, window, sendKeyEventID, (jint) EVENT_KEY_PRESSED, + (jint) 0, (jint) wParam, (jchar) -1); + useDefWindowProc = 1; + break; + + case WM_KEYUP: + // FIXME: need to interpret the key events in order to compute the modifiers + (*env)->CallVoidMethod(env, window, sendKeyEventID, (jint) EVENT_KEY_RELEASED, + (jint) 0, (jint) wParam, (jchar) -1); + useDefWindowProc = 1; + break; + + case WM_SIZE: + GetClientRect(wnd, &rc); + (*env)->CallVoidMethod(env, window, sizeChangedID, (jint) rc.right, (jint) rc.bottom); + break; + + // FIXME: define constants for the mouse buttons and modifiers + case WM_LBUTTONDOWN: + (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + (jint) wParam, (jint) LOWORD(lParam), (jint) HIWORD(lParam), (jint) 1); + useDefWindowProc = 1; + break; + + case WM_LBUTTONUP: + (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + (jint) wParam, (jint) LOWORD(lParam), (jint) HIWORD(lParam), (jint) 1); + useDefWindowProc = 1; + break; + + case WM_MBUTTONDOWN: + (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + (jint) wParam, (jint) LOWORD(lParam), (jint) HIWORD(lParam), (jint) 2); + useDefWindowProc = 1; + break; + + case WM_MBUTTONUP: + (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + (jint) wParam, (jint) LOWORD(lParam), (jint) HIWORD(lParam), (jint) 2); + useDefWindowProc = 1; + break; + + case WM_RBUTTONDOWN: + (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + (jint) wParam, (jint) LOWORD(lParam), (jint) HIWORD(lParam), (jint) 3); + useDefWindowProc = 1; + break; + + case WM_RBUTTONUP: + (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + (jint) wParam, (jint) LOWORD(lParam), (jint) HIWORD(lParam), (jint) 3); + useDefWindowProc = 1; + break; + + case WM_MOUSEMOVE: + (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + (jint) wParam, (jint) LOWORD(lParam), (jint) HIWORD(lParam), (jint) 0); + useDefWindowProc = 1; + break; + + // FIXME: generate EVENT_MOUSE_ENTERED, EVENT_MOUSE_EXITED + default: + useDefWindowProc = 1; + } + + if (useDefWindowProc) + return DefWindowProc(wnd, message, wParam, lParam); + return 0; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_initIDs + (JNIEnv *env, jclass clazz) +{ + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); + windowClosedID = (*env)->GetMethodID(env, clazz, "windowClosed", "()V"); + windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + if (sizeChangedID == NULL || + positionChangedID == NULL || + windowClosedID == NULL || + windowDestroyedID == NULL || + sendMouseEventID == NULL || + sendKeyEventID == NULL) { + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: LoadLibraryW + * Signature: (Ljava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_LoadLibraryW + (JNIEnv *env, jclass clazz, jstring dllName) +{ + jchar* _dllName = GetNullTerminatedStringChars(env, dllName); + HMODULE lib = LoadLibraryW(_dllName); + free(_dllName); + return (jlong) (intptr_t) lib; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: RegisterWindowClass + * Signature: (Ljava/lang/String;J)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_RegisterWindowClass + (JNIEnv *env, jclass clazz, jstring appName, jlong hInstance) +{ + WNDCLASS* wc; +#ifndef UNICODE + const char* _appName = NULL; +#endif + + wc = calloc(1, sizeof(WNDCLASS)); + /* register class */ + wc->style = CS_HREDRAW | CS_VREDRAW; + wc->lpfnWndProc = (WNDPROC)wndProc; + wc->cbClsExtra = 0; + wc->cbWndExtra = 0; + /* This cast is legal because the HMODULE for a DLL is the same as + its HINSTANCE -- see MSDN docs for DllMain */ + wc->hInstance = (HINSTANCE) hInstance; + wc->hIcon = NULL; + wc->hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); + wc->hbrBackground = GetStockObject(BLACK_BRUSH); + wc->lpszMenuName = NULL; +#ifdef UNICODE + wc->lpszClassName = GetNullTerminatedStringChars(env, appName); +#else + _appName = (*env)->GetStringUTFChars(env, appName, NULL); + wc->lpszClassName = strdup(_appName); + (*env)->ReleaseStringUTFChars(env, appName, _appName); +#endif + if (!RegisterClass(wc)) { + free((void *)wc->lpszClassName); + free(wc); + return 0; + } + return (jlong) (intptr_t) wc; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: CreateWindow + * Signature: (Ljava/lang/String;JJIIII)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_CreateWindow + (JNIEnv *env, jobject obj, jstring windowClassName, jlong hInstance, jlong visualID, + jint jx, jint jy, jint defaultWidth, jint defaultHeight) +{ + const TCHAR* wndClassName = NULL; + DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; + int x=(int)jx, y=(int)jy; + int width=(int)defaultWidth, height=(int)defaultHeight; + HWND window = NULL; + +#ifdef UNICODE + wndClassName = GetNullTerminatedStringChars(env, windowClassName); +#else + wndClassName = (*env)->GetStringUTFChars(env, windowClassName, NULL); +#endif + + // FIXME: until we have valid values coming down from the + // application code, use some default values +#ifdef UNDER_CE + // Prefer to not have any surprises in the initial window sizing or placement + width = GetSystemMetrics(SM_CXSCREEN); + height = GetSystemMetrics(SM_CYSCREEN); + x = y = 0; +#else + x = CW_USEDEFAULT; + y = 0; + windowStyle |= WS_OVERLAPPEDWINDOW; +#endif + + (void) visualID; // FIXME: use the visualID .. + + window = CreateWindow(wndClassName, wndClassName, windowStyle, + x, y, width, height, + NULL, NULL, + (HINSTANCE) hInstance, + NULL); +#ifdef UNICODE + free((void*) wndClassName); +#else + (*env)->ReleaseStringUTFChars(env, windowClassName, wndClassName); +#endif + + if (window != NULL) { +#if defined(UNDER_CE) || _MSC_VER <= 1200 + SetWindowLong(window, GWL_USERDATA, (intptr_t) (*env)->NewGlobalRef(env, obj)); +#else + SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) (*env)->NewGlobalRef(env, obj)); +#endif + ShowWindow(window, SW_SHOWNORMAL); + } + return (jlong) (intptr_t) window; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: DestroyWindow + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_DestroyWindow + (JNIEnv *env, jobject obj, jlong window) +{ + DestroyWindow((HWND) window); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: GetDC + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_GetDC + (JNIEnv *env, jobject obj, jlong window) +{ + return (jlong) GetDC((HWND) window); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: ReleaseDC + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_ReleaseDC + (JNIEnv *env, jobject obj, jlong window, jlong dc) +{ + ReleaseDC((HWND) window, (HDC) dc); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: setVisible0 + * Signature: (JZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setVisible0 + (JNIEnv *_env, jclass clazz, jlong window, jboolean visible) +{ + HWND hWnd = (HWND) (intptr_t) window; + if (visible) { + ShowWindow(hWnd, SW_SHOW); + } else { + ShowWindow(hWnd, SW_HIDE); + } +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: DispatchMessages + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_DispatchMessages + (JNIEnv *_env, jclass clazz, jlong window, jint eventMask) +{ + int i = 0; + MSG msg; + BOOL gotOne; + + env = _env; + + if(eventMask<0) { + eventMask *= -1; + /* FIXME: re-select input mask + long xevent_mask_key = 0; + long xevent_mask_ptr = 0; + long xevent_mask_win = 0; + if( 0 != ( eventMask & EVENT_MOUSE ) ) { + xevent_mask_ptr |= ButtonPressMask|ButtonReleaseMask|PointerMotionMask; + } + if( 0 != ( eventMask & EVENT_KEY ) ) { + xevent_mask_key |= KeyPressMask|KeyReleaseMask; + } + if( 0 != ( eventMask & EVENT_WINDOW ) ) { + xevent_mask_win |= ExposureMask; + } + + XSelectInput(dpy, w, xevent_mask_win|xevent_mask_key|xevent_mask_ptr); + */ + } + + // Periodically take a break + do { + gotOne = PeekMessage(&msg, (HWND) window, 0, 0, PM_REMOVE); + if (gotOne) { + ++i; + switch (msg.message) { + case WM_CLOSE: + case WM_DESTROY: + case WM_SIZE: + if( ! ( eventMask & EVENT_WINDOW ) ) { + continue; + } + break; + + case WM_CHAR: + case WM_KEYDOWN: + case WM_KEYUP: + if( ! ( eventMask & EVENT_KEY ) ) { + continue; + } + break; + + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MOUSEMOVE: + if( ! ( eventMask & EVENT_MOUSE ) ) { + continue; + } + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } while (gotOne && i < 100); + + env = NULL; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: setSize0 + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setSize0 + (JNIEnv *env, jobject obj, jlong window, jint width, jint height) +{ + RECT r; + HWND w = (HWND) window; + GetWindowRect(w, &r); + MoveWindow(w, r.left, r.top, width, height, TRUE); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: setFullScreen0 + * Signature: (JZ)Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setFullScreen0 + (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen) +{ +#ifdef UNDER_CE + int screenWidth; + int screenHeight; + HWND win = (HWND) window; + + if (fullscreen) { + screenWidth = GetSystemMetrics(SM_CXSCREEN); + screenHeight = GetSystemMetrics(SM_CYSCREEN); + // NOTE: looks like SHFullScreen and/or aygshell.dll is not available on the APX 2500 any more + // First, hide all of the shell parts + // SHFullScreen(win, + // SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON); + MoveWindow(win, 0, 0, screenWidth, screenHeight, TRUE); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) screenWidth, (jint) screenHeight); + } else { + RECT rc; + int width, height; + + // First, show all of the shell parts + // SHFullScreen(win, + // SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON | SHFS_SHOWSTARTICON); + // Now resize the window to the size of the work area + SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE); + width = rc.right - rc.left; + height = rc.bottom - rc.top; + MoveWindow(win, rc.left, rc.top, width, height, TRUE); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); + } + return JNI_TRUE; +#else + /* For the time being, full-screen not supported on the desktop */ + return JNI_FALSE; +#endif +} diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c new file mode 100755 index 000000000..7789e11b1 --- /dev/null +++ b/src/newt/native/X11Window.c @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2008 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 materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * 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 WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, 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 + * DISTRIBUTING 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 OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> + +#include "com_sun_javafx_newt_x11_X11Window.h" + +#include "EventListener.h" +#include "MouseEvent.h" +#include "KeyEvent.h" + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + #define DBG_PRINT(args...) fprintf(stderr, args) + + #define DUMP_VISUAL_INFO(a,b) _dumpVisualInfo((a),(b)) + + static void _dumpVisualInfo(const char * msg, XVisualInfo *pVisualQuery) { + if(pVisualQuery!=NULL) { + fprintf(stderr, "%s: screen %d, visual: %p, visual-id: 0x%X, depth: %d, class %d, cmap sz: %d, bpp: 3x%d, rgb 0x%X 0x%X 0x%X\n", + msg, + pVisualQuery->screen, + pVisualQuery->visual, + (int)pVisualQuery->visualid, + pVisualQuery->depth, + pVisualQuery->class, + pVisualQuery->colormap_size, + pVisualQuery->bits_per_rgb, + (int)pVisualQuery->red_mask, + (int)pVisualQuery->green_mask, + (int)pVisualQuery->blue_mask + ); + } else { + fprintf(stderr, "%s: NULL XVisualInfo\n", msg); + } + } + +#else + + #define DBG_PRINT(args...) + + #define DUMP_VISUAL_INFO(a,b) + +#endif + +/** + * Keycode + */ + +#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b)) + +static jint X11KeySym2NewtVKey(KeySym keySym) { + if(IS_WITHIN(keySym,XK_F1,XK_F12)) + return (keySym-XK_F1)+VK_F1; + + switch(keySym) { + case XK_Alt_L: + case XK_Alt_R: + return VK_ALT; + + case XK_Left: + return VK_LEFT; + case XK_Right: + return VK_RIGHT; + case XK_Up: + return VK_UP; + case XK_Down: + return VK_DOWN; + case XK_Page_Up: + return VK_PAGE_UP; + case XK_Page_Down: + return VK_PAGE_DOWN; + case XK_Shift_L: + case XK_Shift_R: + return VK_SHIFT; + case XK_Control_L: + case XK_Control_R: + return VK_CONTROL; + } + return keySym; +} + +/** + * Display + */ + +/* + * Class: com_sun_javafx_newt_x11_X11Display + * Method: CreateDisplay + * Signature: (Ljava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Display_CreateDisplay + (JNIEnv *env, jobject obj, jstring displayName) +{ + Display * dpy = NULL; + const char * _displayName = NULL; + if(displayName!=0) { + _displayName = (*env)->GetStringUTFChars(env, displayName, 0); + } + dpy = XOpenDisplay(_displayName); + if(_displayName!=0) { + (*env)->ReleaseStringChars(env, displayName, (const jchar *)_displayName); + } + if(dpy==NULL) { + fprintf(stderr, "couldn't open display connection..\n"); + } + return (jlong) (intptr_t) dpy; +} + +/** + * Screen + */ + +/* + * Class: com_sun_javafx_newt_x11_X11Screen + * Method: GetScreen + * Signature: (JI)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Screen_GetScreen + (JNIEnv *env, jobject obj, jlong display, jint screen_index) +{ + Display * dpy = (Display *)(intptr_t)display; + Screen * scrn= NULL; + if(dpy==NULL) { + fprintf(stderr, "[GetScreen] invalid display connection..\n"); + return 0; + } + scrn = ScreenOfDisplay(dpy,screen_index); + if(scrn==NULL) { + scrn=DefaultScreenOfDisplay(dpy); + } + if(scrn==NULL) { + fprintf(stderr, "couldn't get screen ..\n"); + } + return (jlong) (intptr_t) scrn; +} + +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_x11_X11Screen_getWidth0 + (JNIEnv *env, jobject obj, jlong display, jint scrn_idx) +{ + Display * dpy = (Display *) (intptr_t) display; + return (jint) XDisplayWidth( dpy, scrn_idx); +} + +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_x11_X11Screen_getHeight0 + (JNIEnv *env, jobject obj, jlong display, jint scrn_idx) +{ + Display * dpy = (Display *) (intptr_t) display; + return (jint) XDisplayHeight( dpy, scrn_idx); +} + + +/** + * Window + */ + +static jmethodID sizeChangedID = NULL; +static jmethodID positionChangedID = NULL; +static jmethodID windowClosedID = NULL; +static jmethodID windowDestroyedID = NULL; +static jmethodID windowCreatedID = NULL; +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Window_initIDs + (JNIEnv *env, jclass clazz) +{ + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); + windowClosedID = (*env)->GetMethodID(env, clazz, "windowClosed", "()V"); + windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); + windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(JJ)V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + if (sizeChangedID == NULL || + positionChangedID == NULL || + windowClosedID == NULL || + windowDestroyedID == NULL || + windowCreatedID == NULL || + sendMouseEventID == NULL || + sendKeyEventID == NULL) { + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: CreateWindow + * Signature: (JJIJIIII)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow + (JNIEnv *env, jobject obj, jlong display, jlong screen, jint screen_index, + jlong visualID, + jint x, jint y, jint width, jint height) +{ + Display * dpy = NULL; + Screen * scrn = NULL; + int scrn_idx = (int)screen_index; + Window windowParent = 0; + Window window = 0; + + XVisualInfo visualTemplate; + XVisualInfo *pVisualQuery = NULL; + Visual *visual = NULL; + int depth; + + XSetWindowAttributes xswa; + unsigned long attrMask; + + int n; + + DBG_PRINT( "CreateWindow %x/%d %dx%d\n", x, y, width, height); + + dpy = (Display *)(intptr_t)display; + if(dpy==NULL) { + fprintf(stderr, "[CreateWindow] invalid display connection..\n"); + return 0; + } + + scrn = (Screen *)(intptr_t)screen; + if(scrn==NULL) { + fprintf(stderr, "invalid screen connection..\n"); + return 0; + } + + if(visualID>0) { + // try given VisualID on screen + memset(&visualTemplate, 0, sizeof(XVisualInfo)); + visualTemplate.screen = scrn_idx; + visualTemplate.visualid = (VisualID)visualID; + pVisualQuery = XGetVisualInfo(dpy, VisualIDMask|VisualScreenMask, &visualTemplate,&n); + DUMP_VISUAL_INFO("Given VisualID,ScreenIdx", pVisualQuery); + if(pVisualQuery!=NULL) { + visual = pVisualQuery->visual; + depth = pVisualQuery->depth; + visualID = (jlong)pVisualQuery->visualid; + XFree(pVisualQuery); + pVisualQuery=NULL; + } + DBG_PRINT( "trying given (screen %d, visualID: %d) found: %p\n", scrn_idx, (int)visualID, visual); + } + if (visual==NULL) + { + // try default .. + visual = XDefaultVisualOfScreen(scrn); + if(visual!=NULL) { + visualID = (jlong)visual->visualid; + // try given VisualID on screen + memset(&visualTemplate, 0, sizeof(XVisualInfo)); + visualTemplate.screen = scrn_idx; + visualTemplate.visualid = (VisualID)visualID; + pVisualQuery = XGetVisualInfo(dpy, VisualIDMask|VisualScreenMask, &visualTemplate,&n); + DUMP_VISUAL_INFO("Given ScreenIdx, Default VisualID", pVisualQuery); + if(pVisualQuery!=NULL) { + visual = pVisualQuery->visual; + depth = pVisualQuery->depth; + visualID = (jlong)pVisualQuery->visualid; + XFree(pVisualQuery); + pVisualQuery=NULL; + } else { + visual = NULL; + visualID = 0; + } + DBG_PRINT( "default visual (screen %d, visualID: %d) found: %p\n", scrn_idx, (int)visualID, visual); + } + } + if (visual==NULL) + { + fprintf(stderr, "could not query any Visual, bail out!\n"); + return 0; + } + + if(pVisualQuery!=NULL) { + XFree(pVisualQuery); + pVisualQuery=NULL; + } + + windowParent = XRootWindowOfScreen(scrn); + + attrMask = (CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect) ; + + memset(&xswa, 0, sizeof(xswa)); + xswa.override_redirect = False; // decorated + xswa.border_pixel = 0; + xswa.background_pixel = 0; + xswa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask; + xswa.colormap = XCreateColormap(dpy, + XRootWindow(dpy, scrn_idx), + visual, + AllocNone); + + window = XCreateWindow(dpy, + windowParent, + x, y, + width, height, + 0, // border width + depth, + InputOutput, + visual, + attrMask, + &xswa); + XClearWindow(dpy, window); + + (*env)->CallVoidMethod(env, obj, windowCreatedID, visualID, (jlong) window); + + return (jlong) window; +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: CloseWindow + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_CloseWindow + (JNIEnv *env, jobject obj, jlong display, jlong window) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + + /** + XUngrabPointer(dpy, CurrentTime); + XUngrabKeyboard(dpy, CurrentTime); + */ + XSelectInput(dpy, w, 0); + XUnmapWindow(dpy, w); + XSync(dpy, True); + XDestroyWindow(dpy, w); +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: setVisible0 + * Signature: (JJZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setVisible0 + (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean visible) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + DBG_PRINT( "setVisible0 vis %d\n", visible); + if(visible==JNI_TRUE) { + XMapRaised(dpy, w); + XSync(dpy, False); + + XSetInputFocus(dpy, w, RevertToParent, CurrentTime); + + } else { + /** + XUngrabPointer(dpy, CurrentTime); + XUngrabKeyboard(dpy, CurrentTime); + */ + XUnmapWindow(dpy, w); + XSync(dpy, False); + } +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: DispatchMessages + * Signature: (JJI)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_DispatchMessages + (JNIEnv *env, jobject obj, jlong display, jlong window, jint eventMask) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + + if(eventMask<0) { + long xevent_mask_key = 0; + long xevent_mask_ptr = 0; + long xevent_mask_win = 0; + eventMask *= -1; + if( 0 != ( eventMask & EVENT_MOUSE ) ) { + xevent_mask_ptr |= ButtonPressMask|ButtonReleaseMask|PointerMotionMask; + } + if( 0 != ( eventMask & EVENT_KEY ) ) { + xevent_mask_key |= KeyPressMask|KeyReleaseMask; + } + if( 0 != ( eventMask & EVENT_WINDOW ) ) { + xevent_mask_win |= ExposureMask; + } + + XSelectInput(dpy, w, xevent_mask_win|xevent_mask_key|xevent_mask_ptr); + + /** + if(0!=xevent_mask_ptr) { + XGrabPointer(dpy, w, True, xevent_mask_ptr, + GrabModeAsync, GrabModeAsync, w, None, CurrentTime); + } + if(0!=xevent_mask_key) { + XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } */ + + } + + // Periodically take a break + while( XPending(dpy)>0 ) { + XEvent evt; + KeySym keySym; + char keyChar; + char text[255]; + + XNextEvent(dpy, &evt); + + switch(evt.type) { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + if( ! ( eventMask & EVENT_MOUSE ) ) { + continue; + } + break; + case KeyPress: + case KeyRelease: + if( ! ( eventMask & EVENT_KEY ) ) { + continue; + } + break; + case FocusIn: + case FocusOut: + case DestroyNotify: + case CreateNotify: + case VisibilityNotify: + if( ! ( eventMask & EVENT_WINDOW ) ) { + continue; + } + break; + } + + // FIXME: support resize and window re-positioning events + + switch(evt.type) { + case ButtonPress: + if(evt.xbutton.window==w) { + (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + (jint) evt.xbutton.state, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button); + } + break; + case ButtonRelease: + if(evt.xbutton.window==w) { + (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + (jint) evt.xbutton.state, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button); + } + break; + case MotionNotify: + if(evt.xmotion.window==w) { + (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + (jint) evt.xmotion.state, + (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0); + } + break; + case KeyPress: + if(evt.xkey.window==w) { + if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { + keyChar=text[0]; + } else { + keyChar=0; + } + (*env)->CallVoidMethod(env, obj, sendKeyEventID, (jint) EVENT_KEY_PRESSED, + (jint) evt.xkey.state, + X11KeySym2NewtVKey(keySym), (jchar) keyChar); + } + break; + case KeyRelease: + if(evt.xkey.window==w) { + if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { + keyChar=text[0]; + } else { + keyChar=0; + } + (*env)->CallVoidMethod(env, obj, sendKeyEventID, (jint) EVENT_KEY_RELEASED, + (jint) evt.xkey.state, + X11KeySym2NewtVKey(keySym), (jchar) keyChar); + } + break; + case FocusIn: + case FocusOut: + if(evt.xfocus.window==w) { + } + break; + case DestroyNotify: + if(evt.xdestroywindow.window==w) { + (*env)->CallVoidMethod(env, obj, windowDestroyedID); + } + break; + case CreateNotify: + if(evt.xcreatewindow.window==w) { + (*env)->CallVoidMethod(env, obj, windowCreatedID); + } + break; + case VisibilityNotify: + if(evt.xvisibility.window==w) { + } + break; + case Expose: + if(evt.xvisibility.window==w) { + DBG_PRINT( "event . sizeChangedID call\n"); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) evt.xexpose.width, (jint) evt.xexpose.height); + } + break; + } + } +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: setSize0 + * Signature: (JJIIIZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setSize0 + (JNIEnv *env, jobject obj, jlong display, jlong window, jint width, jint height, jint decorationToggle, jboolean isVisible) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + + DBG_PRINT( "setSize0 %dx%d, dec %d, vis %d\n", width, height, decorationToggle, isVisible); + + if(0!=decorationToggle) { + XSetWindowAttributes xswa; + unsigned long attrMask=CWOverrideRedirect; + + if(isVisible==JNI_TRUE) { + DBG_PRINT( "setSize0 . unmap\n"); + XUnmapWindow(dpy, w); + XSync(dpy, False); + } + + if(decorationToggle<0) { + /* undecorated */ + xswa.override_redirect = True; + } else { + /* decorated */ + xswa.override_redirect = False; + } + XChangeWindowAttributes(dpy, w, attrMask, &xswa); + + if(isVisible==JNI_TRUE) { + DBG_PRINT( "setSize0 . map\n"); + XMapRaised(dpy, w); + XSync(dpy, False); + } + } + DBG_PRINT( "setSize0 . XConfigureWindow\n"); + XWindowChanges xwc; + xwc.width=width; + xwc.height=height; + XConfigureWindow(dpy, w, CWWidth|CWHeight, &xwc); + XSync(dpy, False); + + DBG_PRINT( "setSize0 . sizeChangedID call\n"); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: setPosition0 + * Signature: (JJII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setPosition0 + (JNIEnv *env, jobject obj, jlong display, jlong window, jint x, jint y) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + + DBG_PRINT( "setPos0 . XConfigureWindow\n"); + XWindowChanges xwc; + xwc.x=x; + xwc.y=y; + XConfigureWindow(dpy, w, CWX|CWY, &xwc); + + // (*env)->CallVoidMethod(env, obj, positionChangedID, (jint) width, (jint) height); +} + |