summaryrefslogtreecommitdiffstats
path: root/src/newt/native
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/native')
-rw-r--r--src/newt/native/InputEvent.h31
-rw-r--r--src/newt/native/KDWindow.c12
-rw-r--r--src/newt/native/KeyEvent.h388
-rw-r--r--src/newt/native/MacWindow.m975
-rw-r--r--src/newt/native/NewtCommon.c99
-rw-r--r--src/newt/native/NewtCommon.h26
-rw-r--r--src/newt/native/NewtMacWindow.h126
-rw-r--r--src/newt/native/NewtMacWindow.m1267
-rw-r--r--src/newt/native/ScreenMode.h16
-rw-r--r--src/newt/native/Window.h17
-rw-r--r--src/newt/native/WindowsWindow.c2236
-rw-r--r--src/newt/native/X11Common.h5
-rw-r--r--src/newt/native/X11Display.c424
-rw-r--r--src/newt/native/X11Event.c305
-rw-r--r--src/newt/native/X11Event.h9
-rw-r--r--src/newt/native/X11RandR11.c371
-rw-r--r--src/newt/native/X11RandR13.c519
-rw-r--r--src/newt/native/X11Screen.c422
-rw-r--r--src/newt/native/X11Screen.h38
-rw-r--r--src/newt/native/X11Window.c366
-rw-r--r--src/newt/native/XCBEvent.c308
-rw-r--r--src/newt/native/XCBEvent.h10
-rw-r--r--src/newt/native/bcm_vc_iv.c373
-rw-r--r--src/newt/native/bcm_vc_iv.h130
24 files changed, 5805 insertions, 2668 deletions
diff --git a/src/newt/native/InputEvent.h b/src/newt/native/InputEvent.h
index 51c56c474..2de46f82e 100644
--- a/src/newt/native/InputEvent.h
+++ b/src/newt/native/InputEvent.h
@@ -38,15 +38,26 @@
#define EVENT_CTRL_MASK (1 << 1)
#define EVENT_META_MASK (1 << 2)
#define EVENT_ALT_MASK (1 << 3)
-#define EVENT_ALT_GRAPH_MASK (1 << 5)
-#define EVENT_BUTTON1_MASK (1 << 6)
-#define EVENT_BUTTON2_MASK (1 << 7)
-#define EVENT_BUTTON3_MASK (1 << 8)
-#define EVENT_BUTTON4_MASK (1 << 9)
-#define EVENT_BUTTON5_MASK (1 << 10)
-#define EVENT_BUTTON6_MASK (1 << 11)
-#define EVENT_AUTOREPEAT_MASK (1 << 15)
-#define EVENT_CONFINED_MASK (1 << 16)
-#define EVENT_INVISIBLE_MASK (1 << 17)
+#define EVENT_ALT_GRAPH_MASK (1 << 4)
+
+#define EVENT_BUTTON1_MASK (1 << 5)
+#define EVENT_BUTTON2_MASK (1 << 6)
+#define EVENT_BUTTON3_MASK (1 << 7)
+#define EVENT_BUTTON4_MASK (1 << 8)
+#define EVENT_BUTTON5_MASK (1 << 9)
+#define EVENT_BUTTON6_MASK (1 << 10)
+#define EVENT_BUTTON7_MASK (1 << 11)
+#define EVENT_BUTTON8_MASK (1 << 12)
+#define EVENT_BUTTON9_MASK (1 << 13)
+
+/** 16 buttons */
+#define EVENT_BUTTONLAST_MASK (1 << 20)
+
+/** 16 buttons */
+#define EVENT_BUTTONALL_MASK ( 0xffff << 5 )
+
+#define EVENT_AUTOREPEAT_MASK (1 << 29)
+#define EVENT_CONFINED_MASK (1 << 30)
+#define EVENT_INVISIBLE_MASK (1 << 31)
#endif
diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c
index f1d6aecdf..cfec60dc1 100644
--- a/src/newt/native/KDWindow.c
+++ b/src/newt/native/KDWindow.c
@@ -161,14 +161,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages
if(KD_INPUT_POINTER_SELECT==ptr->index) {
DBG_PRINT( "event mouse click: src: %p, s:%d, (%d,%d)\n", userData, ptr->select, ptr->x, ptr->y);
(*env)->CallVoidMethod(env, javaWindow, sendMouseEventID,
- (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED,
+ (ptr->select==0) ? (jshort) EVENT_MOUSE_RELEASED : (jshort) EVENT_MOUSE_PRESSED,
(jint) 0,
- (jint) ptr->x, (jint) ptr->y, 1, 0);
+ (jint) ptr->x, (jint) ptr->y, (short)1, 0.0f);
} else {
DBG_PRINT( "event mouse: src: %d, s:%p, i:0x%X (%d,%d)\n", userData, ptr->select, ptr->index, ptr->x, ptr->y);
- (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED,
0,
- (jint) ptr->x, (jint) ptr->y, 0, 0);
+ (jint) ptr->x, (jint) ptr->y, (jshort)0, 0.0f);
}
}
break;
@@ -193,8 +193,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_WindowDriver_initIDs
sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V");
if (windowCreatedID == NULL ||
sizeChangedID == NULL ||
visibleChangedID == NULL ||
diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h
index 0f7b1606b..c0a366a17 100644
--- a/src/newt/native/KeyEvent.h
+++ b/src/newt/native/KeyEvent.h
@@ -31,197 +31,203 @@
#define EVENT_KEY_PRESSED 300
#define EVENT_KEY_RELEASED 301
-#define EVENT_KEY_TYPED 302
-
-#define J_CHAR_UNDEFINED 0xFFFF;
-#define J_VK_ENTER '\n'
-#define J_VK_BACK_SPACE '\b'
-#define J_VK_TAB '\t'
-#define J_VK_CANCEL 0x03
-#define J_VK_CLEAR 0x0C
-#define J_VK_SHIFT 0x10
-#define J_VK_CONTROL 0x11
-#define J_VK_ALT 0x12
-#define J_VK_PAUSE 0x13
-#define J_VK_CAPS_LOCK 0x14
-#define J_VK_ESCAPE 0x1B
-#define J_VK_SPACE 0x20
-#define J_VK_PAGE_UP 0x21
-#define J_VK_PAGE_DOWN 0x22
-#define J_VK_END 0x23
-#define J_VK_HOME 0x24
-#define J_VK_LEFT 0x25
-#define J_VK_UP 0x26
-#define J_VK_RIGHT 0x27
-#define J_VK_DOWN 0x28
-#define J_VK_COMMA 0x2C
-#define J_VK_MINUS 0x2D
-#define J_VK_PERIOD 0x2E
-#define J_VK_SLASH 0x2F
-#define J_VK_0 0x30
-#define J_VK_1 0x31
-#define J_VK_2 0x32
-#define J_VK_3 0x33
-#define J_VK_4 0x34
-#define J_VK_5 0x35
-#define J_VK_6 0x36
-#define J_VK_7 0x37
-#define J_VK_8 0x38
-#define J_VK_9 0x39
-#define J_VK_SEMICOLON 0x3B
-#define J_VK_EQUALS 0x3D
-#define J_VK_A 0x41
-#define J_VK_B 0x42
-#define J_VK_C 0x43
-#define J_VK_D 0x44
-#define J_VK_E 0x45
-#define J_VK_F 0x46
-#define J_VK_G 0x47
-#define J_VK_H 0x48
-#define J_VK_I 0x49
-#define J_VK_J 0x4A
-#define J_VK_K 0x4B
-#define J_VK_L 0x4C
-#define J_VK_M 0x4D
-#define J_VK_N 0x4E
-#define J_VK_O 0x4F
-#define J_VK_P 0x50
-#define J_VK_Q 0x51
-#define J_VK_R 0x52
-#define J_VK_S 0x53
-#define J_VK_T 0x54
-#define J_VK_U 0x55
-#define J_VK_V 0x56
-#define J_VK_W 0x57
-#define J_VK_X 0x58
-#define J_VK_Y 0x59
-#define J_VK_Z 0x5A
-#define J_VK_OPEN_BRACKET 0x5B
-#define J_VK_BACK_SLASH 0x5C
-#define J_VK_CLOSE_BRACKET 0x5D
-#define J_VK_NUMPAD0 0x60
-#define J_VK_NUMPAD1 0x61
-#define J_VK_NUMPAD2 0x62
-#define J_VK_NUMPAD3 0x63
-#define J_VK_NUMPAD4 0x64
-#define J_VK_NUMPAD5 0x65
-#define J_VK_NUMPAD6 0x66
-#define J_VK_NUMPAD7 0x67
-#define J_VK_NUMPAD8 0x68
-#define J_VK_NUMPAD9 0x69
-#define J_VK_MULTIPLY 0x6A
-#define J_VK_ADD 0x6B
-#define J_VK_SEPARATOR 0x6C
-#define J_VK_SUBTRACT 0x6D
-#define J_VK_DECIMAL 0x6E
-#define J_VK_DIVIDE 0x6F
-#define J_VK_DELETE 0x7F /* ASCII DEL */
-#define J_VK_NUM_LOCK 0x90
-#define J_VK_SCROLL_LOCK 0x91
-#define J_VK_F1 0x70
-#define J_VK_F2 0x71
-#define J_VK_F3 0x72
-#define J_VK_F4 0x73
-#define J_VK_F5 0x74
-#define J_VK_F6 0x75
-#define J_VK_F7 0x76
-#define J_VK_F8 0x77
-#define J_VK_F9 0x78
-#define J_VK_F10 0x79
-#define J_VK_F11 0x7A
-#define J_VK_F12 0x7B
-#define J_VK_F13 0xF000
-#define J_VK_F14 0xF001
-#define J_VK_F15 0xF002
-#define J_VK_F16 0xF003
-#define J_VK_F17 0xF004
-#define J_VK_F18 0xF005
-#define J_VK_F19 0xF006
-#define J_VK_F20 0xF007
-#define J_VK_F21 0xF008
-#define J_VK_F22 0xF009
-#define J_VK_F23 0xF00A
-#define J_VK_F24 0xF00B
-#define J_VK_PRINTSCREEN 0x9A
-#define J_VK_INSERT 0x9B
-#define J_VK_HELP 0x9C
-#define J_VK_META 0x9D
-#define J_VK_BACK_QUOTE 0xC0
-#define J_VK_QUOTE 0xDE
-#define J_VK_KP_UP 0xE0
-#define J_VK_KP_DOWN 0xE1
-#define J_VK_KP_LEFT 0xE2
-#define J_VK_KP_RIGHT 0xE3
-#define J_VK_DEAD_GRAVE 0x80
-#define J_VK_DEAD_ACUTE 0x81
-#define J_VK_DEAD_CIRCUMFLEX 0x82
-#define J_VK_DEAD_TILDE 0x83
-#define J_VK_DEAD_MACRON 0x84
-#define J_VK_DEAD_BREVE 0x85
-#define J_VK_DEAD_ABOVEDOT 0x86
-#define J_VK_DEAD_DIAERESIS 0x87
-#define J_VK_DEAD_ABOVERING 0x88
-#define J_VK_DEAD_DOUBLEACUTE 0x89
-#define J_VK_DEAD_CARON 0x8a
-#define J_VK_DEAD_CEDILLA 0x8b
-#define J_VK_DEAD_OGONEK 0x8c
-#define J_VK_DEAD_IOTA 0x8d
-#define J_VK_DEAD_VOICED_SOUND 0x8e
-#define J_VK_DEAD_SEMIVOICED_SOUND 0x8f
-#define J_VK_AMPERSAND 0x96
-#define J_VK_ASTERISK 0x97
-#define J_VK_QUOTEDBL 0x98
-#define J_VK_LESS 0x99
-#define J_VK_GREATER 0xa0
-#define J_VK_BRACELEFT 0xa1
-#define J_VK_BRACERIGHT 0xa2
-#define J_VK_AT 0x0200
-#define J_VK_COLON 0x0201
-#define J_VK_CIRCUMFLEX 0x0202
-#define J_VK_DOLLAR 0x0203
-#define J_VK_EURO_SIGN 0x0204
-#define J_VK_EXCLAMATION_MARK 0x0205
-#define J_VK_INVERTED_EXCLAMATION_MARK 0x0206
-#define J_VK_LEFT_PARENTHESIS 0x0207
-#define J_VK_NUMBER_SIGN 0x0208
-#define J_VK_PLUS 0x0209
-#define J_VK_RIGHT_PARENTHESIS 0x020A
-#define J_VK_UNDERSCORE 0x020B
-#define J_VK_WINDOWS 0x020C
-#define J_VK_CONTEXT_MENU 0x020D
-#define J_VK_FINAL 0x0018
-#define J_VK_CONVERT 0x001C
-#define J_VK_NONCONVERT 0x001D
-#define J_VK_ACCEPT 0x001E
-#define J_VK_MODECHANGE 0x001F
-#define J_VK_KANA 0x0015
-#define J_VK_KANJI 0x0019
-#define J_VK_ALPHANUMERIC 0x00F0
-#define J_VK_KATAKANA 0x00F1
-#define J_VK_HIRAGANA 0x00F2
-#define J_VK_FULL_WIDTH 0x00F3
-#define J_VK_HALF_WIDTH 0x00F4
-#define J_VK_ROMAN_CHARACTERS 0x00F5
-#define J_VK_ALL_CANDIDATES 0x0100
-#define J_VK_PREVIOUS_CANDIDATE 0x0101
-#define J_VK_CODE_INPUT 0x0102
-#define J_VK_JAPANESE_KATAKANA 0x0103
-#define J_VK_JAPANESE_HIRAGANA 0x0104
-#define J_VK_JAPANESE_ROMAN 0x0105
-#define J_VK_KANA_LOCK 0x0106
-#define J_VK_INPUT_METHOD_ON_OFF 0x0107
-#define J_VK_CUT 0xFFD1
-#define J_VK_COPY 0xFFCD
-#define J_VK_PASTE 0xFFCF
-#define J_VK_UNDO 0xFFCB
-#define J_VK_AGAIN 0xFFC9
-#define J_VK_FIND 0xFFD0
-#define J_VK_PROPS 0xFFCA
-#define J_VK_STOP 0xFFC8
-#define J_VK_COMPOSE 0xFF20
-#define J_VK_ALT_GRAPH 0xFF7E
-#define J_VK_BEGIN 0xFF58
-#define J_VK_UNDEFINED 0x0
+
+#define J_VK_UNDEFINED ( 0x0U )
+#define J_VK_HOME ( 0x02U )
+#define J_VK_END ( 0x03U )
+#define J_VK_FINAL ( 0x04U )
+#define J_VK_PRINTSCREEN ( 0x05U )
+#define J_VK_BACK_SPACE ( 0x08U )
+#define J_VK_TAB ( 0x09U )
+#define J_VK_PAGE_DOWN ( 0x0BU )
+#define J_VK_CLEAR ( 0x0CU )
+#define J_VK_ENTER ( 0x0DU )
+#define J_VK_SHIFT ( 0x0FU )
+#define J_VK_PAGE_UP ( 0x10U )
+#define J_VK_CONTROL ( 0x11U )
+#define J_VK_ALT ( 0x12U )
+#define J_VK_ALT_GRAPH ( 0x13U )
+#define J_VK_CAPS_LOCK ( 0x14U )
+#define J_VK_PAUSE ( 0x16U )
+#define J_VK_SCROLL_LOCK ( 0x17U )
+#define J_VK_CANCEL ( 0x18U )
+#define J_VK_INSERT ( 0x1AU )
+#define J_VK_ESCAPE ( 0x1BU )
+#define J_VK_CONVERT ( 0x1CU )
+#define J_VK_NONCONVERT ( 0x1DU )
+#define J_VK_ACCEPT ( 0x1EU )
+#define J_VK_MODECHANGE ( 0x1FU )
+
+//
+// Unicode: Printable [0x20 - 0x7E]
+//
+
+#define J_VK_SPACE ( 0x20U )
+#define J_VK_EXCLAMATION_MARK ( 0x21U )
+#define J_VK_QUOTEDBL ( 0x22U )
+#define J_VK_NUMBER_SIGN ( 0x23U )
+#define J_VK_DOLLAR ( 0x24U )
+#define J_VK_PERCENT ( 0x25U )
+#define J_VK_AMPERSAND ( 0x26U )
+#define J_VK_QUOTE ( 0x27U )
+#define J_VK_LEFT_PARENTHESIS ( 0x28U )
+#define J_VK_RIGHT_PARENTHESIS ( 0x29U )
+#define J_VK_ASTERISK ( 0x2AU )
+#define J_VK_PLUS ( 0x2BU )
+#define J_VK_COMMA ( 0x2CU )
+#define J_VK_MINUS ( 0x2DU )
+#define J_VK_PERIOD ( 0x2EU )
+#define J_VK_SLASH ( 0x2FU )
+#define J_VK_0 ( 0x30U )
+#define J_VK_1 ( 0x31U )
+#define J_VK_2 ( 0x32U )
+#define J_VK_3 ( 0x33U )
+#define J_VK_4 ( 0x34U )
+#define J_VK_5 ( 0x35U )
+#define J_VK_6 ( 0x36U )
+#define J_VK_7 ( 0x37U )
+#define J_VK_8 ( 0x38U )
+#define J_VK_9 ( 0x39U )
+#define J_VK_COLON ( 0x3AU )
+#define J_VK_SEMICOLON ( 0x3BU )
+#define J_VK_LESS ( 0x3CU )
+#define J_VK_EQUALS ( 0x3DU )
+#define J_VK_GREATER ( 0x3EU )
+#define J_VK_QUESTIONMARK ( 0x3FU )
+#define J_VK_AT ( 0x40U )
+#define J_VK_A ( 0x41U )
+#define J_VK_B ( 0x42U )
+#define J_VK_C ( 0x43U )
+#define J_VK_D ( 0x44U )
+#define J_VK_E ( 0x45U )
+#define J_VK_F ( 0x46U )
+#define J_VK_G ( 0x47U )
+#define J_VK_H ( 0x48U )
+#define J_VK_I ( 0x49U )
+#define J_VK_J ( 0x4AU )
+#define J_VK_K ( 0x4BU )
+#define J_VK_L ( 0x4CU )
+#define J_VK_M ( 0x4DU )
+#define J_VK_N ( 0x4EU )
+#define J_VK_O ( 0x4FU )
+#define J_VK_P ( 0x50U )
+#define J_VK_Q ( 0x51U )
+#define J_VK_R ( 0x52U )
+#define J_VK_S ( 0x53U )
+#define J_VK_T ( 0x54U )
+#define J_VK_U ( 0x55U )
+#define J_VK_V ( 0x56U )
+#define J_VK_W ( 0x57U )
+#define J_VK_X ( 0x58U )
+#define J_VK_Y ( 0x59U )
+#define J_VK_Z ( 0x5AU )
+#define J_VK_OPEN_BRACKET ( 0x5BU )
+#define J_VK_BACK_SLASH ( 0x5CU )
+#define J_VK_CLOSE_BRACKET ( 0x5DU )
+#define J_VK_CIRCUMFLEX ( 0x5EU )
+#define J_VK_UNDERSCORE ( 0x5FU )
+#define J_VK_BACK_QUOTE ( 0x60U )
+#define J_VK_F1 ( 0x60U+ 1U )
+#define J_VK_F2 ( 0x60U+ 2U )
+#define J_VK_F3 ( 0x60U+ 3U )
+#define J_VK_F4 ( 0x60U+ 4U )
+#define J_VK_F5 ( 0x60U+ 5U )
+#define J_VK_F6 ( 0x60U+ 6U )
+#define J_VK_F7 ( 0x60U+ 7U )
+#define J_VK_F8 ( 0x60U+ 8U )
+#define J_VK_F9 ( 0x60U+ 9U )
+#define J_VK_F10 ( 0x60U+10U )
+#define J_VK_F11 ( 0x60U+11U )
+#define J_VK_F12 ( 0x60U+12U )
+#define J_VK_F13 ( 0x60U+13U )
+#define J_VK_F14 ( 0x60U+14U )
+#define J_VK_F15 ( 0x60U+15U )
+#define J_VK_F16 ( 0x60U+16U )
+#define J_VK_F17 ( 0x60U+17U )
+#define J_VK_F18 ( 0x60U+18U )
+#define J_VK_F19 ( 0x60U+19U )
+#define J_VK_F20 ( 0x60U+20U )
+#define J_VK_F21 ( 0x60U+21U )
+#define J_VK_F22 ( 0x60U+22U )
+#define J_VK_F23 ( 0x60U+23U )
+#define J_VK_F24 ( 0x60U+24U )
+#define J_VK_LEFT_BRACE ( 0x7BU )
+#define J_VK_PIPE ( 0x7CU )
+#define J_VK_RIGHT_BRACE ( 0x7DU )
+#define J_VK_TILDE ( 0x7EU )
+
+//
+// Unicode: Non printable controls: [0x7F - 0x9F]
+//
+
+#define J_VK_SEPARATOR ( 0x7FU )
+#define J_VK_NUMPAD0 ( 0x80U )
+#define J_VK_NUMPAD1 ( 0x81U )
+#define J_VK_NUMPAD2 ( 0x82U )
+#define J_VK_NUMPAD3 ( 0x83U )
+#define J_VK_NUMPAD4 ( 0x84U )
+#define J_VK_NUMPAD5 ( 0x85U )
+#define J_VK_NUMPAD6 ( 0x86U )
+#define J_VK_NUMPAD7 ( 0x87U )
+#define J_VK_NUMPAD8 ( 0x88U )
+#define J_VK_NUMPAD9 ( 0x89U )
+#define J_VK_DECIMAL ( 0x8AU )
+#define J_VK_ADD ( 0x8BU )
+#define J_VK_SUBTRACT ( 0x8CU )
+#define J_VK_MULTIPLY ( 0x8DU )
+#define J_VK_DIVIDE ( 0x8EU )
+
+#define J_VK_DELETE ( 0x93U )
+#define J_VK_NUM_LOCK ( 0x94U )
+#define J_VK_LEFT ( 0x95U )
+#define J_VK_UP ( 0x96U )
+#define J_VK_RIGHT ( 0x97U )
+#define J_VK_DOWN ( 0x98U )
+#define J_VK_CONTEXT_MENU ( 0x99U )
+#define J_VK_WINDOWS ( 0x9AU )
+#define J_VK_META ( 0x9BU )
+#define J_VK_HELP ( 0x9CU )
+#define J_VK_COMPOSE ( 0x9DU )
+#define J_VK_BEGIN ( 0x9EU )
+#define J_VK_STOP ( 0x9FU )
+
+//
+// Unicode: Printable [0x00A0 - 0xDFFF]
+//
+
+#define J_VK_INVERTED_EXCLAMATION_MARK ( 0xA1U )
+#define J_VK_EURO_SIGN ( 0x20ACU )
+
+//
+// Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+//
+
+/* for Sun keyboards */
+#define J_VK_CUT ( 0xF879U )
+#define J_VK_COPY ( 0xF87AU )
+#define J_VK_PASTE ( 0xF87BU )
+#define J_VK_UNDO ( 0xF87CU )
+#define J_VK_AGAIN ( 0xF87DU )
+#define J_VK_FIND ( 0xF87EU )
+#define J_VK_PROPS ( 0xF87FU )
+
+/* for input method support on Asian Keyboards */
+#define J_VK_INPUT_METHOD_ON_OFF ( 0xF890U )
+#define J_VK_CODE_INPUT ( 0xF891U )
+#define J_VK_ROMAN_CHARACTERS ( 0xF892U )
+#define J_VK_ALL_CANDIDATES ( 0xF893U )
+#define J_VK_PREVIOUS_CANDIDATE ( 0xF894U )
+#define J_VK_ALPHANUMERIC ( 0xF895U )
+#define J_VK_KATAKANA ( 0xF896U )
+#define J_VK_HIRAGANA ( 0xF897U )
+#define J_VK_FULL_WIDTH ( 0xF898U )
+#define J_VK_HALF_WIDTH ( 0xF89AU )
+#define J_VK_JAPANESE_KATAKANA ( 0xF89BU )
+#define J_VK_JAPANESE_HIRAGANA ( 0xF89CU )
+#define J_VK_JAPANESE_ROMAN ( 0xF89DU )
+#define J_VK_KANA_LOCK ( 0xF89FU )
+
+#define J_VK_KEYBOARD_INVISIBLE ( 0xF8FFU )
#endif
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index b9c339285..2bd11da3c 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -62,12 +62,36 @@ static NSString* jstringToNSString(JNIEnv* env, jstring jstr)
return str;
}
-static void setFrameTopLeftPoint(NSWindow* pWin, NewtMacWindow* mWin, jint x, jint y) {
- NSPoint pS = [mWin newtScreenWinPos2OSXScreenPos: NSMakePoint(x, y)];
+static void setWindowClientTopLeftPoint(NewtMacWindow* mWin, jint x, jint y, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPoint.0 - window: %p %d/%d, display %d\n", mWin, (int)x, (int)y, (int)doDisplay);
+ NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)];
+ DBG_PRINT( "setWindowClientTopLeftPoint.1: %d/%d\n", (int)pS.x, (int)pS.y);
+
[mWin setFrameOrigin: pS];
+ DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y);
+
+ if( doDisplay ) {
+ NSView* mView = [mWin contentView];
+ [mWin invalidateCursorRectsForView: mView];
+ }
+}
- NSView* mView = [mWin contentView];
- [mWin invalidateCursorRectsForView: mView];
+static void setWindowClientTopLeftPointAndSize(NewtMacWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d, display %d\n", mWin, (int)x, (int)y, (int)width, (int)height, (int)doDisplay);
+ NSSize clientSZ = NSMakeSize(width, height);
+ NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: clientSZ];
+ NSSize topSZ = [mWin newtClientSize2TLSize: clientSZ];
+ NSRect rect = { pS, topSZ };
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.1: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+ [mWin setFrame: rect display:doDisplay];
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+ // -> display:YES
+ // if( doDisplay ) {
+ // NSView* mView = [mWin contentView];
+ // [mWin invalidateCursorRectsForView: mView];
+ // }
}
#ifdef VERBOSE_ON
@@ -76,22 +100,38 @@ static int getRetainCount(NSObject * obj) {
}
#endif
-static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView) {
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtView *view, BOOL enable) {
+ DBG_PRINT( "setJavaWindowObject.0: View %p\n", view);
+ if( !enable) {
+ jobject globJavaWindowObject = [view getJavaWindowObject];
+ if( NULL != globJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.1: View %p - Clear old javaWindowObject %p\n", view, globJavaWindowObject);
+ (*env)->DeleteGlobalRef(env, globJavaWindowObject);
+ [view setJavaWindowObject: NULL];
+ }
+ } else if( NULL != newJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject);
+ jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject);
+ [view setJavaWindowObject: globJavaWindowObject];
+ }
+ DBG_PRINT( "setJavaWindowObject.X: View %p\n", view);
+}
+
+static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView, BOOL setJavaWindow) {
NSView* oldNSView = [win contentView];
- NewtView* oldView = NULL;
+ NewtView* oldNewtView = NULL;
#ifdef VERBOSE_ON
int dbgIdx = 1;
#endif
- if( [oldNSView isMemberOfClass:[NewtView class]] ) {
- oldView = (NewtView *) oldNSView;
+ if( [oldNSView isKindOfClass:[NewtView class]] ) {
+ oldNewtView = (NewtView *) oldNSView;
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d), parent view %p\n",
- dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView), pview);
+ dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView), pview);
- if(NULL!=oldNSView) {
+ if( NULL!=oldNSView ) {
NS_DURING
// Available >= 10.5 - Makes the menubar disapear
BOOL iifs;
@@ -106,34 +146,21 @@ NS_DURING
NS_HANDLER
NS_ENDHANDLER
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d)\n",
- dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView));
- if( NULL != oldView ) {
- jobject globJavaWindowObject = [oldView getJavaWindowObject];
- (*env)->DeleteGlobalRef(env, globJavaWindowObject);
- [oldView setJavaWindowObject: NULL];
- [oldView setDestroyNotifySent: false];
+ if( NULL != oldNewtView ) {
+ [oldNewtView setDestroyNotifySent: false];
+ setJavaWindowObject(env, NULL, oldNewtView, NO);
}
[oldNSView removeFromSuperviewWithoutNeedingDisplay];
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n",
dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
- if(NULL!=newView) {
- jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject);
- [newView setJavaWindowObject: globJavaWindowObject];
+ if( NULL!=newView ) {
[newView setDestroyNotifySent: false];
- {
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
- [newView setJVMHandle: jvmHandle];
- [newView setJVMVersion: jvmVersion];
+ if( setJavaWindow ) {
+ setJavaWindowObject(env, javaWindowObject, newView, YES);
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d)\n",
@@ -152,12 +179,10 @@ NS_ENDHANDLER
dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
// make sure the insets are updated in the java object
- [win updateInsets: env];
+ [win updateInsets: env jwin:javaWindowObject];
DBG_PRINT( "changeContentView.X win %p, view (%p,%d -> %p,%d)\n",
win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView));
-
- [pool release];
}
/*
@@ -173,6 +198,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_initNSAp
if(initialized) return JNI_TRUE;
initialized = 1;
+ NewtCommon_init(env);
+
// 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
@@ -248,50 +275,151 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplic
[pool release];
}
-static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) {
- NSArray *screens = [NSScreen screens];
- if(screen_idx<0) screen_idx=0;
- if(screen_idx>=[screens count]) screen_idx=0;
- return (NSScreen *) [screens objectAtIndex: screen_idx];
+static NSImage * createNSImageFromData(JNIEnv *env, unsigned char * iconData, jint jiconWidth, jint jiconHeight) {
+ if( NULL != iconData ) {
+ NSInteger iconWidth = (NSInteger) jiconWidth;
+ NSInteger iconHeight = (NSInteger) jiconHeight;
+ const NSInteger bpc = 8 /* bits per component */, spp=4 /* RGBA */, bpp = bpc * spp;
+ const NSBitmapFormat bfmt = NSAlphaNonpremultipliedBitmapFormat;
+ const BOOL hasAlpha = YES;
+
+ NSBitmapImageRep* bir = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: &iconData
+ pixelsWide: iconWidth
+ pixelsHigh: iconHeight
+ bitsPerSample: bpc
+ samplesPerPixel: spp
+ hasAlpha: hasAlpha
+ isPlanar: NO
+ colorSpaceName: NSCalibratedRGBColorSpace
+ bitmapFormat: bfmt
+ bytesPerRow: iconWidth*4
+ bitsPerPixel: bpp];
+ [bir autorelease];
+ NSImage* nsImage = [[NSImage alloc] initWithCGImage: [bir CGImage] size:NSZeroSize];
+ return nsImage;
+ }
+ return NULL;
}
/*
- * Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: getWidthImpl
- * Signature: (I)I
+ * Class: jogamp_newt_driver_macosx_DisplayDriver
+ * Method: setAppIcon0
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getWidthImpl0
- (JNIEnv *env, jclass clazz, jint screen_idx)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height)
{
+ if( 0 == pixels ) {
+ return;
+ }
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx);
- NSRect rect = [screen frame];
-
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
+ if( NULL != nsImage ) {
+ [nsImage autorelease];
+ [NSApp setApplicationIconImage: nsImage];
+ }
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
[pool release];
+}
- return (jint) (rect.size.width);
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
+{
+ if( 0 == pixels ) {
+ return 0;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
+ NSCursor * res = NULL;
+ if( NULL != nsImage ) {
+ [nsImage autorelease];
+ NSPoint hotP = { hotX, hotY };
+ res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP];
+ }
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+ [pool release];
+ DBG_PRINT( "createPointerIcon0 %p\n", res);
+ return (jlong) (intptr_t) res;
}
-/*
- * Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: getHeightImpl
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getHeightImpl0
- (JNIEnv *env, jclass clazz, jint screen_idx)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPointerIcon0
+ (JNIEnv *env, jobject unused, jlong handle)
{
+ NSCursor * c = (NSCursor*) (intptr_t) handle ;
+ if( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c);
+ return;
+ }
+ DBG_PRINT( "destroyPointerIcon0 %p\n", c);
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [c release];
+ [pool release];
+}
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx);
- NSRect rect = [screen frame];
+NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap) {
+ NSArray *screens = [NSScreen screens];
+ if( screen_idx<0 || screen_idx>=[screens count] ) {
+ if( cap ) {
+ screen_idx=0;
+ } else {
+ return NULL;
+ }
+ }
+ return (NSScreen *) [screens objectAtIndex: screen_idx];
+}
- [pool release];
+NSScreen * NewtScreen_getNSScreenByCoord(int x, int y) {
+ NSArray *screens = [NSScreen screens];
+ int i;
+ for(i=[screens count]-1; i>=0; i--) {
+ NSScreen * screen = (NSScreen *) [screens objectAtIndex: i];
+ NSRect frame = [screen frame];
+ if( x >= frame.origin.x &&
+ y >= frame.origin.y &&
+ x < frame.origin.x + frame.size.width &&
+ y < frame.origin.y + frame.size.height ) {
+ return screen;
+ }
+ }
+ return (NSScreen *) [screens objectAtIndex: 0];
+}
- return (jint) (rect.size.height);
+static void NewtScreen_dump() {
+#ifdef VERBOSE_ON
+ NSArray *screens = [NSScreen screens];
+ int i;
+ for(i=0; i<[screens count]; i++) {
+ NSScreen * screen = (NSScreen *) [screens objectAtIndex: i];
+ NSRect screenFrame = [screen frame];
+ NSRect screenVisibleFrame = [screen visibleFrame];
+ CGFloat pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+ NSWindowDepth depth = [screen depth]; // an (int) value!
+ DBG_PRINT( "NSScreen #%d (%p): Frame %lf/%lf %lfx%lf (vis %lf/%lf %lfx%lf), scale %lf, depth %d\n",
+ i, screen,
+ screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height,
+ screenVisibleFrame.origin.x, screenVisibleFrame.origin.y, screenVisibleFrame.size.width, screenVisibleFrame.size.height,
+ pixelScale, depth);
+ }
+#endif
}
-static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
+
+CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
// Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
NSDictionary * dict = [screen deviceDescription];
NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
@@ -325,11 +453,25 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key)
/*
* Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: getScreenSizeMM0
+ * Method: getMonitorCount0
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorCount0
+ (JNIEnv *env, jobject obj)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSArray *screens = [NSScreen screens];
+ [pool release];
+ return (jint) [screens count];
+}
+
+/*
+ * Class: jogamp_newt_driver_macosx_ScreenDriver
+ * Method: getMonitorProps0
* Signature: (I)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenSizeMM0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorProps0
+ (JNIEnv *env, jobject obj, jint crt_idx)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -339,33 +481,58 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
timespec_now(&t0);
#endif
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.1: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL);
#endif
-
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.2: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL);
#endif
- CGSize screenDim = CGDisplayScreenSize(display);
+ CGSize sizeMM = CGDisplayScreenSize(display);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.3: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.3: %ld ms\n", td_ms); fflush(NULL);
#endif
- jint prop[ 2 ];
- prop[0] = (jint) screenDim.width;
- prop[1] = (jint) screenDim.height;
+ CGRect dBounds = CGDisplayBounds (display); // origin top-left
+#ifdef VERBOSE_ON
+ BOOL usesGL = CGDisplayUsesOpenGLAcceleration(display);
+ NSRect sFrame = [screen frame]; // origin bottom-left
+ DBG_PRINT( "getMonitorProps0: scrn %d, top-left displayBounds[%d/%d %dx%d], bottom-left screenFrame[%d/%d %dx%d], usesGL %d\n", (int)crt_idx,
+ (int)dBounds.origin.x, (int)dBounds.origin.y, (int)dBounds.size.width, (int)dBounds.size.height,
+ (int)sFrame.origin.x, (int)sFrame.origin.y, (int)sFrame.size.width, (int)sFrame.size.height,
+ (int)usesGL);
+#endif
- jintArray properties = (*env)->NewIntArray(env, 2);
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+ jint prop[ propCount ];
+ int offset = 0;
+ prop[offset++] = propCount;
+ prop[offset++] = crt_idx;
+ prop[offset++] = (jint) sizeMM.width;
+ prop[offset++] = (jint) sizeMM.height;
+ prop[offset++] = (jint) dBounds.origin.x; // rotated viewport x (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.y; // rotated viewport y (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.width; // rotated viewport width (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.height; // rotated viewport height (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.x; // rotated viewport x (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.y; // rotated viewport y (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.width; // rotated viewport width (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.height; // rotated viewport height (window units, will be fixed in java code)
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
}
- (*env)->SetIntArrayRegion(env, properties, 0, 2, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
[pool release];
@@ -374,16 +541,26 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
/*
* Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: getScreenMode0
- * Signature: (IIII)[I
+ * Method: getMonitorMode0
+ * Signature: (II)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenMode0
- (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorMode0
+ (JNIEnv *env, jobject obj, jint crt_idx, jint mode_idx)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
+ CGFloat pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
CFArrayRef availableModes = CGDisplayAvailableModes(display);
@@ -392,12 +569,13 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
CFDictionaryRef mode = NULL;
int currentCCWRot = (int)CGDisplayRotation(display);
jint ccwRot = 0;
+ int nativeId = 0;
#ifdef VERBOSE_ON
if(0 >= mode_idx) {
// only for current mode (-1) and first mode (scanning)
- DBG_PRINT( "getScreenMode0: scrn %d (%p, %p), mode %d, avail: %d/%d, current rot %d ccw\n",
- (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
+ DBG_PRINT( "getScreenMode0: scrn %d (s %p, d %p, pscale %lf), mode %d, avail: %d/%d, current rot %d ccw\n",
+ (int)crt_idx, screen, (void*)(intptr_t)display, pixelScale, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
}
#endif
@@ -406,21 +584,27 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n",
(int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
[pool release];
- return (*env)->NewIntArray(env, 0);
+ return NULL;
} else if(-1 < mode_idx) {
// only at initialization time, where index >= 0
- prop_num++; // add 1st extra prop, mode_idx
- mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
+ nativeId = mode_idx / ROTMODES_PER_REALMODE;
ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
+ mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId);
} else {
// current mode
mode = CGDisplayCurrentMode(display);
ccwRot = currentCCWRot;
+ CFRange range = CFRangeMake (0, numberOfAvailableModes);
+ nativeId = CFArrayGetFirstIndexOfValue(availableModes, range, (CFDictionaryRef)mode);
}
// mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
int mWidth = CGDDGetModeWidth(mode);
int mHeight = CGDDGetModeHeight(mode);
+ if( -1 == mode_idx ) {
+ mWidth *= (int)pixelScale; // accomodate HiDPI
+ mHeight *= (int)pixelScale; // accomodate HiDPI
+ }
// swap width and height, since OSX reflects rotated dimension, we don't
if ( 90 == currentCCWRot || 270 == currentCCWRot ) {
@@ -429,36 +613,30 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
mHeight = tempWidth;
}
- jint prop[ prop_num ];
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
int propIndex = 0;
- int propIndexRes = 0;
- if( -1 < mode_idx ) {
- prop[propIndex++] = mode_idx;
- }
int refreshRate = CGDDGetModeRefreshRate(mode);
int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8)
- prop[propIndex++] = 0; // set later for verification of iterator
- propIndexRes = propIndex;
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
prop[propIndex++] = mWidth;
prop[propIndex++] = mHeight;
prop[propIndex++] = CGDDGetModeBitsPerPixel(mode);
- prop[propIndex++] = widthMM;
- prop[propIndex++] = heightMM;
- prop[propIndex++] = fRefreshRate;
+ prop[propIndex++] = fRefreshRate * 100; // Hz*100
+ prop[propIndex++] = 0; // flags
+ prop[propIndex++] = nativeId;
prop[propIndex++] = ccwRot;
- prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
-
- DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d / %d Hz, rot %d ccw\n",
+
+ DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %d / %d Hz, nativeId %d, rot %d ccw\n",
(int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes,
- (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2],
- (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], refreshRate, (int)prop[propIndexRes+6]);
+ (int)prop[1], (int)prop[2], (int)prop[3],
+ (int)prop[4], refreshRate, (int)prop[6], (int)prop[7]);
- jintArray properties = (*env)->NewIntArray(env, prop_num);
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
}
- (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
// CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef
[pool release];
@@ -468,36 +646,47 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
/*
* Class: jogamp_newt_driver_macosx_ScreenDriver
- * Method: setScreenMode0
- * Signature: (II)Z
+ * Method: setMonitorMode0
+ * Signature: (III)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setScreenMode0
- (JNIEnv *env, jobject object, jint scrn_idx, jint mode_idx)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setMonitorMode0
+ (JNIEnv *env, jobject object, jint crt_idx, jint nativeId, jint ccwRot)
{
jboolean res = JNI_TRUE;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return JNI_FALSE;
+ }
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
CFArrayRef availableModes = CGDisplayAvailableModes(display);
-#ifdef VERBOSE_ON
CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes);
+#ifdef VERBOSE_ON
CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes;
#endif
- CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
- // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
- int ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
- DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), mode %d, rot %d ccw, avail: %d/%d\n",
- (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+ DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), nativeID %d, rot %d ccw, avail: %d/%d\n",
+ (int)crt_idx, screen, (void*)(intptr_t)display, (int)nativeId, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+
+ CFDictionaryRef mode = NULL;
- if(ccwRot!=0) {
+ if( 0 != ccwRot ) {
// FIXME: How to rotate the display/screen on OSX programmatically ?
DBG_PRINT( "setScreenMode0: Don't know how to rotate screen on OS X: rot %d ccw\n", ccwRot);
res = JNI_FALSE;
+ } else {
+ if( numberOfAvailableModes <= nativeId ) {
+ res = JNI_FALSE;
+ } else {
+ mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId);
+ // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
+ }
}
- if(JNI_TRUE == res) {
+
+ if( NULL != mode ) {
CGError err = CGDisplaySwitchToMode(display, mode);
if(kCGErrorSuccess != err) {
DBG_PRINT( "setScreenMode0: SetMode failed: %d\n", (int)err);
@@ -526,6 +715,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtScreen_dump();
+
jclass c;
c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
@@ -553,48 +744,106 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0
return (jboolean) res;
}
-/*
+/**
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: createView0
+ * Signature: (IIII)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d (START)\n",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h);
+
+ NSRect rectView = NSMakeRect(0, 0, w, h);
+ NewtView *myView = [[NewtView alloc] initWithFrame: rectView] ;
+ DBG_PRINT( "createView0.X - new view: %p\n", myView);
+
+ [pool release];
+
+ return (jlong) (intptr_t) myView;
+}
+
+/**
+ * Method creates a deferred un-initialized Window, hence no special invocation required inside method.
+ *
* Class: jogamp_newt_driver_macosx_WindowDriver
* Method: createWindow0
- * Signature: (JIIIIZIIIJ)J
+ * Signature: (IIIIZIIJ)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow0
- (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean opaque, jboolean fullscreen, jint styleMask,
- jint bufferingType, jint screen_idx, jlong jview)
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h,
+ jboolean fullscreen, jint styleMask, jint bufferingType, jlong jview)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* myView = (NewtView*) (intptr_t) jview ;
- DBG_PRINT( "createWindow0 - %p (this), %p (parent), %d/%d %dx%d, opaque %d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n",
- (void*)(intptr_t)jthis, (void*)(intptr_t)parent, (int)x, (int)y, (int)w, (int)h, (int) opaque, (int)fullscreen,
- (int)styleMask, (int)bufferingType, (int)screen_idx, myView);
-
- NSArray *screens = [NSScreen screens];
- if(screen_idx<0) screen_idx=0;
- if(screen_idx>=[screens count]) screen_idx=0;
- NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx];
- NSRect rect;
+ DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, view %p (START)\n",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen,
+ (int)styleMask, (int)bufferingType, myView);
+ (void)myView;
if (fullscreen) {
styleMask = NSBorderlessWindowMask;
- rect = [myScreen frame];
- x = 0;
- y = 0;
- w = (jint) (rect.size.width);
- h = (jint) (rect.size.height);
- } else {
- rect = NSMakeRect(x, y, w, h);
}
+ NSRect rectWin = NSMakeRect(x, y, w, h);
// Allocate the window
- NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rect
+ NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rectWin
styleMask: (NSUInteger) styleMask
backing: (NSBackingStoreType) bufferingType
- defer: NO
- screen: myScreen
+ defer: YES
isFullscreenWindow: fullscreen];
- [myWindow setReleasedWhenClosed: YES]; // default
+ // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+ DBG_PRINT( "createWindow0.X - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+ [pool release];
+
+ return (jlong) ((intptr_t) myWindow);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: initWindow0
+ * Signature: (JJIIIIFZZZJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0
+ (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, jfloat reqPixelScale,
+ jboolean opaque, jboolean visible, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
+ NewtView* myView = (NewtView*) (intptr_t) jview ;
+ BOOL fullscreen = myWindow->isFullscreenWindow;
+
+ DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, reqPixScale %f, opaque %d, fs %d, visible %d, view %p (START)\n",
+ (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, (float)reqPixelScale,
+ (int) opaque, (int)fullscreen, (int)visible, myView);
+
+NS_DURING
+ // HiDPI scaling: Setup - Available >= 10.7
+ if( 1.0 == reqPixelScale ) {
+ [myView setWantsBestResolutionOpenGLSurface: NO];
+ } else {
+ [myView setWantsBestResolutionOpenGLSurface: YES];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ [myWindow setReleasedWhenClosed: NO]; // We control NSWindow destruction!
[myWindow setPreservesContentDuringLiveResize: NO];
+NS_DURING
+ if ( [myWindow respondsToSelector:@selector(setRestorable:)] ) {
+ // Available >= 10.7 - Removes restauration 'feature', really close
+ [myWindow setRestorable: NO];
+ }
+NS_HANDLER
+NS_ENDHANDLER
NSObject* nsParentObj = (NSObject*) ((intptr_t) parent);
NSWindow* parentWindow = NULL;
@@ -602,15 +851,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow
if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
parentWindow = (NSWindow*) nsParentObj;
parentView = [parentWindow contentView];
- DBG_PRINT( "createWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
+ DBG_PRINT( "initWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
} else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
parentView = (NSView*) nsParentObj;
parentWindow = [parentView window];
- DBG_PRINT( "createWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow);
+ DBG_PRINT( "initWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow);
} else {
- DBG_PRINT( "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
+ DBG_PRINT( "initWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
}
- DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]);
+ DBG_PRINT( "initWindow0 - is visible.1: %d\n", [myWindow isVisible]);
// Remove animations for child windows
if(NULL != parentWindow) {
@@ -628,11 +877,11 @@ NS_ENDHANDLER
#endif
if(opaque) {
[myWindow setOpaque: YES];
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
+ DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
if (!fullscreen) {
[myWindow setShowsResizeIndicator: YES];
}
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
+ DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
} else {
[myWindow setOpaque: NO];
[myWindow setBackgroundColor: [NSColor clearColor]];
@@ -640,35 +889,29 @@ NS_ENDHANDLER
// specify we want mouse-moved events
[myWindow setAcceptsMouseMovedEvents:YES];
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
- // Use given NewtView or allocate an NewtView if NULL
- if(NULL == myView) {
- myView = [[NewtView alloc] initWithFrame: rect] ;
- DBG_PRINT( "createWindow0.%d - use new view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView));
- } else {
- DBG_PRINT( "createWindow0.%d - use given view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView));
- }
-
- DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n",
- dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
// Set the content view
- changeContentView(env, jthis, parentView, myWindow, myView);
+ changeContentView(env, jthis, parentView, myWindow, myView, NO);
+ [myWindow setInitialFirstResponder: myView];
- DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n",
- dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
if(NULL!=parentWindow) {
[myWindow attachToParent: parentWindow];
}
- // Immediately re-position the window based on an upper-left coordinate system
- setFrameTopLeftPoint(parentWindow, myWindow, x, y);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d, visible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible], visible);
- // force surface creation
- [myView lockFocus];
- [myView unlockFocus];
+ // Immediately re-position this window based on an upper-left coordinate system
+ setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO);
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
NS_DURING
// concurrent view rendering
@@ -676,49 +919,115 @@ NS_DURING
if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) {
[myWindow setAllowsConcurrentViewDrawing: YES];
}
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) {
[myView setCanDrawConcurrently: YES];
}
NS_HANDLER
NS_ENDHANDLER
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
// visible on front
- [myWindow orderFront: myWindow];
+ if( visible ) {
+ [myWindow orderFront: myWindow];
+ }
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // force surface creation
+ // [myView lockFocus];
+ // [myView unlockFocus];
+
+ // Set the next responder to be the window so that we can forward
+ // right mouse button down events
+ [myView setNextResponder: myWindow];
+
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
+
+ [myView setDestroyNotifySent: false];
+ setJavaWindowObject(env, jthis, myView, YES);
+
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
NS_DURING
- // Available >= 10.5 - Makes the menubar disapear
- if(fullscreen) {
+ if( fullscreen ) {
+ /**
+ * See Bug 914: We don't use exclusive fullscreen anymore (capturing display)
+ * allowing ALT-TAB to allow process/app switching!
+ * Shall have no penalty on modern GPU and is also recommended, see bottom box @
+ * <https://developer.apple.com/library/mac/documentation/graphicsimaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html>
+ *
+ NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y);
if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) {
+ // Available >= 10.5 - Makes the menubar disapear
[myView enterFullScreenMode: myScreen withOptions:NULL];
+ } */
+ if( myWindow->hasPresentationSwitch ) {
+ DBG_PRINT( "initWindow0.%d - %p view %p, setPresentationOptions 0x%X\n",
+ dbgIdx++, myWindow, myView, (int)myWindow->fullscreenPresentationOptions);
+ [NSApp setPresentationOptions: myWindow->fullscreenPresentationOptions];
}
}
NS_HANDLER
NS_ENDHANDLER
- // Set the next responder to be the window so that we can forward
- // right mouse button down events
- [myView setNextResponder: myWindow];
-
- DBG_PRINT( "createWindow0 - %p (this), %p (parent): new window: %p, view %p,%d (END)\n",
- (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView));
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
[pool release];
-
- return (jlong) ((intptr_t) myWindow);
+ DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p\n",
+ (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
}
-// Footnote: Our view handling produces random 'Assertion failure' even w/o parenting:
-//
-// [NSThemeFrame lockFocus], /SourceCache/AppKit/AppKit-1138.23/AppKit.subproj/NSView.m:6053
-// [NSThemeFrame(0x7fe94bc72c80) lockFocus] failed with window=0x7fe94bc445a0, windowNumber=9425, [self isHiddenOrHasHiddenAncestor]=0
-// ..
-// AppKit 0x00007fff89621001 -[NSView lockFocus] + 250
-// AppKit 0x00007fff8961eafa -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 3780
-// AppKit 0x00007fff8961793e -[NSView displayIfNeeded] + 1676
-// AppKit 0x00007fff8961707d _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 648
-//
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: setPixelScale0
+ * Signature: (JJF)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPixelScale0
+ (JNIEnv *env, jobject jthis, jlong window, jlong view, jfloat reqPixelScale)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
+ NewtView* myView = (NewtView*) (intptr_t) view ;
+#ifdef VERBOSE_ON
+ int dbgIdx = 1;
+#endif
+
+ DBG_PRINT( "setPixelScale0 - %p (this), %p (window), view %p, reqPixScale %f (START)\n",
+ (void*)(intptr_t)jthis, myWindow, myView, (float)reqPixelScale);
-/*
+NS_DURING
+ // HiDPI scaling: Setup - Available >= 10.7
+ if( 1.0 == reqPixelScale ) {
+ [myView setWantsBestResolutionOpenGLSurface: NO];
+ } else {
+ [myView setWantsBestResolutionOpenGLSurface: YES];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ DBG_PRINT( "setPixelScale0.%d - %p (this), window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, myWindow, myView);
+
+ [pool release];
+ DBG_PRINT( "setPixelScale0.X - %p (this), window: %p, view %p\n",
+ (void*)(intptr_t)jthis, myWindow, myView);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
* Class: jogamp_newt_driver_macosx_WindowDriver
* Method: close0
* Signature: (J)V
@@ -726,31 +1035,50 @@ NS_ENDHANDLER
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0
(JNIEnv *env, jobject unused, jlong window)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "windowClose.0 - NULL NEWT win - abort\n");
+ return;
+ }
+ BOOL isNSWin = [mWin isKindOfClass:[NSWindow class]];
+ BOOL isNewtWin = [mWin isKindOfClass:[NewtMacWindow class]];
+ NSWindow *pWin = [mWin parentWindow];
+ DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin);
+ (void)isNSWin; // silence
+ if( !isNewtWin ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* mView = (NewtView *)[mWin contentView];
- NSWindow* pWin = [mWin parentWindow];
- BOOL destroyNotifySent = (NULL != mView) ? [mView getDestroyNotifySent] : false;
+ BOOL fullscreen = mWin->isFullscreenWindow;
+ BOOL destroyNotifySent, isNSView, isNewtView;
+ if( NULL != mView ) {
+ isNSView = [mView isKindOfClass:[NSView class]];
+ isNewtView = [mView isKindOfClass:[NewtView class]];
+ destroyNotifySent = isNewtView ? [mView getDestroyNotifySent] : false;
+ } else {
+ isNSView = false;
+ isNewtView = false;
+ destroyNotifySent = false;
+ }
- DBG_PRINT( "windowClose.0 - %p,%d, destroyNotifySent %d, view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), destroyNotifySent, mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isNSView %d, isNewtView %d], fullscreen %d, parent %p\n",
+ mWin, destroyNotifySent, mView, isNSView, isNewtView, (int)fullscreen, pWin);
- [mWin setUnrealized];
+ [mWin setRealized: NO];
- if(NULL!=mView) {
+ if( isNewtView ) {
// cleanup view
- jobject javaWindowObject = [mView getJavaWindowObject];
[mView setDestroyNotifySent: true];
- if(NULL!=javaWindowObject) {
- DBG_PRINT( "windowClose.0: Clear global javaWindowObject reference (%p)\n", javaWindowObject);
- (*env)->DeleteGlobalRef(env, javaWindowObject);
- [mView setJavaWindowObject: NULL];
- }
+ setJavaWindowObject(env, NULL, mView, NO);
}
NS_DURING
+ /**
+ * See Bug 914: We don't use exclusive fullscreen anymore (capturing display)
+ * See initWindow0(..) above ..
if(NULL!=mView) {
- // Available >= 10.5 - Makes the menubar disapear
BOOL iifs;
if ( [mView respondsToSelector:@selector(isInFullScreenMode)] ) {
iifs = [mView isInFullScreenMode];
@@ -760,9 +1088,15 @@ NS_DURING
if(iifs && [mView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) {
[mView exitFullScreenModeWithOptions: NULL];
}
- // Note: mWin's release will also release it's mView!
- // [mWin setContentView: nil];
- // [mView release];
+ } */
+ // Note: mWin's release will also release it's mView!
+ DBG_PRINT( "windowClose.1a - %p view %p, fullscreen %d, hasPresSwitch %d, defaultPresentationOptions 0x%X\n",
+ mWin, mView, (int)fullscreen, (int)mWin->hasPresentationSwitch, (int)mWin->defaultPresentationOptions);
+
+ if( fullscreen && mWin->hasPresentationSwitch ) {
+ DBG_PRINT( "windowClose.1b - %p view %p, setPresentationOptions 0x%X\n",
+ mWin, mView, (int)mWin->defaultPresentationOptions);
+ [NSApp setPresentationOptions: mWin->defaultPresentationOptions];
}
NS_HANDLER
NS_ENDHANDLER
@@ -770,19 +1104,13 @@ NS_ENDHANDLER
if(NULL!=pWin) {
[mWin detachFromParent: pWin];
}
- [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
+ [mWin orderOut: mWin];
- DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.2 - %p view %p, parent %p\n", mWin, mView, pWin);
- // Only release window, if release is not yet in process.
- // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked.
- if(!destroyNotifySent) {
- [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
- }
+ [mWin release];
- DBG_PRINT( "windowClose.X - %p,%d, released %d, view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), !destroyNotifySent, mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.Xp\n");
[pool release];
}
@@ -790,16 +1118,16 @@ NS_ENDHANDLER
/*
* Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: lockSurface0
- * Signature: (J)Z
+ * Signature: (JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurface0
- (JNIEnv *env, jclass clazz, jlong window)
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
if(NO == [mWin isRealized]) {
return JNI_FALSE;
}
- NewtView * mView = (NewtView *) [mWin contentView];
+ NewtView * mView = (NewtView *) ((intptr_t) view);
return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE;
/** deadlocks, since we render independent of focus
return [mView lockFocusIfCanDraw] == YES ? JNI_TRUE : JNI_FALSE; */
@@ -808,14 +1136,15 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurfa
/*
* Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: unlockSurface0
- * Signature: (J)V
+ * Signature: (JJ)Z
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0
- (JNIEnv *env, jclass clazz, jlong window)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
{
- NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- NewtView * mView = (NewtView *) [mWin contentView];
- [mView softUnlock];
+ // NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
+ (void) window;
+ NewtView * mView = (NewtView *) ((intptr_t) view);
+ return [mView softUnlock] == YES ? JNI_TRUE : JNI_FALSE;
/** deadlocks, since we render independent of focus
[mView unlockFocus]; */
}
@@ -833,12 +1162,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0
#ifdef VERBOSE_ON
BOOL hasFocus = [mWin isKeyWindow];
#endif
-
DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus);
+ [mWin setAcceptsMouseMovedEvents: YES];
[mWin makeFirstResponder: nil];
- [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
- [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
+ [mWin orderFrontRegardless];
+ [mWin makeKeyWindow];
DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force);
@@ -861,10 +1190,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0
DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
if( hasFocus ) {
if(NULL != pWin) {
- // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO];
- [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
+ // [mWin makeFirstResponder: pWin];
+ [pWin makeKeyWindow];
} else {
- [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO];
+ [pWin resignKeyWindow];
}
}
DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin);
@@ -881,13 +1210,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0
(JNIEnv *env, jobject unused, jlong window)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSWindow* mWin = (NSWindow*) ((intptr_t) window);
+ NSWindow* pWin = [mWin parentWindow];
- DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
- [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
+ if( NULL == pWin ) {
+ [mWin orderFrontRegardless];
+ } else {
+ [mWin orderWindow: NSWindowAbove relativeTo: [pWin windowNumber]];
+ }
- DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin);
[pool release];
}
@@ -904,12 +1238,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0
NSWindow* mWin = (NSWindow*) ((intptr_t) window);
NSWindow* pWin = [mWin parentWindow];
- DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin);
+ DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
- if(NULL == pWin) {
- [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
+ if( NULL == pWin ) {
+ [mWin orderOut: mWin];
} else {
- [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO];
+ [mWin orderWindow: NSWindowOut relativeTo: [pWin windowNumber]];
}
DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
@@ -941,7 +1275,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: contentView
+ * Method: contentView0
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0
@@ -949,38 +1283,38 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSView* nsView = [win contentView];
+ NewtView* newtView = NULL;
- DBG_PRINT( "contentView0 - window: %p (START)\n", win);
+ if( [nsView isKindOfClass:[NewtView class]] ) {
+ newtView = (NewtView *) nsView;
+ }
- jlong res = (jlong) ((intptr_t) [win contentView]);
+ DBG_PRINT( "contentView0 - window: %p, view: %p, newtView %p\n", win, nsView, newtView);
- DBG_PRINT( "contentView0 - window: %p (END)\n", win);
+ jlong res = (jlong) ((intptr_t) nsView);
[pool release];
return res;
}
-/*
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
* Class: jogamp_newt_driver_macosx_WindowDriver
* Method: changeContentView
- * Signature: (J)J
+ * Signature: (J)V
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0
(JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* newView = (NewtView *) ((intptr_t) jview);
NewtMacWindow* win = (NewtMacWindow*) ((intptr_t) window);
- NSView* oldNSView = [win contentView];
- NewtView* oldView = NULL;
- if( [oldNSView isMemberOfClass:[NewtView class]] ) {
- oldView = (NewtView *) oldNSView;
- }
-
- DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d (%d) -> %p,%d)\n",
- win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d)\n",
+ win, newView, getRetainCount(newView));
NSObject *nsParentObj = (NSObject*) ((intptr_t) parentWindowOrView);
NSView* pView = NULL;
@@ -993,62 +1327,49 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeConten
}
}
- changeContentView(env, jthis, pView, win, newView);
+ changeContentView(env, jthis, pView, win, newView, YES);
- DBG_PRINT( "changeContentView0.X - win %p, view (%p,%d (%d) -> %p,%d)\n",
- win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ DBG_PRINT( "changeContentView0.X\n");
[pool release];
-
- return (jlong) ((intptr_t) oldView);
}
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: setContentSize
- * Signature: (JII)V
+ * Method: setWindowClientTopLeftPointAndSize0
+ * Signature: (JIIIIZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setContentSize0
- (JNIEnv *env, jobject unused, jlong window, jint w, jint h)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
- DBG_PRINT( "setContentSize0 - window: %p (START)\n", win);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin);
- NSSize sz = NSMakeSize(w, h);
- [win setContentSize: sz];
+ setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display);
- DBG_PRINT( "setContentSize0 - window: %p (END)\n", win);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin);
[pool release];
}
/*
* Class: jogamp_newt_driver_macosx_WindowDriver
- * Method: setFrameTopLeftPoint
- * Signature: (JJII)V
+ * Method: setWindowClientTopLeftPoint0
+ * Signature: (JIIZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setFrameTopLeftPoint0
- (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
- NSObject *nsParentObj = (NSObject*) ((intptr_t) parent);
- NSWindow* pWin = NULL;
- if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
- pWin = (NSWindow*) nsParentObj;
- } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
- NSView* pView = (NSView*) nsParentObj;
- pWin = [pView window];
- }
-
- DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (START)\n", mWin, pWin);
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin);
- setFrameTopLeftPoint(pWin, mWin, x, y);
+ setWindowClientTopLeftPoint(mWin, x, y, display);
- DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (END)\n", mWin, pWin);
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin);
[pool release];
}
@@ -1064,7 +1385,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
- DBG_PRINT( "setAlwaysOnTop0 - window: %p (START)\n", win);
+ DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (START)\n", win, (int)atop);
if(atop) {
[win setLevel:NSFloatingWindowLevel];
@@ -1072,7 +1393,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo
[win setLevel:NSNormalWindowLevel];
}
- DBG_PRINT( "setAlwaysOnTop0 - window: %p (END)\n", win);
+ DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (END)\n", win, (int)atop);
[pool release];
}
@@ -1085,31 +1406,60 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo
JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocationOnScreen0
(JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y)
{
- NSObject *nsObj = (NSObject*) ((intptr_t) win);
- NewtMacWindow * mWin = NULL;
-
- if( [nsObj isKindOfClass:[NewtMacWindow class]] ) {
- mWin = (NewtMacWindow*) nsObj;
- } else {
- NewtCommon_throwNewRuntimeException(env, "not NewtMacWindow %p\n", nsObj);
+ NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) win;
+ if( ![mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return NULL;
}
-
NSPoint p0 = [mWin getLocationOnScreen: NSMakePoint(src_x, src_y)];
return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y);
}
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0
+ (JNIEnv *env, jobject unused, jlong window, jlong handle)
+{
+ NSCursor *c = (NSCursor*) (intptr_t) handle ;
+ if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c);
+ return;
+ }
+ NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setPointerIcon: c];
+ [pool release];
+}
+
/*
* Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: setPointerVisible0
* Signature: (JZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0
(JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO
- hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO];
- return JNI_TRUE;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO
+ hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO];
+ [pool release];
}
/*
@@ -1117,12 +1467,22 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointe
* Method: confinePointer0
* Signature: (JZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0
(JNIEnv *env, jclass clazz, jlong window, jboolean confine)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO];
- return JNI_TRUE;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO];
+ [pool release];
}
/*
@@ -1134,6 +1494,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0
(JNIEnv *env, jclass clazz, jlong window, jint x, jint y)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMousePosition: [mWin newtClientWinPos2OSXScreenPos: NSMakePoint(x, y)]];
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]];
+ [pool release];
}
diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c
index 7f070e7d3..231d6182f 100644
--- a/src/newt/native/NewtCommon.c
+++ b/src/newt/native/NewtCommon.c
@@ -5,17 +5,43 @@
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
+static JavaVM *_jvmHandle = NULL;
+static int _jvmVersion = 0;
+
+void NewtCommon_init(JNIEnv *env) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ NewtCommon_FatalError(env, "NEWT: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
+ jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "NEWT: Can't find %s", ClazzNameRuntimeException);
+ }
+ runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==runtimeExceptionClz) {
+ NewtCommon_FatalError(env, "NEWT: Can't use %s", ClazzNameRuntimeException);
+ }
+ }
+}
+
void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- fprintf(stderr, "%s\n", buffer);
- (*env)->FatalError(env, buffer);
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
+ }
}
void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
@@ -23,23 +49,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if(NULL==_jvmHandle) {
+ NewtCommon_FatalError(env, "NEWT: NULL JVM handle, call NewtCommon_init 1st\n");
+ return;
+ }
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
-}
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
-void NewtCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
- jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
- if(NULL==c) {
- NewtCommon_FatalError(env, "NEWT: can't find %s", ClazzNameRuntimeException);
- }
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- NewtCommon_FatalError(env, "NEWT: can't use %s", ClazzNameRuntimeException);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
}
}
}
@@ -65,37 +86,57 @@ const char * NewtCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmet
jchar* NewtCommon_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);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) {
+JNIEnv* NewtCommon_GetJNIEnv(int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "NEWT GetJNIEnv: NULL JVM handle, call NewtCommon_init 1st\n");
+ return NULL;
+ }
+
// retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
+ envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ if( asDaemon ) {
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
+ } else {
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
+ }
+ if( JNI_OK != envRes ) {
+ fprintf(stderr, "NEWT GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "NEWT GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "NEWT GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
return curEnv;
}
+void NewtCommon_ReleaseJNIEnv (int shallBeDetached) {
+ if(NULL == _jvmHandle) {
+ fprintf(stderr, "NEWT ReleaseJNIEnv: No JavaVM handle registered, call NewtCommon_init(..) 1st");
+ } else if(shallBeDetached) {
+ (*_jvmHandle)->DetachCurrentThread(_jvmHandle);
+ }
+}
+
diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h
index 9a4e5ac70..43db72b5b 100644
--- a/src/newt/native/NewtCommon.h
+++ b/src/newt/native/NewtCommon.h
@@ -42,23 +42,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
/**
*
- * 1) Store jvmHandle and jvmVersion
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
+ NewtCommon_init(env);
*
* 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
*
+ int asDaemon = 0;
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -70,12 +65,13 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
.. your JNIEnv code here ..
*
- * 4) Detach thread from JVM, if required
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
*
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
*/
-JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached);
+JNIEnv* NewtCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
+void NewtCommon_ReleaseJNIEnv (int shallBeDetached);
#endif
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
index c0912ad3c..0f80df2d7 100644
--- a/src/newt/native/NewtMacWindow.h
+++ b/src/newt/native/NewtMacWindow.h
@@ -41,53 +41,55 @@
// #define VERBOSE_ON 1
#ifdef VERBOSE_ON
- #define DBG_PRINT(...) NSLog(@ __VA_ARGS__)
+ #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) ; fflush(stderr)
// #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
#else
#define DBG_PRINT(...)
#endif
+// #define DBG_LIFECYCLE 1
+
+NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap);
+NSScreen * NewtScreen_getNSScreenByCoord(int x, int y);
+CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen);
+
@interface NewtView : NSView
{
jobject javaWindowObject;
- // This is set while messages are being dispatched and cleared afterward
- JavaVM *jvmHandle;
- int jvmVersion;
-
volatile BOOL destroyNotifySent;
- volatile BOOL softLocked;
+ volatile int softLockCount;
pthread_mutex_t softLockSync;
- NSTrackingRectTag ptrTrackingTag;
+ volatile NSTrackingRectTag ptrTrackingTag;
NSRect ptrRect;
NSCursor * myCursor;
+ BOOL modsDown[4]; // shift, ctrl, alt/option, win/command
+
+ BOOL mouseConfined;
+ BOOL mouseInside;
+ BOOL mouseVisible;
+ BOOL cursorIsHidden;
+ NSPoint lastInsideMousePosition;
}
- (id)initWithFrame:(NSRect)frameRect;
+
+#ifdef DBG_LIFECYCLE
- (void) release;
+#endif
- (void) dealloc;
-/* Set during event dispatching cycle */
-- (void) setJVMHandle: (JavaVM*) vm;
-- (JavaVM*) getJVMHandle;
-- (void) setJVMVersion: (int) ver;
-- (int) getJVMVersion;
-
/* Register or deregister (NULL) the java Window object,
ie, if NULL, no events are send */
- (void) setJavaWindowObject: (jobject) javaWindowObj;
- (jobject) getJavaWindowObject;
-- (void) rightMouseDown: (NSEvent*) theEvent;
-- (void) resetCursorRects;
-- (NSCursor *) cursor;
-
- (void) setDestroyNotifySent: (BOOL) v;
- (BOOL) getDestroyNotifySent;
- (BOOL) softLock;
-- (void) softUnlock;
+- (BOOL) softUnlock;
- (BOOL) needsDisplay;
- (void) displayIfNeeded;
@@ -96,6 +98,42 @@
- (void) viewDidHide;
- (void) viewDidUnhide;
- (BOOL) acceptsFirstResponder;
+- (BOOL) becomeFirstResponder;
+- (BOOL) resignFirstResponder;
+
+- (void) removeCursorRects;
+- (void) addCursorRects;
+- (void) removeMyCursor;
+- (void) resetCursorRects;
+- (void) setPointerIcon: (NSCursor*)c;
+- (void) mouseEntered: (NSEvent*) theEvent;
+- (void) mouseExited: (NSEvent*) theEvent;
+- (BOOL) updateMouseInside;
+- (void) cursorHide:(BOOL)v enter:(int)enterState;
+- (void) setPointerIcon:(NSCursor*)c;
+- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus;
+- (BOOL) isMouseVisible;
+- (void) setMouseConfined:(BOOL)v;
+- (void) setMousePosition:(NSPoint)p;
+- (void) mouseMoved: (NSEvent*) theEvent;
+- (void) scrollWheel: (NSEvent*) theEvent;
+- (void) mouseDown: (NSEvent*) theEvent;
+- (void) mouseDragged: (NSEvent*) theEvent;
+- (void) mouseUp: (NSEvent*) theEvent;
+- (void) rightMouseDown: (NSEvent*) theEvent;
+- (void) rightMouseDragged: (NSEvent*) theEvent;
+- (void) rightMouseUp: (NSEvent*) theEvent;
+- (void) otherMouseDown: (NSEvent*) theEvent;
+- (void) otherMouseDragged: (NSEvent*) theEvent;
+- (void) otherMouseUp: (NSEvent*) theEvent;
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType;
+- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
+
+- (void) handleFlagsChanged:(NSUInteger) mods;
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods;
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType;
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType;
+- (void) viewDidChangeBackingProperties;
@end
@@ -105,14 +143,12 @@
@interface NewtMacWindow : NSWindow
#endif
{
- BOOL isFullscreenWindow;
- BOOL mouseConfined;
- BOOL mouseVisible;
- BOOL mouseInside;
- BOOL cursorIsHidden;
BOOL realized;
- NSPoint lastInsideMousePosition;
@public
+ BOOL hasPresentationSwitch;
+ NSUInteger defaultPresentationOptions;
+ NSUInteger fullscreenPresentationOptions;
+ BOOL isFullscreenWindow;
int cachedInsets[4]; // l, r, t, b
}
@@ -122,32 +158,31 @@
styleMask: (NSUInteger) windowStyle
backing: (NSBackingStoreType) bufferingType
defer: (BOOL) deferCreation
- screen:(NSScreen *)screen
isFullscreenWindow:(BOOL)isfs;
+#ifdef DBG_LIFECYCLE
- (void) release;
+#endif
- (void) dealloc;
-- (void) setUnrealized;
+- (void) setRealized: (BOOL)v;
- (BOOL) isRealized;
-- (void) updateInsets: (JNIEnv*) env;
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin;
- (void) attachToParent: (NSWindow*) parent;
- (void) detachFromParent: (NSWindow*) parent;
-- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p;
-- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p;
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p;
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz;
+- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p;
+- (NSSize) newtClientSize2TLSize: (NSSize) nsz;
- (NSPoint) getLocationOnScreen: (NSPoint) p;
-- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
-
-- (BOOL) isMouseInside;
-- (void) cursorHide:(BOOL)v;
-- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus;
-- (void) setMouseConfined:(BOOL)v;
-- (void) setMousePosition:(NSPoint)p;
-- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType;
-- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType;
- (void) focusChanged: (BOOL) gained;
+- (void) keyDown: (NSEvent*) theEvent;
+- (void) keyUp: (NSEvent*) theEvent;
+- (void) flagsChanged: (NSEvent *) theEvent;
+- (BOOL) acceptsMouseMovedEvents;
+- (BOOL) acceptsFirstResponder;
- (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder;
- (BOOL) canBecomeKeyWindow;
@@ -155,20 +190,7 @@
- (void) resignKeyWindow;
- (void) windowDidBecomeKey: (NSNotification *) notification;
- (void) windowDidResignKey: (NSNotification *) notification;
-- (void) keyDown: (NSEvent*) theEvent;
-- (void) keyUp: (NSEvent*) theEvent;
-- (void) mouseEntered: (NSEvent*) theEvent;
-- (void) mouseExited: (NSEvent*) theEvent;
-- (void) mouseMoved: (NSEvent*) theEvent;
-- (void) scrollWheel: (NSEvent*) theEvent;
-- (void) mouseDown: (NSEvent*) theEvent;
-- (void) mouseDragged: (NSEvent*) theEvent;
-- (void) mouseUp: (NSEvent*) theEvent;
-- (void) rightMouseDown: (NSEvent*) theEvent;
-- (void) rightMouseDragged: (NSEvent*) theEvent;
-- (void) rightMouseUp: (NSEvent*) theEvent;
-- (void) otherMouseDown: (NSEvent*) theEvent;
-- (void) otherMouseUp: (NSEvent*) theEvent;
+
- (void) windowDidResize: (NSNotification*) notification;
- (void) windowDidMove: (NSNotification*) notification;
- (BOOL) windowClosingImpl: (BOOL) force;
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index b58b99e38..caf9e54e0 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -36,70 +36,171 @@
#import "KeyEvent.h"
#import "MouseEvent.h"
-jint GetDeltaY(NSEvent *event, jint javaMods) {
- CGFloat deltaY = 0.0;
+#include <CoreFoundation/CoreFoundation.h>
+#include <Carbon/Carbon.h> /* For kVK_ constants, and TIS functions. */
+
+#include <math.h>
+
+#define PRINTF(...) NSLog(@ __VA_ARGS__)
+
+static jfloat GetDelta(NSEvent *event, jint javaMods[]) {
CGEventRef cgEvent = [event CGEvent];
+ CGFloat deltaY = 0.0;
+ CGFloat deltaX = 0.0;
+ CGFloat delta = 0.0;
if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) {
// mouse pad case
- deltaY =
- CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
- // fprintf(stderr, "WHEEL/PAD: %lf\n", (double)deltaY);
+ deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
+ deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
+ // fprintf(stderr, "WHEEL/PAD: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
+ if( fabsf(deltaX) > fabsf(deltaY) ) {
+ javaMods[0] |= EVENT_SHIFT_MASK;
+ delta = deltaX;
+ } else {
+ delta = deltaY;
+ }
} else {
// traditional mouse wheel case
+ deltaX = [event deltaX];
deltaY = [event deltaY];
- // fprintf(stderr, "WHEEL/TRAD: %lf\n", (double)deltaY);
- if (deltaY == 0.0 && (javaMods & EVENT_SHIFT_MASK) != 0) {
+ // fprintf(stderr, "WHEEL/TRACK: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
+ if (deltaY == 0.0 && (javaMods[0] & EVENT_SHIFT_MASK) != 0) {
// shift+vertical wheel scroll produces horizontal scroll
// we convert it to vertical
- deltaY = [event deltaX];
+ delta = deltaX;
+ } else {
+ delta = deltaY;
}
- if (-1.0 < deltaY && deltaY < 1.0) {
- deltaY *= 10.0;
+ if (-1.0 < delta && delta < 1.0) {
+ delta *= 10.0;
} else {
- if (deltaY < 0.0) {
- deltaY = deltaY - 0.5f;
+ if (delta < 0.0) {
+ delta = delta - 0.5f;
} else {
- deltaY = deltaY + 0.5f;
+ delta = delta + 0.5f;
+ }
+ }
+ }
+ // fprintf(stderr, "WHEEL/RES: %lf - 0x%X\n", (double)delta, javaMods[0]);
+ return (jfloat) delta;
+}
+
+#define kVK_Shift 0x38
+#define kVK_Option 0x3A
+#define kVK_Control 0x3B
+#define kVK_Command 0x37
+
+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;
+}
+
+static CFStringRef CKCH_CreateStringForKey(CGKeyCode keyCode, const UCKeyboardLayout *keyboardLayout) {
+ UInt32 keysDown = 0;
+ UniChar chars[4];
+ UniCharCount realLength;
+
+ UCKeyTranslate(keyboardLayout, keyCode,
+ kUCKeyActionDisplay, 0,
+ LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
+ &keysDown, sizeof(chars) / sizeof(chars[0]), &realLength, chars);
+
+ return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1);
+}
+
+static CFMutableDictionaryRef CKCH_CreateCodeToCharDict(TISInputSourceRef keyboard) {
+ CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
+ if( NULL == layoutData ) {
+ return NULL;
+ }
+ const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
+
+ CFMutableDictionaryRef codeToCharDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, NULL, NULL);
+ if ( NULL != codeToCharDict ) {
+ intptr_t i;
+ for (i = 0; i < 128; ++i) {
+ CFStringRef string = CKCH_CreateStringForKey((CGKeyCode)i, keyboardLayout);
+ if( NULL != string ) {
+ CFIndex stringLen = CFStringGetLength (string);
+ if ( 0 < stringLen ) {
+ UniChar character = CFStringGetCharacterAtIndex(string, 0);
+ DBG_PRINT("CKCH: MAP 0x%X -> %c\n", (int)i, character);
+ CFDictionaryAddValue(codeToCharDict, (const void *)i, (const void *)(intptr_t)character);
+ }
+ CFRelease(string);
}
}
}
- // fprintf(stderr, "WHEEL/res: %d\n", (int)deltaY);
- return (jint) deltaY;
+ return codeToCharDict;
+}
+
+static CFMutableDictionaryRef CKCH_USCodeToNNChar = NULL;
+
+static void CKCH_CreateDictionaries() {
+ TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
+ if( NULL != currentKeyboard ) {
+ CKCH_USCodeToNNChar = CKCH_CreateCodeToCharDict(currentKeyboard);
+ CFRelease(currentKeyboard);
+ }
+}
+
+static UniChar CKCH_CharForKeyCode(jshort keyCode) {
+ UniChar rChar = 0;
+
+ if ( NULL != CKCH_USCodeToNNChar ) {
+ intptr_t code = (intptr_t) keyCode;
+ intptr_t character = 0;
+
+ if ( CFDictionaryGetValueIfPresent(CKCH_USCodeToNNChar, (void *)code, (const void **)&character) ) {
+ rChar = (UniChar) character;
+ DBG_PRINT("CKCH: OK 0x%X -> 0x%X\n", (int)keyCode, (int)rChar);
+ }
+ }
+ return rChar;
}
static jmethodID enqueueMouseEventID = NULL;
-static jmethodID sendMouseEventID = NULL;
static jmethodID enqueueKeyEventID = NULL;
-static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
static jmethodID insetsChangedID = NULL;
static jmethodID sizeChangedID = NULL;
+static jmethodID updatePixelScaleID = NULL;
static jmethodID visibleChangedID = NULL;
static jmethodID positionChangedID = NULL;
static jmethodID focusChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-// Can't use USE_SENDIO_DIRECT, ie w/o enqueueing to EDT,
+// Need to enqueue all events to EDT,
// since we may operate on AWT-AppKit (Main Thread)
// and direct issuing 'requestFocus()' would deadlock:
// AWT-AppKit
// AWT-EventQueue-0
-//
-// #define USE_SENDIO_DIRECT 1
@implementation NewtView
- (id)initWithFrame:(NSRect)frameRect
{
+ id res = [super initWithFrame:frameRect];
javaWindowObject = NULL;
- jvmHandle = NULL;
- jvmVersion = 0;
destroyNotifySent = NO;
- softLocked = NO;
+ softLockCount = 0;
pthread_mutexattr_t softLockSyncAttr;
pthread_mutexattr_init(&softLockSyncAttr);
@@ -107,59 +208,46 @@ static jmethodID windowRepaintID = NULL;
pthread_mutex_init(&softLockSync, &softLockSyncAttr); // recursive
ptrTrackingTag = 0;
-
- /**
- NSCursor crs = [NSCursor arrowCursor];
- NSImage crsImg = [crs image];
- NSPoint crsHot = [crs hotSpot];
- myCursor = [[NSCursor alloc] initWithImage: crsImg hotSpot:crsHot];
- */
myCursor = NULL;
- return [super initWithFrame:frameRect];
+ modsDown[0] = NO; // shift
+ modsDown[1] = NO; // ctrl
+ modsDown[2] = NO; // alt
+ modsDown[3] = NO; // win
+ mouseConfined = NO;
+ mouseVisible = YES;
+ mouseInside = NO;
+ cursorIsHidden = NO;
+
+ DBG_PRINT("NewtView::create: %p (refcnt %d)\n", res, (int)[res retainCount]);
+ return res;
}
+#ifdef DBG_LIFECYCLE
- (void) release
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtView::release\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+ DBG_PRINT("NewtView::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
[super release];
}
+#endif
- (void) dealloc
{
- if(softLocked) {
+ DBG_PRINT("NewtView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+ if( 0 < softLockCount ) {
NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n");
}
+ [self removeCursorRects];
+ [self removeMyCursor];
+
pthread_mutex_destroy(&softLockSync);
-#ifdef VERBOSE_ON
- NSLog(@"NewtView::dealloc\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+ DBG_PRINT("NewtView::dealloc.X: %p\n", self);
[super dealloc];
}
-- (void) setJVMHandle: (JavaVM*) vm
-{
- jvmHandle = vm;
-}
-- (JavaVM*) getJVMHandle
-{
- return jvmHandle;
-}
-
-- (void) setJVMVersion: (int) ver
-{
- jvmVersion = ver;
-}
-
-- (int) getJVMVersion
-{
- return jvmVersion;
-}
-
- (void) setJavaWindowObject: (jobject) javaWindowObj
{
javaWindowObject = javaWindowObj;
@@ -170,32 +258,6 @@ static jmethodID windowRepaintID = NULL;
return javaWindowObject;
}
-- (void) rightMouseDown: (NSEvent*) theEvent
-{
- NSResponder* next = [self nextResponder];
- if (next != nil) {
- [next rightMouseDown: theEvent];
- }
-}
-
-- (void) resetCursorRects
-{
- [super resetCursorRects];
-
- if(0 != ptrTrackingTag) {
- // [self removeCursorRect: ptrRect cursor: myCursor];
- [self removeTrackingRect: ptrTrackingTag];
- }
- ptrRect = [self bounds];
- // [self addCursorRect: ptrRect cursor: myCursor];
- ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO];
-}
-
-- (NSCursor *) cursor
-{
- return myCursor;
-}
-
- (void) setDestroyNotifySent: (BOOL) v
{
destroyNotifySent = v;
@@ -209,18 +271,27 @@ static jmethodID windowRepaintID = NULL;
- (BOOL) softLock
{
// DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self());
- // NSLog(@"NewtView::softLock: %@",[NSThread callStackSymbols]);
- pthread_mutex_lock(&softLockSync);
- softLocked = YES;
+ int err;
+ if( 0 != ( err = pthread_mutex_lock(&softLockSync) ) ) {
+ NSLog(@"NewtView::softLock failed: errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ softLockCount++;
// DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self());
- return softLocked;
+ return 0 < softLockCount;
}
-- (void) softUnlock
+- (BOOL) softUnlock
{
// DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self());
- softLocked = NO;
- pthread_mutex_unlock(&softLockSync);
+ softLockCount--;
+ int err;
+ if( 0 != ( err = pthread_mutex_unlock(&softLockSync) ) ) {
+ softLockCount++;
+ NSLog(@"NewtView::softUnlock failed: Not locked by current thread - errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ return YES;
}
- (BOOL) needsDisplay
@@ -256,7 +327,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -265,12 +336,11 @@ static jmethodID windowRepaintID = NULL;
NSRect viewFrame = [self frame];
(*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE, // defer ..
- dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y,
- dirtyRect.size.width, dirtyRect.size.height);
+ (int)dirtyRect.origin.x, (int)viewFrame.size.height - (int)dirtyRect.origin.y,
+ (int)dirtyRect.size.width, (int)dirtyRect.size.height);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void) viewDidHide
@@ -280,7 +350,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("viewDidHide: null JNIEnv\n");
return;
@@ -288,9 +358,8 @@ static jmethodID windowRepaintID = NULL;
(*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_FALSE);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
[super viewDidHide];
}
@@ -302,7 +371,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("viewDidUnhide: null JNIEnv\n");
return;
@@ -310,9 +379,8 @@ static jmethodID windowRepaintID = NULL;
(*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_TRUE);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
[super viewDidUnhide];
}
@@ -322,232 +390,152 @@ static jmethodID windowRepaintID = NULL;
return YES;
}
-@end
-
-@implementation NewtMacWindow
-
-+ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
+- (BOOL) becomeFirstResponder
{
- enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
- sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
- visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
- insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
- positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V");
- focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
- windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
- windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
- requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
- if (enqueueMouseEventID && sendMouseEventID && enqueueKeyEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID &&
- positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
- {
- return YES;
- }
- return NO;
+ DBG_PRINT( "*************** View.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
}
-- (id) initWithContentRect: (NSRect) contentRect
- styleMask: (NSUInteger) windowStyle
- backing: (NSBackingStoreType) bufferingType
- defer: (BOOL) deferCreation
- screen:(NSScreen *)screen
- isFullscreenWindow:(BOOL)isfs
+- (BOOL) resignFirstResponder
{
- id res = [super initWithContentRect: contentRect
- styleMask: windowStyle
- backing: bufferingType
- defer: deferCreation
- screen: screen];
- isFullscreenWindow = isfs;
- // Why is this necessary? Without it we don't get any of the
- // delegate methods like resizing and window movement.
- [self setDelegate: self];
- cachedInsets[0] = 0; // l
- cachedInsets[1] = 0; // r
- cachedInsets[2] = 0; // t
- cachedInsets[3] = 0; // b
- mouseConfined = NO;
- mouseVisible = YES;
- mouseInside = NO;
- cursorIsHidden = NO;
- realized = YES;
- return res;
+ DBG_PRINT( "*************** View.resignFirstResponder\n");
+ return [super resignFirstResponder];
}
-- (void) release
+- (void) removeCursorRects
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtWindow::release\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
- [super release];
+ if(0 != ptrTrackingTag) {
+ if(NULL != myCursor) {
+ [self removeCursorRect: ptrRect cursor: myCursor];
+ }
+ [self removeTrackingRect: ptrTrackingTag];
+ ptrTrackingTag = 0;
+ }
}
-- (void) dealloc
+- (void) addCursorRects
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtWindow::dealloc\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
- [super dealloc];
+ ptrRect = [self bounds];
+ if(NULL != myCursor) {
+ [self addCursorRect: ptrRect cursor: myCursor];
+ }
+ ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO];
}
-- (void) setUnrealized
+- (void) removeMyCursor
{
- realized = NO;
+ if(NULL != myCursor) {
+ [myCursor release];
+ myCursor = NULL;
+ }
}
-- (BOOL) isRealized
+- (void) resetCursorRects
{
- return realized;
+ [super resetCursorRects];
+
+ [self removeCursorRects];
+ [self addCursorRects];
}
-- (void) updateInsets: (JNIEnv*) env
+- (void) setPointerIcon: (NSCursor*)c
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
+ DBG_PRINT( "setPointerIcon: %p -> %p, top %p, mouseInside %d\n", myCursor, c, [NSCursor currentCursor], (int)mouseInside);
+ if( c != myCursor ) {
+ [self removeCursorRects];
+ [self removeMyCursor];
+ myCursor = c;
+ if( NULL != myCursor ) {
+ [myCursor retain];
+ }
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (env==NULL || javaWindowObject == NULL) {
- return;
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ [nsWin invalidateCursorRectsForView: self];
}
-
- NSRect frameRect = [self frame];
- NSRect contentRect = [self contentRectForFrameRect: frameRect];
-
- // note: this is a simplistic implementation which doesn't take
- // into account DPI and scaling factor
- CGFloat l = contentRect.origin.x - frameRect.origin.x;
- cachedInsets[0] = (int)l; // l
- cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r
- cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t
- cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b
-
- DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
-
- (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
-}
-
-- (void) attachToParent: (NSWindow*) parent
-{
- DBG_PRINT( "attachToParent.1\n");
- [parent addChildWindow: self ordered: NSWindowAbove];
- DBG_PRINT( "attachToParent.2\n");
- [self setParentWindow: parent];
- DBG_PRINT( "attachToParent.X\n");
}
-- (void) detachFromParent: (NSWindow*) parent
+- (void) mouseEntered: (NSEvent*) theEvent
{
- DBG_PRINT( "detachFromParent.1\n");
- [self setParentWindow: nil];
- if(NULL != parent) {
- DBG_PRINT( "detachFromParent.2\n");
- [parent removeChildWindow: self];
+ DBG_PRINT( "mouseEntered: confined %d, visible %d, PointerIcon %p, top %p\n", mouseConfined, mouseVisible, myCursor, [NSCursor currentCursor]);
+ mouseInside = YES;
+ [self cursorHide: !mouseVisible enter: 1];
+ if(NO == mouseConfined) {
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED];
+ }
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ [nsWin makeFirstResponder: self];
}
- DBG_PRINT( "detachFromParent.X\n");
-}
-
-/**
- * p abs screen position w/ top-left origin
- * returns: abs screen position w/ bottom-left origin
- */
-- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p
-{
- NSView* mView = [self contentView];
- NSRect mViewFrame = [mView frame];
- int totalHeight = mViewFrame.size.height + cachedInsets[2] + cachedInsets[3]; // height + insets[top+bottom]
-
- NSScreen* screen = [self screen];
- NSRect screenFrame = [screen frame];
-
- return NSMakePoint(screenFrame.origin.x + p.x + cachedInsets[0],
- screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight);
}
-/**
- * p rel client window position w/ top-left origin
- * returns: abs screen position w/ bottom-left origin
- */
-- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p
+- (void) mouseExited: (NSEvent*) theEvent
{
- NSRect winFrame = [self frame];
-
- NSView* mView = [self contentView];
- NSRect mViewFrame = [mView frame];
-
- return NSMakePoint(winFrame.origin.x + p.x,
- winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view
+ DBG_PRINT( "mouseExited: confined %d, visible %d, PointerIcon %p, top %p\n", mouseConfined, mouseVisible, myCursor, [NSCursor currentCursor]);
+ if(NO == mouseConfined) {
+ mouseInside = NO;
+ [self cursorHide: NO enter: -1];
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED];
+ [self resignFirstResponder];
+ } else {
+ [self setMousePosition: lastInsideMousePosition];
+ }
}
/**
- * y-flips input / output
- * p rel client window position w/ top-left origin
- * returns: location in 0/0 top-left space.
+ * p abs screen position w/ bottom-left origin
*/
-- (NSPoint) getLocationOnScreen: (NSPoint) p
+- (void) setMousePosition:(NSPoint)p
{
- NSScreen* screen = [self screen];
- NSRect screenRect = [screen frame];
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ NSScreen* screen = [nsWin screen];
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
+ CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+ CGRect frameTL = CGDisplayBounds (display); // origin top-left
+ NSRect frameBL = [screen frame]; // origin bottom-left
+ CGPoint pt = { p.x, frameTL.origin.y + frameTL.size.height - ( p.y - frameBL.origin.y ) }; // y-flip from BL-screen -> TL-screen
- NSRect r;
- r.origin.x = p.x;
- r.origin.y = viewFrame.size.height - p.y; // y-flip
- r.size.width = 0;
- r.size.height = 0;
- // NSRect rS = [win convertRectToScreen: r]; // 10.7
- NSPoint oS = [self convertBaseToScreen: r.origin];
- oS.y = screenRect.origin.y + screenRect.size.height - oS.y;
- return oS;
-}
+ DBG_PRINT( "setMousePosition: point-in[%d/%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n",
+ (int)p.x, (int)p.y,
+ (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height,
+ (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height,
+ (int)pt.x, (int)pt.y);
-- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p
-{
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
-
- NSRect r;
- r.origin.x = p.x;
- r.origin.y = p.y;
- r.size.width = 0;
- r.size.height = 0;
- // NSRect rS = [win convertRectFromScreen: r]; // 10.7
- NSPoint oS = [self convertScreenToBase: r.origin];
- oS.y = viewFrame.size.height - oS.y; // y-flip
- return oS;
+ CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft);
+ CGEventPost (kCGHIDEventTap, ev);
+ }
}
-- (BOOL) isMouseInside
+- (BOOL) updateMouseInside
{
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
+ NSRect viewFrame = [self frame];
NSPoint l1 = [NSEvent mouseLocation];
NSPoint l0 = [self screenPos2NewtClientWinPos: l1];
- return viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) &&
- viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ;
+ mouseInside = viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) &&
+ viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ;
+ return mouseInside;
}
- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus
{
mouseVisible = v;
- mouseInside = [self isMouseInside];
+ [self updateMouseInside];
DBG_PRINT( "setMouseVisible: confined %d, visible %d (current: %d), mouseInside %d, hasFocus %d\n",
mouseConfined, mouseVisible, !cursorIsHidden, mouseInside, focus);
if(YES == focus && YES == mouseInside) {
- [self cursorHide: !mouseVisible];
+ [self cursorHide: !mouseVisible enter: 0];
}
}
+- (BOOL) isMouseVisible
+{
+ return mouseVisible;
+}
-- (void) cursorHide:(BOOL)v
+- (void) cursorHide:(BOOL)v enter:(int)enterState
{
- DBG_PRINT( "cursorHide: %d -> %d\n", cursorIsHidden, v);
+ DBG_PRINT( "cursorHide: %d -> %d, enter %d; PointerIcon: %p, top %p\n",
+ cursorIsHidden, v, enterState, myCursor, [NSCursor currentCursor]);
if(v) {
if(!cursorIsHidden) {
[NSCursor hide];
@@ -567,108 +555,105 @@ static jmethodID windowRepaintID = NULL;
DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible);
}
-- (void) setMousePosition:(NSPoint)p
+- (void) mouseMoved: (NSEvent*) theEvent
{
- NSScreen* screen = [self screen];
- NSRect screenRect = [screen frame];
+ if( mouseInside ) {
+ NSCursor * currentCursor = [NSCursor currentCursor];
+ BOOL setCursor = NULL != myCursor && NO == cursorIsHidden && currentCursor != myCursor;
+ DBG_PRINT( "mouseMoved.set: %d; mouseInside %d, CursorHidden %d, PointerIcon: %p, top %p\n",
+ setCursor, mouseInside, cursorIsHidden, myCursor, currentCursor);
+ if( setCursor ) {
+ // FIXME: Workaround missing NSCursor update for 'fast moving' pointer
+ [myCursor set];
+ }
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ }
+}
- CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin)
- CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft);
- CGEventPost (kCGHIDEventTap, ev);
+- (void) scrollWheel: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED];
}
-static jint mods2JavaMods(NSUInteger mods)
+- (void) mouseDown: (NSEvent*) theEvent
{
- 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;
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
}
-- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType
+- (void) mouseDragged: (NSEvent*) theEvent
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (javaWindowObject == NULL) {
- DBG_PRINT("sendKeyEvent: null javaWindowObject\n");
- return;
- }
- int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
- if(NULL==env) {
- DBG_PRINT("sendKeyEvent: null JNIEnv\n");
- return;
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // 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
+{
+ NSResponder* next = [self nextResponder];
+ if (next != nil) {
+ [next rightMouseDown: theEvent];
}
+ // FIXME: ^^ OR [super rightMouseDown: theEvent] ?
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
- int i;
- jint keyCode = (jint) [event keyCode];
- NSString* chars = [event charactersIgnoringModifiers];
- int len = [chars length];
- jint javaMods = mods2JavaMods([event modifierFlags]);
+- (void) rightMouseDragged: (NSEvent*) theEvent
+{
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
- 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];
+- (void) rightMouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+}
- DBG_PRINT("sendKeyEvent: %d/%d char 0x%X, code 0x%X\n", i, len, (int)keyChar, (int)keyCode);
+- (void) otherMouseDown: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID,
- evType, javaMods, keyCode, keyChar);
- #else
- (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
- evType, javaMods, keyCode, keyChar);
- #endif
- }
+- (void) otherMouseDragged: (NSEvent*) theEvent
+{
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+- (void) otherMouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
}
-- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
if (javaWindowObject == NULL) {
DBG_PRINT("sendMouseEvent: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("sendMouseEvent: null JNIEnv\n");
return;
}
- jint javaMods = mods2JavaMods([event modifierFlags]);
+ jint javaMods[] = { 0 } ;
+ javaMods[0] = mods2JavaMods([event modifierFlags]);
// convert to 1-based button number (or use zero if no button is involved)
// TODO: detect mouse button when mouse wheel scrolled
- jint javaButtonNum = 0;
- jint scrollDeltaY = 0;
+ jshort javaButtonNum = 0;
+ jfloat scrollDeltaY = 0.0f;
switch ([event type]) {
case NSScrollWheel: {
- scrollDeltaY = GetDeltaY(event, javaMods);
+ scrollDeltaY = GetDelta(event, javaMods);
javaButtonNum = 1;
break;
}
@@ -699,246 +684,537 @@ static jint mods2JavaMods(NSUInteger mods)
NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]];
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, javaWindowObject, sendMouseEventID,
- evType, javaMods,
- (jint) location.x, (jint) location.y,
- javaButtonNum, scrollDeltaY);
- #else
(*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE,
- evType, javaMods,
+ evType, javaMods[0],
(jint) location.x, (jint) location.y,
javaButtonNum, scrollDeltaY);
- #endif
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p
+{
+ NSRect viewFrame = [self frame];
+
+ NSRect r;
+ r.origin.x = p.x;
+ r.origin.y = p.y;
+ r.size.width = 0;
+ r.size.height = 0;
+ // NSRect rS = [[self window] convertRectFromScreen: r]; // 10.7
+ NSPoint oS = [[self window] convertScreenToBase: r.origin];
+ oS.y = viewFrame.size.height - oS.y; // y-flip
+ return oS;
+}
+
+- (void) handleFlagsChanged:(NSUInteger) mods
+{
+ [self handleFlagsChanged: NSShiftKeyMask keyIndex: 0 keyCode: kVK_Shift modifiers: mods];
+ [self handleFlagsChanged: NSControlKeyMask keyIndex: 1 keyCode: kVK_Control modifiers: mods];
+ [self handleFlagsChanged: NSAlternateKeyMask keyIndex: 2 keyCode: kVK_Option modifiers: mods];
+ [self handleFlagsChanged: NSCommandKeyMask keyIndex: 3 keyCode: kVK_Command modifiers: mods];
+}
+
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods
+{
+ if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) ) {
+ modsDown[keyIdx] = YES;
+ [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_PRESSED];
+ } else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) ) {
+ modsDown[keyIdx] = NO;
+ [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_RELEASED];
}
}
-- (void) focusChanged: (BOOL) gained
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType
{
- DBG_PRINT( "focusChanged: gained %d\n", gained);
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ jshort keyCode = (jshort) [event keyCode];
+ NSString* chars = [event charactersIgnoringModifiers];
+ NSUInteger mods = [event modifierFlags];
+ [self sendKeyEvent: keyCode characters: chars modifiers: mods eventType: evType];
+}
+
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType
+{
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("sendKeyEvent: null javaWindowObject\n");
return;
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("sendKeyEvent: null JNIEnv\n");
+ return;
+ }
+
+ int i;
+ int len = NULL != chars ? [chars length] : 0;
+ jint javaMods = mods2JavaMods(mods);
+
+ if(len > 0) {
+ // printable chars
+ for (i = 0; i < len; i++) {
+ // Note: the key code in the NSEvent does not map to anything we can use
+ UniChar keyChar = (UniChar) [chars characterAtIndex: i];
+ UniChar keySymChar = CKCH_CharForKeyCode(keyCode);
+
+ DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X, mods 0x%X/0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar,
+ (int)mods, (int)javaMods, (int)keySymChar);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar);
+ }
+ } else {
+ // non-printable chars
+ jchar keyChar = (jchar) 0;
+
+ DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, keyChar, keyChar);
+ }
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (void)viewDidChangeBackingProperties
+{
+ [super viewDidChangeBackingProperties];
+
+ // HiDPI scaling
+ BOOL useHiDPI = [self wantsBestResolutionOpenGLSurface];
+ CGFloat pixelScaleNative = [[self window] backingScaleFactor];
+ CGFloat pixelScaleUse = useHiDPI ? pixelScaleNative : 1.0;
+ DBG_PRINT("viewDidChangeBackingProperties: PixelScale: HiDPI %d, native %f -> use %f\n", useHiDPI, (float)pixelScaleNative, (float)pixelScaleUse);
+ [[self layer] setContentsScale: pixelScaleUse];
+
if (javaWindowObject == NULL) {
- DBG_PRINT("focusChanged: null javaWindowObject\n");
+ DBG_PRINT("viewDidChangeBackingProperties: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("focusChanged: null JNIEnv\n");
+ DBG_PRINT("viewDidChangeBackingProperties: null JNIEnv\n");
return;
}
- (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+ (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, JNI_TRUE, (jfloat)pixelScaleUse, (jfloat)pixelScaleNative); // defer
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+
+@end
+
+@implementation NewtMacWindow
+
++ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
+{
+ enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V");
+ enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V");
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
+ updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFF)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
+ insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V");
+ focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
+ windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
+ requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
+ if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID &&
+ positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
+ {
+ CKCH_CreateDictionaries();
+ return YES;
+ }
+ return NO;
+}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+- (id) initWithContentRect: (NSRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSBackingStoreType) bufferingType
+ defer: (BOOL) deferCreation
+ isFullscreenWindow:(BOOL)isfs
+{
+ id res = [super initWithContentRect: contentRect
+ styleMask: windowStyle
+ backing: bufferingType
+ defer: deferCreation];
+ // OSX 10.6
+ if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] &&
+ [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) {
+ hasPresentationSwitch = YES;
+ defaultPresentationOptions = [NSApp currentSystemPresentationOptions];
+ fullscreenPresentationOptions =
+ // NSApplicationPresentationDefault|
+ // NSApplicationPresentationAutoHideDock|
+ NSApplicationPresentationHideDock|
+ // NSApplicationPresentationAutoHideMenuBar|
+ NSApplicationPresentationHideMenuBar|
+ NSApplicationPresentationDisableAppleMenu|
+ // NSApplicationPresentationDisableProcessSwitching|
+ // NSApplicationPresentationDisableSessionTermination|
+ NSApplicationPresentationDisableHideApplication|
+ // NSApplicationPresentationDisableMenuBarTransparency|
+ // NSApplicationPresentationFullScreen| // OSX 10.7
+ 0 ;
+ } else {
+ hasPresentationSwitch = NO;
+ defaultPresentationOptions = 0;
+ fullscreenPresentationOptions = 0;
}
+
+ isFullscreenWindow = isfs;
+ // Why is this necessary? Without it we don't get any of the
+ // delegate methods like resizing and window movement.
+ [self setDelegate: self];
+
+ cachedInsets[0] = 0; // l
+ cachedInsets[1] = 0; // r
+ cachedInsets[2] = 0; // t
+ cachedInsets[3] = 0; // b
+
+ realized = YES;
+ DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n",
+ res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]);
+ return res;
}
-- (BOOL) becomeFirstResponder
+#ifdef DBG_LIFECYCLE
+- (void) release
{
- DBG_PRINT( "*************** becomeFirstResponder\n");
- return [super becomeFirstResponder];
+ DBG_PRINT("NewtWindow::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"%@",[NSThread callStackSymbols]);
+ [super release];
}
+#endif
-- (BOOL) resignFirstResponder
+- (void) dealloc
{
- DBG_PRINT( "*************** resignFirstResponder\n");
- return [super resignFirstResponder];
+ DBG_PRINT("NewtWindow::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+
+ NewtView* mView = (NewtView *)[self contentView];
+ if( NULL != mView ) {
+ [mView release];
+ }
+ [super dealloc];
+ DBG_PRINT("NewtWindow::dealloc.X: %p\n", self);
}
-- (BOOL) canBecomeKeyWindow
+- (void) setRealized: (BOOL)v
{
- // Even if the window is borderless, we still want it to be able
- // to become the key window to receive keyboard events
- return YES;
+ realized = v;
}
-- (void) becomeKeyWindow
+- (BOOL) isRealized
{
- DBG_PRINT( "*************** becomeKeyWindow\n");
- [super becomeKeyWindow];
+ return realized;
}
-- (void) resignKeyWindow
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin
{
- DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
- if(!isFullscreenWindow) {
- [super resignKeyWindow];
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ cachedInsets[0] = (int)l; // l
+ cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r
+ cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t
+ cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+
+ DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+
+ if( NULL != env && NULL != javaWin ) {
+ (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
}
}
-- (void) windowDidBecomeKey: (NSNotification *) notification
+- (void) attachToParent: (NSWindow*) parent
{
- DBG_PRINT( "*************** windowDidBecomeKey\n");
- mouseInside = [self isMouseInside];
- if(YES == mouseInside) {
- [self cursorHide: !mouseVisible];
+ DBG_PRINT( "attachToParent.1\n");
+ [parent addChildWindow: self ordered: NSWindowAbove];
+ DBG_PRINT( "attachToParent.2\n");
+ [self setParentWindow: parent];
+ DBG_PRINT( "attachToParent.X\n");
+}
+
+- (void) detachFromParent: (NSWindow*) parent
+{
+ DBG_PRINT( "detachFromParent.1\n");
+ [self setParentWindow: nil];
+ if(NULL != parent) {
+ DBG_PRINT( "detachFromParent.2\n");
+ [parent removeChildWindow: self];
}
- [self focusChanged: YES];
+ DBG_PRINT( "detachFromParent.X\n");
}
-- (void) windowDidResignKey: (NSNotification *) notification
+/**
+ * p abs screen position of client-area pos w/ top-left origin, using contentView's client NSSize
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p
{
- DBG_PRINT( "*************** windowDidResignKey\n");
- // Implicit mouse exit by OS X
- [self focusChanged: NO];
+ NSView* mView = [self contentView];
+ NSRect mViewFrame = [mView frame];
+ return [self newtAbsClientTLWinPos2AbsBLScreenPos: p size: mViewFrame.size];
}
-- (void) keyDown: (NSEvent*) theEvent
+/**
+ * p abs screen position of client-area pos w/ top-left origin, using given client NSSize
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz
{
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED];
+ int totalHeight = nsz.height + cachedInsets[3]; // height + insets.bottom
+
+ DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: point-in[%d/%d], size-in[%dx%d], insets bottom %d -> totalHeight %d\n",
+ (int)p.x, (int)p.y, (int)nsz.width, (int)nsz.height, cachedInsets[3], totalHeight);
+
+ NSScreen* screen = [self screen];
+
+ CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+ CGRect frameTL = CGDisplayBounds (display); // origin top-left
+ NSRect frameBL = [screen frame]; // origin bottom-left
+ NSPoint r = NSMakePoint(p.x, frameBL.origin.y + frameBL.size.height - ( p.y - frameTL.origin.y ) - totalHeight); // y-flip from TL-screen -> BL-screen
+
+ DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen tl[%d/%d %dx%d] bl[%d/%d %dx%d -> %d/%d\n",
+ (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height,
+ (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height,
+ (int)r.x, (int)r.y);
+
+ return r;
}
-- (void) keyUp: (NSEvent*) theEvent
+/**
+ * p rel client window position w/ top-left origin
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p
{
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED];
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED];
+ NSRect winFrame = [self frame];
+
+ NSView* mView = [self contentView];
+ NSRect mViewFrame = [mView frame];
+ NSPoint r = NSMakePoint(winFrame.origin.x + p.x,
+ winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view
+
+ DBG_PRINT( "newtRelClientTLWinPos2AbsBLScreenPos: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d] -> %d/%d\n",
+ (int)p.x, (int)p.y,
+ (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height,
+ (int)mViewFrame.origin.x, (int)mViewFrame.origin.y, (int)mViewFrame.size.width, (int)mViewFrame.size.height,
+ (int)r.x, (int)r.y);
+
+ return r;
}
-- (void) mouseEntered: (NSEvent*) theEvent
+- (NSSize) newtClientSize2TLSize: (NSSize) nsz
{
- DBG_PRINT( "mouseEntered: confined %d, visible %d\n", mouseConfined, mouseVisible);
- mouseInside = YES;
- [self cursorHide: !mouseVisible];
- if(NO == mouseConfined) {
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED];
+ NSSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom
+ return topSZ;
+}
+
+/**
+ * y-flips input / output
+ * p rel client window position w/ top-left origin
+ * returns: location in 0/0 top-left space.
+ */
+- (NSPoint) getLocationOnScreen: (NSPoint) p
+{
+ NSView* view = [self contentView];
+ NSRect viewFrame = [view frame];
+ NSRect r;
+ r.origin.x = p.x;
+ r.origin.y = viewFrame.size.height - p.y; // y-flip
+ r.size.width = 0;
+ r.size.height = 0;
+ // NSRect rS = [self convertRectToScreen: r]; // 10.7
+ NSPoint oS = [self convertBaseToScreen: r.origin]; // BL-screen
+
+ NSScreen* screen = [self screen];
+ CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+ CGRect frameTL = CGDisplayBounds (display); // origin top-left
+ NSRect frameBL = [screen frame]; // origin bottom-left
+ oS.y = frameTL.origin.y + frameTL.size.height - ( oS.y - frameBL.origin.y ); // y-flip from BL-screen -> TL-screen
+
+#ifdef VERBOSE_ON
+ NSRect winFrame = [self frame];
+ DBG_PRINT( "getLocationOnScreen: point-in[%d/%d], winFrame[%d/%d %dx%d], viewFrame[%d/%d %dx%d], screen tl[%d/%d %dx%d] bl[%d/%d %dx%d] -> %d/%d\n",
+ (int)p.x, (int)p.y,
+ (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height,
+ (int)viewFrame.origin.x, (int)viewFrame.origin.y, (int)viewFrame.size.width, (int)viewFrame.size.height,
+ (int)frameTL.origin.x, (int)frameTL.origin.y, (int)frameTL.size.width, (int)frameTL.size.height,
+ (int)frameBL.origin.x, (int)frameBL.origin.y, (int)frameBL.size.width, (int)frameBL.size.height,
+ (int)oS.x, (int)oS.y);
+#endif
+
+ return oS;
+}
+
+- (void) focusChanged: (BOOL) gained
+{
+ DBG_PRINT( "focusChanged: gained %d\n", gained);
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
+ return;
}
+ jobject javaWindowObject = [newtView getJavaWindowObject];
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("focusChanged: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("focusChanged: null JNIEnv\n");
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
-- (void) mouseExited: (NSEvent*) theEvent
+- (void) keyDown: (NSEvent*) theEvent
{
- DBG_PRINT( "mouseExited: confined %d, visible %d\n", mouseConfined, mouseVisible);
- if(NO == mouseConfined) {
- mouseInside = NO;
- [self cursorHide: NO];
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED];
- } else {
- [self setMousePosition: lastInsideMousePosition];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_PRESSED];
}
}
-- (void) mouseMoved: (NSEvent*) theEvent
+- (void) keyUp: (NSEvent*) theEvent
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_RELEASED];
+ }
}
-- (void) scrollWheel: (NSEvent*) theEvent
+- (void) flagsChanged:(NSEvent *) theEvent
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED];
+ NSUInteger mods = [theEvent modifierFlags];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView handleFlagsChanged: mods];
+ }
}
-- (void) mouseDown: (NSEvent*) theEvent
+- (BOOL) acceptsMouseMovedEvents
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ return YES;
}
-- (void) mouseDragged: (NSEvent*) theEvent
+- (BOOL) acceptsFirstResponder
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ return YES;
}
-- (void) mouseUp: (NSEvent*) theEvent
+- (BOOL) becomeFirstResponder
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** Win.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
}
-- (void) rightMouseDown: (NSEvent*) theEvent
+- (BOOL) resignFirstResponder
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ DBG_PRINT( "*************** Win.resignFirstResponder\n");
+ return [super resignFirstResponder];
}
-- (void) rightMouseDragged: (NSEvent*) theEvent
+- (BOOL) canBecomeKeyWindow
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ // Even if the window is borderless, we still want it to be able
+ // to become the key window to receive keyboard events
+ return YES;
}
-- (void) rightMouseUp: (NSEvent*) theEvent
+- (void) becomeKeyWindow
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** becomeKeyWindow\n");
+ [super becomeKeyWindow];
}
-- (void) otherMouseDown: (NSEvent*) theEvent
+- (void) resignKeyWindow
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
+ if(!isFullscreenWindow) {
+ [super resignKeyWindow];
+ }
}
-- (void) otherMouseDragged: (NSEvent*) theEvent
+- (void) windowDidBecomeKey: (NSNotification *) notification
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ DBG_PRINT( "*************** windowDidBecomeKey\n");
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ BOOL mouseInside = [newtView updateMouseInside];
+ if(YES == mouseInside) {
+ [newtView cursorHide: ![newtView isMouseVisible] enter: 1];
+ }
+ }
+ [self focusChanged: YES];
}
-- (void) otherMouseUp: (NSEvent*) theEvent
+- (void) windowDidResignKey: (NSNotification *) notification
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** windowDidResignKey\n");
+ // Implicit mouse exit by OS X
+ [self focusChanged: NO];
}
- (void)windowDidResize: (NSNotification*) notification
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (javaWindowObject == NULL) {
- DBG_PRINT("windowDidResize: null javaWindowObject\n");
- return;
- }
+ jobject javaWindowObject = NULL;
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
- if(NULL==env) {
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+
+ if( NULL == env ) {
DBG_PRINT("windowDidResize: null JNIEnv\n");
return;
}
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ javaWindowObject = [newtView getJavaWindowObject];
+ }
+ if( NULL != javaWindowObject ) {
+ // update insets on every window resize for lack of better hook place
+ [self updateInsets: env jwin:javaWindowObject];
- // update insets on every window resize for lack of better hook place
- [self updateInsets: env];
-
- NSRect frameRect = [self frame];
- NSRect contentRect = [self contentRectForFrameRect: frameRect];
-
- (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE,
- (jint) contentRect.size.width,
- (jint) contentRect.size.height, JNI_FALSE);
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_TRUE, // defer
+ (jint) contentRect.size.width,
+ (jint) contentRect.size.height, JNI_FALSE);
}
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void)windowDidMove: (NSNotification*) notification
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
return;
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
+ jobject javaWindowObject = [newtView getJavaWindowObject];
if (javaWindowObject == NULL) {
DBG_PRINT("windowDidMove: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("windowDidMove: null JNIEnv\n");
return;
@@ -948,9 +1224,8 @@ static jint mods2JavaMods(NSUInteger mods)
p0 = [self getLocationOnScreen: p0];
(*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (BOOL)windowShouldClose: (id) sender
@@ -966,41 +1241,38 @@ static jint mods2JavaMods(NSUInteger mods)
- (BOOL) windowClosingImpl: (BOOL) force
{
jboolean closed = JNI_FALSE;
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- [self cursorHide: NO];
-
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
return NO;
}
- NewtView* view = (NewtView *) nsview;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [newtView cursorHide: NO enter: -1];
- if( false == [view getDestroyNotifySent] ) {
- jobject javaWindowObject = [view getJavaWindowObject];
+ if( false == [newtView getDestroyNotifySent] ) {
+ jobject javaWindowObject = [newtView getJavaWindowObject];
DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject);
if (javaWindowObject == NULL) {
DBG_PRINT("windowWillClose: null javaWindowObject\n");
+ [pool release];
return NO;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("windowWillClose: null JNIEnv\n");
+ [pool release];
return NO;
}
-
- [view setDestroyNotifySent: true]; // earmark assumption of being closed
+ [newtView setDestroyNotifySent: true]; // earmark assumption of being closed
closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE);
if(!force && !closed) {
// not closed on java side, not force -> clear flag
- [view setDestroyNotifySent: false];
+ [newtView setDestroyNotifySent: false];
}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed);
} else {
DBG_PRINT( "*************** windowWillClose (skip)\n");
@@ -1010,3 +1282,4 @@ static jint mods2JavaMods(NSUInteger mods)
}
@end
+
diff --git a/src/newt/native/ScreenMode.h b/src/newt/native/ScreenMode.h
index bb782910e..56c424b11 100644
--- a/src/newt/native/ScreenMode.h
+++ b/src/newt/native/ScreenMode.h
@@ -33,12 +33,18 @@
#ifndef _SCREEN_MODE_H
#define _SCREEN_MODE_H
-#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */
-#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */
-#define NUM_MONITOR_MODE_PROPERTIES 3 /* ScreenSizeMM[width, height], refresh-rate */
-#define NUM_SCREEN_MODE_PROPERTIES 1 /* rotation */
+#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */
+#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */
+#define NUM_SIZEANDRATE_PROPERTIES 2 /* refresh-rate, flags */
+#define NUM_MONITOR_MODE_PROPERTIES 2 /* id, rotation */
-#define NUM_SCREEN_MODE_PROPERTIES_ALL 8 /* count + the above */
+#define NUM_MONITOR_MODE_PROPERTIES_ALL 8 /* count + the above */
+
+#define MIN_MONITOR_DEVICE_PROPERTIES 15 /* count + id, ScreenSizeMM[width, height], rotated Viewport pixel-units, rotated Viewport pixel-units, currentMonitorModeId, rotation, supportedModeId+ */
+ /* Viewport := [x, y, width, height] (4 elements) */
+
+#define FLAG_INTERLACE ( 1 << 0 )
+#define FLAG_DOUBLESCAN ( 1 << 1 )
#endif
diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h
index 4755c4fc5..d9ee5fd1f 100644
--- a/src/newt/native/Window.h
+++ b/src/newt/native/Window.h
@@ -38,8 +38,9 @@
#define FLAG_HAS_PARENT ( 1 << 8 )
#define FLAG_IS_UNDECORATED ( 1 << 9 )
#define FLAG_IS_FULLSCREEN ( 1 << 10 )
-#define FLAG_IS_ALWAYSONTOP ( 1 << 11 )
-#define FLAG_IS_VISIBLE ( 1 << 12 )
+#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 11 )
+#define FLAG_IS_ALWAYSONTOP ( 1 << 12 )
+#define FLAG_IS_VISIBLE ( 1 << 13 )
#define TST_FLAG_CHANGE_PARENTING(f) ( 0 != ( (f) & FLAG_CHANGE_PARENTING ) )
#define TST_FLAG_CHANGE_DECORATION(f) ( 0 != ( (f) & FLAG_CHANGE_DECORATION ) )
@@ -47,11 +48,11 @@
#define TST_FLAG_CHANGE_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONTOP ) )
#define TST_FLAG_CHANGE_VISIBILITY(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) )
-#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) )
-#define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) )
-#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
-#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
-#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) )
-#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) )
+#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) )
+#define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) )
+#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
+#define TST_FLAG_IS_FULLSCREEN_SPAN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN_SPAN ) )
+#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) )
+#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) )
#endif
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 40252f59b..70d0c6f83 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -32,6 +32,16 @@
*
*/
+//
+// Min. required version Windows 7 (For WM_TOUCH)
+//
+#if WINVER < 0x0601
+#error WINVER must be >= 0x0601
+#endif
+#if _WIN32_WINNT < 0x0601
+#error _WIN32_WINNT must be >= 0x0601
+#endif
+
#include <Windows.h>
#include <Windowsx.h>
#include <tchar.h>
@@ -49,13 +59,22 @@
#define strdup(s) _strdup(s)
#endif
+/* GetProcAddress doesn't exist in A/W variants under desktop Windows */
+#ifndef UNDER_CE
+#define GetProcAddressA GetProcAddress
+#endif
+
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif //WM_MOUSEWHEEL
-#ifndef WHEEL_DELTA
-#define WHEEL_DELTA 120
-#endif //WHEEL_DELTA
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif //WM_MOUSEHWHEEL
+
+#ifndef WHEEL_DELTAf
+#define WHEEL_DELTAf (120.0f)
+#endif //WHEEL_DELTAf
#ifndef WHEEL_PAGESCROLL
#define WHEEL_PAGESCROLL (UINT_MAX)
@@ -64,6 +83,30 @@
#ifndef GET_WHEEL_DELTA_WPARAM // defined for (_WIN32_WINNT >= 0x0500)
#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
#endif
+#ifndef GET_KEYSTATE_WPARAM
+#define GET_KEYSTATE_WPARAM(wParam) ((short)LOWORD(wParam))
+#endif
+
+#ifndef WM_HSCROLL
+#define WM_HSCROLL 0x0114
+#endif
+#ifndef WM_VSCROLL
+#define WM_VSCROLL 0x0115
+#endif
+
+#ifndef WH_MOUSE
+#define WH_MOUSE 7
+#endif
+#ifndef WH_MOUSE_LL
+#define WH_MOUSE_LL 14
+#endif
+
+#ifndef WM_TOUCH
+#define WM_TOUCH 0x0240
+#endif
+#ifndef TOUCH_COORD_TO_PIXEL
+#define TOUCH_COORD_TO_PIXEL(l) (l/100)
+#endif
#ifndef MONITOR_DEFAULTTONULL
#define MONITOR_DEFAULTTONULL 0
@@ -80,6 +123,9 @@
#ifndef DISPLAY_DEVICE_ACTIVE
#define DISPLAY_DEVICE_ACTIVE 0x00000001
#endif
+#ifndef DM_INTERLACED
+#define DM_INTERLACED 2
+#endif
#include "jogamp_newt_driver_windows_DisplayDriver.h"
#include "jogamp_newt_driver_windows_ScreenDriver.h"
@@ -111,504 +157,442 @@ static jmethodID focusChangedID = NULL;
static jmethodID visibleChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
static jmethodID sendMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
+static jmethodID sendTouchScreenEventID = NULL;
static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
+typedef WINBOOL (WINAPI *CloseTouchInputHandlePROCADDR)(HANDLE hTouchInput);
+typedef WINBOOL (WINAPI *GetTouchInputInfoPROCADDR)(HANDLE hTouchInput, UINT cInputs, PTOUCHINPUT pInputs, int cbSize);
+typedef WINBOOL (WINAPI *IsTouchWindowPROCADDR)(HWND hWnd,PULONG pulFlags);
+typedef WINBOOL (WINAPI *RegisterTouchWindowPROCADDR)(HWND hWnd,ULONG ulFlags);
+typedef WINBOOL (WINAPI *UnregisterTouchWindowPROCADDR)(HWND hWnd);
+
+static int WinTouch_func_avail = 0;
+static CloseTouchInputHandlePROCADDR WinTouch_CloseTouchInputHandle = NULL;
+static GetTouchInputInfoPROCADDR WinTouch_GetTouchInputInfo = NULL;
+static IsTouchWindowPROCADDR WinTouch_IsTouchWindow = NULL;
+static RegisterTouchWindowPROCADDR WinTouch_RegisterTouchWindow = NULL;
+static UnregisterTouchWindowPROCADDR WinTouch_UnregisterTouchWindow = NULL;
+
static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd);
typedef struct {
JNIEnv* jenv;
jobject jinstance;
+ /* client size width */
+ int width;
+ /* client size height */
+ int height;
+ /** Tristate: -1 HIDE, 0 NOP, 1 SHOW */
+ int setPointerVisible;
+ /** Tristate: -1 RESET, 0 NOP, 1 SET-NEW */
+ int setPointerAction;
+ HCURSOR setPointerHandle;
+ HCURSOR defPointerHandle;
+ /** Bool: 0 NOP, 1 FULLSCREEN */
+ int isFullscreen;
+ /** Bool: 0 TOP, 1 CHILD */
+ int isChildWindow;
+ int pointerCaptured;
+ int pointerInside;
+ int touchDownCount;
+ int touchDownLastUp; // mitigate LBUTTONUP after last TOUCH lift
+ int supportsMTouch;
} WindowUserData;
typedef struct {
- UINT javaKey;
- UINT windowsKey;
+ USHORT javaKey;
+ USHORT windowsKey;
+ USHORT windowsScanCodeUS;
} KeyMapEntry;
// Static table, arranged more or less spatially.
static KeyMapEntry keyMapTable[] = {
// Modifier keys
- {J_VK_CAPS_LOCK, VK_CAPITAL},
- {J_VK_SHIFT, VK_SHIFT},
- {J_VK_CONTROL, VK_CONTROL},
- {J_VK_ALT, VK_MENU},
- {J_VK_NUM_LOCK, VK_NUMLOCK},
+ {J_VK_CAPS_LOCK, VK_CAPITAL, 0},
+ {J_VK_SHIFT, VK_SHIFT, 0},
+ {J_VK_SHIFT, VK_LSHIFT, 0},
+ {J_VK_SHIFT, VK_RSHIFT, 0},
+ {J_VK_CONTROL, VK_CONTROL, 0},
+ {J_VK_CONTROL, VK_LCONTROL, 0},
+ {J_VK_CONTROL, VK_RCONTROL, 0},
+ {J_VK_ALT, VK_MENU, 0},
+ {J_VK_ALT, VK_LMENU, 0},
+ {J_VK_ALT_GRAPH, VK_RMENU, 0},
+ {J_VK_NUM_LOCK, VK_NUMLOCK, 0},
// Miscellaneous Windows keys
- {J_VK_WINDOWS, VK_LWIN},
- {J_VK_WINDOWS, VK_RWIN},
- {J_VK_CONTEXT_MENU, VK_APPS},
+ {J_VK_WINDOWS, VK_LWIN, 0},
+ {J_VK_WINDOWS, VK_RWIN, 0},
+ {J_VK_CONTEXT_MENU, VK_APPS, 0},
// Alphabet
- {J_VK_A, 'A'},
- {J_VK_B, 'B'},
- {J_VK_C, 'C'},
- {J_VK_D, 'D'},
- {J_VK_E, 'E'},
- {J_VK_F, 'F'},
- {J_VK_G, 'G'},
- {J_VK_H, 'H'},
- {J_VK_I, 'I'},
- {J_VK_J, 'J'},
- {J_VK_K, 'K'},
- {J_VK_L, 'L'},
- {J_VK_M, 'M'},
- {J_VK_N, 'N'},
- {J_VK_O, 'O'},
- {J_VK_P, 'P'},
- {J_VK_Q, 'Q'},
- {J_VK_R, 'R'},
- {J_VK_S, 'S'},
- {J_VK_T, 'T'},
- {J_VK_U, 'U'},
- {J_VK_V, 'V'},
- {J_VK_W, 'W'},
- {J_VK_X, 'X'},
- {J_VK_Y, 'Y'},
- {J_VK_Z, 'Z'},
- {J_VK_0, '0'},
- {J_VK_1, '1'},
- {J_VK_2, '2'},
- {J_VK_3, '3'},
- {J_VK_4, '4'},
- {J_VK_5, '5'},
- {J_VK_6, '6'},
- {J_VK_7, '7'},
- {J_VK_8, '8'},
- {J_VK_9, '9'},
- {J_VK_ENTER, VK_RETURN},
- {J_VK_SPACE, VK_SPACE},
- {J_VK_BACK_SPACE, VK_BACK},
- {J_VK_TAB, VK_TAB},
- {J_VK_ESCAPE, VK_ESCAPE},
- {J_VK_INSERT, VK_INSERT},
- {J_VK_DELETE, VK_DELETE},
- {J_VK_HOME, VK_HOME},
- {J_VK_END, VK_END},
- {J_VK_PAGE_UP, VK_PRIOR},
- {J_VK_PAGE_DOWN, VK_NEXT},
- {J_VK_CLEAR, VK_CLEAR}, // NumPad 5
+ {J_VK_A, 'A', 0},
+ {J_VK_B, 'B', 0},
+ {J_VK_C, 'C', 0},
+ {J_VK_D, 'D', 0},
+ {J_VK_E, 'E', 0},
+ {J_VK_F, 'F', 0},
+ {J_VK_G, 'G', 0},
+ {J_VK_H, 'H', 0},
+ {J_VK_I, 'I', 0},
+ {J_VK_J, 'J', 0},
+ {J_VK_K, 'K', 0},
+ {J_VK_L, 'L', 0},
+ {J_VK_M, 'M', 0},
+ {J_VK_N, 'N', 0},
+ {J_VK_O, 'O', 0},
+ {J_VK_P, 'P', 0},
+ {J_VK_Q, 'Q', 0},
+ {J_VK_R, 'R', 0},
+ {J_VK_S, 'S', 0},
+ {J_VK_T, 'T', 0},
+ {J_VK_U, 'U', 0},
+ {J_VK_V, 'V', 0},
+ {J_VK_W, 'W', 0},
+ {J_VK_X, 'X', 0},
+ {J_VK_Y, 'Y', 0},
+ {J_VK_Z, 'Z', 0},
+ {J_VK_0, '0', 0},
+ {J_VK_1, '1', 0},
+ {J_VK_2, '2', 0},
+ {J_VK_3, '3', 0},
+ {J_VK_4, '4', 0},
+ {J_VK_5, '5', 0},
+ {J_VK_6, '6', 0},
+ {J_VK_7, '7', 0},
+ {J_VK_8, '8', 0},
+ {J_VK_9, '9', 0},
+ {J_VK_ENTER, VK_RETURN, 0},
+ {J_VK_SPACE, VK_SPACE, 0},
+ {J_VK_BACK_SPACE, VK_BACK, 0},
+ {J_VK_TAB, VK_TAB, 0},
+ {J_VK_ESCAPE, VK_ESCAPE, 0},
+ {J_VK_INSERT, VK_INSERT, 0},
+ {J_VK_DELETE, VK_DELETE, 0},
+ {J_VK_HOME, VK_HOME, 0},
+ // {J_VK_BEGIN, VK_BEGIN, 0}, // not mapped
+ {J_VK_END, VK_END, 0},
+ {J_VK_PAGE_UP, VK_PRIOR, 0},
+ {J_VK_PAGE_DOWN, VK_NEXT, 0},
+ {J_VK_CLEAR, VK_CLEAR, 0}, // NumPad 5
// NumPad with NumLock off & extended arrows block (triangular)
- {J_VK_LEFT, VK_LEFT},
- {J_VK_RIGHT, VK_RIGHT},
- {J_VK_UP, VK_UP},
- {J_VK_DOWN, VK_DOWN},
+ {J_VK_LEFT, VK_LEFT, 0},
+ {J_VK_RIGHT, VK_RIGHT, 0},
+ {J_VK_UP, VK_UP, 0},
+ {J_VK_DOWN, VK_DOWN, 0},
// NumPad with NumLock on: numbers
- {J_VK_NUMPAD0, VK_NUMPAD0},
- {J_VK_NUMPAD1, VK_NUMPAD1},
- {J_VK_NUMPAD2, VK_NUMPAD2},
- {J_VK_NUMPAD3, VK_NUMPAD3},
- {J_VK_NUMPAD4, VK_NUMPAD4},
- {J_VK_NUMPAD5, VK_NUMPAD5},
- {J_VK_NUMPAD6, VK_NUMPAD6},
- {J_VK_NUMPAD7, VK_NUMPAD7},
- {J_VK_NUMPAD8, VK_NUMPAD8},
- {J_VK_NUMPAD9, VK_NUMPAD9},
+ {J_VK_NUMPAD0, VK_NUMPAD0, 0},
+ {J_VK_NUMPAD1, VK_NUMPAD1, 0},
+ {J_VK_NUMPAD2, VK_NUMPAD2, 0},
+ {J_VK_NUMPAD3, VK_NUMPAD3, 0},
+ {J_VK_NUMPAD4, VK_NUMPAD4, 0},
+ {J_VK_NUMPAD5, VK_NUMPAD5, 0},
+ {J_VK_NUMPAD6, VK_NUMPAD6, 0},
+ {J_VK_NUMPAD7, VK_NUMPAD7, 0},
+ {J_VK_NUMPAD8, VK_NUMPAD8, 0},
+ {J_VK_NUMPAD9, VK_NUMPAD9, 0},
// NumPad with NumLock on
- {J_VK_MULTIPLY, VK_MULTIPLY},
- {J_VK_ADD, VK_ADD},
- {J_VK_SEPARATOR, VK_SEPARATOR},
- {J_VK_SUBTRACT, VK_SUBTRACT},
- {J_VK_DECIMAL, VK_DECIMAL},
- {J_VK_DIVIDE, VK_DIVIDE},
+ {J_VK_MULTIPLY, VK_MULTIPLY, 0},
+ {J_VK_ADD, VK_ADD, 0},
+ {J_VK_SEPARATOR, VK_SEPARATOR, 0},
+ {J_VK_SUBTRACT, VK_SUBTRACT, 0},
+ {J_VK_DECIMAL, VK_DECIMAL, 0},
+ {J_VK_DIVIDE, VK_DIVIDE, 0},
// Functional keys
- {J_VK_F1, VK_F1},
- {J_VK_F2, VK_F2},
- {J_VK_F3, VK_F3},
- {J_VK_F4, VK_F4},
- {J_VK_F5, VK_F5},
- {J_VK_F6, VK_F6},
- {J_VK_F7, VK_F7},
- {J_VK_F8, VK_F8},
- {J_VK_F9, VK_F9},
- {J_VK_F10, VK_F10},
- {J_VK_F11, VK_F11},
- {J_VK_F12, VK_F12},
- {J_VK_F13, VK_F13},
- {J_VK_F14, VK_F14},
- {J_VK_F15, VK_F15},
- {J_VK_F16, VK_F16},
- {J_VK_F17, VK_F17},
- {J_VK_F18, VK_F18},
- {J_VK_F19, VK_F19},
- {J_VK_F20, VK_F20},
- {J_VK_F21, VK_F21},
- {J_VK_F22, VK_F22},
- {J_VK_F23, VK_F23},
- {J_VK_F24, VK_F24},
-
- {J_VK_PRINTSCREEN, VK_SNAPSHOT},
- {J_VK_SCROLL_LOCK, VK_SCROLL},
- {J_VK_PAUSE, VK_PAUSE},
- {J_VK_CANCEL, VK_CANCEL},
- {J_VK_HELP, VK_HELP},
+ {J_VK_F1, VK_F1, 0},
+ {J_VK_F2, VK_F2, 0},
+ {J_VK_F3, VK_F3, 0},
+ {J_VK_F4, VK_F4, 0},
+ {J_VK_F5, VK_F5, 0},
+ {J_VK_F6, VK_F6, 0},
+ {J_VK_F7, VK_F7, 0},
+ {J_VK_F8, VK_F8, 0},
+ {J_VK_F9, VK_F9, 0},
+ {J_VK_F10, VK_F10, 0},
+ {J_VK_F11, VK_F11, 0},
+ {J_VK_F12, VK_F12, 0},
+ {J_VK_F13, VK_F13, 0},
+ {J_VK_F14, VK_F14, 0},
+ {J_VK_F15, VK_F15, 0},
+ {J_VK_F16, VK_F16, 0},
+ {J_VK_F17, VK_F17, 0},
+ {J_VK_F18, VK_F18, 0},
+ {J_VK_F19, VK_F19, 0},
+ {J_VK_F20, VK_F20, 0},
+ {J_VK_F21, VK_F21, 0},
+ {J_VK_F22, VK_F22, 0},
+ {J_VK_F23, VK_F23, 0},
+ {J_VK_F24, VK_F24, 0},
+
+ {J_VK_PRINTSCREEN, VK_SNAPSHOT, 0},
+ {J_VK_SCROLL_LOCK, VK_SCROLL, 0},
+ {J_VK_PAUSE, VK_PAUSE, 0},
+ {J_VK_CANCEL, VK_CANCEL, 0},
+ {J_VK_HELP, VK_HELP, 0},
+
+ // Since we unify mappings via US kbd layout .. this is valid:
+ {J_VK_SEMICOLON, VK_OEM_1, 0}, // US only ';:'
+ {J_VK_EQUALS, VK_OEM_PLUS, 0}, // '=+'
+ {J_VK_COMMA, VK_OEM_COMMA, 0}, // ',<'
+ {J_VK_MINUS, VK_OEM_MINUS, 0}, // '-_'
+ {J_VK_PERIOD, VK_OEM_PERIOD, 0}, // '.>'
+ {J_VK_SLASH, VK_OEM_2, 0}, // US only '/?'
+ {J_VK_BACK_QUOTE, VK_OEM_3, 0}, // US only '`~'
+ {J_VK_OPEN_BRACKET, VK_OEM_4, 0}, // US only '[}'
+ {J_VK_BACK_SLASH, VK_OEM_5, 0}, // US only '\|'
+ {J_VK_CLOSE_BRACKET, VK_OEM_6, 0}, // US only ']}'
+ {J_VK_QUOTE, VK_OEM_7, 0}, // US only ''"'
+ // {J_VK_????, VK_OEM_8, 0}, // varies ..
+ // {J_VK_????, VK_OEM_102, 0}, // angle-bracket or backslash key on RT 102-key kbd
// Japanese
/*
- {J_VK_CONVERT, VK_CONVERT},
- {J_VK_NONCONVERT, VK_NONCONVERT},
- {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
- {J_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC},
- {J_VK_KATAKANA, VK_DBE_KATAKANA},
- {J_VK_HIRAGANA, VK_DBE_HIRAGANA},
- {J_VK_FULL_WIDTH, VK_DBE_DBCSCHAR},
- {J_VK_HALF_WIDTH, VK_DBE_SBCSCHAR},
- {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
+ {J_VK_CONVERT, VK_CONVERT, 0},
+ {J_VK_NONCONVERT, VK_NONCONVERT, 0},
+ {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI, 0},
+ {J_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC, 0},
+ {J_VK_KATAKANA, VK_DBE_KATAKANA, 0},
+ {J_VK_HIRAGANA, VK_DBE_HIRAGANA, 0},
+ {J_VK_FULL_WIDTH, VK_DBE_DBCSCHAR, 0},
+ {J_VK_HALF_WIDTH, VK_DBE_SBCSCHAR, 0},
+ {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN, 0},
*/
- {J_VK_UNDEFINED, 0}
-};
-
-/*
-Dynamic mapping table for OEM VK codes. This table is refilled
-by BuildDynamicKeyMapTable when keyboard layout is switched.
-(see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
-*/
-typedef struct {
- // OEM VK codes known in advance
- UINT windowsKey;
- // depends on input langauge (kbd layout)
- UINT javaKey;
-} DynamicKeyMapEntry;
-
-static DynamicKeyMapEntry dynamicKeyMapTable[] = {
- {0x00BA, J_VK_UNDEFINED}, // VK_OEM_1
- {0x00BB, J_VK_UNDEFINED}, // VK_OEM_PLUS
- {0x00BC, J_VK_UNDEFINED}, // VK_OEM_COMMA
- {0x00BD, J_VK_UNDEFINED}, // VK_OEM_MINUS
- {0x00BE, J_VK_UNDEFINED}, // VK_OEM_PERIOD
- {0x00BF, J_VK_UNDEFINED}, // VK_OEM_2
- {0x00C0, J_VK_UNDEFINED}, // VK_OEM_3
- {0x00DB, J_VK_UNDEFINED}, // VK_OEM_4
- {0x00DC, J_VK_UNDEFINED}, // VK_OEM_5
- {0x00DD, J_VK_UNDEFINED}, // VK_OEM_6
- {0x00DE, J_VK_UNDEFINED}, // VK_OEM_7
- {0x00DF, J_VK_UNDEFINED}, // VK_OEM_8
- {0x00E2, J_VK_UNDEFINED}, // VK_OEM_102
- {0, 0}
+ {J_VK_UNDEFINED, 0, 0}
};
-// Auxiliary tables used to fill the above dynamic table. We first
-// find the character for the OEM VK code using ::MapVirtualKey and
-// then go through these auxiliary tables to map it to Java VK code.
+#ifndef KLF_ACTIVATE
+ #define KLF_ACTIVATE 0x00000001
+#endif
+#ifndef MAPVK_VK_TO_VSC
+ #define MAPVK_VK_TO_VSC 0
+#endif
+#ifndef MAPVK_VSC_TO_VK
+ #define MAPVK_VSC_TO_VK 1
+#endif
+#ifndef MAPVK_VK_TO_CHAR
+ #define MAPVK_VK_TO_CHAR 2
+#endif
+#ifndef MAPVK_VSC_TO_VK_EX
+ #define MAPVK_VSC_TO_VK_EX 3
+#endif
+#ifndef MAPVK_VK_TO_VSC_EX
+ #define MAPVK_VK_TO_VSC_EX 4
+#endif
-typedef struct {
- WCHAR c;
- UINT javaKey;
-} CharToVKEntry;
-
-static const CharToVKEntry charToVKTable[] = {
- {L'!', J_VK_EXCLAMATION_MARK},
- {L'"', J_VK_QUOTEDBL},
- {L'#', J_VK_NUMBER_SIGN},
- {L'$', J_VK_DOLLAR},
- {L'&', J_VK_AMPERSAND},
- {L'\'', J_VK_QUOTE},
- {L'(', J_VK_LEFT_PARENTHESIS},
- {L')', J_VK_RIGHT_PARENTHESIS},
- {L'*', J_VK_ASTERISK},
- {L'+', J_VK_PLUS},
- {L',', J_VK_COMMA},
- {L'-', J_VK_MINUS},
- {L'.', J_VK_PERIOD},
- {L'/', J_VK_SLASH},
- {L':', J_VK_COLON},
- {L';', J_VK_SEMICOLON},
- {L'<', J_VK_LESS},
- {L'=', J_VK_EQUALS},
- {L'>', J_VK_GREATER},
- {L'@', J_VK_AT},
- {L'[', J_VK_OPEN_BRACKET},
- {L'\\', J_VK_BACK_SLASH},
- {L']', J_VK_CLOSE_BRACKET},
- {L'^', J_VK_CIRCUMFLEX},
- {L'_', J_VK_UNDERSCORE},
- {L'`', J_VK_BACK_QUOTE},
- {L'{', J_VK_BRACELEFT},
- {L'}', J_VK_BRACERIGHT},
- {0x00A1, J_VK_INVERTED_EXCLAMATION_MARK},
- {0x20A0, J_VK_EURO_SIGN}, // ????
- {0,0}
-};
+#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
-// For dead accents some layouts return ASCII punctuation, while some
-// return spacing accent chars, so both should be listed. NB: MS docs
-// say that conversion routings return spacing accent character, not
-// combining.
-static const CharToVKEntry charToDeadVKTable[] = {
- {L'`', J_VK_DEAD_GRAVE},
- {L'\'', J_VK_DEAD_ACUTE},
- {0x00B4, J_VK_DEAD_ACUTE},
- {L'^', J_VK_DEAD_CIRCUMFLEX},
- {L'~', J_VK_DEAD_TILDE},
- {0x02DC, J_VK_DEAD_TILDE},
- {0x00AF, J_VK_DEAD_MACRON},
- {0x02D8, J_VK_DEAD_BREVE},
- {0x02D9, J_VK_DEAD_ABOVEDOT},
- {L'"', J_VK_DEAD_DIAERESIS},
- {0x00A8, J_VK_DEAD_DIAERESIS},
- {0x02DA, J_VK_DEAD_ABOVERING},
- {0x02DD, J_VK_DEAD_DOUBLEACUTE},
- {0x02C7, J_VK_DEAD_CARON}, // aka hacek
- {L',', J_VK_DEAD_CEDILLA},
- {0x00B8, J_VK_DEAD_CEDILLA},
- {0x02DB, J_VK_DEAD_OGONEK},
- {0x037A, J_VK_DEAD_IOTA}, // ASCII ???
- {0x309B, J_VK_DEAD_VOICED_SOUND},
- {0x309C, J_VK_DEAD_SEMIVOICED_SOUND},
- {0,0}
-};
+static HKL kbdLayoutUS = 0;
+static const LPCSTR US_LAYOUT_NAME = "00000409";
-// ANSI CP identifiers are no longer than this
-#define MAX_ACP_STR_LEN 7
+static BYTE kbdState[256];
+static USHORT spaceScanCode;
-static void BuildDynamicKeyMapTable()
-{
+static void InitKeyMapTableScanCode(JNIEnv *env) {
HKL hkl = GetKeyboardLayout(0);
- // Will need this to reset layout after dead keys.
- UINT spaceScanCode = MapVirtualKeyEx(VK_SPACE, 0, hkl);
- DynamicKeyMapEntry *dynamic;
-
- LANGID idLang = LOWORD(GetKeyboardLayout(0));
- UINT codePage;
- TCHAR strCodePage[MAX_ACP_STR_LEN];
- // use the LANGID to create a LCID
- LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
- // get the ANSI code page associated with this locale
- if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE,
- strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
- {
- codePage = _ttoi(strCodePage);
- } else {
- codePage = GetACP();
+ int i;
+
+ kbdLayoutUS = LoadKeyboardLayout( US_LAYOUT_NAME, 0 /* ? KLF_ACTIVATE ? */ );
+ if( 0 == kbdLayoutUS ) {
+ int lastError = (int) GetLastError();
+ kbdLayoutUS = hkl; // use prev. layout .. well
+ STD_PRINT("Warning: NEWT Windows: LoadKeyboardLayout(US, ..) failed: winErr 0x%X %d\n", lastError, lastError);
}
+ ActivateKeyboardLayout(hkl, 0);
- // Entries in dynamic table that maps between Java VK and Windows
- // VK are built in three steps:
- // 1. Map windows VK to ANSI character (cannot map to unicode
- // directly, since ::ToUnicode is not implemented on win9x)
- // 2. Convert ANSI char to Unicode char
- // 3. Map Unicode char to Java VK via two auxilary tables.
+ spaceScanCode = MapVirtualKeyEx(VK_SPACE, MAPVK_VK_TO_VSC, hkl);
- for (dynamic = dynamicKeyMapTable; dynamic->windowsKey != 0; ++dynamic)
- {
- char cbuf[2] = { '\0', '\0'};
- WCHAR ucbuf[2] = { L'\0', L'\0' };
- int nchars;
- UINT scancode;
- const CharToVKEntry *charMap;
- int nconverted;
- WCHAR uc;
- BYTE kbdState[256];
-
- // Defaults to J_VK_UNDEFINED
- dynamic->javaKey = J_VK_UNDEFINED;
-
- GetKeyboardState(kbdState);
-
- kbdState[dynamic->windowsKey] |= 0x80; // Press the key.
-
- // Unpress modifiers, since they are most likely pressed as
- // part of the keyboard switching shortcut.
- kbdState[VK_CONTROL] &= ~0x80;
- kbdState[VK_SHIFT] &= ~0x80;
- kbdState[VK_MENU] &= ~0x80;
-
- scancode = MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
- nchars = ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
- (WORD*)cbuf, 0, hkl);
-
- // Auxiliary table used to map Unicode character to Java VK.
- // Will assign a different table for dead keys (below).
- charMap = charToVKTable;
-
- if (nchars < 0) { // Dead key
- char junkbuf[2] = { '\0', '\0'};
- // Use a different table for dead chars since different layouts
- // return different characters for the same dead key.
- charMap = charToDeadVKTable;
-
- // We also need to reset layout so that next translation
- // is unaffected by the dead status. We do this by
- // translating <SPACE> key.
- kbdState[dynamic->windowsKey] &= ~0x80;
- kbdState[VK_SPACE] |= 0x80;
-
- ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
- (WORD*)junkbuf, 0, hkl);
+ // Setup keyMapTable's windowsScanCodeUS
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ USHORT scancode = (USHORT) MapVirtualKeyEx(keyMapTable[i].windowsKey, MAPVK_VK_TO_VSC_EX, kbdLayoutUS);
+ #ifdef DEBUG_KEYS
+ if( 0 == scancode ) {
+ int lastError = (int) GetLastError();
+ STD_PRINT("*** WindowsWindow: InitKeyMapTableScanCode: No ScanCode for windows vkey 0x%X (item %d), winErr 0x%X %d\n",
+ keyMapTable[i].windowsKey, i, lastError, lastError);
}
+ STD_PRINT("*** WindowsWindow: InitKeyMapTableScanCode: %3.3d windows vkey 0x%X -> scancode 0x%X\n",
+ i, keyMapTable[i].windowsKey, scancode);
+ #endif
+ keyMapTable[i].windowsScanCodeUS = scancode;
+ }
+}
- nconverted = MultiByteToWideChar(codePage, 0,
- cbuf, 1, ucbuf, 2);
+static void ParseWmVKeyAndScanCode(USHORT winVKey, BYTE winScanCode, BYTE flags, USHORT *outJavaVKeyUS, USHORT *outJavaVKeyXX, USHORT *outUTF16Char) {
+ wchar_t uniChars[2] = { L'\0', L'\0' }; // uint16_t
+ USHORT winVKeyUS = 0;
+ int nUniChars, i, j;
+ USHORT javaVKeyUS = J_VK_UNDEFINED;
+ USHORT javaVKeyXX = J_VK_UNDEFINED;
- uc = ucbuf[0];
- {
- const CharToVKEntry *map;
- for (map = charMap; map->c != 0; ++map) {
- if (uc == map->c) {
- dynamic->javaKey = map->javaKey;
- break;
- }
+ HKL hkl = GetKeyboardLayout(0);
+
+ //
+ // winVKey, winScanCode -> UTF16 w/ current KeyboardLayout
+ //
+ GetKeyboardState(kbdState);
+ kbdState[winVKey] |= 0x80;
+ nUniChars = ToUnicodeEx(winVKey, winScanCode, kbdState, uniChars, 2, 0, hkl);
+ kbdState[winVKey] &= ~0x80;
+
+ *outUTF16Char = (USHORT)(uniChars[0]); // Note: Even dead key are written in uniChar's ..
+
+ if ( 0 > nUniChars ) { // Dead key
+ char junkbuf[2] = { '\0', '\0'};
+
+ // We need to reset layout so that next translation
+ // is unaffected by the dead status. We do this by
+ // translating <SPACE> key.
+ kbdState[VK_SPACE] |= 0x80;
+ ToAsciiEx(VK_SPACE, spaceScanCode, kbdState, (WORD*)junkbuf, 0, hkl);
+ kbdState[VK_SPACE] &= ~0x80;
+ }
+
+ //
+ // winVKey -> javaVKeyXX
+ //
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ if ( keyMapTable[i].windowsKey == winVKey ) {
+ javaVKeyXX = keyMapTable[i].javaKey;
+ break;
+ }
+ }
+ if( IS_WITHIN( winVKey, VK_NUMPAD0, VK_DIVIDE ) ) {
+ // Use modded keySym for keypad for US and NN
+ winVKeyUS = winVKey;
+ javaVKeyUS = javaVKeyXX;
+ } else {
+ // Assume extended scan code 0xE0 if extended flags is set (no 0xE1 from WM_KEYUP/WM_KEYDOWN)
+ USHORT winScanCodeExt = winScanCode;
+ if( 0 != ( 0x01 & flags ) ) {
+ winScanCodeExt |= 0xE000;
+ }
+
+ //
+ // winVKey, winScanCodeExt -> javaVKeyUS w/ US KeyboardLayout
+ //
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ if ( keyMapTable[i].windowsScanCodeUS == winScanCodeExt ) {
+ winVKeyUS = keyMapTable[i].windowsKey;
+ javaVKeyUS = keyMapTable[i].javaKey;
+ break;
}
}
+ if( J_VK_UNDEFINED == javaVKeyUS ) {
+ javaVKeyUS = javaVKeyXX;
+ }
+ }
+
+ *outJavaVKeyUS = javaVKeyUS;
+ *outJavaVKeyXX = javaVKeyXX;
- } // for each VK_OEM_*
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: ParseWmVKeyAndScanCode winVKey 0x%X, winScanCode 0x%X, flags 0x%X -> UTF(0x%X, %c, res %d, sizeof %d), vKeys( US(win 0x%X, java 0x%X), XX(win 0x%X, java 0x%X))\n",
+ (int)winVKey, (int)winScanCode, (int)flags,
+ *outUTF16Char, *outUTF16Char, nUniChars, sizeof(uniChars[0]),
+ winVKeyUS, javaVKeyUS, winVKey, javaVKeyXX);
+#endif
}
-static jint GetModifiers() {
+static jint GetModifiers(USHORT jkey) {
jint modifiers = 0;
// have to do &0xFFFF to avoid runtime assert caused by compiling with
// /RTCcsu
- if (HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0 || J_VK_CONTROL == jkey ) {
modifiers |= EVENT_CTRL_MASK;
}
- if (HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0 || J_VK_SHIFT == jkey ) {
modifiers |= EVENT_SHIFT_MASK;
}
- if (HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_LMENU) & 0xFFFF)) != 0 || J_VK_ALT == jkey ) {
modifiers |= EVENT_ALT_MASK;
}
- if (HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_RMENU) & 0xFFFF)) != 0 || (USHORT)J_VK_ALT_GRAPH == jkey ) {
+ modifiers |= EVENT_ALT_GRAPH_MASK;
+ }
+ if ( HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON1_MASK;
}
- if (HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON2_MASK;
}
- if (HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON3_MASK;
}
return modifiers;
}
-static int WmChar(JNIEnv *env, jobject window, UINT character, UINT repCnt,
- UINT flags, BOOL system)
-{
+/**
+static BOOL IsAltKeyDown(BYTE flags, BOOL system) {
// The Alt modifier is reported in the 29th bit of the lParam,
- // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
- BOOL alt_is_down = (flags & (1<<13)) != 0;
- if (system && alt_is_down) {
- if (character == VK_SPACE) {
- return 1;
- }
- }
+ // i.e., it is the 5th bit of `flags' (which is HIBYTE(HIWORD(lParam))).
+ return system && ( flags & (1<<5) ) != 0;
+} */
- if (character == VK_RETURN) {
- character = J_VK_ENTER;
- }
- (*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_TYPED,
- GetModifiers(),
- (jint) -1,
- (jchar) character);
- return 1;
-}
-
-UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers)
-{
- int i, j;
- // for the general case, use a bi-directional table
- for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
- if (keyMapTable[i].windowsKey == windowsKey) {
- return keyMapTable[i].javaKey;
- }
- }
- for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
- if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
- if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) {
- return dynamicKeyMapTable[j].javaKey;
- } else {
- break;
- }
- }
- }
-
- return J_VK_UNDEFINED;
-}
-
-static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
- UINT flags, BOOL system)
-{
- UINT modifiers = 0, jkey = 0, character = -1;
+static int WmKeyDown(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+ UINT modifiers = 0;
+ USHORT javaVKeyUS=0, javaVKeyXX=0, utf16Char=0;
if (wkey == VK_PROCESSKEY) {
return 1;
}
- modifiers = GetModifiers();
- jkey = WindowsKeyToJavaKey(wkey, modifiers);
+ ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char);
-/*
- character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
-*/
+ modifiers = GetModifiers( javaVKeyUS );
(*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_PRESSED,
- modifiers,
- (jint) jkey,
- (jchar) character);
-
- /* windows does not create a WM_CHAR for the Del key
- for some reason, so we need to create the KEY_TYPED event on the
- WM_KEYDOWN.
- */
- if (jkey == J_VK_DELETE) {
- (*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_TYPED,
- GetModifiers(),
- (jint) -1,
- (jchar) '\177');
- }
+ (jshort) EVENT_KEY_PRESSED,
+ (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char);
return 0;
}
-static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
- UINT flags, BOOL system)
-{
- UINT modifiers = 0, jkey = 0, character = -1;
+static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+ UINT modifiers = 0;
+ USHORT javaVKeyUS=0, javaVKeyXX=0, utf16Char=0;
if (wkey == VK_PROCESSKEY) {
return 1;
}
- modifiers = GetModifiers();
- jkey = WindowsKeyToJavaKey(wkey, modifiers);
-/*
- character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
-*/
+ ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char);
+
+ modifiers = GetModifiers( javaVKeyUS );
(*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_RELEASED,
- modifiers,
- (jint) jkey,
- (jchar) character);
+ (jshort) EVENT_KEY_RELEASED,
+ (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char);
return 0;
}
static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jboolean force) {
HWND pHwnd, current;
+ BOOL isEnabled = IsWindowEnabled(hwnd);
pHwnd = GetParent(hwnd);
current = GetFocus();
- DBG_PRINT("*** WindowsWindow: requestFocus.S parent %p, window %p, isCurrent %d\n",
- (void*) pHwnd, (void*)hwnd, current==hwnd);
+ DBG_PRINT("*** WindowsWindow: requestFocus.S force %d, parent %p, window %p, isEnabled %d, isCurrent %d\n",
+ (int)force, (void*)pHwnd, (void*)hwnd, isEnabled, current==hwnd);
- if( JNI_TRUE==force || current!=hwnd) {
+ if( JNI_TRUE==force || current!=hwnd || !isEnabled ) {
UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if(!isEnabled) {
+ EnableWindow(hwnd, TRUE);
+ }
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags);
SetForegroundWindow(hwnd); // Slightly Higher Priority
- SetFocus(hwnd);// Sets Keyboard Focus To Window
+ SetFocus(hwnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window)
if(NULL!=pHwnd) {
SetActiveWindow(hwnd);
}
- DBG_PRINT("*** WindowsWindow: requestFocus.X1\n");
+ current = GetFocus();
+ DBG_PRINT("*** WindowsWindow: requestFocus.X1 isCurrent %d\n", current==hwnd);
}
DBG_PRINT("*** WindowsWindow: requestFocus.XX\n");
}
@@ -620,7 +604,33 @@ static void NewtWindows_trackPointerLeave(HWND hwnd) {
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
tme.dwHoverTime = 0; // we don't use TME_HOVER
- TrackMouseEvent(&tme);
+ BOOL ok = TrackMouseEvent(&tme);
+ DBG_PRINT( "*** WindowsWindow: trackPointerLeave: %d\n", ok);
+ #ifdef VERBOSE_ON
+ if(!ok) {
+ int lastError = (int) GetLastError();
+ DBG_PRINT( "*** WindowsWindow: trackPointerLeave: lastError 0x%X %d\n", lastError, lastError);
+ }
+ #endif
+ (void)ok;
+}
+
+static jboolean NewtWindows_setFullScreen(jboolean fullscreen)
+{
+ int flags = 0;
+ DEVMODE dm;
+
+ // initialize the DEVMODE structure
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
+ {
+ return JNI_FALSE;
+ }
+ flags = ( JNI_TRUE == fullscreen ) ? CDS_FULLSCREEN : CDS_RESET ;
+
+ return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE;
}
#if 0
@@ -711,7 +721,7 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
{
LONG style = GetWindowLong(hwnd, GWL_STYLE);
- BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP|WS_SYSMENU)) != 0;
+ BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP)) != 0;
if (!bIsUndecorated) {
/* Get outer frame sizes. */
if (style & WS_THICKFRAME) {
@@ -745,11 +755,11 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
#endif
-static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
+static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type)
{
RECT rc;
- int w, h;
BOOL isVisible = IsWindowVisible(wnd);
+ jobject window = wud->jinstance;
if (type == SIZE_MINIMIZED) {
// TODO: deal with minimized window sizing
@@ -762,29 +772,147 @@ static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
GetClientRect(wnd, &rc);
// we report back the dimensions of the client area
- w = (int) ( rc.right - rc.left );
- h = (int) ( rc.bottom - rc.top );
+ wud->width = (int) ( rc.right - rc.left );
+ wud->height = (int) ( rc.bottom - rc.top );
- DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, w, h, isVisible);
+ DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, wud->width, wud->height, isVisible);
- (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, w, h, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE);
}
-static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
- WPARAM wParam, LPARAM lParam)
+#ifdef TEST_MOUSE_HOOKS
+
+static HHOOK hookLLMP;
+static HHOOK hookMP;
+
+static LRESULT CALLBACK HookLowLevelMouseProc (int code, WPARAM wParam, LPARAM lParam)
{
+ // if (code == HC_ACTION)
+ {
+ const char *msg;
+ char msg_buff[128];
+ switch (wParam)
+ {
+ case WM_LBUTTONDOWN: msg = "WM_LBUTTONDOWN"; break;
+ case WM_LBUTTONUP: msg = "WM_LBUTTONUP"; break;
+ case WM_MOUSEMOVE: msg = "WM_MOUSEMOVE"; break;
+ case WM_MOUSEWHEEL: msg = "WM_MOUSEWHEEL"; break;
+ case WM_MOUSEHWHEEL: msg = "WM_MOUSEHWHEEL"; break;
+ case WM_RBUTTONDOWN: msg = "WM_RBUTTONDOWN"; break;
+ case WM_RBUTTONUP: msg = "WM_RBUTTONUP"; break;
+ default:
+ sprintf(msg_buff, "Unknown msg: %u", wParam);
+ msg = msg_buff;
+ break;
+ }//switch
+
+ const MSLLHOOKSTRUCT *p = (MSLLHOOKSTRUCT*)lParam;
+ DBG_PRINT("**** LLMP: Code: 0x%X: %s - %d/%d\n", code, msg, (int)p->pt.x, (int)p->pt.y);
+ //} else {
+ // DBG_PRINT("**** LLMP: CODE: 0x%X\n", code);
+ }
+ return CallNextHookEx(hookLLMP, code, wParam, lParam);
+}
+
+static LRESULT CALLBACK HookMouseProc (int code, WPARAM wParam, LPARAM lParam)
+{
+ // if (code == HC_ACTION)
+ {
+ const char *msg;
+ char msg_buff[128];
+ switch (wParam)
+ {
+ case WM_LBUTTONDOWN: msg = "WM_LBUTTONDOWN"; break;
+ case WM_LBUTTONUP: msg = "WM_LBUTTONUP"; break;
+ case WM_MOUSEMOVE: msg = "WM_MOUSEMOVE"; break;
+ case WM_MOUSEWHEEL: msg = "WM_MOUSEWHEEL"; break;
+ case WM_MOUSEHWHEEL: msg = "WM_MOUSEHWHEEL"; break;
+ case WM_RBUTTONDOWN: msg = "WM_RBUTTONDOWN"; break;
+ case WM_RBUTTONUP: msg = "WM_RBUTTONUP"; break;
+ default:
+ sprintf(msg_buff, "Unknown msg: %u", wParam);
+ msg = msg_buff;
+ break;
+ }//switch
+
+ const MOUSEHOOKSTRUCT *p = (MOUSEHOOKSTRUCT*)lParam;
+ DBG_PRINT("**** MP: Code: 0x%X: %s - hwnd %p, %d/%d\n", code, msg, p->hwnd, (int)p->pt.x, (int)p->pt.y);
+ //} else {
+ // DBG_PRINT("**** MP: CODE: 0x%X\n", code);
+ }
+ return CallNextHookEx(hookMP, code, wParam, lParam);
+}
+
+#endif
+
+static BOOL SafeShowCursor(BOOL show) {
+ int count, countPre;
+ BOOL b;
+
+ if( show ) {
+ count = ShowCursor(TRUE);
+ if(count < 0) {
+ do {
+ countPre = count;
+ count = ShowCursor(TRUE);
+ } while( count > countPre && count < 0 );
+ }
+ b = count>=0 ? TRUE : FALSE;
+ } else {
+ count = ShowCursor(FALSE);
+ if(count >= 0) {
+ do {
+ countPre = count;
+ count = ShowCursor(FALSE);
+ } while( count < countPre && count >= 0 );
+ }
+ b = count<0 ? TRUE : FALSE;
+ }
+ return b;
+}
+
+static void sendTouchScreenEvent(JNIEnv *env, jobject window,
+ short eventType, int modifiers, int actionIdx,
+ int count, jint* pointerNames, jint* x, jint* y, jfloat* pressure, float maxPressure) {
+ jintArray jNames = (*env)->NewIntArray(env, count);
+ if (jNames == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (names) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jNames, 0, count, pointerNames);
+
+ jintArray jX = (*env)->NewIntArray(env, count);
+ if (jX == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (x) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jX, 0, count, x);
+
+ jintArray jY = (*env)->NewIntArray(env, count);
+ if (jY == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (y) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jY, 0, count, y);
+
+ jfloatArray jPressure = (*env)->NewFloatArray(env, count);
+ if (jPressure == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate float array (pressure) of size %d", count);
+ }
+ (*env)->SetFloatArrayRegion(env, jPressure, 0, count, pressure);
+
+ (*env)->CallVoidMethod(env, window, sendTouchScreenEventID,
+ (jshort)eventType, (jint)modifiers, (jint)actionIdx,
+ jNames, jX, jY, jPressure, (jfloat)maxPressure);
+}
+
+
+static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
LRESULT res = 0;
int useDefWindowProc = 0;
JNIEnv *env = NULL;
jobject window = NULL;
BOOL isKeyDown = FALSE;
WindowUserData * wud;
-
-#ifdef DEBUG_KEYS
- if ( WM_KEYDOWN == message ) {
- STD_PRINT("*** WindowsWindow: wndProc window %p, 0x%X %d/%d\n", wnd, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
- }
-#endif
+ WORD repCnt;
+ BYTE scanCode, flags;
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
wud = (WindowUserData *) GetWindowLong(wnd, GWL_USERDATA);
@@ -797,216 +925,580 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
env = wud->jenv;
window = wud->jinstance;
- // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, 0x%X %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+ // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, msg 0x%X, %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
if (NULL==window || NULL==env) {
return DefWindowProc(wnd, message, wParam, lParam);
}
switch (message) {
+ //
+ // The signal pipeline for destruction is:
+ // Java::DestroyWindow(wnd) _or_ window-close-button ->
+ // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY
+ case WM_CLOSE:
+ (*env)->CallBooleanMethod(env, window, windowDestroyNotifyID, JNI_FALSE);
+ break;
- //
- // The signal pipeline for destruction is:
- // Java::DestroyWindow(wnd) _or_ window-close-button ->
- // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY
- case WM_CLOSE:
- (*env)->CallBooleanMethod(env, window, windowDestroyNotifyID, JNI_FALSE);
- break;
-
- case WM_DESTROY:
- {
-#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
- SetWindowLong(wnd, GWL_USERDATA, (intptr_t) NULL);
-#else
- SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL);
-#endif
- free(wud); wud=NULL;
- (*env)->DeleteGlobalRef(env, window);
- }
- break;
+ case WM_DESTROY:
+ {
+ #if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ SetWindowLong(wnd, GWL_USERDATA, (intptr_t) NULL);
+ #else
+ SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL);
+ #endif
+ free(wud); wud=NULL;
+ (*env)->DeleteGlobalRef(env, window);
+ }
+ break;
- case WM_SYSCHAR:
- useDefWindowProc = WmChar(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_ACTIVATE: {
+ HWND wndPrev = (HWND) lParam;
+ BOOL fMinimized = (BOOL) HIWORD(wParam);
+ int fActive = LOWORD(wParam);
+ BOOL inactive = WA_INACTIVE==fActive;
+ #ifdef VERBOSE_ON
+ BOOL anyActive = WA_ACTIVE==fActive, clickActive = WA_CLICKACTIVE==fActive;
+ DBG_PRINT("*** WindowsWindow: WM_ACTIVATE window %p, prev %p, minimized %d, active %d (any %d, click %d, inactive %d), FS %d\n",
+ wnd, wndPrev, fMinimized, fActive, anyActive, clickActive, inactive, wud->isFullscreen);
+ #endif
+ if( wud->isFullscreen ) {
+ // Bug 916 - NEWT Fullscreen Mode on Windows ALT-TAB doesn't allow Application Switching
+ // Remedy for 'some' display drivers, i.e. Intel HD:
+ // Explicitly push fullscreen window to BOTTOM when inactive (ALT-TAB)
+ UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if( inactive ) {
+ SetWindowPos(wnd, HWND_BOTTOM, 0, 0, 0, 0, flags);
+ } else {
+ SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, flags);
+ SetForegroundWindow(wnd); // Slightly Higher Priority
+ }
+ }
+ useDefWindowProc = 1;
+ }
+ break;
- case WM_CHAR:
- useDefWindowProc = WmChar(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), TRUE);
- break;
-
- case WM_KEYDOWN:
-#ifdef DEBUG_KEYS
- STD_PRINT("*** WindowsWindow: windProc sending window %p -> %p, 0x%X %d/%d\n", wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
-#endif
- useDefWindowProc = WmKeyDown(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_SETTINGCHANGE:
+ if (wParam == SPI_SETNONCLIENTMETRICS) {
+ // make sure insets are updated, we don't need to resize the window
+ // because the size of the client area doesn't change
+ (void)UpdateInsets(env, window, wnd);
+ } else {
+ useDefWindowProc = 1;
+ }
+ break;
- case WM_KEYUP:
- useDefWindowProc = WmKeyUp(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_SIZE:
+ WmSize(env, wud, wnd, (UINT)wParam);
+ break;
- case WM_SIZE:
- WmSize(env, window, wnd, (UINT)wParam);
- break;
+ case WM_SHOWWINDOW:
+ (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE);
+ break;
- case WM_SETTINGCHANGE:
- if (wParam == SPI_SETNONCLIENTMETRICS) {
- // make sure insets are updated, we don't need to resize the window
- // because the size of the client area doesn't change
- (void)UpdateInsets(env, window, wnd);
- } else {
+ case WM_MOVE:
+ DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam));
useDefWindowProc = 1;
+ break;
+
+ case WM_PAINT: {
+ RECT r;
+ if (GetUpdateRect(wnd, &r, FALSE /* do not erase background */)) {
+ // clear the whole client area and issue repaint for it, w/o looping through erase background
+ ValidateRect(wnd, NULL); // clear all!
+ (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ } else {
+ // shall not happen ?
+ ValidateRect(wnd, NULL); // clear all!
+ }
+ // return 0 == done
+ break;
}
- break;
+ case WM_ERASEBKGND:
+ // ignore erase background
+ (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this
+ break;
+ case WM_SETCURSOR :
+ if (0 != wud->setPointerVisible) { // Tristate, -1, 0, 1
+ BOOL visibilityChangeSuccessful;
+ if (1 == wud->setPointerVisible) {
+ visibilityChangeSuccessful = SafeShowCursor(TRUE);
+ } else /* -1 == wud->setPointerVisible */ {
+ visibilityChangeSuccessful = SafeShowCursor(FALSE);
+ }
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR requested visibility: %d success: %d\n", wud->setPointerVisible, visibilityChangeSuccessful);
+ wud->setPointerVisible = 0;
+ // own signal, consumed, no further processing
+ res = 1;
+ } else if( 0 != wud->setPointerAction ) {
+ if( -1 == wud->setPointerAction ) {
+ wud->setPointerHandle = wud->defPointerHandle;
+ }
+ HCURSOR preHandle = SetCursor(wud->setPointerHandle);
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon change %d: pre %p -> set %p, def %p\n",
+ wud->setPointerAction, (void*)preHandle, (void*)wud->setPointerHandle, (void*)wud->defPointerHandle);
+ wud->setPointerAction = 0;
+ // own signal, consumed, no further processing
+ res = 1;
+ } else if( HTCLIENT == LOWORD(lParam) ) {
+ BOOL setCur = wud->isChildWindow && wud->defPointerHandle != wud->setPointerHandle;
+ #ifdef VERBOSE_ON
+ HCURSOR cur = GetCursor();
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon NOP [1 custom-override] set %p, def %p, cur %p, isChild %d, setCur %d\n",
+ (void*)wud->setPointerHandle, (void*)wud->defPointerHandle, (void*)cur, wud->isChildWindow, setCur);
+ #endif
+ if( setCur ) {
+ SetCursor(wud->setPointerHandle);
+ // own signal, consumed, no further processing
+ res = 1;
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon NOP [2 parent-override] set %p, def %p\n", (void*)wud->setPointerHandle, (void*)wud->defPointerHandle);
+ // NOP for us, allow parent to act
+ res = 0;
+ }
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR !HTCLIENT\n");
+ // NOP for us, allow parent to act
+ res = 0;
+ }
+ break;
- case WM_LBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 1, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SETFOCUS:
+ DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p\n", wnd, (HWND)wParam);
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE);
+ useDefWindowProc = 1;
+ break;
- case WM_LBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 1, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_KILLFOCUS:
+ DBG_PRINT("*** WindowsWindow: WM_KILLFOCUS window %p, received %p, inside %d, captured %d, tDown %d\n",
+ wnd, (HWND)wParam, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount);
+ if( wud->touchDownCount == 0 ) {
+ wud->pointerInside = 0;
+ if( wud->pointerCaptured ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
+ useDefWindowProc = 1;
+ } else {
+ // quick focus .. we had it already, are enabled ..
+ SetFocus(wnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window)
+ }
+ break;
- case WM_MBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 2, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSCHAR:
+ useDefWindowProc = 1;
+ break;
- case WM_MBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 2, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSKEYDOWN:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_SYSKEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyDown(env, window, (USHORT)wParam, repCnt, scanCode, flags, TRUE);
+ break;
- case WM_RBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 3, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSKEYUP:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_SYSKEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyUp(env, window, (USHORT)wParam, repCnt, scanCode, flags, TRUE);
+ break;
- case WM_RBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 3, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_CHAR:
+ useDefWindowProc = 1;
+ break;
+
+ case WM_KEYDOWN:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_KEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyDown(env, window, wParam, repCnt, scanCode, flags, FALSE);
+ break;
- case WM_MOUSEMOVE:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_MOVED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 0, (jint) 0);
- useDefWindowProc = 1;
- break;
- case WM_MOUSELEAVE:
- (*env)->CallVoidMethod(env, window, enqueueMouseEventID, JNI_FALSE,
- (jint) EVENT_MOUSE_EXITED,
- 0,
- (jint) -1, (jint) -1, // fake
- (jint) 0, (jint) 0);
- useDefWindowProc = 1;
- break;
- // Java synthesizes EVENT_MOUSE_ENTERED
-
- case WM_MOUSEWHEEL: {
- // need to convert the coordinates to component-relative
- int x = GET_X_LPARAM(lParam);
- int y = GET_Y_LPARAM(lParam);
- POINT eventPt;
- eventPt.x = x;
- eventPt.y = y;
- ScreenToClient(wnd, &eventPt);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_WHEEL_MOVED,
- GetModifiers(),
- (jint) eventPt.x, (jint) eventPt.y,
- (jint) 1, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f));
- useDefWindowProc = 1;
- break;
- }
+ case WM_KEYUP:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_KEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyUp(env, window, wParam, repCnt, scanCode, flags, FALSE);
+ break;
- case WM_SETFOCUS:
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE);
- useDefWindowProc = 1;
- break;
+ case WM_LBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_LBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 1, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_KILLFOCUS:
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
- useDefWindowProc = 1;
- break;
+ case WM_LBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_LBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 < wud->touchDownLastUp ) {
+ // mitigate LBUTTONUP after last TOUCH lift
+ wud->touchDownLastUp = 0;
+ } else if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 1, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_SHOWWINDOW:
- (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE);
- break;
+ case WM_MBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_MBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 2, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_MOVE:
- DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam));
- useDefWindowProc = 1;
- break;
+ case WM_MBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_MBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 2, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_PAINT: {
- RECT r;
- useDefWindowProc = 0;
- if (GetUpdateRect(wnd, &r, TRUE /* erase background */)) {
- /*
- jint width = r.right-r.left;
- jint height = r.bottom-r.top;
- if (width > 0 && height > 0) {
- (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, r.left, r.top, width, height);
+ case WM_RBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_RBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 3, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
+
+ case WM_RBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_RBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 3, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE: {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( 0 == wud->pointerCaptured && 0 != ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 1;
+ SetCapture(wnd);
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ SetCursor(wud->setPointerHandle);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 0, (jfloat) 0.0f);
+ }
+ useDefWindowProc = 1;
+ }
+ break;
+ case WM_MOUSELEAVE: {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ wud->pointerInside = 0;
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_EXITED,
+ 0,
+ (jint) -1, (jint) -1, // fake
+ (jshort) 0, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
+ // Java synthesizes EVENT_MOUSE_ENTERED
+
+ case WM_HSCROLL: { // Only delivered if windows has WS_HSCROLL, hence dead code!
+ int sb = LOWORD(wParam);
+ int modifiers = GetModifiers( 0 ) | EVENT_SHIFT_MASK;
+ float rotation;
+ switch(sb) {
+ case SB_LINELEFT:
+ rotation = 1.0f;
+ break;
+ case SB_PAGELEFT:
+ rotation = 2.0f;
+ break;
+ case SB_LINERIGHT:
+ rotation = -1.0f;
+ break;
+ case SB_PAGERIGHT:
+ rotation = -1.0f;
+ break;
+ }
+ DBG_PRINT("*** WindowsWindow: WM_HSCROLL 0x%X, rotation %f, mods 0x%X\n", sb, rotation, modifiers);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_WHEEL_MOVED,
+ modifiers,
+ (jint) 0, (jint) 0,
+ (jshort) 1, (jfloat) rotation);
+ useDefWindowProc = 1;
+ break;
}
- ValidateRect(wnd, &r);
- */
+ case WM_MOUSEHWHEEL: /* tilt */
+ case WM_MOUSEWHEEL: /* rotation */ {
+ // need to convert the coordinates to component-relative
+ int x = GET_X_LPARAM(lParam);
+ int y = GET_Y_LPARAM(lParam);
+ int modifiers = GetModifiers( 0 );
+ float rotationOrTilt = (float)(GET_WHEEL_DELTA_WPARAM(wParam))/WHEEL_DELTAf;
+ int vKeys = GET_KEYSTATE_WPARAM(wParam);
+ POINT eventPt;
+ eventPt.x = x;
+ eventPt.y = y;
+ ScreenToClient(wnd, &eventPt);
+
+ if( WM_MOUSEHWHEEL == message ) {
+ modifiers |= EVENT_SHIFT_MASK;
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEHWHEEL %d/%d, tilt %f, vKeys 0x%X, mods 0x%X\n",
+ (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers);
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEWHEEL %d/%d, rotation %f, vKeys 0x%X, mods 0x%X\n",
+ (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_WHEEL_MOVED,
+ modifiers,
+ (jint) eventPt.x, (jint) eventPt.y,
+ (jshort) 1, (jfloat) rotationOrTilt);
+ useDefWindowProc = 1;
+ break;
}
- break;
- }
- case WM_ERASEBKGND:
- // ignore erase background
- (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
- useDefWindowProc = 0;
- res = 1; // OpenGL, etc .. erases the background, hence we claim to have just done this
- break;
+ case WM_TOUCH: if( wud->supportsMTouch ) {
+ UINT cInputs = LOWORD(wParam);
+ // DBG_PRINT("*** WindowsWindow: WM_TOUCH window %p, cInputs %d\n", wnd, cInputs);
+ HTOUCHINPUT hTouch = (HTOUCHINPUT)lParam;
+ PTOUCHINPUT pInputs = (PTOUCHINPUT) calloc(cInputs, sizeof(TOUCHINPUT));
+ if (NULL != pInputs) {
+ if ( WinTouch_GetTouchInputInfo(hTouch, cInputs, pInputs, sizeof(TOUCHINPUT)) ) {
+ UINT i;
+ short eventType[cInputs];
+ jint modifiers = GetModifiers( 0 );
+ jint actionIdx = -1;
+ jint pointerNames[cInputs];
+ jint x[cInputs], y[cInputs];
+ jfloat pressure[cInputs];
+ jfloat maxPressure = 1.0F; // FIXME: n/a on windows ?
+ int allPInside = 0 < cInputs;
+ int sendFocus = 0;
+
+ for (i=0; i < cInputs; i++) {
+ PTOUCHINPUT pTi = & pInputs[i];
+ POINT eventPt;
+ int isDown = pTi->dwFlags & TOUCHEVENTF_DOWN;
+ int isUp = pTi->dwFlags & TOUCHEVENTF_UP;
+ int isMove = pTi->dwFlags & TOUCHEVENTF_MOVE;
+
+ int isPrim = pTi->dwFlags & TOUCHEVENTF_PRIMARY;
+ int isNoCoalesc = pTi->dwFlags & TOUCHEVENTF_NOCOALESCE;
+
+ #ifdef VERBOSE_ON
+ const char * touchAction;
+ if( isDown ) {
+ touchAction = "down";
+ } else if( isUp ) {
+ touchAction = "_up_";
+ } else if( isMove ) {
+ touchAction = "move";
+ } else {
+ touchAction = "undf";
+ }
+ #endif
+
+ pointerNames[i] = (jint)pTi->dwID;
+ eventPt.x = TOUCH_COORD_TO_PIXEL(pTi->x);
+ eventPt.y = TOUCH_COORD_TO_PIXEL(pTi->y);
+ ScreenToClient(wnd, &eventPt);
+
+ int pInside = 0 <= eventPt.x && 0 <= eventPt.y && eventPt.x < wud->width && eventPt.y < wud->height;
+ allPInside &= pInside;
+
+ x[i] = (jint)eventPt.x;
+ y[i] = (jint)eventPt.y;
+ pressure[i] = 1.0F; // FIXME: n/a on windows ?
+ if(isDown) {
+ sendFocus = 0 == wud->touchDownCount;
+ eventType[i] = (jshort) EVENT_MOUSE_PRESSED;
+ wud->touchDownCount++;
+ wud->touchDownLastUp = 0;
+ } else if(isUp) {
+ eventType[i] = (jshort) EVENT_MOUSE_RELEASED;
+ wud->touchDownCount--;
+ // mitigate LBUTTONUP after last TOUCH lift
+ wud->touchDownLastUp = 0 == wud->touchDownCount;
+ } else if(isMove) {
+ eventType[i] = (jshort) EVENT_MOUSE_MOVED;
+ wud->touchDownLastUp = 0;
+ } else {
+ eventType[i] = (jshort) 0;
+ }
+ if(isPrim) {
+ actionIdx = (jint)i;
+ }
+
+ #ifdef VERBOSE_ON
+ DBG_PRINT("*** WindowsWindow: WM_TOUCH[%d/%d].%s name 0x%x, prim %d, nocoalsc %d, %d/%d [%dx%d] inside [%d/%d], tDown [c %d, lastUp %d]\n",
+ (i+1), cInputs, touchAction, (int)(pTi->dwID), isPrim, isNoCoalesc, x[i], y[i], wud->width, wud->height,
+ pInside, allPInside, wud->touchDownCount, wud->touchDownLastUp);
+ #endif
+ }
+ wud->pointerInside = allPInside;
+ if( sendFocus ) {
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ }
+ int sentCount = 0, updownCount=0, moveCount=0;
+ // Primary first, if available!
+ if( 0 <= actionIdx ) {
+ sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ // 1 Move second ..
+ for (i=0; i < cInputs; i++) {
+ short et = eventType[i];
+ if( (jshort) EVENT_MOUSE_MOVED == et ) {
+ if( i != actionIdx && 0 == moveCount ) {
+ sendTouchScreenEvent(env, window, et, modifiers, i,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ moveCount++;
+ }
+ }
+ // Up and downs last
+ for (i=0; i < cInputs; i++) {
+ short et = eventType[i];
+ if( (jshort) EVENT_MOUSE_MOVED != et ) {
+ if( i != actionIdx ) {
+ sendTouchScreenEvent(env, window, et, modifiers, i,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ updownCount++;
+ }
+ }
+ DBG_PRINT("*** WindowsWindow: WM_TOUCH.summary pCount %d, prim %d, updown %d, move %d, sent %d, inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ cInputs, actionIdx, updownCount, moveCount, sentCount, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+
+ // Message processed - close it
+ WinTouch_CloseTouchInputHandle(hTouch);
+ } else {
+ useDefWindowProc = 1;
+ }
+ free(pInputs);
+ }
+ break;
+ }
- default:
- useDefWindowProc = 1;
+ default:
+ useDefWindowProc = 1;
}
- if (useDefWindowProc)
+
+ if (useDefWindowProc) {
return DefWindowProc(wnd, message, wParam, lParam);
+ }
return res;
}
@@ -1028,12 +1520,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMes
// DBG_PRINT("*** WindowsWindow.DispatchMessages0: thread 0x%X - gotOne %d\n", (int)GetCurrentThreadId(), (int)gotOne);
if (gotOne) {
++i;
-#ifdef DEBUG_KEYS
- if(WM_KEYDOWN == msg.message) {
- STD_PRINT("*** WindowsWindow: DispatchMessages window %p, 0x%X %d/%d\n", msg.hwnd, msg.message, (int)LOWORD(msg.lParam), (int)HIWORD(msg.lParam));
- }
-#endif
- TranslateMessage(&msg);
+ // TranslateMessage(&msg); // No more needed: We translate V_KEY -> UTF Char manually in key up/down
DispatchMessage(&msg);
}
} while (gotOne && i < 100);
@@ -1041,11 +1528,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMes
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getOriginX0
- * Signature: (I)I
+ * Method: getVirtualOriginX0
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginX0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS) > 1) {
return (jint)GetSystemMetrics(SM_XVIRTUALSCREEN);
@@ -1056,11 +1543,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getOriginY0
- * Signature: (I)I
+ * Method: getVirtualOriginY0
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginY0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS ) > 1) {
return (jint)GetSystemMetrics(SM_YVIRTUALSCREEN);
@@ -1071,11 +1558,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getWidthImpl
- * Signature: (I)I
+ * Method: getVirtualWidthImpl
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualWidthImpl0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS) > 1) {
return (jint)GetSystemMetrics(SM_CXVIRTUALSCREEN);
@@ -1086,11 +1573,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getHeightImpl
- * Signature: (I)I
+ * Method: getVirtualHeightImpl
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getHeightImpl0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualHeightImpl0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS ) > 1) {
return (jint)GetSystemMetrics(SM_CYVIRTUALSCREEN);
@@ -1142,65 +1629,137 @@ static int NewtScreen_RotationNewtCCW2NativeCCW(JNIEnv *env, jint newt) {
return native;
}
-/*
-static void NewtScreen_scanDisplayDevices() {
- DISPLAY_DEVICE device;
- int i = 0;
- LPCTSTR name;
- while(NULL != (name = NewtScreen_getDisplayDeviceName(&device, i))) {
- fprintf(stderr, "*** [%d]: <%s> active %d\n", i, name, ( 0 != ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
- i++;
+static LPCTSTR NewtScreen_getAdapterName(DISPLAY_DEVICE * device, int crt_idx) {
+ memset(device, 0, sizeof(DISPLAY_DEVICE));
+ device->cb = sizeof(DISPLAY_DEVICE);
+ if( FALSE == EnumDisplayDevices(NULL, crt_idx, device, 0) ) {
+ DBG_PRINT("*** WindowsWindow: getAdapterName.EnumDisplayDevices(crt_idx %d) -> FALSE\n", crt_idx);
+ return NULL;
}
-}*/
-static LPCTSTR NewtScreen_getDisplayDeviceName(DISPLAY_DEVICE * device, int scrn_idx) {
- device->cb = sizeof(DISPLAY_DEVICE);
- if( FALSE == EnumDisplayDevices(NULL, scrn_idx, device, 0) ) {
- DBG_PRINT("*** WindowsWindow: getDisplayDeviceName.EnumDisplayDevices(scrn_idx %d) -> FALSE\n", scrn_idx);
+ if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) {
return NULL;
}
- if( 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
- DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(scrn_idx %d)\n", scrn_idx);
+ return device->DeviceName;
+}
+
+static LPCTSTR NewtScreen_getMonitorName(LPCTSTR adapterName, DISPLAY_DEVICE * device, int monitor_idx, BOOL onlyActive) {
+ memset(device, 0, sizeof(DISPLAY_DEVICE));
+ device->cb = sizeof(DISPLAY_DEVICE);
+ if( 0 == monitor_idx ) {
+ if( FALSE == EnumDisplayDevices(adapterName, monitor_idx, device, 0) ) {
+ DBG_PRINT("*** WindowsWindow: getDisplayName.EnumDisplayDevices(monitor_idx %d).adapter -> FALSE\n", monitor_idx);
+ return NULL;
+ }
+ }
+
+ if( onlyActive && 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
+ DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(monitor_idx %d).display\n", monitor_idx);
+ return NULL;
+ }
+ if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) {
return NULL;
}
return device->DeviceName;
}
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_dumpMonitorInfo0
+ (JNIEnv *env, jclass clazz)
+{
+ DISPLAY_DEVICE aDevice, dDevice;
+ int i = 0, j;
+ LPCTSTR aName, dName;
+ while(NULL != (aName = NewtScreen_getAdapterName(&aDevice, i))) {
+ fprintf(stderr, "*** [%d]: <%s> flags 0x%X active %d\n", i, aName, aDevice.StateFlags, ( 0 != ( aDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+ j=0;
+ while(NULL != (dName = NewtScreen_getMonitorName(aName, &dDevice, j, FALSE))) {
+ fprintf(stderr, "*** [%d][%d]: <%s> flags 0x%X active %d\n", i, j, dName, dDevice.StateFlags, ( 0 != ( dDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+ j++;
+ }
+ i++;
+ }
+}
+
static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) {
return CreateDC("DISPLAY", displayDeviceName, NULL, NULL);
}
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: getScreenMode0
- * Signature: (II)[I
+ * Method: getAdapterName0
+ * Signature: (I)Ljava/lang/String;
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScreenMode0
- (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx)
+JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getAdapterName0
+ (JNIEnv *env, jobject obj, jint crt_idx)
{
DISPLAY_DEVICE device;
- int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
- LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
- if(NULL == deviceName) {
- DBG_PRINT("*** WindowsWindow: getScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
- return (*env)->NewIntArray(env, 0);
+ LPCTSTR adapterName = NewtScreen_getAdapterName(&device, crt_idx);
+ DBG_PRINT("*** WindowsWindow: getAdapterName(crt_idx %d) -> %s, active %d\n", crt_idx,
+ (NULL==adapterName?"nil":adapterName), 0 == ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ));
+ if(NULL == adapterName) {
+ return NULL;
}
+#ifdef UNICODE
+ return (*env)->NewString(env, adapterName, wcslen(adapterName));
+#else
+ return (*env)->NewStringUTF(env, adapterName);
+#endif
+}
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getActiveMonitorName0
+ * Signature: (Ljava/lang/String;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getActiveMonitorName0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx)
+{
+ DISPLAY_DEVICE device;
+ LPCTSTR monitorName;
+#ifdef UNICODE
+ LPCTSTR adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+ monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE);
+ DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName));
+ free((void*) adapterName);
+#else
+ LPCTSTR adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+ monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE);
+ DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName));
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+ if(NULL == monitorName) {
+ return NULL;
+ }
+#ifdef UNICODE
+ return (*env)->NewString(env, monitorName, wcslen(monitorName));
+#else
+ return (*env)->NewStringUTF(env, monitorName);
+#endif
+}
+
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getMonitorMode0
+ * Signature: (Ljava/lang/String;I)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorMode0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint mode_idx)
+{
+ DISPLAY_DEVICE device;
+ LPCTSTR adapterName;
+ {
+#ifdef UNICODE
+ adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+#else
+ adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+#endif
+ }
int devModeID;
- int widthmm, heightmm;
if(-1 < mode_idx) {
- // only at initialization time, where index >= 0
- HDC hdc = NewtScreen_createDisplayDC(deviceName);
- widthmm = GetDeviceCaps(hdc, HORZSIZE);
- heightmm = GetDeviceCaps(hdc, VERTSIZE);
- DeleteDC(hdc);
devModeID = (int) mode_idx;
- prop_num++; // add 1st extra prop, mode_idx
} else {
- widthmm = 0;
- heightmm = 0;
devModeID = ENUM_CURRENT_SETTINGS;
}
@@ -1208,11 +1767,18 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScre
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
- if (0 == EnumDisplaySettingsEx(deviceName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE)) {
- DBG_PRINT("*** WindowsWindow: getScreenMode.EnumDisplaySettingsEx(mode_idx %d/%d) -> NULL\n", mode_idx, devModeID);
+ int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE);
+ DBG_PRINT("*** WindowsWindow: getMonitorMode.EnumDisplaySettingsEx(%s, mode_idx %d/%d) -> %d\n", adapterName, mode_idx, devModeID, res);
+#ifdef UNICODE
+ free((void*) adapterName);
+#else
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+
+ if (0 == res) {
return (*env)->NewIntArray(env, 0);
}
-
+
// swap width and height, since Windows reflects rotated dimension, we don't
if (DMDO_90 == dm.dmDisplayOrientation || DMDO_270 == dm.dmDisplayOrientation) {
int tempWidth = dm.dmPelsWidth;
@@ -1220,43 +1786,114 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScre
dm.dmPelsHeight = tempWidth;
}
- jint prop[ prop_num ];
+ int flags = 0;
+ if( 0 != ( dm.dmDisplayFlags & DM_INTERLACED ) ) {
+ flags |= FLAG_INTERLACE;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
int propIndex = 0;
- if( -1 < mode_idx ) {
- prop[propIndex++] = mode_idx;
- }
- prop[propIndex++] = 0; // set later for verification of iterator
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
prop[propIndex++] = dm.dmPelsWidth;
prop[propIndex++] = dm.dmPelsHeight;
prop[propIndex++] = dm.dmBitsPerPel;
- prop[propIndex++] = widthmm;
- prop[propIndex++] = heightmm;
- prop[propIndex++] = dm.dmDisplayFrequency;
+ prop[propIndex++] = dm.dmDisplayFrequency * 100; // Hz*100
+ prop[propIndex++] = flags;
+ prop[propIndex++] = 0; // not bound to id
prop[propIndex++] = NewtScreen_RotationNativeCCW2NewtCCW(env, dm.dmDisplayOrientation);
- prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
- jintArray properties = (*env)->NewIntArray(env, prop_num);
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
}
- (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
return properties;
}
/*
* Class: jogamp_newt_driver_windows_ScreenDriver
- * Method: setScreenMode0
- * Signature: (IIIIII)Z
+ * Method: getMonitorDevice0
+ * Signature: (Ljava/lang/String;I)[I
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScreenMode0
- (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jint rate, jint rot)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorDevice0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx)
{
DISPLAY_DEVICE device;
- LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
- if(NULL == deviceName) {
- DBG_PRINT("*** WindowsWindow: setScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
+ LPCTSTR adapterName;
+ {
+#ifdef UNICODE
+ adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+#else
+ adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+#endif
+ }
+
+ HDC hdc = NewtScreen_createDisplayDC(adapterName);
+ int widthmm = GetDeviceCaps(hdc, HORZSIZE);
+ int heightmm = GetDeviceCaps(hdc, VERTSIZE);
+ DeleteDC(hdc);
+ int devModeID = ENUM_CURRENT_SETTINGS;
+
+ DEVMODE dm;
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, 0);
+ DBG_PRINT("*** WindowsWindow: getMonitorDevice.EnumDisplaySettingsEx(%s, devModeID %d) -> %d\n", adapterName, devModeID, res);
+#ifdef UNICODE
+ free((void*) adapterName);
+#else
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+ if (0 == res) {
+ return (*env)->NewIntArray(env, 0);
+ }
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = propCount;
+ prop[propIndex++] = monitor_idx;
+ prop[propIndex++] = widthmm;
+ prop[propIndex++] = heightmm;
+ prop[propIndex++] = dm.dmPosition.x; // rotated viewport pixel units
+ prop[propIndex++] = dm.dmPosition.y; // rotated viewport pixel units
+ prop[propIndex++] = dm.dmPelsWidth; // rotated viewport pixel units
+ prop[propIndex++] = dm.dmPelsHeight; // rotated viewport pixel units
+ prop[propIndex++] = dm.dmPosition.x; // rotated viewport window units (same)
+ prop[propIndex++] = dm.dmPosition.y; // rotated viewport window units (same)
+ prop[propIndex++] = dm.dmPelsWidth; // rotated viewport window units (same)
+ prop[propIndex++] = dm.dmPelsHeight; // rotated viewport window units (same)
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: setMonitorMode0
+ * Signature: (IIIIIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setMonitorMode0
+ (JNIEnv *env, jobject object, jint monitor_idx, jint x, jint y, jint width, jint height, jint bits, jint rate, jint flags, jint rot)
+{
+ DISPLAY_DEVICE adapterDevice, monitorDevice;
+ LPCTSTR adapterName = NewtScreen_getAdapterName(&adapterDevice, monitor_idx);
+ if(NULL == adapterName) {
+ DBG_PRINT("*** WindowsWindow: setMonitorMode.getAdapterName(monitor_idx %d) -> NULL\n", monitor_idx);
+ return JNI_FALSE;
+ }
+ LPCTSTR monitorName = NewtScreen_getMonitorName(adapterName, &monitorDevice, 0, TRUE);
+ if(NULL == monitorName) {
+ DBG_PRINT("*** WindowsWindow: setMonitorMode.getMonitorName(monitor_idx 0) -> NULL\n");
return JNI_FALSE;
}
@@ -1264,10 +1901,17 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
// initialize the DEVMODE structure
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
+ if( 0 <= x && 0 <= y ) {
+ dm.dmPosition.x = (int)x;
+ dm.dmPosition.y = (int)y;
+ }
dm.dmPelsWidth = (int)width;
dm.dmPelsHeight = (int)height;
dm.dmBitsPerPel = (int)bits;
dm.dmDisplayFrequency = (int)rate;
+ if( 0 != ( flags & FLAG_INTERLACE ) ) {
+ dm.dmDisplayFlags |= DM_INTERLACED;
+ }
dm.dmDisplayOrientation = NewtScreen_RotationNewtCCW2NativeCCW(env, rot);
// swap width and height, since Windows reflects rotated dimension, we don't
@@ -1277,9 +1921,12 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
dm.dmPelsHeight = tempWidth;
}
- dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+ dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
+ if( 0 <= x && 0 <= y ) {
+ dm.dmFields |= DM_POSITION;
+ }
- return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, 0) ) ? JNI_TRUE : JNI_FALSE ;
+ return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(adapterName, &dm, NULL, 0, NULL) ) ? JNI_TRUE : JNI_FALSE ;
}
/*
@@ -1288,7 +1935,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
- (JNIEnv *env, jclass clazz)
+ (JNIEnv *env, jclass clazz, jlong hInstance)
{
NewtCommon_init(env);
@@ -1299,10 +1946,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
- enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
+ sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SII[I[I[I[FF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V");
requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
if (insetsChangedID == NULL ||
@@ -1312,14 +1958,30 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
visibleChangedID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
- enqueueMouseEventID == NULL ||
sendMouseEventID == NULL ||
- enqueueKeyEventID == NULL ||
+ sendTouchScreenEventID == NULL ||
sendKeyEventID == NULL ||
requestFocusID == NULL) {
return JNI_FALSE;
}
- BuildDynamicKeyMapTable();
+ InitKeyMapTableScanCode(env);
+
+ {
+ HANDLE shell = LoadLibrary(TEXT("user32.dll"));
+ if (shell) {
+ WinTouch_CloseTouchInputHandle = (CloseTouchInputHandlePROCADDR) GetProcAddressA(shell, "CloseTouchInputHandle");
+ WinTouch_GetTouchInputInfo = (GetTouchInputInfoPROCADDR) GetProcAddressA(shell, "GetTouchInputInfo");
+ WinTouch_IsTouchWindow = (IsTouchWindowPROCADDR) GetProcAddressA(shell, "IsTouchWindow");
+ WinTouch_RegisterTouchWindow = (RegisterTouchWindowPROCADDR) GetProcAddressA(shell, "RegisterTouchWindow");
+ WinTouch_UnregisterTouchWindow = (UnregisterTouchWindowPROCADDR) GetProcAddressA(shell, "UnregisterTouchWindow");
+ if(NULL != WinTouch_CloseTouchInputHandle && NULL != WinTouch_GetTouchInputInfo &&
+ NULL != WinTouch_IsTouchWindow && NULL != WinTouch_RegisterTouchWindow && NULL != WinTouch_UnregisterTouchWindow) {
+ WinTouch_func_avail = 1;
+ } else {
+ WinTouch_func_avail = 0;
+ }
+ }
+ }
return JNI_TRUE;
}
@@ -1365,20 +2027,21 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible,
UpdateWindow(hwnd);
}
+#define WS_DEFAULT_STYLES (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP)
+
/*
* Class: jogamp_newt_driver_windows_WindowDriver
* Method: CreateWindow
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindow0
(JNIEnv *env, jobject obj,
- jlong hInstance, jstring jWndClassName, jstring jWndName,
- jlong parent,
- jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags)
+ jlong hInstance, jstring jWndClassName, jstring jWndName, jint winMajor, jint winMinor,
+ jlong parent, jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags)
{
HWND parentWindow = (HWND) (intptr_t) parent;
const TCHAR* wndClassName = NULL;
const TCHAR* wndName = NULL;
- DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_TABSTOP;
+ DWORD windowStyle = WS_DEFAULT_STYLES | WS_VISIBLE;
int x=(int)jx, y=(int)jy;
int width=(int)defaultWidth, height=(int)defaultHeight;
HWND window = NULL;
@@ -1415,8 +2078,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
(HINSTANCE) (intptr_t) hInstance,
NULL);
- DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n",
- (int)GetCurrentThreadId(), parentWindow, window, x, y, width, height,
+ DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, win %d.%d parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n",
+ (int)GetCurrentThreadId(), winMajor, winMinor, parentWindow, window, x, y, width, height,
TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition);
if (NULL == window) {
@@ -1427,6 +2090,31 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData));
wud->jinstance = (*env)->NewGlobalRef(env, obj);
wud->jenv = env;
+ wud->width = width;
+ wud->height = height;
+ wud->setPointerVisible = 0;
+ wud->setPointerAction = 0;
+ wud->defPointerHandle = LoadCursor( NULL, IDC_ARROW);
+ wud->setPointerHandle = wud->defPointerHandle;
+ wud->isFullscreen = 0;
+ wud->isChildWindow = NULL!=parentWindow;
+ wud->pointerCaptured = 0;
+ wud->pointerInside = 0;
+ wud->touchDownCount = 0;
+ wud->touchDownLastUp = 0;
+ wud->supportsMTouch = 0;
+ if ( WinTouch_func_avail && winMajor > 6 || ( winMajor == 6 && winMinor >= 1 ) ) {
+ int value = GetSystemMetrics(SM_DIGITIZER);
+ if (value & NID_READY) { /* ready */
+ if (value & NID_MULTI_INPUT) { /* multitouch */
+ wud->supportsMTouch = 1;
+ }
+ if (value & NID_INTEGRATED_TOUCH) { /* Integrated touch */
+ }
+ }
+ }
+ DBG_PRINT("*** WindowsWindow: CreateWindow winTouchFuncAvail %d, supportsMTouch %d\n", WinTouch_func_avail, wud->supportsMTouch);
+
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
SetWindowLong(window, GWL_USERDATA, (intptr_t) wud);
#else
@@ -1459,6 +2147,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
NewtWindow_setVisiblePosSize(window, TST_FLAG_IS_ALWAYSONTOP(flags), TRUE, x, y, width, height);
}
+ if( wud->supportsMTouch ) {
+ WinTouch_RegisterTouchWindow(window, 0);
+ }
}
#ifdef UNICODE
@@ -1469,6 +2160,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
(*env)->ReleaseStringUTFChars(env, jWndName, wndName);
#endif
+#ifdef TEST_MOUSE_HOOKS
+ hookLLMP = SetWindowsHookEx(WH_MOUSE_LL, &HookLowLevelMouseProc, (HINSTANCE) (intptr_t) hInstance, 0);
+ hookMP = SetWindowsHookEx(WH_MOUSE_LL, &HookMouseProc, (HINSTANCE) (intptr_t) hInstance, 0);
+ DBG_PRINT("**** LLMP Hook %p, MP Hook %p\n", hookLLMP, hookMP);
+#endif
+
return (jlong) (intptr_t) window;
}
@@ -1487,24 +2184,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_MonitorFrom
#endif
}
-static jboolean NewtWindows_setFullScreen(jboolean fullscreen)
-{
- int flags = 0;
- DEVMODE dm;
- // initialize the DEVMODE structure
- ZeroMemory(&dm, sizeof(dm));
- dm.dmSize = sizeof(dm);
-
- if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
- {
- return JNI_FALSE;
- }
-
- flags = ( JNI_TRUE == fullscreen ) ? CDS_FULLSCREEN : CDS_RESET ;
-
- return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE;
-}
-
/*
* Class: jogamp_newt_driver_windows_WindowDriver
* Method: reconfigureWindow0
@@ -1516,16 +2195,23 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
{
HWND hwndP = (HWND) (intptr_t) parent;
HWND hwnd = (HWND) (intptr_t) window;
- DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
+ DWORD windowStyle = WS_DEFAULT_STYLES;
BOOL styleChange = TST_FLAG_CHANGE_DECORATION(flags) || TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ;
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
- DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d\n",
+
+ DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d, isChild %d, isFullscreen %d\n",
parent, window, x, y, width, height,
TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags),
TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags),
TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags),
TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
- TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), styleChange);
+ TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), styleChange, wud->isChildWindow, wud->isFullscreen);
if (!IsWindow(hwnd)) {
DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed window %p is invalid\n", (void*)hwnd);
@@ -1537,6 +2223,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
return;
}
+ wud->isChildWindow = NULL != hwndP;
+
if(TST_FLAG_IS_VISIBLE(flags)) {
windowStyle |= WS_VISIBLE ;
}
@@ -1547,11 +2235,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
//
if( TST_FLAG_CHANGE_PARENTING(flags) && NULL == hwndP ) {
// TOP: in -> out
+
+ // HIDE to allow setting ICONs (Windows bug?) .. WS_VISIBLE (style) will reset visibility
+ ShowWindow(hwnd, SW_HIDE);
+
SetParent(hwnd, NULL);
}
if( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on
// TOP: in -> out
+ wud->isFullscreen = 1;
NewtWindows_setFullScreen(JNI_TRUE);
}
@@ -1569,6 +2262,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off
// CHILD: out -> in
+ wud->isFullscreen = 0;
NewtWindows_setFullScreen(JNI_FALSE);
}
@@ -1587,7 +2281,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
}
}
- DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X\n");
+ DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X isChild %d, isFullscreen %d\n", wud->isChildWindow, wud->isFullscreen);
}
/*
@@ -1629,34 +2323,16 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_setPoint
(JNIEnv *env, jclass clazz, jlong window, jboolean mouseVisible)
{
HWND hwnd = (HWND) (intptr_t) window;
- int res, resOld, i;
- jboolean b;
-
- if(JNI_TRUE == mouseVisible) {
- res = ShowCursor(TRUE);
- if(res < 0) {
- i=0;
- do {
- resOld = res;
- res = ShowCursor(TRUE);
- } while(res!=resOld && res<0 && ++i<10);
- }
- b = res>=0 ? JNI_TRUE : JNI_FALSE;
- } else {
- res = ShowCursor(FALSE);
- if(res >= 0) {
- i=0;
- do {
- resOld = res;
- res = ShowCursor(FALSE);
- } while(res!=resOld && res>=0 && ++i<10);
- }
- b = res<0 ? JNI_TRUE : JNI_FALSE;
- }
-
- DBG_PRINT( "*** WindowsWindow: setPointerVisible0: %d, res %d/%d\n", mouseVisible, res, b);
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+ wud->setPointerVisible = mouseVisible ? 1 : -1;
+ SendMessage(hwnd, WM_SETCURSOR, 0, 0);
- return b;
+ return JNI_TRUE;
}
/*
@@ -1671,12 +2347,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_confineP
jboolean res;
if(JNI_TRUE == confine) {
- // SetCapture(hwnd);
- // res = ( GetCapture() == hwnd ) ? JNI_TRUE : JNI_FALSE;
RECT rect = { l, t, r, b };
res = ClipCursor(&rect) ? JNI_TRUE : JNI_FALSE;
} else {
- // res = ReleaseCapture() ? JNI_TRUE : JNI_FALSE;
res = ClipCursor(NULL) ? JNI_TRUE : JNI_FALSE;
}
DBG_PRINT( "*** WindowsWindow: confinePointer0: %d, [ l %d t %d r %d b %d ], res %d\n",
@@ -1697,16 +2370,93 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0
SetCursorPos(x, y);
}
-/*
- * Class: Java_jogamp_newt_driver_windows_WindowDriver
- * Method: trackPointerLeave0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_trackPointerLeave0
- (JNIEnv *env, jclass clazz, jlong window)
-{
+JNIEXPORT jlong JNICALL
+Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, jobject _unused,
+ jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) {
+
+ if( 0 == pixels ) {
+ return 0;
+ }
+
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ const int bytes = 4 * width * height; // BGRA8888
+
+ DWORD dwWidth, dwHeight;
+ BITMAPV5HEADER bi;
+ HBITMAP hBitmap;
+ void *lpBits;
+ HICON handle = NULL;
+
+ dwWidth = width; // width of cursor
+ dwHeight = height; // height of cursor
+
+ ZeroMemory(&bi,sizeof(BITMAPV5HEADER));
+ bi.bV5Size = sizeof(BITMAPV5HEADER);
+ bi.bV5Width = dwWidth;
+ bi.bV5Height = -1 * dwHeight;
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ // The following mask specification specifies a supported 32 BPP
+ // alpha format for Windows XP.
+ bi.bV5RedMask = 0x00FF0000;
+ bi.bV5GreenMask = 0x0000FF00;
+ bi.bV5BlueMask = 0x000000FF;
+ bi.bV5AlphaMask = 0xFF000000;
+
+ HDC hdc;
+ hdc = GetDC(NULL);
+
+ // Create the DIB section with an alpha channel.
+ hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
+ (void **)&lpBits, NULL, (DWORD)0);
+
+ memcpy(lpBits, pixelPtr + pixels_byte_offset, bytes);
+
+ ReleaseDC(NULL,hdc);
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
+ // Create an empty mask bitmap.
+ HBITMAP hMonoBitmap = CreateBitmap(dwWidth,dwHeight,1,1,NULL);
+
+ ICONINFO ii;
+ ii.fIcon = isCursor ? FALSE : TRUE;
+ ii.xHotspot = hotX;
+ ii.yHotspot = hotY;
+ ii.hbmMask = hMonoBitmap;
+ ii.hbmColor = hBitmap;
+
+ // Create the alpha cursor with the alpha DIB section.
+ handle = CreateIconIndirect(&ii);
+
+ DeleteObject(hBitmap);
+ DeleteObject(hMonoBitmap);
+
+ return (jlong) (intptr_t) handle;
+}
+
+JNIEXPORT void JNICALL
+Java_jogamp_newt_driver_windows_DisplayDriver_destroyIcon0(JNIEnv *env, jobject _unused, jlong jhandle) {
+ HICON handle = (HICON) (intptr_t) jhandle;
+ DestroyIcon(handle);
+}
+
+JNIEXPORT void JNICALL
+Java_jogamp_newt_driver_windows_WindowDriver_setPointerIcon0(JNIEnv *env, jobject _unused, jlong window, jlong iconHandle) {
HWND hwnd = (HWND) (intptr_t) window;
- DBG_PRINT( "*** WindowsWindow: trackMouseLeave0\n");
- NewtWindows_trackPointerLeave(hwnd);
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+ wud->setPointerAction = 0 != iconHandle ? 1 : -1;
+ wud->setPointerHandle = (HCURSOR) (intptr_t) iconHandle;
+ SendMessage(hwnd, WM_SETCURSOR, 0, 0);
}
diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h
index 128b6b6f1..e58cdb755 100644
--- a/src/newt/native/X11Common.h
+++ b/src/newt/native/X11Common.h
@@ -45,8 +45,10 @@
#include <X11/extensions/Xrandr.h>
-#include "jogamp_newt_driver_x11_ScreenDriver.h"
#include "jogamp_newt_driver_x11_DisplayDriver.h"
+#include "jogamp_newt_driver_x11_ScreenDriver.h"
+#include "jogamp_newt_driver_x11_RandR11.h"
+#include "jogamp_newt_driver_x11_RandR13.h"
#include "jogamp_newt_driver_x11_WindowDriver.h"
#include "Window.h"
@@ -70,7 +72,6 @@ extern jclass X11NewtWindowClazz;
extern jmethodID insetsChangedID;
extern jmethodID visibleChangedID;
-void NewtDisplay_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync);
jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning);
Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return);
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 84b3a7630..b62a9b234 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -28,7 +28,9 @@
#include "X11Common.h"
-#define USE_SENDIO_DIRECT 1
+#include <X11/Xcursor/Xcursor.h>
+
+// #include <X11/XKBlib.h> // XKB disabled for now
jclass X11NewtWindowClazz = NULL;
jmethodID insetsChangedID = NULL;
@@ -46,107 +48,35 @@ static jmethodID focusChangedID = NULL;
static jmethodID reparentNotifyID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
static jmethodID sendMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
-static JavaVM *jvmHandle = NULL;
-static int jvmVersion = 0;
-
-static void setupJVMVars(JNIEnv * env) {
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- }
- jvmVersion = (*env)->GetVersion(env);
-}
-
-static XErrorHandler origErrorHandler = NULL ;
-static int errorHandlerQuiet = 0 ;
-static int errorHandlerDebug = 0 ;
-static int errorHandlerThrowException = 0;
-
-static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
-{
- if(!errorHandlerQuiet) {
- const char * errnoStr = strerror(errno);
- char threadName[80];
- char errCodeStr[80];
- char reqCodeStr[80];
-
- int shallBeDetached = 0;
- JNIEnv *jniEnv = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
-
- (void) NewtCommon_GetStaticStringMethod(jniEnv, X11NewtWindowClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
- snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
- XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
- XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
-
- fprintf(stderr, "Info: Newt X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
- threadName, e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
- (int)e->request_code, (int)e->minor_code, reqCodeStr);
-
- if( errorHandlerDebug ) {
- (*jniEnv)->CallStaticVoidMethod(jniEnv, X11NewtWindowClazz, dumpStackID);
- }
-
- if(errorHandlerThrowException) {
- if(NULL != jniEnv) {
- NewtCommon_throwNewRuntimeException(jniEnv, "Newt X11 Error (Thread: %s): %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
- threadName, e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
- (int)e->request_code, (int)e->minor_code, reqCodeStr);
- } else {
- fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
- #if 0
- if(NULL!=origErrorHandler) {
- origErrorHandler(dpy, e);
- }
- #endif
- }
- }
- fflush(stderr);
-
- if (NULL != jniEnv && shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
- }
-
- return 0;
-}
-
-void NewtDisplay_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync) {
- errorHandlerQuiet = quiet;
- if(onoff) {
- if(NULL==origErrorHandler) {
- setupJVMVars(env);
- origErrorHandler = XSetErrorHandler(x11ErrorHandler);
- if(sync && NULL!=dpy) {
- XSync(dpy, False);
- }
- }
- } else {
- if(NULL!=origErrorHandler) {
- if(sync && NULL!=dpy) {
- XSync(dpy, False);
- }
- XSetErrorHandler(origErrorHandler);
- origErrorHandler = NULL;
- }
- }
-}
-
/**
* Keycode
*/
+// #define DEBUG_KEYS 1
+
#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)+J_VK_F1;
- if(IS_WITHIN(keySym,XK_KP_0,XK_KP_9))
- return (keySym-XK_KP_0)+J_VK_NUMPAD0;
+/**
+ * QT Reference:
+ * <http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/kernel/qkeymapper_x11.cpp#line879>
+ */
+static short X11KeySym2NewtVKey(KeySym keySym) {
+ if( IS_WITHIN( keySym, XK_a, XK_z ) ) {
+ return ( keySym - XK_a ) + J_VK_A ;
+ }
+ if( IS_WITHIN( keySym, XK_0, XK_9 ) ) {
+ return ( keySym - XK_0 ) + J_VK_0 ;
+ }
+ if( IS_WITHIN( keySym, XK_KP_0, XK_KP_9 ) ) {
+ return ( keySym - XK_KP_0 ) + J_VK_NUMPAD0 ;
+ }
+ if( IS_WITHIN( keySym, XK_F1, XK_F12 ) ) {
+ return ( keySym - XK_F1 ) + J_VK_F1 ;
+ }
switch(keySym) {
case XK_Return:
@@ -160,8 +90,6 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_TAB;
case XK_Cancel:
return J_VK_CANCEL;
- case XK_Clear:
- return J_VK_CLEAR;
case XK_Shift_L:
case XK_Shift_R:
return J_VK_SHIFT;
@@ -169,8 +97,15 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
case XK_Control_R:
return J_VK_CONTROL;
case XK_Alt_L:
- case XK_Alt_R:
return J_VK_ALT;
+ case XK_Alt_R:
+ case XK_ISO_Level3_Shift:
+ return J_VK_ALT_GRAPH;
+ case XK_Super_L:
+ case XK_Super_R:
+ return J_VK_WINDOWS;
+ case XK_Menu:
+ return J_VK_CONTEXT_MENU;
case XK_Pause:
return J_VK_PAUSE;
case XK_Caps_Lock:
@@ -189,6 +124,10 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
case XK_End:
case XK_KP_End:
return J_VK_END;
+ case XK_Begin:
+ return J_VK_BEGIN;
+ case XK_KP_Begin: // NumPad 5 - equal behavior w/ QT/Windows
+ return J_VK_CLEAR;
case XK_Home:
case XK_KP_Home:
return J_VK_HOME;
@@ -216,6 +155,7 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_DECIMAL;
case XK_KP_Divide:
return J_VK_DIVIDE;
+ case XK_Clear: // equal behavior w/ QT
case XK_Delete:
case XK_KP_Delete:
return J_VK_DELETE;
@@ -230,28 +170,43 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_INSERT;
case XK_Help:
return J_VK_HELP;
+ case XK_grave:
+ return J_VK_BACK_QUOTE;
+ case XK_apostrophe:
+ return J_VK_QUOTE;
}
return keySym;
}
-static jint X11InputState2NewtModifiers(unsigned int xstate) {
+#define ShiftCtrlModMask ( ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask )
+
+static jboolean altGraphDown = JNI_FALSE;
+
+static jint X11InputState2NewtModifiers(unsigned int xstate, jshort javaVKey, jboolean keyDown) {
jint modifiers = 0;
- if ((ControlMask & xstate) != 0) {
+ if ( (ControlMask & xstate) != 0 || J_VK_CONTROL == javaVKey ) {
modifiers |= EVENT_CTRL_MASK;
}
- if ((ShiftMask & xstate) != 0) {
+ if ( (ShiftMask & xstate) != 0 || J_VK_SHIFT == javaVKey ) {
modifiers |= EVENT_SHIFT_MASK;
}
- if ((Mod1Mask & xstate) != 0) {
+ if ( J_VK_ALT == javaVKey ) {
+ altGraphDown = JNI_FALSE;
modifiers |= EVENT_ALT_MASK;
+ } else if ( (short)J_VK_ALT_GRAPH == javaVKey ) {
+ altGraphDown = keyDown;
+ modifiers |= EVENT_ALT_GRAPH_MASK;
+ } else if ( (Mod1Mask & xstate) != 0 ) {
+ // XK_Alt_L or XK_Alt_R
+ modifiers |= altGraphDown ? EVENT_ALT_GRAPH_MASK : EVENT_ALT_MASK;
}
- if ((Button1Mask & xstate) != 0) {
+ if ( (Button1Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON1_MASK;
}
- if ((Button2Mask & xstate) != 0) {
+ if ( (Button2Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON2_MASK;
}
- if ((Button3Mask & xstate) != 0) {
+ if ( (Button3Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON3_MASK;
}
@@ -273,9 +228,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
{
jclass c;
- if(debug) {
- errorHandlerDebug = 1 ;
- }
NewtCommon_init(env);
if(NULL==X11NewtWindowClazz) {
@@ -290,6 +242,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
}
}
+ // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJ)V"); // Variant using XKB
displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;");
dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V");
@@ -301,10 +254,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V");
- enqueueMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V");
requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V");
if (displayCompletedID == NULL ||
@@ -318,9 +269,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
reparentNotifyID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
- enqueueMouseEventID == NULL ||
sendMouseEventID == NULL ||
- enqueueKeyEventID == NULL ||
sendKeyEventID == NULL ||
requestFocusID == NULL) {
return JNI_FALSE;
@@ -341,6 +290,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
Display * dpy = (Display *)(intptr_t)display;
jlong javaObjectAtom;
jlong windowDeleteAtom;
+ // jlong kbdHandle; // XKB disabled for now
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -359,10 +309,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
}
// XSetCloseDownMode(dpy, RetainTemporary); // Just a try ..
+ // kbdHandle = (jlong) (intptr_t) XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd); // XKB disabled for now
DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy);
- (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom);
+ (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/); // XKB disabled for now
}
/*
@@ -371,11 +322,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
* Signature: (JJJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
- (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
{
Display * dpy = (Display *)(intptr_t)display;
Atom wm_javaobject_atom = (Atom)javaObjectAtom;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -385,6 +337,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
(void) wm_javaobject_atom;
(void) wm_delete_atom;
+ // XkbFreeKeyboard(kbdDesc, XkbAllNamesMask, True); // XKB disabled for now
+
XSync(dpy, True); // discard all pending events
DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy);
}
@@ -392,13 +346,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
/*
* Class: jogamp_newt_driver_x11_DisplayDriver
* Method: DispatchMessages
- * Signature: (JIJJ)V
+ * Signature: (JJJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0
- (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
{
Display * dpy = (Display *) (intptr_t) display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now
int num_events = 100;
int autoRepeatModifiers = 0;
@@ -406,20 +361,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
return;
}
+ /** XKB disabled for now
+ if( NULL == kbdDesc) {
+ NewtCommon_throwNewRuntimeException(env, "NULL kbd handle, bail out!");
+ return;
+ } */
+
// Periodically take a break
while( num_events > 0 ) {
jobject jwindow = NULL;
XEvent evt;
KeySym keySym = 0;
+ KeyCode keyCode = 0;
+ jshort javaVKeyUS = 0;
+ jshort javaVKeyNN = 0;
jint modifiers = 0;
- char keyChar = 0;
+ uint16_t keyChar = 0;
+ jstring keyString = NULL;
char text[255];
// XEventsQueued(dpy, X):
- // QueuedAlready : No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
+ // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
// QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available
// QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more ..
- if ( 0 >= XPending(dpy) ) {
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
// DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
return;
}
@@ -427,19 +392,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
XNextEvent(dpy, &evt);
num_events--;
- if( 0==evt.xany.window ) {
- NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
- return ;
- }
-
if(dpy!=evt.xany.display) {
NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
return ;
}
- // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+ if( 0==evt.xany.window ) {
+ DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type);
+ continue;
+ }
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
#ifdef VERBOSE_ON
@@ -449,11 +412,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
#endif
);
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
-
if(NULL==jwindow) {
- fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
- (void*)dpy, evt.type, (void*)evt.xany.window);
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window);
continue;
}
@@ -470,26 +430,73 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
} else {
autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
}
+ } else {
+ autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
}
// fall through intended
- case KeyPress:
- if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
- KeySym lower_return = 0, upper_return = 0;
- keyChar=text[0];
- XConvertCase(keySym, &lower_return, &upper_return);
- // always return upper case, set modifier masks (SHIFT, ..)
- keySym = X11KeySym2NewtVKey(upper_return);
- } else {
- keyChar=0;
- keySym = X11KeySym2NewtVKey(keySym);
+ case KeyPress: {
+ KeySym shiftedKeySym; // layout depending keySym w/ SHIFT
+ KeySym unShiftedKeySym; // layout depending keySym w/o SHIFT
+ unsigned int xkey_state = evt.xkey.state;
+
+ keyCode = evt.xkey.keycode;
+
+ // Layout depending keySym w/o SHIFT,
+ // using fixed group 0 (US default layout)
+ //
+ // unsigned int mods_rtrn = 0;
+ // Bool res = XkbTranslateKeyCode (kbdDesc, keyCode, 0, &mods_rtrn, &keySym); // XKB disabled for now
+ // if( !res ) {
+ keySym = XkbKeycodeToKeysym(dpy, keyCode, 0 /* group */, 0 /* shift level */);
+ // }
+
+ text[0] = 0; text[1] = 0; text[2] = 0;
+ int charCount = XLookupString(&evt.xkey, text, 2, &shiftedKeySym, NULL);
+ if( 1 == charCount ) {
+ keyChar = 0x00FF & (uint16_t) (text[0]);
+ } else if( 2 == charCount ) {
+ // Example: UTF-16: 00DF, UTF-8: c3 9f, LATIN SMALL LETTER SHARP S
+ keyChar = ( 0x00FF & (uint16_t)(text[0]) ) << 8 | ( 0x00FF & (uint16_t)(text[1]) ); // UTF-16BE
+ keyString = (*env)->NewStringUTF(env, text);
+ }
+
+ #ifdef DEBUG_KEYS
+ fprintf(stderr, "NEWT X11 Key.0: keyCode 0x%X keySym 0x%X, (shifted: 0x%X)\n",
+ (int)keyCode, (int)keySym, (int) shiftedKeySym);
+ #endif
+ if( IS_WITHIN( shiftedKeySym, XK_KP_Space, XK_KP_9 ) ) {
+ // Use modded keySym for keypad for US and NN
+ keySym = shiftedKeySym;
+ unShiftedKeySym = shiftedKeySym;
+ } else if( 0 == keyChar ) {
+ // Use keyCode's keySym for dead-key (aka modifiers, etc)
+ unShiftedKeySym = keySym;
+ } else if( 0 == ( evt.xkey.state & ShiftCtrlModMask ) ) {
+ // Use non modded keySym
+ unShiftedKeySym = shiftedKeySym;
+ } else {
+ evt.xkey.state = evt.xkey.state & ~ShiftCtrlModMask; // clear shift, ctrl and Mod*
+ XLookupString(&evt.xkey, text, 0, &unShiftedKeySym, NULL);
+ // unShiftedKeySym = XLookupKeysym(&evt.xkey, 0 /* index ? */);
+ }
+
+ javaVKeyNN = X11KeySym2NewtVKey(unShiftedKeySym);
+ javaVKeyUS = X11KeySym2NewtVKey(keySym);
+ modifiers |= X11InputState2NewtModifiers(xkey_state, javaVKeyNN, evt.type == KeyPress) | autoRepeatModifiers;
+
+ #ifdef DEBUG_KEYS
+ fprintf(stderr, "NEWT X11 Key.X: keyCode 0x%X keySym 0x%X, (0x%X, shifted: 0x%X), keyChar '%c' 0x%X %d, javaVKey[US 0x%X, NN 0x%X], xstate 0x%X %u, jmods 0x%X\n",
+ (int)keyCode, (int)keySym, (int) unShiftedKeySym, (int)shiftedKeySym, keyChar, keyChar, charCount,
+ (int)javaVKeyUS, (int)javaVKeyNN,
+ (int)xkey_state, (int)xkey_state, (int)modifiers);
+ #endif
}
- modifiers |= X11InputState2NewtModifiers(evt.xkey.state) | autoRepeatModifiers;
break;
case ButtonPress:
case ButtonRelease:
case MotionNotify:
- modifiers |= X11InputState2NewtModifiers(evt.xbutton.state);
+ modifiers |= X11InputState2NewtModifiers(evt.xbutton.state, 0, JNI_FALSE);
break;
default:
@@ -499,87 +506,43 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
switch(evt.type) {
case ButtonPress:
(*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED,
modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
- modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #endif
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
break;
case ButtonRelease:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
- modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED,
modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #endif
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
break;
case MotionNotify:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
- modifiers,
- (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED,
modifiers,
- (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/);
break;
case EnterNotify:
DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED,
modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
break;
case LeaveNotify:
DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED,
modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ break;
+ case MappingNotify:
+ DBG_PRINT( "X11: event . MappingNotify call %p type %d\n", (void*)evt.xmapping.window, evt.xmapping.type);
+ XRefreshKeyboardMapping(&evt.xmapping);
break;
case KeyPress:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
- modifiers, keySym, (jchar) -1);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
- modifiers, keySym, (jchar) -1);
- #endif
-
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED,
+ modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
break;
case KeyRelease:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
- modifiers, keySym, (jchar) -1);
-
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED,
- modifiers, keySym, (jchar) keyChar);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
- modifiers, keySym, (jchar) -1);
-
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED,
- modifiers, keySym, (jchar) keyChar);
- #endif
-
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED,
+ modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
break;
case DestroyNotify:
DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
@@ -709,4 +672,59 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
}
}
+/*
+ * Class: Java_jogamp_newt_driver_x11_DisplayDriver
+ * Method: createPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
+{
+ Cursor c;
+
+ if( 0 != pixels ) {
+ Display * dpy = (Display *) (intptr_t) display;
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ XcursorImage ci;
+ ci.version = 1; // XCURSOR_IMAGE_VERSION;
+ ci.size = width; // nominal size (assume square ..)
+ ci.width = width;
+ ci.height = height;
+ ci.xhot = hotX;
+ ci.yhot = hotY;
+ ci.delay = 0;
+ ci.pixels = (XcursorPixel *)(intptr_t)(pixelPtr + pixels_byte_offset);
+
+ c = XcursorImageLoadCursor (dpy, &ci);
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+ DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", (pixelPtr+pixels_byte_offset), width, height, hotX, hotY, (void *)c);
+
+ } else {
+ c = 0;
+ }
+ return (jlong) (intptr_t) c;
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_x11_DisplayDriver
+ * Method: destroyPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_destroyPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong handle)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+
+ if( 0 != handle ) {
+ Cursor c = (Cursor) (intptr_t) handle;
+ DBG_PRINT( "X11: destroyPointerIcon0: %p\n", (void *)c);
+ XFreeCursor(dpy, c);
+ }
+}
+
diff --git a/src/newt/native/X11Event.c b/src/newt/native/X11Event.c
new file mode 100644
index 000000000..32a55c67c
--- /dev/null
+++ b/src/newt/native/X11Event.c
@@ -0,0 +1,305 @@
+
+#include "X11Event.h"
+
+void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong windowDeleteAtom) {
+ Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ int num_events = 100;
+ int autoRepeatModifiers = 0;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ XEvent evt;
+ KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ char text[255];
+
+ // XEventsQueued(dpy, X):
+ // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
+ // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available
+ // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more ..
+ // if ( 0 >= XPending(dpy) )
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) )
+ {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+
+ XNextEvent(dpy, &evt);
+ num_events--;
+
+ if(dpy!=evt.xany.display) {
+ NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
+ return ;
+ }
+
+ if( 0==evt.xany.window ) {
+ DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type);
+ continue;
+ }
+
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+
+ jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window);
+ continue;
+ }
+
+ switch(evt.type) {
+ case KeyRelease:
+ if (XEventsQueued(dpy, QueuedAfterReading)) {
+ XEvent nevt;
+ XPeekEvent(dpy, &nevt);
+
+ if (nevt.type == KeyPress && nevt.xkey.time == evt.xkey.time &&
+ nevt.xkey.keycode == evt.xkey.keycode)
+ {
+ autoRepeatModifiers |= EVENT_AUTOREPEAT_MASK;
+ } else {
+ autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
+ }
+ }
+ // fall through intended
+ case KeyPress:
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ KeySym lower_return = 0, upper_return = 0;
+ keyChar=text[0];
+ XConvertCase(keySym, &lower_return, &upper_return);
+ // always return upper case, set modifier masks (SHIFT, ..)
+ keySym = X11KeySym2NewtVKey(upper_return);
+ } else {
+ keyChar=0;
+ keySym = X11KeySym2NewtVKey(keySym);
+ }
+ modifiers |= X11InputState2NewtModifiers(evt.xkey.state) | autoRepeatModifiers;
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ modifiers |= X11InputState2NewtModifiers(evt.xbutton.state);
+ break;
+
+ default:
+ break;
+ }
+
+ switch(evt.type) {
+ case ButtonPress:
+ (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #endif
+ break;
+ case ButtonRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #endif
+ break;
+ case MotionNotify:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case EnterNotify:
+ DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case LeaveNotify:
+ DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case KeyPress:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, keySym, (jchar) -1);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, keySym, (jchar) -1);
+ #endif
+
+ break;
+ case KeyRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, keySym, (jchar) -1);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
+ modifiers, keySym, (jchar) -1);
+ #endif
+
+ break;
+ case DestroyNotify:
+ DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
+ (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event);
+ if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) {
+ // ignore child destroy notification
+ }
+ break;
+ case CreateNotify:
+ DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n",
+ (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent);
+ break;
+ case ConfigureNotify:
+ DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n",
+ (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above,
+ evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height,
+ evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
+ if ( evt.xconfigure.window == evt.xconfigure.event ) {
+ // ignore child window change notification
+ {
+ // update insets
+ int left, right, top, bottom;
+ NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+ }
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom
+ jboolean closed;
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE);
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed);
+ // Called by Window.java: CloseWindow();
+ num_events = 0; // end loop in case of destroyed display
+ }
+ break;
+
+ case FocusIn:
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
+ break;
+
+ case Expose:
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
+
+ if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ }
+ break;
+
+ case MapNotify:
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect,
+ evt.xmap.event!=evt.xmap.window);
+ if( evt.xmap.event == evt.xmap.window ) {
+ // ignore child window notification
+ {
+ // update insets
+ int left, right, top, bottom;
+ NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+ }
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
+ }
+ break;
+
+ case UnmapNotify:
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n",
+ (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure,
+ evt.xunmap.event!=evt.xunmap.window);
+ if( evt.xunmap.event == evt.xunmap.window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
+ }
+ break;
+
+ case ReparentNotify:
+ {
+ jlong parentResult; // 0 if root, otherwise proper value
+ Window winRoot, winTopParent;
+ #ifdef VERBOSE_ON
+ Window oldParentRoot, oldParentTopParent;
+ Window parentRoot, parentTopParent;
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) {
+ oldParentRoot=0; oldParentTopParent = 0;
+ }
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) {
+ parentRoot=0; parentTopParent = 0;
+ }
+ #endif
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) {
+ winRoot=0; winTopParent = 0;
+ }
+ if(evt.xreparent.parent == winRoot) {
+ parentResult = 0; // our java indicator for root window
+ } else {
+ parentResult = (jlong) (intptr_t) evt.xreparent.parent;
+ }
+ #ifdef VERBOSE_ON
+ DBG_PRINT( "X11: event . ReparentNotify: call %d/%d OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ evt.xreparent.x, evt.xreparent.y,
+ (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent,
+ (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
+ (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
+ #endif
+ (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent);
+ }
+ break;
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window);
+ }
+ }
+}
diff --git a/src/newt/native/X11Event.h b/src/newt/native/X11Event.h
new file mode 100644
index 000000000..969bcdeed
--- /dev/null
+++ b/src/newt/native/X11Event.h
@@ -0,0 +1,9 @@
+
+#ifndef _X11Event_h
+#define _X11Event_h
+
+#include "X11Common.h"
+
+extern void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom);
+
+#endif /* _X11Event_h */
diff --git a/src/newt/native/X11RandR11.c b/src/newt/native/X11RandR11.c
new file mode 100644
index 000000000..38d61289b
--- /dev/null
+++ b/src/newt/native/X11RandR11.c
@@ -0,0 +1,371 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "X11Screen.h"
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getAvailableScreenRotations0
+ * Signature: (JI)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getAvailableScreenRotations0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+ int num_rotations = 0;
+ Rotation cur_rotation, rotations_supported;
+ int rotations[4];
+ int major, minor;
+
+ rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
+
+ if(0 != (rotations_supported & RR_Rotate_0)) {
+ rotations[num_rotations++] = 0;
+ }
+ if(0 != (rotations_supported & RR_Rotate_90)) {
+ rotations[num_rotations++] = 90;
+ }
+ if(0 != (rotations_supported & RR_Rotate_180)) {
+ rotations[num_rotations++] = 180;
+ }
+ if(0 != (rotations_supported & RR_Rotate_270)) {
+ rotations[num_rotations++] = 270;
+ }
+
+ jintArray properties = NULL;
+
+ if(num_rotations>0) {
+ properties = (*env)->NewIntArray(env, num_rotations);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
+ }
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getNumScreenResolution0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getNumScreenResolutions0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getNumScreenResolution0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getNumScreenResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ DBG_PRINT("getNumScreenResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes);
+
+ return num_sizes;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenResolutions0
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenResolution0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ // Fill the properties in temp jint array
+ int propIndex = 0;
+ jint prop[4];
+
+ prop[propIndex++] = xrrs[(int)resMode_idx].width;
+ prop[propIndex++] = xrrs[(int)resMode_idx].height;
+ prop[propIndex++] = xrrs[(int)resMode_idx].mwidth;
+ prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
+
+ jintArray properties = (*env)->NewIntArray(env, 4);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenRates0
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenRates0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ int num_rates;
+ short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
+
+ jint prop[num_rates];
+ int i;
+ for(i=0; i<num_rates; i++) {
+ prop[i] = (int) rates[i];
+ /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
+ }
+
+ jintArray properties = (*env)->NewIntArray(env, num_rates);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenConfiguration0
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenConfiguration0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getScreenConfiguration0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ // get current resolutions and frequencies
+ XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getScreenConfiguration0.2 (XRRGetScreenInfo): %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ return (jlong) (intptr_t) conf;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: freeScreenConfiguration0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR11_freeScreenConfiguration0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration );
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenRate0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenRate0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+
+ short original_rate = XRRConfigCurrentRate(conf);
+ DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
+
+ return (jint) original_rate;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenRotation0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenRotation0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+ Rotation rotation;
+
+ XRRConfigCurrentConfiguration(conf, &rotation);
+
+ return NewtScreen_XRotation2Degree(env, rotation);
+}
+
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenResolutionIndex0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenResolutionIndex0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+
+ short original_rate = XRRConfigCurrentRate(conf);
+
+ Rotation original_rotation;
+ SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
+
+ DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
+ return (jint)original_size_id;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: setCurrentScreenModeStart0
+ * Signature: (JIJIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModeStart0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+ Window root = RootWindow(dpy, (int)screen_idx);
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n",
+ resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
+
+ int xrot = NewtScreen_Degree2XRotation(env, rotation);
+
+ XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
+
+ XSync(dpy, False);
+ XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, xrot, (short)freq, CurrentTime);
+ XSync(dpy, False);
+
+ return JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: setCurrentScreenModePollEnd0
+ * Signature: (JIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModePollEnd0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ int randr_event_base, randr_error_base;
+ XEvent evt;
+ XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
+ XRRScreenConfiguration *conf;
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
+
+ int done = 0;
+ int rot;
+ do {
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
+ return JNI_FALSE; // not done
+ }
+ XNextEvent(dpy, &evt);
+
+ switch (evt.type - randr_event_base) {
+ case RRScreenChangeNotify:
+ if(0 < scn_event->rotation ) {
+ rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(1) %p (root %p) resIdx %d rot %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index, rot,
+ scn_event->width, scn_event->height);
+ // done = scn_event->size_index == resMode_idx; // not reliable ..
+ done = rot == rotation &&
+ scn_event->width == xrrs[resMode_idx].width &&
+ scn_event->height == xrrs[resMode_idx].height;
+ } else {
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(0) %p (root %p) resIdx %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index,
+ scn_event->width, scn_event->height);
+ }
+ break;
+ default:
+ DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
+ }
+ XRRUpdateConfiguration(&evt);
+ } while(!done);
+
+ XSync(dpy, False);
+
+ return done ? JNI_TRUE : JNI_FALSE;
+}
+
diff --git a/src/newt/native/X11RandR13.c b/src/newt/native/X11RandR13.c
new file mode 100644
index 000000000..4e92a32b4
--- /dev/null
+++ b/src/newt/native/X11RandR13.c
@@ -0,0 +1,519 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "X11Common.h"
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getScreenResources0
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+
+ XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); // 1.3
+ // XRRScreenResources *res = XRRGetScreenResources( dpy, root); // 1.2
+
+ return (jlong) (intptr_t) res;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: freeScreenResources0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeScreenResources0
+ (JNIEnv *env, jclass clazz, jlong screenResources)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ if( NULL != resources ) {
+ XRRFreeScreenResources( resources );
+ }
+}
+
+#define SAFE_STRING(s) (NULL==s?"":s)
+
+static void dumpOutputs(const char *prefix, Display *dpy, XRRScreenResources *resources, int noutput, RROutput * outputs) {
+ int i, j;
+ fprintf(stderr, "%s %p: Output count %d\n", prefix, resources, noutput);
+ for(i=0; i<noutput; i++) {
+ RROutput output = outputs[i];
+ XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+ fprintf(stderr, " Output[%d]: id %#lx, crtx 0x%X, name %s (%d), %lux%lu, ncrtc %d, .., nmode %d (preferred %d)\n",
+ i, output, xrrOutputInfo->crtc, SAFE_STRING(xrrOutputInfo->name), xrrOutputInfo->nameLen, xrrOutputInfo->mm_width, xrrOutputInfo->mm_height,
+ xrrOutputInfo->ncrtc, xrrOutputInfo->nmode, xrrOutputInfo->npreferred);
+ for(j=0; j<xrrOutputInfo->nmode; j++) {
+ fprintf(stderr, " Output[%d].Mode[%d].id %#lx\n", i, j, xrrOutputInfo->modes[j]);
+ }
+ XRRFreeOutputInfo (xrrOutputInfo);
+ }
+}
+
+/** Returns vertical refresh rate in hertz */
+static float getVRefresh(XRRModeInfo *mode) {
+ float rate;
+ unsigned int vTotal = mode->vTotal;
+
+ if (mode->modeFlags & RR_DoubleScan) {
+ /* doublescan doubles the number of lines */
+ vTotal *= 2;
+ }
+
+ if (mode->modeFlags & RR_Interlace) {
+ /* interlace splits the frame into two fields */
+ /* the field rate is what is typically reported by monitors */
+ vTotal /= 2;
+ }
+
+ if (mode->hTotal && vTotal) {
+ rate = ( (float) mode->dotClock /
+ ( (float) mode->hTotal * (float) vTotal )
+ );
+ } else {
+ rate = 0;
+ }
+ return rate;
+}
+
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_dumpInfo0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ int pos[] = { 0, 0 } ;
+ int i, j, minWidth, minHeight, maxWidth, maxHeight;
+
+ int vs_width = DisplayWidth(dpy, screen_idx);
+ int vs_height = DisplayHeight(dpy, screen_idx);
+ int vs_width_mm = DisplayWidthMM(dpy, screen_idx);
+ int vs_height_mm = DisplayHeightMM(dpy, screen_idx);
+ fprintf(stderr, "ScreenVirtualSize: %dx%d %dx%d mm\n", vs_width, vs_height, vs_width_mm, vs_height_mm);
+
+ XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight);
+ fprintf(stderr, "XRRGetScreenSizeRange: %dx%d .. %dx%d\n", minWidth, minHeight, maxWidth, maxHeight);
+
+ if( NULL == resources ) {
+ fprintf(stderr, "XRRScreenResources NULL\n");
+ return;
+ }
+ fprintf(stderr, "XRRScreenResources %p: Crtc count %d\n", resources, resources->ncrtc);
+ for(i=0; i<resources->ncrtc; i++) {
+ RRCrtc crtc = resources->crtcs[i];
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
+ fprintf(stderr, "Crtc[%d]: %d/%d %dx%d, rot 0x%X, mode.id %#lx\n",
+ i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height, xrrCrtcInfo->rotations, xrrCrtcInfo->mode);
+ for(j=0; j<xrrCrtcInfo->noutput; j++) {
+ fprintf(stderr, " Crtc[%d].Output[%d].id %#lx\n", i, j, xrrCrtcInfo->outputs[j]);
+ }
+ XRRFreeCrtcInfo(xrrCrtcInfo);
+ }
+
+ dumpOutputs("XRRScreenResources.outputs", dpy, resources, resources->noutput, resources->outputs);
+
+ fprintf(stderr, "XRRScreenResources %p: Mode count %d\n", resources, resources->nmode);
+ for(i=0; i<resources->nmode; i++) {
+ XRRModeInfo *mode = &resources->modes[i];
+
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ float refresh = getVRefresh(mode);
+ fprintf(stderr, "Mode[%d, id %#lx]: %ux%u@%f, name %s\n", i, mode->id, mode->width, mode->height, refresh, SAFE_STRING(mode->name));
+ }
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorDeviceCount0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDeviceCount0
+ (JNIEnv *env, jclass clazz, jlong screenResources)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ return ( NULL != resources ) ? resources->ncrtc : 0;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorInfoHandle0
+ * Signature: (JIJI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorInfoHandle0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint crt_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+
+ if( NULL == resources || crt_idx >= resources->ncrtc ) {
+ return 0;
+ }
+ RRCrtc crtc = resources->crtcs[crt_idx];
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
+
+ return (jlong) (intptr_t) xrrCrtcInfo;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: freeMonitorInfoHandle0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeMonitorInfoHandle0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ if( NULL != xrrCrtcInfo ) {
+ XRRFreeCrtcInfo( xrrCrtcInfo );
+ }
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getAvailableRotations0
+ * Signature: (J)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getAvailableRotations0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ if( NULL == xrrCrtcInfo ) {
+ return NULL;
+ }
+ Rotation rotations_supported = xrrCrtcInfo->rotations;
+
+ int num_rotations = 0;
+ int rotations[4];
+ if(0 != (rotations_supported & RR_Rotate_0)) {
+ rotations[num_rotations++] = 0;
+ }
+ if(0 != (rotations_supported & RR_Rotate_90)) {
+ rotations[num_rotations++] = 90;
+ }
+ if(0 != (rotations_supported & RR_Rotate_180)) {
+ rotations[num_rotations++] = 180;
+ }
+ if(0 != (rotations_supported & RR_Rotate_270)) {
+ rotations[num_rotations++] = 270;
+ }
+
+ jintArray properties = NULL;
+
+ if(num_rotations>0) {
+ properties = (*env)->NewIntArray(env, num_rotations);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
+ }
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorViewport0
+ * Signature: (J)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorViewport0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == xrrCrtcInfo ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ jsize propCount = 4;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = xrrCrtcInfo->x;
+ prop[propIndex++] = xrrCrtcInfo->y;
+ prop[propIndex++] = xrrCrtcInfo->width;
+ prop[propIndex++] = xrrCrtcInfo->height;
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorMode0
+ * Signature: (JI)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorMode0
+ (JNIEnv *env, jclass clazz, jlong screenResources, jint mode_idx)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+
+ if( NULL == resources || mode_idx >= resources->nmode ) {
+ return NULL;
+ }
+
+ XRRModeInfo *mode = &resources->modes[mode_idx];
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100
+ int flags = 0;
+ if (mode->modeFlags & RR_Interlace) {
+ flags |= FLAG_INTERLACE;
+ }
+ if (mode->modeFlags & RR_DoubleScan) {
+ flags |= FLAG_DOUBLESCAN;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int propIndex = 0;
+
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ prop[propIndex++] = mode->width;
+ prop[propIndex++] = mode->height;
+ prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp
+ prop[propIndex++] = refresh;
+ prop[propIndex++] = flags;
+ prop[propIndex++] = mode->id;
+ prop[propIndex++] = -1; // rotation placeholder
+
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorCurrentMode0
+ * Signature: (JJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorCurrentMode0
+ (JNIEnv *env, jclass clazz, jlong screenResources, jlong monitorInfo)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == resources || NULL == xrrCrtcInfo ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ int modeId = xrrCrtcInfo->mode;
+ XRRModeInfo *mode = NULL;
+ int i;
+ for(i=0; i<resources->nmode; i++) {
+ XRRModeInfo *imode = &resources->modes[i];
+ if( imode->id == modeId ) {
+ mode = imode;
+ break;
+ }
+ }
+ if( NULL == mode ) {
+ // oops ..
+ return NULL;
+ }
+
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100
+ int flags = 0;
+ if (mode->modeFlags & RR_Interlace) {
+ flags |= FLAG_INTERLACE;
+ }
+ if (mode->modeFlags & RR_DoubleScan) {
+ flags |= FLAG_DOUBLESCAN;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int propIndex = 0;
+
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ prop[propIndex++] = mode->width;
+ prop[propIndex++] = mode->height;
+ prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp
+ prop[propIndex++] = refresh;
+ prop[propIndex++] = flags;
+ prop[propIndex++] = mode->id;
+ prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
+
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorDevice0
+ * Signature: (JJJJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice0
+ (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ RROutput output = xrrCrtcInfo->outputs[0];
+ XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+ int numModes = xrrOutputInfo->nmode;
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 + numModes;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = propCount;
+ prop[propIndex++] = crt_idx;
+ prop[propIndex++] = xrrOutputInfo->mm_width;
+ prop[propIndex++] = xrrOutputInfo->mm_height;
+ prop[propIndex++] = xrrCrtcInfo->x; // rotated viewport pixel units
+ prop[propIndex++] = xrrCrtcInfo->y; // rotated viewport pixel units
+ prop[propIndex++] = xrrCrtcInfo->width; // rotated viewport pixel units
+ prop[propIndex++] = xrrCrtcInfo->height; // rotated viewport pixel units
+ prop[propIndex++] = xrrCrtcInfo->x; // rotated viewport window units (same)
+ prop[propIndex++] = xrrCrtcInfo->y; // rotated viewport window units (same)
+ prop[propIndex++] = xrrCrtcInfo->width; // rotated viewport window units (same)
+ prop[propIndex++] = xrrCrtcInfo->height; // rotated viewport window units (same)
+ prop[propIndex++] = xrrCrtcInfo->mode; // current mode id
+ prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
+ int i;
+ for(i=0; i<numModes; i++) {
+ // avail modes ..
+ prop[propIndex++] = xrrOutputInfo->modes[i];
+ }
+
+ XRRFreeOutputInfo (xrrOutputInfo);
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: setMonitorMode0
+ * Signature: (JJJIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setMonitorMode0
+ (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx, jint modeId, jint rotation, jint x, jint y)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ jboolean res = JNI_FALSE;
+
+ if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+ // n/a
+ return res;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return res;
+ }
+
+ if( 0 >= modeId ) {
+ // oops ..
+ return res;
+ }
+
+ if( 0 > x || 0 > y ) {
+ x = xrrCrtcInfo->x;
+ y = xrrCrtcInfo->y;
+ }
+
+ Status status = XRRSetCrtcConfig( dpy, resources, resources->crtcs[crt_idx], CurrentTime,
+ x, y, modeId, NewtScreen_Degree2XRotation(env, rotation),
+ xrrCrtcInfo->outputs, xrrCrtcInfo->noutput );
+ res = status == RRSetConfigSuccess;
+
+ return res;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: setScreenViewport0
+ * Signature: (JIJIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setScreenViewport0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint x, jint y, jint width, jint height)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ jboolean res = JNI_FALSE;
+
+ if( NULL == resources ) {
+ // n/a
+ return JNI_FALSE;
+ }
+
+ XRRSetScreenSize (dpy, root, width, height, DisplayWidthMM(dpy, screen_idx), DisplayHeightMM(dpy, screen_idx));
+ return JNI_TRUE;
+}
+
+
diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c
index 334c39727..152a092c9 100644
--- a/src/newt/native/X11Screen.c
+++ b/src/newt/native/X11Screen.c
@@ -29,7 +29,7 @@
// #define VERBOSE_ON 1
// #define DBG_PERF 1
-#include "X11Common.h"
+#include "X11Screen.h"
#ifdef DBG_PERF
#include "timespec.h"
@@ -74,418 +74,66 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getHeight0
return (jint) DisplayHeight( dpy, scrn_idx);
}
-static int showedRandRVersion = 0;
-
-static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) {
- if( 0 == XRRQueryVersion(dpy, major, minor) ) {
- return False;
- }
- if(0 == showedRandRVersion) {
- DBG_PRINT("X11 RandR Version %d.%d\n", *major, *minor);
- showedRandRVersion = 1;
- }
- return True;
-}
-
-static Bool NewtScreen_hasRANDR(Display *dpy) {
- int major, minor;
- return NewtScreen_getRANDRVersion(dpy, &major, &minor);
-}
-
-static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
- int rot;
+int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
+ int degree;
if(xrotation == RR_Rotate_0) {
- rot = 0;
+ degree = 0;
}
else if(xrotation == RR_Rotate_90) {
- rot = 90;
+ degree = 90;
}
else if(xrotation == RR_Rotate_180) {
- rot = 180;
+ degree = 180;
}
else if(xrotation == RR_Rotate_270) {
- rot = 270;
+ degree = 270;
} else {
NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation);
}
- return rot;
+ return degree;
}
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getAvailableScreenModeRotations0
- * Signature: (JI)I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailableScreenModeRotations0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
- Window root = RootWindow(dpy, (int)scrn_idx);
- int num_rotations = 0;
- Rotation cur_rotation, rotations_supported;
- int rotations[4];
- int major, minor;
-
- if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) {
- fprintf(stderr, "RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
- }
-
- rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
-
- if(0 != (rotations_supported & RR_Rotate_0)) {
- rotations[num_rotations++] = 0;
- }
- if(0 != (rotations_supported & RR_Rotate_90)) {
- rotations[num_rotations++] = 90;
- }
- if(0 != (rotations_supported & RR_Rotate_180)) {
- rotations[num_rotations++] = 180;
+int NewtScreen_Degree2XRotation(JNIEnv *env, int degree) {
+ int xrot;
+ if(degree == 0) {
+ xrot = RR_Rotate_0;
}
- if(0 != (rotations_supported & RR_Rotate_270)) {
- rotations[num_rotations++] = 270;
+ else if(degree == 90) {
+ xrot = RR_Rotate_90;
}
-
- jintArray properties = NULL;
-
- if(num_rotations>0) {
- properties = (*env)->NewIntArray(env, num_rotations);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
- }
-
- // move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
- }
-
- return properties;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getNumScreenModeResolution0
- * Signature: (JI)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
-#ifdef DBG_PERF
- struct timespec t0, t1, td;
- long td_ms;
- timespec_now(&t0);
-#endif
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0: RANDR not available\n");
- return 0;
+ else if(degree == 180) {
+ xrot = RR_Rotate_180;
}
-
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getNumScreenModeResolution0.1: %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getNumScreenModeResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- DBG_PRINT("getNumScreenModeResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes);
-
- return num_sizes;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getScreenModeResolutions0
- * Signature: (JII)[I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0: RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
- }
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- // Fill the properties in temp jint array
- int propIndex = 0;
- jint prop[4];
-
- prop[propIndex++] = xrrs[(int)resMode_idx].width;
- prop[propIndex++] = xrrs[(int)resMode_idx].height;
- prop[propIndex++] = xrrs[(int)resMode_idx].mwidth;
- prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
-
- jintArray properties = (*env)->NewIntArray(env, 4);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
+ else if(degree == 270) {
+ xrot = RR_Rotate_270;
+ } else {
+ NewtCommon_throwNewRuntimeException(env, "invalid degree: %d", degree);
}
-
- // move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
-
- return properties;
+ return xrot;
}
/*
* Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getScreenModeRates0
- * Signature: (JII)[I
+ * Method: GetRandRVersion0
+ * Signature: (J)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getRandRVersion0
+ (JNIEnv *env, jclass clazz, jlong display)
{
- Display *dpy = (Display *) (intptr_t) display;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0: RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
- }
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ Display * dpy = (Display *)(intptr_t)display;
+ jint version[2];
+ if( 0 == XRRQueryVersion(dpy, &version[0], &version[1] ) ) {
+ version[0] = 0;
+ version[1] = 0;
}
-
- int num_rates;
- short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
-
- jint prop[num_rates];
- int i;
- for(i=0; i<num_rates; i++) {
- prop[i] = (int) rates[i];
- /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
- }
-
- jintArray properties = (*env)->NewIntArray(env, num_rates);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
+ jintArray jversion = (*env)->NewIntArray(env, 2);
+ if (jversion == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
}
// move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
+ (*env)->SetIntArrayRegion(env, jversion, 0, 2, version);
- return properties;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getScreenConfiguration0
- * Signature: (JI)J
- */
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenConfiguration0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
- Window root = RootWindow(dpy, (int)screen_idx);
-#ifdef DBG_PERF
- struct timespec t0, t1, td;
- long td_ms;
- timespec_now(&t0);
-#endif
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenConfiguration0: RANDR not available\n");
- return 0;
- }
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getScreenConfiguration0.1: %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- // get current resolutions and frequencies
- XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getScreenConfiguration0.2 (XRRGetScreenInfo): %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- return (jlong) (intptr_t) conf;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: freeScreenConfiguration0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_freeScreenConfiguration0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration );
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getCurrentScreenRate0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRate0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-
- short original_rate = XRRConfigCurrentRate(conf);
- DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
-
- return (jint) original_rate;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getCurrentScreenRotation0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRotation0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
- Rotation rotation;
-
- XRRConfigCurrentConfiguration(conf, &rotation);
-
- return NewtScreen_XRotation2Degree(env, rotation);
-}
-
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: getCurrentScreenResolutionIndex0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenResolutionIndex0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-
- short original_rate = XRRConfigCurrentRate(conf);
-
- Rotation original_rotation;
- SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
-
- DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
- return (jint)original_size_id;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: setCurrentScreenModeStart0
- * Signature: (JIJIII)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModeStart0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation)
-{
- Display *dpy = (Display *) (intptr_t) display;
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
- Window root = RootWindow(dpy, (int)screen_idx);
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
- int rot;
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- switch(rotation) {
- case 0:
- rot = RR_Rotate_0;
- break;
- case 90:
- rot = RR_Rotate_90;
- break;
- case 180:
- rot = RR_Rotate_180;
- break;
- case 270:
- rot = RR_Rotate_270;
- break;
- default:
- NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation);
- }
-
- DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n",
- resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
-
- XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
-
- XSync(dpy, False);
- XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime);
- XSync(dpy, False);
-
- return JNI_TRUE;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_ScreenDriver
- * Method: setCurrentScreenModePollEnd0
- * Signature: (J)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
-{
- Display *dpy = (Display *) (intptr_t) display;
- int randr_event_base, randr_error_base;
- XEvent evt;
- XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0: RANDR not available\n");
- return JNI_FALSE;
- }
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
- XRRScreenConfiguration *conf;
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
-
- int done = 0;
- int rot;
- do {
- if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
- return;
- }
- XNextEvent(dpy, &evt);
-
- switch (evt.type - randr_event_base) {
- case RRScreenChangeNotify:
- rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
- DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n",
- (void*)scn_event->window, (void*)scn_event->root,
- (int)scn_event->size_index, rot,
- scn_event->width, scn_event->height);
- // done = scn_event->size_index == resMode_idx; // not reliable ..
- done = rot == rotation &&
- scn_event->width == xrrs[resMode_idx].width &&
- scn_event->height == xrrs[resMode_idx].height;
- break;
- default:
- DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
- }
- XRRUpdateConfiguration(&evt);
- } while(!done);
-
- XSync(dpy, False);
-
+ return jversion;
}
diff --git a/src/newt/native/X11Screen.h b/src/newt/native/X11Screen.h
new file mode 100644
index 000000000..c81ee05d5
--- /dev/null
+++ b/src/newt/native/X11Screen.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#ifndef _X11SCREEN_H
+#define _X11SCREEN_H
+
+
+#include "X11Common.h"
+
+int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation);
+int NewtScreen_Degree2XRotation(JNIEnv *env, int degree);
+
+#endif /* _X11SCREEN_H */
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 59862f463..2cc66c78d 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -98,11 +98,11 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon
}
jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) {
- Atom actual_type;
- int actual_format;
+ Atom actual_type = 0;
+ int actual_format = 0;
int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ;
unsigned char * jogl_java_object_data_pp = NULL;
- jobject jwindow;
+ jobject jwindow = 0;
{
unsigned long nitems= 0;
@@ -122,7 +122,9 @@ jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong ja
}
if(actual_type!=(Atom)javaObjectAtom || nitems<nitems_32 || NULL==jogl_java_object_data_pp) {
- XFree(jogl_java_object_data_pp);
+ if( NULL != jogl_java_object_data_pp ) {
+ XFree(jogl_java_object_data_pp);
+ }
if(True==showWarning) {
fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom NEWT_JAVA_OBJECT window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, NEWT_JAVA_OBJECT %ld, result 0!\n",
res, nitems, bytes_after, (long)actual_type, (long)javaObjectAtom);
@@ -189,8 +191,8 @@ static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window
return 0; // Error
}
static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left, int *right, int *top, int *bottom) {
- Atom actual_type;
- int actual_format;
+ Atom actual_type = 0;
+ int actual_format = 0;
int nitems_32 = 4; // l, r, t, b
unsigned char * frame_extends_data_pp = NULL;
@@ -210,7 +212,9 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left
}
if(nitems<nitems_32 || NULL==frame_extends_data_pp) {
- XFree(frame_extends_data_pp);
+ if( NULL != frame_extends_data_pp ) {
+ XFree(frame_extends_data_pp);
+ }
// DBG_PRINT( "Warning: NEWT X11Window: Fetched invalid Atom _NET_FRAME_EXTENTS window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, actual_format %d, _NET_FRAME_EXTENTS %ld, result 0!\n",
// res, nitems, bytes_after, (long)actual_type, actual_format, _NET_FRAME_EXTENTS);
return 0; // Error, but ok - ie window not mapped
@@ -271,18 +275,21 @@ static Bool NewtWindows_hasDecorations (Display *dpy, Window w) {
#ifdef DECOR_USE_MWM
Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
- unsigned char *wm_data;
- Atom wm_type;
- int wm_format;
- unsigned long wm_nitems, wm_bytes_after;
+ unsigned char *wm_data = NULL;
+ Atom wm_type = 0;
+ int wm_format = 0;
+ unsigned long wm_nitems = 0, wm_bytes_after = 0;
if( Success == XGetWindowProperty(dpy, w, _MOTIF_WM_HINTS, 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType,
&wm_type, &wm_format, &wm_nitems, &wm_bytes_after, &wm_data) ) {
- if(wm_type != None) {
+ if(wm_type != None && NULL != wm_data && wm_nitems >= PROP_MWM_HINTS_ELEMENTS) {
// unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
unsigned long *hints = (unsigned long *) wm_data;
decor = ( 0 != (hints[0] & MWM_HINTS_DECORATIONS) ) && ( 0 != hints[2] );
}
+ if( NULL != wm_data ) {
+ XFree(wm_data);
+ }
}
#endif
@@ -299,9 +306,8 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
-
-#define _NET_WM_FULLSCREEN ( 1 << 0 )
-#define _NET_WM_ABOVE ( 1 << 1 )
+#define _NET_WM_STATE_FLAG_FULLSCREEN ( 1 << 0 )
+#define _NET_WM_STATE_FLAG_ABOVE ( 1 << 1 )
/**
* Set fullscreen using Extended Window Manager Hints (EWMH)
@@ -314,101 +320,98 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
* and resets it when leaving FS.
* The same is assumed for the decoration state.
*/
-static int NewtWindows_isFullscreenEWMHSupported (Display *dpy, Window w) {
+static int NewtWindows_getSupportedStackingEWMHFlags(Display *dpy, Window w) {
+#ifdef VERBOSE_ON
+ // Code doesn't work reliable on KDE4 ...
Atom _NET_WM_ALLOWED_ACTIONS = XInternAtom( dpy, "_NET_WM_ALLOWED_ACTIONS", False );
Atom _NET_WM_ACTION_FULLSCREEN = XInternAtom( dpy, "_NET_WM_ACTION_FULLSCREEN", False );
Atom _NET_WM_ACTION_ABOVE = XInternAtom( dpy, "_NET_WM_ACTION_ABOVE", False );
- Atom * actions;
- Atom type;
- unsigned long action_len, remain;
- int res = 0, form, i;
+ Atom * actions = NULL;
+ Atom type = 0;
+ unsigned long action_len = 0, remain = 0;
+ int res = 0, form = 0, i = 0;
Status s;
if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, AnyPropertyType,
&type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
- for(i=0; i<action_len; i++) {
- if(_NET_WM_ACTION_FULLSCREEN == actions[i]) {
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i);
- res |= _NET_WM_FULLSCREEN ;
- } else if(_NET_WM_ACTION_ABOVE == actions[i]) {
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
- res |= _NET_WM_ABOVE ;
- }
-#ifdef VERBOSE_ON
- else {
- char * astr = XGetAtomName(dpy, actions[i]);
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr);
- XFree(astr);
+ if( NULL != actions ) {
+ for(i=0; i<action_len; i++) {
+ if(_NET_WM_ACTION_FULLSCREEN == actions[i]) {
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i);
+ res |= _NET_WM_STATE_FLAG_FULLSCREEN ;
+ } else if(_NET_WM_ACTION_ABOVE == actions[i]) {
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
+ res |= _NET_WM_STATE_FLAG_ABOVE ;
+ }
+ else {
+ char * astr = XGetAtomName(dpy, actions[i]);
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr);
+ XFree(astr);
+ }
}
-#endif
+ XFree(actions);
}
DBG_PRINT( "**************** X11: FS EWMH CHECK: 0x%X\n", res);
} else {
DBG_PRINT( "**************** X11: FS EWMH CHECK: XGetWindowProperty failed: %d\n", s);
}
- // above code doesn't work reliable on KDE4 ...
- res = _NET_WM_FULLSCREEN | _NET_WM_ABOVE ;
- return res;
+#endif
+ return _NET_WM_STATE_FLAG_FULLSCREEN | _NET_WM_STATE_FLAG_ABOVE ;
}
-static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
+static Bool NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
Atom _NET_WM_STATE = XInternAtom( dpy, "_NET_WM_STATE", False );
Atom _NET_WM_STATE_ABOVE = XInternAtom( dpy, "_NET_WM_STATE_ABOVE", False );
Atom _NET_WM_STATE_FULLSCREEN = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", False );
- int ewmhMask = NewtWindows_isFullscreenEWMHSupported(dpy, w);
+ int ewmhMask = NewtWindows_getSupportedStackingEWMHFlags(dpy, w);
+ Bool changeFullscreen = 0 != ( ( _NET_WM_STATE_FLAG_FULLSCREEN & ewmhMask ) & ewmhFlags ) ;
+ Bool changeAbove = 0 != ( ( _NET_WM_STATE_FLAG_ABOVE & ewmhMask ) & ewmhFlags ) ;
Bool res = False;
if(0 == ewmhMask) {
return res;
}
- if(!isVisible && True==enable) {
- Atom types[2]={0};
- int ntypes=0;
-
- if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) {
- types[ntypes++] = _NET_WM_STATE_FULLSCREEN;
- }
- if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) {
- types[ntypes++] = _NET_WM_STATE_ABOVE;
- }
- if(ntypes>0) {
- XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
- XSync(dpy, False);
- res = True;
- }
- } else {
- if(enable) {
- NewtWindows_setCWAbove(dpy, w);
- }
- XEvent xev;
- long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
- int i=0;
-
- memset ( &xev, 0, sizeof(xev) );
-
- xev.type = ClientMessage;
- xev.xclient.window = w;
- xev.xclient.message_type = _NET_WM_STATE;
- xev.xclient.format = 32;
+ // _NET_WM_STATE: fullscreen and/or above
+ if( changeFullscreen || changeAbove ) {
+ {
+ // _NET_WM_STATE as event to root window
+ XEvent xev;
+ long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
+ int i=0;
- xev.xclient.data.l[i++] = ( True == enable ) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
- if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) {
- xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
- }
- if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) {
- xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
- }
- xev.xclient.data.l[3] = 1; //source indication for normal applications
+ memset ( &xev, 0, sizeof(xev) );
+
+ xev.type = ClientMessage;
+ xev.xclient.window = w;
+ xev.xclient.message_type = _NET_WM_STATE;
+ xev.xclient.format = 32;
+
+ xev.xclient.data.l[i++] = enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
+ if( changeFullscreen ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
+ }
+ if( changeAbove ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
+ }
+ xev.xclient.data.l[3] = 1; //source indication for normal applications
- if(i>0) {
XSendEvent ( dpy, root, False, mask, &xev );
- res = True;
}
+ // Also change _NET_WM_BYPASS_COMPOSITOR!
+ // A value of 0 indicates no preference.
+ // A value of 1 hints the compositor to disabling compositing of this window.
+ // A value of 2 hints the compositor to not disabling compositing of this window
+ {
+ Atom _NET_WM_BYPASS_COMPOSITOR = XInternAtom( dpy, "_NET_WM_BYPASS_COMPOSITOR", False );
+ unsigned long value = enable ? 1 : 0;
+ XChangeProperty( dpy, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1);
+ }
+ XSync(dpy, False);
+ res = True;
}
- XSync(dpy, False);
- DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN EWMH ON %d, ewmhMask 0x%X, ewmhFlags 0x%X, visible %d: %d\n",
- enable, ewmhMask, ewmhFlags, isVisible, res);
+ DBG_PRINT( "X11: setStackingEWMHFlags ON %d, changeFullscreen %d, changeAbove %d, visible %d: %d\n",
+ enable, changeFullscreen, changeAbove, isVisible, res);
return res;
}
@@ -438,7 +441,7 @@ Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Wind
return 0; // Error
}
-static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) {
+static void NewtWindows_requestFocus (Display *dpy, Window w, Bool force) {
XWindowAttributes xwa;
Window focus_return;
int revert_to_return;
@@ -447,7 +450,7 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy,
XGetInputFocus(dpy, &focus_return, &revert_to_return);
DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w);
- if( JNI_TRUE==force || focus_return!=w) {
+ if( True==force || focus_return!=w) {
DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w);
XRaiseWindow(dpy, w);
NewtWindows_setCWAbove(dpy, w);
@@ -504,6 +507,12 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint
}
}
+static void NewtWindows_setIcon(Display *dpy, Window w, int data_size, const unsigned char * data_ptr) {
+ Atom _NET_WM_ICON = XInternAtom(dpy, "_NET_WM_ICON", False);
+ Atom CARDINAL = XInternAtom(dpy, "CARDINAL", False);
+ XChangeProperty(dpy, w, _NET_WM_ICON, CARDINAL, 32, PropModeReplace, data_ptr, data_size);
+}
+
/*
* Class: jogamp_newt_driver_x11_WindowDriver
* Method: CreateWindow
@@ -512,7 +521,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
(JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index,
jint visualID,
jlong javaObjectAtom, jlong windowDeleteAtom,
- jint x, jint y, jint width, jint height, jboolean autoPosition, int flags)
+ jint x, jint y, jint width, jint height, jboolean autoPosition, int flags,
+ jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct)
{
Display * dpy = (Display *)(intptr_t)display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
@@ -632,12 +642,27 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
{
XEvent event;
int left=0, right=0, top=0, bottom=0;
+ const unsigned char * pixelPtr = NULL;
+
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ DBG_PRINT("X11: CreateWindow icon: size %d, pixels %p, offset %d, direct %d\n", pixelDataSize, (void*)pixels, pixels_byte_offset, pixels_is_direct);
+ if( 0 < pixelDataSize && NULL != pixels ) {
+ pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ DBG_PRINT("X11: CreateWindow icon: NIO %p\n", pixelPtr);
+ NewtWindows_setIcon(dpy, window, (int)pixelDataSize, pixelPtr+pixels_byte_offset);
+ }
XMapWindow(dpy, window);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values
XSync(dpy, False);
+ if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
// send insets before visibility, allowing java code a proper sync point!
NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom);
(*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
@@ -657,7 +682,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
NewtWindows_setPosSize(dpy, window, x, y, width, height);
if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- NewtWindows_setFullscreenEWMH(dpy, root, window, _NET_WM_ABOVE, True, True);
+ NewtWindows_setStackingEWMHFlags(dpy, root, window, _NET_WM_STATE_FLAG_ABOVE, True, True);
}
}
@@ -671,11 +696,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
* Signature: (JJ)V
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
- (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom)
+ (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/) // XKB disabled for now
{
Display * dpy = (Display *) (intptr_t) display;
Window w = (Window)window;
jobject jwindow;
+ XWindowAttributes xwa;
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -683,51 +709,52 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
DBG_PRINT( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)w);
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
-
jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True);
if(NULL==jwindow) {
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!");
return;
}
if ( JNI_FALSE == (*env)->IsSameObject(env, jwindow, obj) ) {
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NewtCommon_throwNewRuntimeException(env, "Internal Error .. Window global ref not the same!");
return;
}
XSync(dpy, False);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
// Drain all events related to this window ..
- Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom);
+ Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
XDestroyWindow(dpy, w);
- XSync(dpy, False);
+ if( None != xwa.colormap ) {
+ XFreeColormap(dpy, xwa.colormap);
+ }
+ XSync(dpy, True); // discard all events now, no more handler
(*env)->DeleteGlobalRef(env, jwindow);
DBG_PRINT( "X11: CloseWindow END\n");
}
-#if 0
+// #define REPARENT_WAIT_FOR_REPARENT_NOTIFY 1
+
+#ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) {
- return (event->type == ReparentNotify) && (event->xreparent.window == (Window) arg);
+ Bool res = (event->type == ReparentNotify) && (event->xreparent.window == (Window) arg);
+ #ifdef VERBOSE_ON
+ if( event->type == ReparentNotify ) {
+ DBG_PRINT( "X11.WaitForReparentNotify: Event ReparentNotify: Result %d, exp %p, has %p\n", (int)res, arg, event->xreparent.window);
+ } else {
+ DBG_PRINT( "X11.WaitForReparentNotify: Event 0x%X: Result %d, exp %p, has %p\n", (int)event->type, (int)res, arg, event->xreparent.window);
+ }
+ #endif
+ return res;
}
#endif
-/**
- * KDE cause lost input focus in fullscreen mode.
- * Using 'XGrabKeyboard(..)' would prevent the loss,
- * but also would disable WM task switcher etc.
- *
- * #define FS_GRAB_KEYBOARD 1
- *
- */
-
/*
* Class: jogamp_newt_driver_x11_WindowDriver
* Method: reconfigureWindow0
@@ -746,51 +773,60 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
XEvent event;
Bool isVisible = !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ;
Bool tempInvisible = ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ) && isVisible ;
+ // Bool tempInvisible = TST_FLAG_CHANGE_PARENTING(flags) && isVisible ;
int fsEWMHFlags = 0;
if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
- fsEWMHFlags |= _NET_WM_FULLSCREEN;
+ if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) { // doesn't work w/ spanning across monitors. See also Bug 770 & Bug 771
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN;
+ }
if( TST_FLAG_IS_FULLSCREEN(flags) ) {
if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // fs on, above on
- } // else { } // fs on, above off
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs on, above on
+ } // else { } // fs on, above off
} else if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // fs off, above off
- } // else { } // fs off, above on
- }
- if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // toggle above
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs off, above off
+ } // else { } // fs off, above on
+ } else if( TST_FLAG_CHANGE_PARENTING(flags) ) {
+ // Fix for Unity WM, i.e. _remove_ persistent previous states
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN; // fs off
+ if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // above off
+ }
+ } else if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) {
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // toggle above
}
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
-
- DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
+ DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d (span %d), alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
(void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w,
x, y, width, height,
TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags),
TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags),
- TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags),
+ TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN_SPAN(flags),
TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
- TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), tempInvisible, fsEWMHFlags);
+ TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags),
+ tempInvisible, fsEWMHFlags);
- // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state shall be enough.
+ // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state should be enough.
// However, we have to consider other cases like reparenting and WM which don't support it.
-
+ #if 0 // Also doesn't work work properly w/ Unity WM
if( fsEWMHFlags && !TST_FLAG_CHANGE_PARENTING(flags) && isVisible &&
+ !TST_FLAG_IS_FULLSCREEN_SPAN(flags) &&
( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) {
Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ;
- if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
- #ifdef FS_GRAB_KEYBOARD
- if(TST_FLAG_CHANGE_FULLSCREEN(flags)) {
- if(TST_FLAG_IS_FULLSCREEN(flags)) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- } else {
- XUngrabKeyboard(dpy, CurrentTime);
- }
- } else if(TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags)) {
- XUngrabKeyboard(dpy, CurrentTime);
+ if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
+ if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration
+ NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
}
- #endif
+ DBG_PRINT( "X11: reconfigureWindow0 X (fs.atop.fast)\n");
+ return;
+ }
+ }
+ #endif
+ // Toggle ALWAYSONTOP (only) w/o visibility or window stacking sideffects
+ if( isVisible && fsEWMHFlags && TST_FLAG_CHANGE_ALWAYSONTOP(flags) &&
+ !TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
+ if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, TST_FLAG_IS_ALWAYSONTOP(flags)) ) {
+ DBG_PRINT( "X11: reconfigureWindow0 X (atop.fast)\n");
return;
}
}
@@ -802,21 +838,22 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
// no need to notify the java side .. just temp change
}
- if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) ||
- ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS off
- NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, False);
- #ifdef FS_GRAB_KEYBOARD
- XUngrabKeyboard(dpy, CurrentTime);
- #endif
+ if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) || // FS off
+ ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop off
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
}
if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) {
// TOP: in -> out
DBG_PRINT( "X11: reconfigureWindow0 PARENTING in->out\n");
XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
- // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
+ XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #endif
XSync(dpy, False);
XSetWMProtocols(dpy, w, &wm_delete_atom, 1); // windowDeleteAtom
+ // Fix for Unity WM, i.e. _remove_ persistent previous states
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
}
if( TST_FLAG_CHANGE_DECORATION(flags) ) {
@@ -831,7 +868,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
// CHILD: out -> in
DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n");
XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
- // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
+ XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #endif
XSync(dpy, False);
}
@@ -840,32 +879,28 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
XMapRaised(dpy, w);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) w );
// no need to notify the java side .. just temp change
- }
-
- if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
+ } else if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
if( TST_FLAG_IS_VISIBLE(flags) ) {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n");
XMapRaised(dpy, w);
+ XSync(dpy, False);
+ // WM may disregard pos/size XConfigureWindow requests for invisible windows!
+ DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height);
+ NewtWindows_setPosSize(dpy, w, x, y, width, height);
} else {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n");
XUnmapWindow(dpy, w);
+ XSync(dpy, False);
}
- XSync(dpy, False);
}
- if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) ||
- ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS on
- NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True);
- #ifdef FS_GRAB_KEYBOARD
- if(TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags)) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- }
- #endif
+ if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) || // FS on
+ ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop on
+ NewtWindows_requestFocus (dpy, w, True);
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, True);
}
- NewtDisplay_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
-
- DBG_PRINT( "X11: reconfigureWindow0 X\n");
+ DBG_PRINT( "X11: reconfigureWindow0 X (full)\n");
}
/*
@@ -876,7 +911,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0
(JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force)
{
- NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ;
+ NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window, JNI_TRUE==force?True:False ) ;
}
/*
@@ -943,6 +978,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0
/*
* Class: Java_jogamp_newt_driver_x11_WindowDriver
+ * Method: setPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong handle)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window w = (Window)window;
+
+ if( 0 == handle ) {
+ DBG_PRINT( "X11: setPointerIcon0: reset\n");
+ XUndefineCursor(dpy, w);
+ } else {
+ Cursor c = (Cursor) (intptr_t) handle;
+ DBG_PRINT( "X11: setPointerIcon0: %p\n", (void*)c);
+ XDefineCursor(dpy, w, c);
+ }
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_x11_WindowDriver
* Method: setPointerVisible0
* Signature: (JJZ)Z
*/
diff --git a/src/newt/native/XCBEvent.c b/src/newt/native/XCBEvent.c
new file mode 100644
index 000000000..d02d5a4ba
--- /dev/null
+++ b/src/newt/native/XCBEvent.c
@@ -0,0 +1,308 @@
+
+#define VERBOSE_ON 1
+
+#include "XCBEvent.h"
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_event.h>
+#include <xcb/xproto.h>
+#include <xcb/xcb_keysyms.h>
+#include <X11/Xlib-xcb.h>
+
+void XCBSetEventQueueOwner(Display *dpy) {
+ XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
+}
+
+void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom) {
+ int num_events = 100;
+ xcb_connection_t *conn = NULL;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+ conn = XGetXCBConnection(dpy);
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ xcb_generic_event_t *evt;
+ // KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ // char text[255];
+
+ evt = xcb_poll_for_event(conn);
+ if(NULL == evt) {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+ num_events--;
+
+ /*if( 0==evt.xany.window ) {
+ free(evt);
+ NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
+ return ;
+ }
+
+ if(dpy!=evt.xany.display) {
+ free(evt);
+ NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
+ return ;
+ }*/
+
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, evt.type);
+
+ // X11WindowDisplayErrorHandlerEnable(1, env);
+
+ // jwindow = X11WindowGetJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, VERBOSE_BOOL);
+
+ //X11WindowDisplayErrorHandlerEnable(0, env);
+
+ /*if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)dpy, evt.type, (void*)evt.xany.window);
+ continue;
+ }*/
+
+ uint8_t xcb_event_type = evt->response_type & ~0x80;
+ xcb_window_t event_window = 0;
+
+ switch( xcb_event_type ) {
+ case XCB_BUTTON_PRESS:
+ case XCB_BUTTON_RELEASE:
+ event_window = ((xcb_button_press_event_t *)evt)->event;
+ modifiers = X11InputState2NewtModifiers(((xcb_button_press_event_t *)evt)->state);
+ break;
+ case XCB_MOTION_NOTIFY:
+ event_window = ((xcb_motion_notify_event_t *)evt)->event;
+ break;
+ case XCB_KEY_PRESS:
+ case XCB_KEY_RELEASE: {
+ xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
+ event_window = _evt->event;
+ /*
+ xcb_keycode_t detail = _evt->detail;
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ KeySym lower_return = 0, upper_return = 0;
+ keyChar=text[0];
+ XConvertCase(keySym, &lower_return, &upper_return);
+ // always return upper case, set modifier masks (SHIFT, ..)
+ keySym = upper_return;
+ modifiers = X11InputState2NewtModifiers(evt.xkey.state);
+ } else {
+ keyChar=0;
+ }*/
+ }
+ break;
+ case XCB_EXPOSE:
+ event_window = ((xcb_expose_event_t *)evt)->window;
+ break;
+ case XCB_MAP_NOTIFY:
+ event_window = ((xcb_map_notify_event_t *)evt)->window;
+ break;
+ case XCB_UNMAP_NOTIFY:
+ event_window = ((xcb_unmap_notify_event_t *)evt)->window;
+ break;
+ }
+ if(0==event_window) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d, no X11 window associated\n",
+ (void*)dpy, xcb_event_type);
+ continue;
+ }
+ jwindow = getJavaWindowProperty(env, dpy, event_window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)(intptr_t)dpy, xcb_event_type, (void*)(intptr_t)event_window);
+ continue;
+ }
+
+ switch( xcb_event_type ) {
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *_evt = (xcb_button_press_event_t *)evt;
+ (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_release_event_t *_evt = (xcb_button_release_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_MOTION_NOTIFY: {
+ xcb_motion_notify_event_t *_evt = (xcb_motion_notify_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_KEY_PRESS: {
+ xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #endif
+ } break;
+ case XCB_KEY_RELEASE: {
+ xcb_key_release_event_t *_evt = (xcb_key_release_event_t *)evt;
+ event_window = ((xcb_key_release_event_t *)evt)->event;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #endif
+
+ } break;
+ /*
+ case DestroyNotify:
+ DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
+ (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event);
+ if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) {
+ // ignore child destroy notification
+ }
+ break;
+ case CreateNotify:
+ DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n",
+ (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent);
+ break;
+ case ConfigureNotify:
+ DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n",
+ (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above,
+ evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height,
+ evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
+ if ( evt.xconfigure.window == evt.xconfigure.event ) {
+ // ignore child window change notification
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) {
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID);
+ // Called by Window.java: CloseWindow();
+ num_events = 0; // end loop in case of destroyed display
+ }
+ break;
+
+ case FocusIn:
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE);
+ break;
+ */
+
+ case XCB_EXPOSE: {
+ xcb_expose_event_t *_evt = (xcb_expose_event_t *)evt;
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)(intptr_t)_evt->window,
+ _evt->x, _evt->y, _evt->width, _evt->height, _evt->count);
+
+ if (_evt->count == 0 && _evt->width > 0 && _evt->height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID,
+ _evt->x, _evt->y, _evt->width, _evt->height);
+ }
+ } break;
+
+ case XCB_MAP_NOTIFY: {
+ xcb_map_notify_event_t *_evt = (xcb_map_notify_event_t *)evt;
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)(intptr_t)_evt->event, (void*)(intptr_t)_evt->window, (int)_evt->override_redirect,
+ _evt->event!=_evt->window);
+ if( _evt->event == _evt->window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
+ }
+ } break;
+
+ case XCB_UNMAP_NOTIFY: {
+ xcb_unmap_notify_event_t *_evt = (xcb_unmap_notify_event_t *)evt;
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, child-event: %d\n",
+ (void*)(intptr_t)_evt->event, (void*)(intptr_t)_evt->window,
+ _evt->event!=_evt->window);
+ if( _evt->event == _evt->window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE);
+ }
+ } break;
+ /*
+
+ case ReparentNotify:
+ {
+ jlong parentResult; // 0 if root, otherwise proper value
+ Window winRoot, winTopParent;
+ #ifdef VERBOSE_ON
+ Window oldParentRoot, oldParentTopParent;
+ Window parentRoot, parentTopParent;
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) {
+ oldParentRoot=0; oldParentTopParent = 0;
+ }
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) {
+ parentRoot=0; parentTopParent = 0;
+ }
+ #endif
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) {
+ winRoot=0; winTopParent = 0;
+ }
+ if(evt.xreparent.parent == winRoot) {
+ parentResult = 0; // our java indicator for root window
+ } else {
+ parentResult = (jlong) (intptr_t) evt.xreparent.parent;
+ }
+ #ifdef VERBOSE_ON
+ DBG_PRINT( "X11: event . ReparentNotify: call OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent,
+ (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
+ (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
+ #endif
+
+ (*env)->CallVoidMethod(env, jwindow, windowReparentedID, parentResult);
+ }
+ break;
+ */
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("XCB: event . unhandled %d 0x%X call %p\n", (int)xcb_event_type, (unsigned int)xcb_event_type, (void*)(intptr_t)event_window);
+ }
+ free(evt);
+ }
+}
+
+
diff --git a/src/newt/native/XCBEvent.h b/src/newt/native/XCBEvent.h
new file mode 100644
index 000000000..d70797566
--- /dev/null
+++ b/src/newt/native/XCBEvent.h
@@ -0,0 +1,10 @@
+
+#ifndef _XCBEvent_h
+#define _XCBEvent_h
+
+#include "X11Common.h"
+
+extern void XCBSetEventQueueOwner(Display *dpy);
+extern void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom);
+
+#endif /* _XCBDisplayXCBEvent_h */
diff --git a/src/newt/native/bcm_vc_iv.c b/src/newt/native/bcm_vc_iv.c
index e41745e14..ee59f0aa6 100644
--- a/src/newt/native/bcm_vc_iv.c
+++ b/src/newt/native/bcm_vc_iv.c
@@ -30,28 +30,50 @@
#include <stdio.h>
#include <string.h>
+/**
+ * See references in header file.
+ */
#include "bcm_vc_iv.h"
#include "jogamp_newt_driver_bcm_vc_iv_DisplayDriver.h"
#include "jogamp_newt_driver_bcm_vc_iv_ScreenDriver.h"
#include "jogamp_newt_driver_bcm_vc_iv_WindowDriver.h"
-#define VERBOSE_ON 1
+// #define VERBOSE_ON 1
#ifdef VERBOSE_ON
- #define DBG_PRINT(...) fprintf(stdout, __VA_ARGS__)
+ #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
#else
#define DBG_PRINT(...)
#endif
+typedef struct {
+ DISPMANX_ELEMENT_HANDLE_T handle; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int width; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int height; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int x;
+ int y;
+ int32_t layer;
+} BCM_ELEMENT_T;
+
+typedef struct {
+ DISPMANX_RESOURCE_HANDLE_T handle;
+ VC_IMAGE_TYPE_T type;
+ uint32_t native_image_handle;
+} BCM_RESOURCE_T;
+
+typedef struct {
+ BCM_ELEMENT_T element;
+ BCM_RESOURCE_T resource;
+ int hotX, hotY;
+} POINTER_ICON_T;
+
static jmethodID setScreenSizeID = NULL;
-static jmethodID windowCreatedID = NULL;
static jmethodID sizeChangedID = NULL;
+static jmethodID positionChangedID = NULL;
static jmethodID visibleChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
-static jmethodID sendMouseEventID = NULL;
-static jmethodID sendKeyEventID = NULL;
/**
* Display
@@ -66,11 +88,210 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_initI
return JNI_TRUE;
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DispatchMessages
- (JNIEnv *env, jobject obj)
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_OpenBCMDisplay0
+ (JNIEnv *env, jclass clazz)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
+ DBG_PRINT( "BCM.Display Open %p\n", (void*)(intptr_t)dispman_display);
+ return (jlong) (intptr_t) dispman_display;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_CloseBCMDisplay0
+ (JNIEnv *env, jclass clazz, jlong display)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ DBG_PRINT( "BCM.Display Close %p\n", (void*)(intptr_t)dispman_display);
+ vc_dispmanx_display_close( dispman_display );
+}
+
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DispatchMessages0
+ (JNIEnv *env, jclass clazz)
{
}
+static void bcm_moveTo(DISPMANX_ELEMENT_HANDLE_T element, uint32_t layer, int x, int y, int width, int height) {
+ VC_RECT_T src_rect;
+ VC_RECT_T dst_rect;
+ uint32_t change_flags = DISPMANX_ELEMENT_CHANGE_DEST_RECT | DISPMANX_ELEMENT_CHANGE_SRC_RECT;
+ DISPMANX_RESOURCE_HANDLE_T mask = 0;
+ DISPMANX_TRANSFORM_T transform = 0;
+
+ uint8_t opacity = 0; // NOP
+
+ dst_rect.x = x;
+ dst_rect.y = y;
+ dst_rect.width = width;
+ dst_rect.height = height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = width << 16;
+ src_rect.height = height << 16;
+
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_change_attributes( dispman_update,
+ element,
+ change_flags,
+ layer,
+ opacity,
+ &dst_rect,
+ &src_rect,
+ mask,
+ transform );
+ vc_dispmanx_update_submit_sync( dispman_update );
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_CreatePointerIcon0
+ (JNIEnv *env, jclass clazz, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
+{
+ if( 0 == pixels ) {
+ return 0;
+ }
+ int32_t success = 0;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+ int x = 0;
+ int y = 0;
+ int pitch = width * 4; // RGBA
+
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+
+ POINTER_ICON_T * p = calloc(1, sizeof(POINTER_ICON_T));
+ p->hotX = hotX;
+ p->hotY = hotY;
+ p->element.layer = 2000;
+ p->element.x = x;
+ p->element.y = y;
+ p->element.width = width;
+ p->element.height = height;
+ p->resource.type = VC_IMAGE_ARGB8888; /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
+ p->resource.handle = vc_dispmanx_resource_create( p->resource.type,
+ width,
+ height,
+ &(p->resource.native_image_handle) );
+
+ dst_rect.x = x;
+ dst_rect.y = y;
+ dst_rect.width = width;
+ dst_rect.height = height;
+
+ vc_dispmanx_resource_write_data( p->resource.handle,
+ p->resource.type,
+ pitch,
+ (void*)(intptr_t)(pixelPtr + pixels_byte_offset),
+ &dst_rect );
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Create PI %p, resource %p\n", p, (void*)(intptr_t)p->resource.handle);
+ return (jlong) (intptr_t) p;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DestroyPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong handle)
+{
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+ if( 0 == p ) {
+ return;
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Destroy.0 PI %p, resource %p, element %p\n",
+ p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle);
+
+ if( 0 != p->element.handle ) {
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->element.handle );
+ p->element.handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ }
+ if( 0 != p->resource.handle ) {
+ vc_dispmanx_resource_delete( p->resource.handle );
+ p->resource.handle = 0;
+ }
+ free( p );
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_SetPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong handle, jboolean enable, jint x, jint y)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+
+ if( 0 == dispman_display || NULL == p || 0 == p->resource.handle ) {
+ return;
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Set.0 %p, PI %p, resource %p, element %p - enable %d - %d/%d\n",
+ (void*)(intptr_t)display, p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, enable, x, y);
+
+ if( enable ) {
+ if( 0 != p->element.handle ) {
+ return;
+ }
+
+ p->element.x = x;
+ p->element.y = y;
+ dst_rect.x = p->element.x - p->hotX;
+ dst_rect.y = p->element.y - p->hotY;
+ dst_rect.width = p->element.width;
+ dst_rect.height = p->element.height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = p->element.width << 16;
+ src_rect.height = p->element.height << 16;
+
+ VC_DISPMANX_ALPHA_T dispman_alpha;
+ memset(&dispman_alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0xFF;
+
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ p->element.handle = vc_dispmanx_element_add ( dispman_update, dispman_display,
+ p->element.layer, &dst_rect,
+ p->resource.handle /*src*/,
+ &src_rect, DISPMANX_PROTECTION_NONE,
+ &dispman_alpha /*alpha */, 0/*clamp*/, 0/*transform*/);
+ vc_dispmanx_update_submit_sync( dispman_update );
+ } else {
+ // DISABLE
+ if( 0 == p->element.handle ) {
+ return;
+ }
+ p->element.x = x;
+ p->element.y = y;
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->element.handle );
+ p->element.handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ }
+ DBG_PRINT( "BCM.Display PointerIcon.Set.X %p, PI %p, resource %p, element %p - enable %d - %d/%d\n",
+ (void*)(intptr_t)display, p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, enable, x, y);
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_MovePointerIcon0
+ (JNIEnv *env, jclass clazz, jlong handle, jint x, jint y)
+{
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+
+ if( NULL == p || 0 == p->element.handle ) {
+ return;
+ }
+ DBG_PRINT( "BCM.Display PointerIcon.Move.0 PI %p, resource %p, element %p - %d/%d\n",
+ p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, x, y);
+ p->element.x = x;
+ p->element.y = y;
+ bcm_moveTo( p->element.handle, p->element.layer, p->element.x - p->hotX, p->element.y - p->hotY, p->element.width, p->element.height);
+}
+
/**
* Screen
*/
@@ -101,8 +322,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_ScreenDriver_initNative
if( graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height) >= 0 ) {
DBG_PRINT( "BCM.Screen initNative ok %dx%d\n", screen_width, screen_height );
(*env)->CallVoidMethod(env, obj, setScreenSizeID, (jint) screen_width, (jint) screen_height);
+ } else {
+ DBG_PRINT( "BCM.Screen initNative failed\n" );
}
- DBG_PRINT( "BCM.Screen initNative failed\n" );
}
/**
@@ -112,18 +334,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_ScreenDriver_initNative
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initIDs
(JNIEnv *env, jclass clazz)
{
- windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V");
sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V");
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
- if (windowCreatedID == NULL ||
- sizeChangedID == NULL ||
+ if (sizeChangedID == NULL ||
+ positionChangedID == NULL ||
visibleChangedID == NULL ||
- windowDestroyNotifyID == NULL ||
- sendMouseEventID == NULL ||
- sendKeyEventID == NULL) {
+ windowDestroyNotifyID == NULL) {
DBG_PRINT( "initIDs failed\n" );
return JNI_FALSE;
}
@@ -131,15 +349,18 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initID
return JNI_TRUE;
}
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWindow
- (JNIEnv *env, jobject obj, jint width, jint height)
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWindow0
+ (JNIEnv *env, jobject obj, jlong display, jint layer, jint x, jint y, jint width, jint height, jboolean opaque, jint alphaBits)
{
int32_t success = 0;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
- dst_rect.x = 0;
- dst_rect.y = 0;
+ if( 0 == display ) {
+ return;
+ }
+ dst_rect.x = x;
+ dst_rect.y = y;
dst_rect.width = width;
dst_rect.height = height;
@@ -148,57 +369,95 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWin
src_rect.width = width << 16;
src_rect.height = height << 16;
- DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
+ VC_DISPMANX_ALPHA_T dispman_alpha;
+ memset(&dispman_alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
+
+ if( JNI_TRUE == opaque ) {
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0;
+ } else {
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0xFF;
+ }
+
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+
+ DBG_PRINT( "BCM.Display Window.Create.0 %p, %d/%d %dx%d, opaque %d, alphaBits %d, layer %d\n",
+ (void*)(intptr_t)dispman_display, x, y, width, height, opaque, alphaBits, layer);
+
+ BCM_ELEMENT_T * p = calloc(1, sizeof(BCM_ELEMENT_T));
DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
- DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
- 0/*layer*/, &dst_rect, 0/*src*/,
- &src_rect, DISPMANX_PROTECTION_NONE,
- 0 /*alpha TODO*/, 0/*clamp*/, 0/*transform*/);
- EGL_DISPMANX_WINDOW_T * nativeWindowPtr = calloc(1, sizeof(EGL_DISPMANX_WINDOW_T));
- nativeWindowPtr->element = dispman_element;
- nativeWindowPtr->width = width;
- nativeWindowPtr->height = height;
+ p->layer = layer;
+ p->x = x;
+ p->y = y;
+ p->width = width;
+ p->height = height;
+ p->handle = vc_dispmanx_element_add ( dispman_update, dispman_display,
+ p->layer, &dst_rect, 0/*src*/,
+ &src_rect, DISPMANX_PROTECTION_NONE,
+ &dispman_alpha /*alpha */, 0/*clamp*/, 0/*transform*/);
vc_dispmanx_update_submit_sync( dispman_update );
(*env)->CallVoidMethod(env, obj, visibleChangedID, JNI_FALSE, JNI_TRUE); // FIXME: or defer=true ?
- return (jlong) (intptr_t) nativeWindowPtr;
-}
+ DBG_PRINT( "BCM.Display Window.Create.X %p, element %p\n",
+ (void*)(intptr_t)dispman_display, (void*)(intptr_t)p->handle);
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_RealizeWindow
- (JNIEnv *env, jobject obj, jlong window)
-{
- return (jlong) (intptr_t) 0;
+ return (jlong) (intptr_t) p;
}
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CloseWindow
- (JNIEnv *env, jobject obj, jlong window, jlong juserData)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CloseWindow0
+ (JNIEnv *env, jobject obj, jlong display, jlong window)
{
- EGL_DISPMANX_WINDOW_T * nativeWindowPtr = (EGL_DISPMANX_WINDOW_T *) (intptr_t) window ;
- free( nativeWindowPtr );
- return 0;
-}
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ BCM_ELEMENT_T * p = (BCM_ELEMENT_T *) (intptr_t) window ;
-/*
- * Class: jogamp_newt_driver_bcm_vc_iv_WindowDriver
- * Method: setVisible0
- * Signature: (JJZ)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setVisible0
- (JNIEnv *env, jobject obj, jlong window, jboolean visible)
-{
-}
+ DBG_PRINT( "BCM.Display Window.Close %p, element %p\n",
+ (void*)(intptr_t)dispman_display, (void*)(intptr_t)p->handle);
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setFullScreen0
- (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen)
-{
+ if( 0 == dispman_display || NULL == p || 0 == p->handle ) {
+ return;
+ }
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->handle );
+ p->handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ free( p );
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_setSize0
- (JNIEnv *env, jobject obj, jlong window, jint width, jint height)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_reconfigure0
+ (JNIEnv *env, jobject obj, jlong window, jint x, jint y, jint width, jint height, jint flags)
{
- // FIXME RESIZE (*env)->CallVoidMethod(env, obj, sizeChangedID, JNI_FALSE, (jint) width, (jint) height, JNI_FALSE);
-}
+ BCM_ELEMENT_T * p = (BCM_ELEMENT_T *) (intptr_t) window ;
+
+ if( NULL == p || 0 == p->handle ) {
+ return;
+ }
+ /***
+ int isVisible = !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ;
+ ...
+ see X11Window.c
+ */
+ int posChanged = p->x != x || p->y != y;
+ int sizeChanged = p->width != width || p->height != height;
+ p->x = x;
+ p->y = y;
+ p->width = width;
+ p->height = height;
+
+ DBG_PRINT( "BCM.Display Window.Reconfig %p, element %p - %d/%d %dx%d\n",
+ p, (void*)(intptr_t)p->handle, p->x, p->y, p->width, p->height);
+
+ bcm_moveTo( p->handle, p->layer, p->x, p->y, p->width, p->height);
+ if( posChanged ) {
+ (*env)->CallVoidMethod(env, obj, positionChangedID, JNI_FALSE, x, y);
+ }
+ if( sizeChanged ) {
+ (*env)->CallVoidMethod(env, obj, sizeChangedID, JNI_FALSE, (jint) width, (jint) height, JNI_FALSE);
+ }
+}
diff --git a/src/newt/native/bcm_vc_iv.h b/src/newt/native/bcm_vc_iv.h
index b43483c10..42189f3d6 100644
--- a/src/newt/native/bcm_vc_iv.h
+++ b/src/newt/native/bcm_vc_iv.h
@@ -29,6 +29,11 @@
#ifndef BCM_VC_IV_H
#define BCM_VC_IV_H
+/**
+ * http://en.wikipedia.org/wiki/VideoCore
+ * https://github.com/raspberrypi/userland
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -150,12 +155,6 @@ typedef struct {
} DISPMANX_CLAMP_T;
-typedef struct {
- DISPMANX_ELEMENT_HANDLE_T element;
- int width; /* This is necessary because dispmanx elements are not queriable. */
- int height;
-} EGL_DISPMANX_WINDOW_T;
-
typedef struct tag_VC_RECT_T {
int32_t x;
int32_t y;
@@ -163,6 +162,102 @@ typedef struct tag_VC_RECT_T {
int32_t height;
} VC_RECT_T;
+/* Types of image supported. */
+/* Please add any new types to the *end* of this list. Also update
+ * case_VC_IMAGE_ANY_xxx macros (below), and the vc_image_type_info table in
+ * vc_image/vc_image_helper.c.
+ */
+typedef enum
+{
+ VC_IMAGE_MIN = 0, //bounds for error checking
+
+ VC_IMAGE_RGB565 = 1,
+ VC_IMAGE_1BPP,
+ VC_IMAGE_YUV420,
+ VC_IMAGE_48BPP,
+ VC_IMAGE_RGB888,
+ VC_IMAGE_8BPP,
+ VC_IMAGE_4BPP, // 4bpp palettised image
+ VC_IMAGE_3D32, /* A separated format of 16 colour/light shorts followed by 16 z values */
+ VC_IMAGE_3D32B, /* 16 colours followed by 16 z values */
+ VC_IMAGE_3D32MAT, /* A separated format of 16 material/colour/light shorts followed by 16 z values */
+ VC_IMAGE_RGB2X9, /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */
+ VC_IMAGE_RGB666, /* 32-bit format holding 18 bits of 6.6.6 RGB */
+ VC_IMAGE_PAL4_OBSOLETE, // 4bpp palettised image with embedded palette
+ VC_IMAGE_PAL8_OBSOLETE, // 8bpp palettised image with embedded palette
+ VC_IMAGE_RGBA32, /* RGB888 with an alpha byte after each pixel */ /* xxx: isn't it BEFORE each pixel? */
+ VC_IMAGE_YUV422, /* a line of Y (32-byte padded), a line of U (16-byte padded), and a line of V (16-byte padded) */
+ VC_IMAGE_RGBA565, /* RGB565 with a transparent patch */
+ VC_IMAGE_RGBA16, /* Compressed (4444) version of RGBA32 */
+ VC_IMAGE_YUV_UV, /* VCIII codec format */
+ VC_IMAGE_TF_RGBA32, /* VCIII T-format RGBA8888 */
+ VC_IMAGE_TF_RGBX32, /* VCIII T-format RGBx8888 */
+ VC_IMAGE_TF_FLOAT, /* VCIII T-format float */
+ VC_IMAGE_TF_RGBA16, /* VCIII T-format RGBA4444 */
+ VC_IMAGE_TF_RGBA5551, /* VCIII T-format RGB5551 */
+ VC_IMAGE_TF_RGB565, /* VCIII T-format RGB565 */
+ VC_IMAGE_TF_YA88, /* VCIII T-format 8-bit luma and 8-bit alpha */
+ VC_IMAGE_TF_BYTE, /* VCIII T-format 8 bit generic sample */
+ VC_IMAGE_TF_PAL8, /* VCIII T-format 8-bit palette */
+ VC_IMAGE_TF_PAL4, /* VCIII T-format 4-bit palette */
+ VC_IMAGE_TF_ETC1, /* VCIII T-format Ericsson Texture Compressed */
+ VC_IMAGE_BGR888, /* RGB888 with R & B swapped */
+ VC_IMAGE_BGR888_NP, /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after each row of pixels */
+ VC_IMAGE_BAYER, /* Bayer image, extra defines which variant is being used */
+ VC_IMAGE_CODEC, /* General wrapper for codec images e.g. JPEG from camera */
+ VC_IMAGE_YUV_UV32, /* VCIII codec format */
+ VC_IMAGE_TF_Y8, /* VCIII T-format 8-bit luma */
+ VC_IMAGE_TF_A8, /* VCIII T-format 8-bit alpha */
+ VC_IMAGE_TF_SHORT,/* VCIII T-format 16-bit generic sample */
+ VC_IMAGE_TF_1BPP, /* VCIII T-format 1bpp black/white */
+ VC_IMAGE_OPENGL,
+ VC_IMAGE_YUV444I, /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */
+ VC_IMAGE_YUV422PLANAR, /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on a per line basis) */
+ VC_IMAGE_ARGB8888, /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
+ VC_IMAGE_XRGB8888, /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */
+
+ VC_IMAGE_YUV422YUYV, /* interleaved 8 bit samples of Y, U, Y, V */
+ VC_IMAGE_YUV422YVYU, /* interleaved 8 bit samples of Y, V, Y, U */
+ VC_IMAGE_YUV422UYVY, /* interleaved 8 bit samples of U, Y, V, Y */
+ VC_IMAGE_YUV422VYUY, /* interleaved 8 bit samples of V, Y, U, Y */
+
+ VC_IMAGE_RGBX32, /* 32bpp like RGBA32 but with unused alpha */
+ VC_IMAGE_RGBX8888, /* 32bpp, corresponding to RGBA with unused alpha */
+ VC_IMAGE_BGRX8888, /* 32bpp, corresponding to BGRA with unused alpha */
+
+ VC_IMAGE_YUV420SP, /* Y as a plane, then UV byte interleaved in plane with with same pitch, half height */
+
+ VC_IMAGE_YUV444PLANAR, /* Y, U, & V planes separately 4:4:4 */
+
+ VC_IMAGE_MAX, //bounds for error checking
+ VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
+} VC_IMAGE_TYPE_T;
+
+/**
+ * From https://github.com/raspberrypi/userland/blob/master/interface/vmcs_host/vc_vchi_dispmanx.h
+ */
+typedef enum {
+ DISPMANX_ELEMENT_CHANGE_LAYER = (1<<0),
+ DISPMANX_ELEMENT_CHANGE_OPACITY = (1<<1),
+ DISPMANX_ELEMENT_CHANGE_DEST_RECT = (1<<2),
+ DISPMANX_ELEMENT_CHANGE_SRC_RECT = (1<<3),
+ DISPMANX_ELEMENT_CHANGE_MASK_RESOURCE = (1<<4),
+ DISPMANX_ELEMENT_CHANGE_TRANSFORM = (1<<5)
+/**
+ * Not working /validated !
+ DISPMANX_ELEMENT_CHANGE_MIN = 0x00,
+ DISPMANX_ELEMENT_CHANGE_SOURCE = 0x01,
+ DISPMANX_ELEMENT_INSERT_ABOVE = 0x80,
+ DISPMANX_ELEMENT_CHANGE_FLAGS = 0x100,
+ DISPMANX_ELEMENT_CHANGE_NOTHING = 0x200,
+ DISPMANX_ELEMENT_CHANGE_ALPHA_FLAGS = 0x400,
+ DISPMANX_ELEMENT_CHANGE_PROTECTION = 0x800,
+ DISPMANX_ELEMENT_CHANGE_MAX = 0x1000
+ */
+} DISPMANX_ELEMENT_CHANGE_T;
+
+
+
extern void bcm_host_init(void);
extern void bcm_host_deinit(void);
@@ -171,15 +266,38 @@ extern int32_t graphics_get_display_size( const uint16_t display_number,
uint32_t *height);
extern DISPMANX_DISPLAY_HANDLE_T vc_dispmanx_display_open( uint32_t device );
+extern int vc_dispmanx_display_close( DISPMANX_DISPLAY_HANDLE_T display );
+
+extern DISPMANX_RESOURCE_HANDLE_T vc_dispmanx_resource_create(VC_IMAGE_TYPE_T type, uint32_t width, uint32_t height, uint32_t *native_image_handle);
+extern int vc_dispmanx_resource_write_data( DISPMANX_RESOURCE_HANDLE_T res, VC_IMAGE_TYPE_T src_type, int src_pitch, void * src_address, const VC_RECT_T * rect );
+//extern int vc_dispmanx_resource_write_data_handle( DISPMANX_RESOURCE_HANDLE_T res, VC_IMAGE_TYPE_T src_type, int src_pitch,
+// VCHI_MEM_HANDLE_T handle, uint32_t offset, const VC_RECT_T * rect );
+extern int vc_dispmanx_resource_delete( DISPMANX_RESOURCE_HANDLE_T res );
+
+
+
extern DISPMANX_UPDATE_HANDLE_T vc_dispmanx_update_start( int32_t priority );
extern DISPMANX_ELEMENT_HANDLE_T vc_dispmanx_element_add ( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display,
int32_t layer, const VC_RECT_T *dest_rect, DISPMANX_RESOURCE_HANDLE_T src,
const VC_RECT_T *src_rect, DISPMANX_PROTECTION_T protection,
VC_DISPMANX_ALPHA_T *alpha,
DISPMANX_CLAMP_T *clamp, DISPMANX_TRANSFORM_T transform );
+extern int vc_dispmanx_element_remove( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element );
+
extern int vc_dispmanx_update_submit_sync( DISPMANX_UPDATE_HANDLE_T update );
+//New function added to VCHI to change attributes, set_opacity does not work there.
+extern int vc_dispmanx_element_change_attributes( DISPMANX_UPDATE_HANDLE_T update,
+ DISPMANX_ELEMENT_HANDLE_T element,
+ uint32_t change_flags,
+ int32_t layer,
+ uint8_t opacity,
+ const VC_RECT_T *dest_rect,
+ const VC_RECT_T *src_rect,
+ DISPMANX_RESOURCE_HANDLE_T mask,
+ DISPMANX_TRANSFORM_T transform );
+
#ifdef __cplusplus
}
#endif