aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native')
-rw-r--r--src/newt/native/EventListener.h9
-rw-r--r--src/newt/native/InputEvent.h43
-rwxr-xr-xsrc/newt/native/KDWindow.c328
-rw-r--r--src/newt/native/KeyEvent.h207
-rw-r--r--src/newt/native/MacWindow.m286
-rw-r--r--src/newt/native/MouseEvent.h13
-rw-r--r--src/newt/native/NewtMacWindow.h53
-rw-r--r--src/newt/native/NewtMacWindow.m293
-rwxr-xr-xsrc/newt/native/WindowsWindow.c515
-rwxr-xr-xsrc/newt/native/X11Window.c618
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);
+}
+