Jogamp
d39b96d0bff9101792f6a62fb928ae9ffae5a1ce
[jogl.git] / src / newt / native / WindowsWindow.c
1 /*
2  * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
3  * 
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  * 
8  * - Redistribution of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * 
11  * - Redistribution in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in the
13  *   documentation and/or other materials provided with the distribution.
14  * 
15  * Neither the name of Sun Microsystems, Inc. or the names of
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  * 
19  * This software is provided "AS IS," without a warranty of any kind. ALL
20  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
23  * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
24  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
25  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
26  * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
27  * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
28  * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
29  * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
30  * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  * 
32  */
33
34 #include <Windows.h>
35 #include <Windowsx.h>
36 #include <tchar.h>
37 #include <stdlib.h>
38 // NOTE: it looks like SHFullScreen and/or aygshell.dll is not available on the APX 2500 any more
39 // #ifdef UNDER_CE
40 // #include "aygshell.h"
41 // #endif
42
43 /* This typedef is apparently needed for Microsoft compilers before VC8,
44    and on Windows CE */
45 #if (_MSC_VER < 1400) || defined(UNDER_CE)
46     #ifdef _WIN64
47         typedef long long intptr_t;
48     #else
49         typedef int intptr_t;
50     #endif
51 #elif _MSC_VER <= 1500
52     #ifdef _WIN64 // [
53         typedef __int64           intptr_t;
54     #else // _WIN64 ][
55         typedef int               intptr_t;
56     #endif // _WIN64 ]
57 #else
58     #include <inttypes.h>
59 #endif
60
61 #if _MSC_VER <= 1500
62     // FIXME: Determine for which MSVC versions ..
63     #define strdup(s) _strdup(s)
64 #endif
65
66 #ifndef WM_MOUSEWHEEL
67 #define WM_MOUSEWHEEL                   0x020A
68 #endif //WM_MOUSEWHEEL
69
70 #ifndef WHEEL_DELTA
71 #define WHEEL_DELTA                     120
72 #endif //WHEEL_DELTA
73
74 #ifndef WHEEL_PAGESCROLL
75 #define WHEEL_PAGESCROLL                (UINT_MAX)
76 #endif //WHEEL_PAGESCROLL
77
78 #ifndef GET_WHEEL_DELTA_WPARAM  // defined for (_WIN32_WINNT >= 0x0500)
79 #define GET_WHEEL_DELTA_WPARAM(wParam)  ((short)HIWORD(wParam))
80 #endif
81
82 #ifndef MONITOR_DEFAULTTONULL
83 #define MONITOR_DEFAULTTONULL 0
84 #endif
85 #ifndef MONITOR_DEFAULTTOPRIMARY
86 #define MONITOR_DEFAULTTOPRIMARY 1
87 #endif
88 #ifndef MONITOR_DEFAULTTONEAREST
89 #define MONITOR_DEFAULTTONEAREST 2
90 #endif
91
92 #include "com_jogamp_javafx_newt_windows_WindowsWindow.h"
93
94 #include "EventListener.h"
95 #include "MouseEvent.h"
96 #include "InputEvent.h"
97 #include "KeyEvent.h"
98
99 // #define VERBOSE_ON 1
100
101 #ifdef VERBOSE_ON
102     #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) 
103 #else
104     #define DBG_PRINT(...)
105 #endif
106
107 static jmethodID sizeChangedID = NULL;
108 static jmethodID insetsChangedID = NULL;
109 static jmethodID positionChangedID = NULL;
110 static jmethodID focusChangedID = NULL;
111 static jmethodID windowDestroyNotifyID = NULL;
112 static jmethodID windowDestroyedID = NULL;
113 static jmethodID sendMouseEventID = NULL;
114 static jmethodID sendKeyEventID = NULL;
115 static jmethodID sendPaintEventID = NULL;
116
117 static RECT* UpdateInsets(JNIEnv *env, HWND hwnd, jobject window);
118
119 typedef struct {
120     JNIEnv* jenv;
121     jobject jinstance;
122 } WindowUserData;
123     
124 typedef struct {
125     UINT javaKey;
126     UINT windowsKey;
127 } KeyMapEntry;
128
129 // Static table, arranged more or less spatially.
130 static KeyMapEntry keyMapTable[] = {
131     // Modifier keys
132     {J_VK_CAPS_LOCK,        VK_CAPITAL},
133     {J_VK_SHIFT,            VK_SHIFT},
134     {J_VK_CONTROL,          VK_CONTROL},
135     {J_VK_ALT,              VK_MENU},
136     {J_VK_NUM_LOCK,         VK_NUMLOCK},
137
138     // Miscellaneous Windows keys
139     {J_VK_WINDOWS,          VK_LWIN},
140     {J_VK_WINDOWS,          VK_RWIN},
141     {J_VK_CONTEXT_MENU,     VK_APPS},
142
143     // Alphabet
144     {J_VK_A,                'A'},
145     {J_VK_B,                'B'},
146     {J_VK_C,                'C'},
147     {J_VK_D,                'D'},
148     {J_VK_E,                'E'},
149     {J_VK_F,                'F'},
150     {J_VK_G,                'G'},
151     {J_VK_H,                'H'},
152     {J_VK_I,                'I'},
153     {J_VK_J,                'J'},
154     {J_VK_K,                'K'},
155     {J_VK_L,                'L'},
156     {J_VK_M,                'M'},
157     {J_VK_N,                'N'},
158     {J_VK_O,                'O'},
159     {J_VK_P,                'P'},
160     {J_VK_Q,                'Q'},
161     {J_VK_R,                'R'},
162     {J_VK_S,                'S'},
163     {J_VK_T,                'T'},
164     {J_VK_U,                'U'},
165     {J_VK_V,                'V'},
166     {J_VK_W,                'W'},
167     {J_VK_X,                'X'},
168     {J_VK_Y,                'Y'},
169     {J_VK_Z,                'Z'},
170     {J_VK_0,                '0'},
171     {J_VK_1,                '1'},
172     {J_VK_2,                '2'},
173     {J_VK_3,                '3'},
174     {J_VK_4,                '4'},
175     {J_VK_5,                '5'},
176     {J_VK_6,                '6'},
177     {J_VK_7,                '7'},
178     {J_VK_8,                '8'},
179     {J_VK_9,                '9'},
180     {J_VK_ENTER,            VK_RETURN},
181     {J_VK_SPACE,            VK_SPACE},
182     {J_VK_BACK_SPACE,       VK_BACK},
183     {J_VK_TAB,              VK_TAB},
184     {J_VK_ESCAPE,           VK_ESCAPE},
185     {J_VK_INSERT,           VK_INSERT},
186     {J_VK_DELETE,           VK_DELETE},
187     {J_VK_HOME,             VK_HOME},
188     {J_VK_END,              VK_END},
189     {J_VK_PAGE_UP,          VK_PRIOR},
190     {J_VK_PAGE_DOWN,        VK_NEXT},
191     {J_VK_CLEAR,            VK_CLEAR}, // NumPad 5
192
193     // NumPad with NumLock off & extended arrows block (triangular)
194     {J_VK_LEFT,             VK_LEFT},
195     {J_VK_RIGHT,            VK_RIGHT},
196     {J_VK_UP,               VK_UP},
197     {J_VK_DOWN,             VK_DOWN},
198
199     // NumPad with NumLock on: numbers
200     {J_VK_NUMPAD0,          VK_NUMPAD0},
201     {J_VK_NUMPAD1,          VK_NUMPAD1},
202     {J_VK_NUMPAD2,          VK_NUMPAD2},
203     {J_VK_NUMPAD3,          VK_NUMPAD3},
204     {J_VK_NUMPAD4,          VK_NUMPAD4},
205     {J_VK_NUMPAD5,          VK_NUMPAD5},
206     {J_VK_NUMPAD6,          VK_NUMPAD6},
207     {J_VK_NUMPAD7,          VK_NUMPAD7},
208     {J_VK_NUMPAD8,          VK_NUMPAD8},
209     {J_VK_NUMPAD9,          VK_NUMPAD9},
210
211     // NumPad with NumLock on
212     {J_VK_MULTIPLY,         VK_MULTIPLY},
213     {J_VK_ADD,              VK_ADD},
214     {J_VK_SEPARATOR,        VK_SEPARATOR},
215     {J_VK_SUBTRACT,         VK_SUBTRACT},
216     {J_VK_DECIMAL,          VK_DECIMAL},
217     {J_VK_DIVIDE,           VK_DIVIDE},
218
219     // Functional keys
220     {J_VK_F1,               VK_F1},
221     {J_VK_F2,               VK_F2},
222     {J_VK_F3,               VK_F3},
223     {J_VK_F4,               VK_F4},
224     {J_VK_F5,               VK_F5},
225     {J_VK_F6,               VK_F6},
226     {J_VK_F7,               VK_F7},
227     {J_VK_F8,               VK_F8},
228     {J_VK_F9,               VK_F9},
229     {J_VK_F10,              VK_F10},
230     {J_VK_F11,              VK_F11},
231     {J_VK_F12,              VK_F12},
232     {J_VK_F13,              VK_F13},
233     {J_VK_F14,              VK_F14},
234     {J_VK_F15,              VK_F15},
235     {J_VK_F16,              VK_F16},
236     {J_VK_F17,              VK_F17},
237     {J_VK_F18,              VK_F18},
238     {J_VK_F19,              VK_F19},
239     {J_VK_F20,              VK_F20},
240     {J_VK_F21,              VK_F21},
241     {J_VK_F22,              VK_F22},
242     {J_VK_F23,              VK_F23},
243     {J_VK_F24,              VK_F24},
244
245     {J_VK_PRINTSCREEN,      VK_SNAPSHOT},
246     {J_VK_SCROLL_LOCK,      VK_SCROLL},
247     {J_VK_PAUSE,            VK_PAUSE},
248     {J_VK_CANCEL,           VK_CANCEL},
249     {J_VK_HELP,             VK_HELP},
250
251     // Japanese
252 /*
253     {J_VK_CONVERT,          VK_CONVERT},
254     {J_VK_NONCONVERT,       VK_NONCONVERT},
255     {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
256     {J_VK_ALPHANUMERIC,     VK_DBE_ALPHANUMERIC},
257     {J_VK_KATAKANA,         VK_DBE_KATAKANA},
258     {J_VK_HIRAGANA,         VK_DBE_HIRAGANA},
259     {J_VK_FULL_WIDTH,       VK_DBE_DBCSCHAR},
260     {J_VK_HALF_WIDTH,       VK_DBE_SBCSCHAR},
261     {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
262 */
263
264     {J_VK_UNDEFINED,        0}
265 };
266
267 /*
268 Dynamic mapping table for OEM VK codes.  This table is refilled
269 by BuildDynamicKeyMapTable when keyboard layout is switched.
270 (see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
271 */
272 typedef struct {
273     // OEM VK codes known in advance
274     UINT windowsKey;
275     // depends on input langauge (kbd layout)
276     UINT javaKey;
277 } DynamicKeyMapEntry;
278
279 static DynamicKeyMapEntry dynamicKeyMapTable[] = {
280     {0x00BA,  J_VK_UNDEFINED}, // VK_OEM_1
281     {0x00BB,  J_VK_UNDEFINED}, // VK_OEM_PLUS
282     {0x00BC,  J_VK_UNDEFINED}, // VK_OEM_COMMA
283     {0x00BD,  J_VK_UNDEFINED}, // VK_OEM_MINUS
284     {0x00BE,  J_VK_UNDEFINED}, // VK_OEM_PERIOD
285     {0x00BF,  J_VK_UNDEFINED}, // VK_OEM_2
286     {0x00C0,  J_VK_UNDEFINED}, // VK_OEM_3
287     {0x00DB,  J_VK_UNDEFINED}, // VK_OEM_4
288     {0x00DC,  J_VK_UNDEFINED}, // VK_OEM_5
289     {0x00DD,  J_VK_UNDEFINED}, // VK_OEM_6
290     {0x00DE,  J_VK_UNDEFINED}, // VK_OEM_7
291     {0x00DF,  J_VK_UNDEFINED}, // VK_OEM_8
292     {0x00E2,  J_VK_UNDEFINED}, // VK_OEM_102
293     {0, 0}
294 };
295
296 // Auxiliary tables used to fill the above dynamic table.  We first
297 // find the character for the OEM VK code using ::MapVirtualKey and
298 // then go through these auxiliary tables to map it to Java VK code.
299
300 typedef struct {
301     WCHAR c;
302     UINT  javaKey;
303 } CharToVKEntry;
304
305 static const CharToVKEntry charToVKTable[] = {
306     {L'!',   J_VK_EXCLAMATION_MARK},
307     {L'"',   J_VK_QUOTEDBL},
308     {L'#',   J_VK_NUMBER_SIGN},
309     {L'$',   J_VK_DOLLAR},
310     {L'&',   J_VK_AMPERSAND},
311     {L'\'',  J_VK_QUOTE},
312     {L'(',   J_VK_LEFT_PARENTHESIS},
313     {L')',   J_VK_RIGHT_PARENTHESIS},
314     {L'*',   J_VK_ASTERISK},
315     {L'+',   J_VK_PLUS},
316     {L',',   J_VK_COMMA},
317     {L'-',   J_VK_MINUS},
318     {L'.',   J_VK_PERIOD},
319     {L'/',   J_VK_SLASH},
320     {L':',   J_VK_COLON},
321     {L';',   J_VK_SEMICOLON},
322     {L'<',   J_VK_LESS},
323     {L'=',   J_VK_EQUALS},
324     {L'>',   J_VK_GREATER},
325     {L'@',   J_VK_AT},
326     {L'[',   J_VK_OPEN_BRACKET},
327     {L'\\',  J_VK_BACK_SLASH},
328     {L']',   J_VK_CLOSE_BRACKET},
329     {L'^',   J_VK_CIRCUMFLEX},
330     {L'_',   J_VK_UNDERSCORE},
331     {L'`',   J_VK_BACK_QUOTE},
332     {L'{',   J_VK_BRACELEFT},
333     {L'}',   J_VK_BRACERIGHT},
334     {0x00A1, J_VK_INVERTED_EXCLAMATION_MARK},
335     {0x20A0, J_VK_EURO_SIGN}, // ????
336     {0,0}
337 };
338
339 // For dead accents some layouts return ASCII punctuation, while some
340 // return spacing accent chars, so both should be listed.  NB: MS docs
341 // say that conversion routings return spacing accent character, not
342 // combining.
343 static const CharToVKEntry charToDeadVKTable[] = {
344     {L'`',   J_VK_DEAD_GRAVE},
345     {L'\'',  J_VK_DEAD_ACUTE},
346     {0x00B4, J_VK_DEAD_ACUTE},
347     {L'^',   J_VK_DEAD_CIRCUMFLEX},
348     {L'~',   J_VK_DEAD_TILDE},
349     {0x02DC, J_VK_DEAD_TILDE},
350     {0x00AF, J_VK_DEAD_MACRON},
351     {0x02D8, J_VK_DEAD_BREVE},
352     {0x02D9, J_VK_DEAD_ABOVEDOT},
353     {L'"',   J_VK_DEAD_DIAERESIS},
354     {0x00A8, J_VK_DEAD_DIAERESIS},
355     {0x02DA, J_VK_DEAD_ABOVERING},
356     {0x02DD, J_VK_DEAD_DOUBLEACUTE},
357     {0x02C7, J_VK_DEAD_CARON},            // aka hacek
358     {L',',   J_VK_DEAD_CEDILLA},
359     {0x00B8, J_VK_DEAD_CEDILLA},
360     {0x02DB, J_VK_DEAD_OGONEK},
361     {0x037A, J_VK_DEAD_IOTA},             // ASCII ???
362     {0x309B, J_VK_DEAD_VOICED_SOUND},
363     {0x309C, J_VK_DEAD_SEMIVOICED_SOUND},
364     {0,0}
365 };
366
367 // ANSI CP identifiers are no longer than this
368 #define MAX_ACP_STR_LEN 7
369
370 static void BuildDynamicKeyMapTable()
371 {
372     HKL hkl = GetKeyboardLayout(0);
373     // Will need this to reset layout after dead keys.
374     UINT spaceScanCode = MapVirtualKeyEx(VK_SPACE, 0, hkl);
375     DynamicKeyMapEntry *dynamic;
376
377     LANGID idLang = LOWORD(GetKeyboardLayout(0));
378     UINT codePage;
379     TCHAR strCodePage[MAX_ACP_STR_LEN];
380     // use the LANGID to create a LCID
381     LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
382     // get the ANSI code page associated with this locale
383     if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE,
384         strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
385     {
386         codePage = _ttoi(strCodePage);
387     } else {
388         codePage = GetACP();
389     }
390
391     // Entries in dynamic table that maps between Java VK and Windows
392     // VK are built in three steps:
393     //   1. Map windows VK to ANSI character (cannot map to unicode
394     //      directly, since ::ToUnicode is not implemented on win9x)
395     //   2. Convert ANSI char to Unicode char
396     //   3. Map Unicode char to Java VK via two auxilary tables.
397
398     for (dynamic = dynamicKeyMapTable; dynamic->windowsKey != 0; ++dynamic)
399     {
400         char cbuf[2] = { '\0', '\0'};
401         WCHAR ucbuf[2] = { L'\0', L'\0' };
402         int nchars;
403         UINT scancode;
404         const CharToVKEntry *charMap;
405         int nconverted;
406         WCHAR uc;
407         BYTE kbdState[256];
408
409         // Defaults to J_VK_UNDEFINED
410         dynamic->javaKey = J_VK_UNDEFINED;
411
412         GetKeyboardState(kbdState);
413
414         kbdState[dynamic->windowsKey] |=  0x80; // Press the key.
415
416         // Unpress modifiers, since they are most likely pressed as
417         // part of the keyboard switching shortcut.
418         kbdState[VK_CONTROL] &= ~0x80;
419         kbdState[VK_SHIFT]   &= ~0x80;
420         kbdState[VK_MENU]    &= ~0x80;
421
422         scancode = MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
423         nchars = ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
424                                  (WORD*)cbuf, 0, hkl);
425
426         // Auxiliary table used to map Unicode character to Java VK.
427         // Will assign a different table for dead keys (below).
428         charMap = charToVKTable;
429
430         if (nchars < 0) { // Dead key
431             char junkbuf[2] = { '\0', '\0'};
432             // Use a different table for dead chars since different layouts
433             // return different characters for the same dead key.
434             charMap = charToDeadVKTable;
435
436             // We also need to reset layout so that next translation
437             // is unaffected by the dead status.  We do this by
438             // translating <SPACE> key.
439             kbdState[dynamic->windowsKey] &= ~0x80;
440             kbdState[VK_SPACE] |= 0x80;
441
442             ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
443                       (WORD*)junkbuf, 0, hkl);
444         }
445
446         nconverted = MultiByteToWideChar(codePage, 0,
447                                          cbuf, 1, ucbuf, 2);
448
449         uc = ucbuf[0];
450         {
451             const CharToVKEntry *map;
452             for (map = charMap;  map->c != 0;  ++map) {
453                 if (uc == map->c) {
454                     dynamic->javaKey = map->javaKey;
455                     break;
456                 }
457             }
458         }
459
460     } // for each VK_OEM_*
461 }
462
463 // Really need to factor this out in to a separate run-time file
464 static jchar* GetNullTerminatedStringChars(JNIEnv* env, jstring str)
465 {
466     jchar* strChars = NULL;
467     strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
468     if (strChars != NULL) {
469         (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
470     }
471     return strChars;
472 }
473
474 static jint GetModifiers() {
475     jint modifiers = 0;
476     // have to do &0xFFFF to avoid runtime assert caused by compiling with
477     // /RTCcsu
478     if (HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0) {
479         modifiers |= EVENT_CTRL_MASK;
480     }
481     if (HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0) {
482         modifiers |= EVENT_SHIFT_MASK;
483     }
484     if (HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0) {
485         modifiers |= EVENT_ALT_MASK;
486     }
487     if (HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0) {
488         modifiers |= EVENT_BUTTON1_MASK;
489     }
490     if (HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0) {
491         modifiers |= EVENT_BUTTON2_MASK;
492     }
493     if (HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0) {
494         modifiers |= EVENT_BUTTON3_MASK;
495     }
496
497     return modifiers;
498 }
499
500 static int WmChar(JNIEnv *env, jobject window, UINT character, UINT repCnt,
501                   UINT flags, BOOL system)
502 {
503     // The Alt modifier is reported in the 29th bit of the lParam,
504     // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
505     BOOL alt_is_down = (flags & (1<<13)) != 0;
506     if (system && alt_is_down) {
507         if (character == VK_SPACE) {
508             return 1;
509         }
510     }
511
512     if (character == VK_RETURN) {
513         character = J_VK_ENTER;
514     }
515     (*env)->CallVoidMethod(env, window, sendKeyEventID,
516                            (jint) EVENT_KEY_TYPED,
517                            GetModifiers(),
518                            (jint) -1,
519                            (jchar) character);
520     return 1;
521 }
522
523 UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers)
524 {
525     int i, j;
526     // for the general case, use a bi-directional table
527     for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
528         if (keyMapTable[i].windowsKey == windowsKey) {
529             return keyMapTable[i].javaKey;
530         }
531     }
532     for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
533         if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
534             if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) {
535                 return dynamicKeyMapTable[j].javaKey;
536             } else {
537                 break;
538             }
539         }
540     }
541
542     return J_VK_UNDEFINED;
543 }
544
545 static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
546                      UINT flags, BOOL system)
547 {
548     UINT modifiers = 0, jkey = 0, character = -1;
549     if (wkey == VK_PROCESSKEY) {
550         return 1;
551     }
552
553     modifiers = GetModifiers();
554     jkey = WindowsKeyToJavaKey(wkey, modifiers);
555
556 /*
557     character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
558 */
559
560     (*env)->CallVoidMethod(env, window, sendKeyEventID,
561                            (jint) EVENT_KEY_PRESSED,
562                            modifiers,
563                            (jint) jkey,
564                            (jchar) character);
565
566     /* windows does not create a WM_CHAR for the Del key
567        for some reason, so we need to create the KEY_TYPED event on the
568        WM_KEYDOWN.
569      */
570     if (jkey == J_VK_DELETE) {
571         (*env)->CallVoidMethod(env, window, sendKeyEventID,
572                                (jint) EVENT_KEY_TYPED,
573                                GetModifiers(),
574                                (jint) -1,
575                                (jchar) '\177');
576     }
577
578     return 0;
579 }
580
581 static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
582                    UINT flags, BOOL system)
583 {
584     UINT modifiers = 0, jkey = 0, character = -1;
585     if (wkey == VK_PROCESSKEY) {
586         return 1;
587     }
588
589     modifiers = GetModifiers();
590     jkey = WindowsKeyToJavaKey(wkey, modifiers);
591 /*
592     character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
593 */
594
595     (*env)->CallVoidMethod(env, window, sendKeyEventID,
596                            (jint) EVENT_KEY_RELEASED,
597                            modifiers,
598                            (jint) jkey,
599                            (jchar) character);
600
601     return 0;
602 }
603
604 static RECT * UpdateInsets(JNIEnv *env, HWND hwnd, jobject window)
605 {
606     // being naughty here
607     static RECT m_insets = { 0, 0, 0, 0 };
608     RECT outside;
609     RECT inside;
610
611     if (IsIconic(hwnd)) {
612         m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = -1;
613         return FALSE;
614     }
615
616     m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0;
617
618     GetClientRect(hwnd, &inside);
619     GetWindowRect(hwnd, &outside);
620
621     if (outside.right - outside.left > 0 && outside.bottom - outside.top > 0) {
622         MapWindowPoints(hwnd, 0, (LPPOINT)&inside, 2);
623         m_insets.top = inside.top - outside.top;
624         m_insets.bottom = outside.bottom - inside.bottom;
625         m_insets.left = inside.left - outside.left;
626         m_insets.right = outside.right - inside.right;
627     } else {
628         m_insets.top = -1;
629     }
630     if (m_insets.left < 0 || m_insets.top < 0 ||
631         m_insets.right < 0 || m_insets.bottom < 0)
632     {
633         LONG style = GetWindowLong(hwnd, GWL_STYLE);
634         // TODO: TDV: better undecorated checking needed
635
636         BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP|WS_SYSMENU)) != 0;
637         if (!bIsUndecorated) {
638             /* Get outer frame sizes. */
639             if (style & WS_THICKFRAME) {
640                 m_insets.left = m_insets.right =
641                     GetSystemMetrics(SM_CXSIZEFRAME);
642                 m_insets.top = m_insets.bottom =
643                     GetSystemMetrics(SM_CYSIZEFRAME);
644             } else {
645                 m_insets.left = m_insets.right =
646                     GetSystemMetrics(SM_CXDLGFRAME);
647                 m_insets.top = m_insets.bottom =
648                     GetSystemMetrics(SM_CYDLGFRAME);
649             }
650
651             /* Add in title. */
652             m_insets.top += GetSystemMetrics(SM_CYCAPTION);
653         } else {
654             /* undo the -1 set above */
655             m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0;
656         }
657     }
658
659     DBG_PRINT("*** WindowsWindow: UpdateInsets window %p, %d/%d %dx%d\n", hwnd, 
660         m_insets.left, m_insets.top, m_insets.right-m_insets.left, m_insets.top-m_insets.bottom);
661
662     (*env)->CallVoidMethod(env, window, insetsChangedID,
663                            m_insets.left, m_insets.top,
664                            m_insets.right, m_insets.bottom);
665     return &m_insets;
666 }
667
668 static void WmSize(JNIEnv *env, HWND wnd, jobject window, UINT type)
669 {
670     RECT rc;
671     int w, h;
672
673     // make sure insets are up to date
674     (void)UpdateInsets(env, wnd, window);
675
676     if (type == SIZE_MINIMIZED) {
677         // TODO: deal with minimized window sizing
678         return;
679     }
680
681     GetClientRect(wnd, &rc);
682     
683     // we report back the dimensions of the client area
684     w = rc.right  - rc.left;
685     h = rc.bottom - rc.top;
686
687     (*env)->CallVoidMethod(env, window, sizeChangedID, w, h);
688 }
689
690 static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
691                                 WPARAM wParam, LPARAM lParam)
692 {
693     int useDefWindowProc = 0;
694     JNIEnv *env = NULL;
695     jobject window = NULL;
696     BOOL isKeyDown = FALSE;
697     WindowUserData * wud;
698
699 #if defined(UNDER_CE) || _MSC_VER <= 1200
700     wud = (WindowUserData *) GetWindowLong(wnd, GWL_USERDATA);
701 #else
702     wud = (WindowUserData *) GetWindowLongPtr(wnd, GWLP_USERDATA);
703 #endif
704     if(NULL==wud) {
705         return DefWindowProc(wnd, message, wParam, lParam);
706     }
707     env = wud->jenv;
708     window = wud->jinstance;
709
710     if (NULL==window || NULL==env) {
711         return DefWindowProc(wnd, message, wParam, lParam);
712     }
713
714     // DBG_PRINT("*** WindowsWindow: window %p -> %p, 0x%X %d/%d\n", wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
715
716     switch (message) {
717
718     //
719     // The signal pipeline for destruction is:
720     //    Java::DestroyWindow(wnd) _or_ window-close-button -> 
721     //     WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY -> Java::windowDestroyed ->
722     //       Java::CleanupWindowResources()
723     case WM_CLOSE:
724         (*env)->CallVoidMethod(env, window, windowDestroyNotifyID);
725         break;
726
727     case WM_DESTROY:
728         {
729 #if defined(UNDER_CE) || _MSC_VER <= 1200
730             SetWindowLong(wnd, GWL_USERDATA, (intptr_t) NULL);
731 #else
732             SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL);
733 #endif
734             free(wud); wud=NULL;
735             (*env)->CallVoidMethod(env, window, windowDestroyedID);
736             (*env)->DeleteGlobalRef(env, window);
737         }
738         break;
739
740     case WM_SYSCHAR:
741         useDefWindowProc = WmChar(env, window, wParam,
742                                   LOWORD(lParam), HIWORD(lParam), FALSE);
743         break;
744
745     case WM_CHAR:
746         useDefWindowProc = WmChar(env, window, wParam,
747                                   LOWORD(lParam), HIWORD(lParam), TRUE);
748         break;
749         
750     case WM_KEYDOWN:
751         useDefWindowProc = WmKeyDown(env, window, wParam,
752                                      LOWORD(lParam), HIWORD(lParam), FALSE);
753         break;
754
755     case WM_KEYUP:
756         useDefWindowProc = WmKeyUp(env, window, wParam,
757                                    LOWORD(lParam), HIWORD(lParam), FALSE);
758         break;
759
760     case WM_SIZE:
761         WmSize(env, wnd, window, (UINT)wParam);
762         break;
763
764     case WM_SETTINGCHANGE:
765         if (wParam == SPI_SETNONCLIENTMETRICS) {
766             // make sure insets are updated, we don't need to resize the window 
767             // because the size of the client area doesn't change
768             (void)UpdateInsets(env, wnd, window);
769         } else {
770             useDefWindowProc = 1;
771         }
772         break;
773
774
775     case WM_LBUTTONDOWN:
776         (*env)->CallVoidMethod(env, window, sendMouseEventID,
777                                (jint) EVENT_MOUSE_PRESSED,
778                                GetModifiers(),
779                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
780                                (jint) 1, (jint) 0);
781         useDefWindowProc = 1;
782         break;
783
784     case WM_LBUTTONUP:
785         (*env)->CallVoidMethod(env, window, sendMouseEventID,
786                                (jint) EVENT_MOUSE_RELEASED,
787                                GetModifiers(),
788                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
789                                (jint) 1, (jint) 0);
790         useDefWindowProc = 1;
791         break;
792
793     case WM_MBUTTONDOWN:
794         (*env)->CallVoidMethod(env, window, sendMouseEventID,
795                                (jint) EVENT_MOUSE_PRESSED,
796                                GetModifiers(),
797                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
798                                (jint) 2, (jint) 0);
799         useDefWindowProc = 1;
800         break;
801
802     case WM_MBUTTONUP:
803         (*env)->CallVoidMethod(env, window, sendMouseEventID,
804                                (jint) EVENT_MOUSE_RELEASED,
805                                GetModifiers(),
806                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
807                                (jint) 2, (jint) 0);
808         useDefWindowProc = 1;
809         break;
810
811     case WM_RBUTTONDOWN:
812         (*env)->CallVoidMethod(env, window, sendMouseEventID,
813                                (jint) EVENT_MOUSE_PRESSED,
814                                GetModifiers(),
815                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
816                                (jint) 3, (jint) 0);
817         useDefWindowProc = 1;
818         break;
819
820     case WM_RBUTTONUP:
821         (*env)->CallVoidMethod(env, window, sendMouseEventID,
822                                (jint) EVENT_MOUSE_RELEASED,
823                                GetModifiers(),
824                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
825                                (jint) 3,  (jint) 0);
826         useDefWindowProc = 1;
827         break;
828
829     case WM_MOUSEMOVE:
830         (*env)->CallVoidMethod(env, window, sendMouseEventID,
831                                (jint) EVENT_MOUSE_MOVED,
832                                GetModifiers(),
833                                (jint) LOWORD(lParam), (jint) HIWORD(lParam),
834                                (jint) 0,  (jint) 0);
835         useDefWindowProc = 1;
836         break;
837
838     case WM_MOUSEWHEEL: {
839         // need to convert the coordinates to component-relative
840         int x = GET_X_LPARAM(lParam);
841         int y = GET_Y_LPARAM(lParam);
842         POINT eventPt;
843         eventPt.x = x;
844         eventPt.y = y;
845         ScreenToClient(wnd, &eventPt);
846         (*env)->CallVoidMethod(env, window, sendMouseEventID,
847                                (jint) EVENT_MOUSE_WHEEL_MOVED,
848                                GetModifiers(),
849                                (jint) eventPt.x, (jint) eventPt.y,
850                                (jint) 0,  (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f));
851         useDefWindowProc = 1;
852         break;
853     }
854
855     case WM_SETFOCUS:
856         (*env)->CallVoidMethod(env, window, focusChangedID,
857                                (jlong)wParam, JNI_TRUE);
858         useDefWindowProc = 1;
859         break;
860
861     case WM_KILLFOCUS:
862         (*env)->CallVoidMethod(env, window, focusChangedID,
863                                (jlong)wParam, JNI_FALSE);
864         useDefWindowProc = 1;
865         break;
866
867     case WM_MOVE:
868         DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, (int)LOWORD(lParam), (int)HIWORD(lParam));
869         (*env)->CallVoidMethod(env, window, positionChangedID,
870                                (jint)LOWORD(lParam), (jint)HIWORD(lParam));
871         useDefWindowProc = 1;
872         break;
873
874     case WM_PAINT: {
875         RECT r;
876         if (GetUpdateRect(wnd, &r, FALSE)) {
877             if ((r.right-r.left) > 0 && (r.bottom-r.top) > 0) {
878                 (*env)->CallVoidMethod(env, window, sendPaintEventID,
879                                        0, r.left, r.top, r.right-r.left, r.bottom-r.top);
880             }
881             ValidateRect(wnd, &r);
882             useDefWindowProc = 0;
883         } else {
884             useDefWindowProc = 1;
885         }
886         break;
887     }
888     case WM_ERASEBKGND:
889         // ignore erase background
890         useDefWindowProc = 0;
891         break;
892
893
894     // FIXME: generate EVENT_MOUSE_ENTERED, EVENT_MOUSE_EXITED
895     default:
896         useDefWindowProc = 1;
897     }
898
899     if (useDefWindowProc)
900         return DefWindowProc(wnd, message, wParam, lParam);
901     return 0;
902 }
903
904 /*
905  * Class:     com_jogamp_javafx_newt_windows_WindowsDisplay
906  * Method:    DispatchMessages
907  * Signature: ()V
908  */
909 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsDisplay_DispatchMessages
910   (JNIEnv *env, jclass clazz)
911 {
912     int i = 0;
913     MSG msg;
914     BOOL gotOne;
915
916     // Periodically take a break
917     do {
918         gotOne = PeekMessage(&msg, (HWND) NULL, 0, 0, PM_REMOVE);
919         if (gotOne) {
920             ++i;
921             TranslateMessage(&msg);
922             DispatchMessage(&msg);
923         }
924     } while (gotOne && i < 100);
925 }
926
927 /*
928  * Class:     com_jogamp_javafx_newt_windows_WindowsDisplay
929  * Method:    LoadLibraryW
930  * Signature: (Ljava/lang/String;)J
931  */
932 JNIEXPORT jlong JNICALL Java_com_jogamp_javafx_newt_windows_WindowsDisplay_LoadLibraryW
933   (JNIEnv *env, jclass clazz, jstring dllName)
934 {
935     jchar* _dllName = GetNullTerminatedStringChars(env, dllName);
936     HMODULE lib = LoadLibraryW(_dllName);
937     free(_dllName);
938     return (jlong) (intptr_t) lib;
939 }
940
941 /*
942  * Class:     com_jogamp_javafx_newt_windows_WindowsDisplay
943  * Method:    RegisterWindowClass
944  * Signature: (Ljava/lang/String;J)I
945  */
946 JNIEXPORT jint JNICALL Java_com_jogamp_javafx_newt_windows_WindowsDisplay_RegisterWindowClass
947   (JNIEnv *env, jclass clazz, jstring wndClassName, jlong hInstance)
948 {
949     ATOM res;
950     WNDCLASS wc;
951 #ifndef UNICODE
952     const char* _wndClassName = NULL;
953 #endif
954
955     /* register class */
956     wc.style = CS_HREDRAW | CS_VREDRAW;
957     wc.lpfnWndProc = (WNDPROC)wndProc;
958     wc.cbClsExtra = 0;
959     wc.cbWndExtra = 0;
960     /* This cast is legal because the HMODULE for a DLL is the same as
961        its HINSTANCE -- see MSDN docs for DllMain */
962     wc.hInstance = (HINSTANCE) (intptr_t) hInstance;
963     wc.hIcon = NULL;
964     wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
965     wc.hbrBackground = GetStockObject(BLACK_BRUSH);
966     wc.lpszMenuName = NULL;
967 #ifdef UNICODE
968     wc.lpszClassName = GetNullTerminatedStringChars(env, wndClassName);
969 #else
970     _wndClassName = (*env)->GetStringUTFChars(env, wndClassName, NULL);
971     wc.lpszClassName = strdup(_wndClassName);
972     (*env)->ReleaseStringUTFChars(env, wndClassName, _wndClassName);
973 #endif
974     res = RegisterClass(&wc);
975
976     free((void *)wc.lpszClassName);
977
978     return (jint)res;
979 }
980
981 /*
982  * Class:     com_jogamp_javafx_newt_windows_WindowsDisplay
983  * Method:    CleanupWindowResources
984  * Signature: (java/lang/String;J)V
985  */
986 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsDisplay_UnregisterWindowClass
987   (JNIEnv *env, jclass clazz, jint wndClassAtom, jlong hInstance)
988 {
989     UnregisterClass(MAKEINTATOM(wndClassAtom), (HINSTANCE) (intptr_t) hInstance);
990 }
991
992 /*
993  * Class:     com_jogamp_javafx_newt_windows_WindowsScreen
994  * Method:    getWidthImpl
995  * Signature: (I)I
996  */
997 JNIEXPORT jint JNICALL Java_com_jogamp_javafx_newt_windows_WindowsScreen_getWidthImpl
998   (JNIEnv *env, jobject obj, jint scrn_idx)
999 {
1000     return (jint)GetSystemMetrics(SM_CXSCREEN);
1001 }
1002
1003 /*
1004  * Class:     com_jogamp_javafx_newt_windows_WindowsScreen
1005  * Method:    getWidthImpl
1006  * Signature: (I)I
1007  */
1008 JNIEXPORT jint JNICALL Java_com_jogamp_javafx_newt_windows_WindowsScreen_getHeightImpl
1009   (JNIEnv *env, jobject obj, jint scrn_idx)
1010 {
1011     return (jint)GetSystemMetrics(SM_CYSCREEN);
1012 }
1013
1014 /*
1015  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1016  * Method:    initIDs
1017  * Signature: ()Z
1018  */
1019 JNIEXPORT jboolean JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_initIDs
1020   (JNIEnv *env, jclass clazz)
1021 {
1022     sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V");
1023     insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(IIII)V");
1024     positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V");
1025     focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(JZ)V");
1026     windowDestroyNotifyID    = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V");
1027     windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V");
1028     sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
1029     sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
1030     sendPaintEventID = (*env)->GetMethodID(env, clazz, "sendPaintEvent", "(IIIII)V");
1031     if (sizeChangedID == NULL ||
1032         insetsChangedID == NULL ||
1033         positionChangedID == NULL ||
1034         focusChangedID == NULL ||
1035         windowDestroyNotifyID == NULL ||
1036         windowDestroyedID == NULL ||
1037         sendMouseEventID == NULL ||
1038         sendPaintEventID == NULL ||
1039         sendKeyEventID == NULL)
1040     {
1041         return JNI_FALSE;
1042     }
1043     BuildDynamicKeyMapTable();
1044     return JNI_TRUE;
1045 }
1046
1047 /*
1048  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1049  * Method:    CreateWindow
1050  * Signature: (JILjava/lang/String;JJZIIII)J
1051  */
1052 JNIEXPORT jlong JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_CreateWindow
1053   (JNIEnv *env, jobject obj, jlong parent, jint wndClassAtom, jstring jWndName, jlong hInstance, jlong visualID,
1054         jboolean bIsUndecorated,
1055         jint jx, jint jy, jint defaultWidth, jint defaultHeight)
1056 {
1057     HWND parentWindow = (HWND) (intptr_t) parent;
1058     const TCHAR* wndName = NULL;
1059     DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
1060     int x=(int)jx, y=(int)jy;
1061     int width=(int)defaultWidth, height=(int)defaultHeight;
1062     HWND window = NULL;
1063
1064 #ifdef UNICODE
1065     wndName = GetNullTerminatedStringChars(env, jWndName);
1066 #else
1067     wndName = (*env)->GetStringUTFChars(env, jWndName, NULL);
1068 #endif
1069
1070     if(NULL!=parentWindow) {
1071         windowStyle |= WS_CHILD ;
1072     } else if (bIsUndecorated) {
1073         windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
1074     } else {
1075         windowStyle |= WS_OVERLAPPEDWINDOW;
1076         x = CW_USEDEFAULT;
1077         y = 0;
1078     }
1079
1080     (void) visualID; // FIXME: use the visualID ..
1081
1082     window = CreateWindow(MAKEINTATOM(wndClassAtom), wndName, windowStyle,
1083                           x, y, width, height,
1084                           parentWindow, NULL,
1085                           (HINSTANCE) (intptr_t) hInstance,
1086                           NULL);
1087
1088     DBG_PRINT("*** WindowsWindow: CreateWindow parent %p, window %p, %d/%d %dx%d\n", parentWindow, window, x, y, width, height);
1089
1090     if (NULL != window) {
1091         WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData));
1092         wud->jinstance = (*env)->NewGlobalRef(env, obj);
1093         wud->jenv = env;
1094 #if defined(UNDER_CE) || _MSC_VER <= 1200
1095         SetWindowLong(window, GWL_USERDATA, (intptr_t) wud);
1096 #else
1097         SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) wud);
1098 #endif
1099
1100         UpdateInsets(env, window, obj);
1101
1102         ShowWindow(window, SW_SHOWNORMAL);
1103     }
1104
1105 #ifdef UNICODE
1106     free((void*) wndName);
1107 #else
1108     (*env)->ReleaseStringUTFChars(env, jWndName, wndName);
1109 #endif
1110
1111
1112     return (jlong) (intptr_t) window;
1113 }
1114
1115 /*
1116  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1117  * Method:    DestroyWindow
1118  * Signature: (J)V
1119  */
1120 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_DestroyWindow
1121   (JNIEnv *env, jobject obj, jlong window)
1122 {
1123     DestroyWindow((HWND) (intptr_t) window);
1124 }
1125
1126 /*
1127  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1128  * Method:    GetDC
1129  * Signature: (J)J
1130  */
1131 JNIEXPORT jlong JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_GetDC
1132   (JNIEnv *env, jobject obj, jlong window)
1133 {
1134     return (jlong) (intptr_t) GetDC((HWND) (intptr_t) window);
1135 }
1136
1137 /*
1138  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1139  * Method:    ReleaseDC
1140  * Signature: (JJ)V
1141  */
1142 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_ReleaseDC
1143   (JNIEnv *env, jobject obj, jlong window, jlong dc)
1144 {
1145     ReleaseDC((HWND) (intptr_t) window, (HDC) (intptr_t) dc);
1146 }
1147
1148 /*
1149  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1150  * Method:    MonitorFromWindow
1151  * Signature: (J)J
1152  */
1153 JNIEXPORT jlong JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_MonitorFromWindow
1154   (JNIEnv *env, jobject obj, jlong window)
1155 {
1156     #if (_WIN32_WINNT >= 0x0500 || _WIN32_WINDOWS >= 0x0410 || WINVER >= 0x0500) && !defined(_WIN32_WCE)
1157         return (jlong) (intptr_t) MonitorFromWindow((HWND) (intptr_t) window, MONITOR_DEFAULTTOPRIMARY);
1158     #else
1159         return 0;
1160     #endif
1161 }
1162
1163 /*
1164  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1165  * Method:    setVisible0
1166  * Signature: (JZ)V
1167  */
1168 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_setVisible0
1169   (JNIEnv *_env, jclass clazz, jlong window, jboolean visible)
1170 {
1171     HWND hWnd = (HWND) (intptr_t) window;
1172     DBG_PRINT("*** WindowsWindow: setVisible window %p, visible: %d\n", hWnd, (int)visible);
1173     if (visible) {
1174         ShowWindow(hWnd, SW_SHOW);
1175     } else {
1176         ShowWindow(hWnd, SW_HIDE);
1177     }
1178 }
1179
1180 /*
1181  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1182  * Method:    setSize0
1183  * Signature: (JII)V
1184  */
1185 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_setSize0
1186   (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height)
1187 {
1188     HWND hwndP = (HWND) (intptr_t) parent;
1189     HWND hwnd = (HWND) (intptr_t) window;
1190     int nWidth=width, nHeight=height;
1191     int nX=x, nY=y;
1192
1193     if(NULL==hwndP) {
1194         // since width, height are the size of the client area, we need to add
1195         // insets
1196         RECT *pInsets = UpdateInsets(env, hwnd, obj);
1197
1198         RECT r;
1199         GetWindowRect(hwnd, &r);
1200
1201         nWidth = width + pInsets->left + pInsets->right;
1202         nHeight = height + pInsets->top + pInsets->bottom;
1203         nX=r.left; nY=r.top; // FIXME: really ?
1204     }
1205
1206     DBG_PRINT("*** WindowsWindow: setSize parent %p, window %p, %d/%d %dx%d -> %d/%d %dx%d\n", 
1207         hwndP, hwnd, 
1208         x, y, width, height,
1209         nX, nY, nWidth, nHeight);
1210
1211     MoveWindow(hwnd, nX, nY, nWidth, nHeight, TRUE);
1212
1213     // we report back the size of client area
1214     (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height);
1215 }
1216
1217 /*
1218  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1219  * Method:    setPosition
1220  * Signature: (JII)V
1221  */
1222 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_setPosition
1223   (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y)
1224 {
1225     UINT flags = SWP_NOACTIVATE | SWP_NOSIZE;
1226     HWND hwndP = (HWND) (intptr_t) parent;
1227     HWND hwnd = (HWND) (intptr_t) window;
1228
1229     if(NULL==hwndP) {
1230         flags |= SWP_NOZORDER;
1231     }
1232
1233     DBG_PRINT("*** WindowsWindow: setPosition parent %p, window %p, %d/%d\n", hwndP, hwnd, x, y);
1234
1235     SetWindowPos(hwnd, hwndP, x, y, 0, 0, flags);
1236 }
1237
1238 /*
1239  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1240  * Method:    setFullscreen
1241  * Signature: (JIIIIZZ)V
1242  */
1243 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_setFullscreen0
1244   (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated, jboolean on)
1245 {
1246     UINT flags;
1247     HWND hwndP = (HWND) (intptr_t) parent;
1248     HWND hwnd = (HWND) (intptr_t) window;
1249     HWND hWndInsertAfter;
1250     DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
1251
1252     if(NULL!=hwndP) {
1253         windowStyle |= WS_CHILD ;
1254     } else if (bIsUndecorated || on) {
1255         windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
1256     } else {
1257         windowStyle |= WS_OVERLAPPEDWINDOW;
1258     }
1259     SetWindowLong(hwnd, GWL_STYLE, windowStyle);
1260
1261     if(on==JNI_TRUE) {
1262         flags = SWP_SHOWWINDOW;
1263         hWndInsertAfter = HWND_TOPMOST;
1264     } else {
1265         flags = SWP_NOACTIVATE | SWP_NOZORDER;
1266         hWndInsertAfter = 0;
1267     }
1268
1269     SetWindowPos(hwnd, hWndInsertAfter, x, y, width, height, flags);
1270
1271     (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height);
1272 }
1273
1274 /*
1275  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1276  * Method:    setTitle
1277  * Signature: (JLjava/lang/String;)V
1278  */
1279 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_setTitle
1280   (JNIEnv *env, jclass clazz, jlong window, jstring title)
1281 {
1282     HWND hwnd = (HWND) (intptr_t) window;
1283     if (title != NULL) {
1284         jchar *titleString = GetNullTerminatedStringChars(env, title);
1285         if (titleString != NULL) {
1286             SetWindowTextW(hwnd, titleString);
1287             free(titleString);
1288         }
1289     }
1290 }
1291
1292 /*
1293  * Class:     com_jogamp_javafx_newt_windows_WindowsWindow
1294  * Method:    requestFocus
1295  * Signature: (J)V
1296  */
1297 JNIEXPORT void JNICALL Java_com_jogamp_javafx_newt_windows_WindowsWindow_requestFocus
1298   (JNIEnv *env, jclass clazz, jlong window)
1299 {
1300     HWND hwnd = (HWND) (intptr_t) window;
1301
1302     if (IsWindow(hwnd)) {
1303         SetFocus(hwnd);
1304     }
1305 }
http://JogAmp.org git info: FAQ, tutorial and man pages.