1 /* gtkwindowpeer.c -- Native implementation of GtkWindowPeer
2 Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
41 #include "gnu_java_awt_peer_gtk_GtkWindowPeer.h"
42 #include <gdk/gdkprivate.h>
44 #include <X11/Xatom.h>
45 #include <gdk/gdkkeysyms.h>
47 #define AWT_WINDOW_CLOSING 201
48 #define AWT_WINDOW_CLOSED 202
49 #define AWT_WINDOW_ICONIFIED 203
50 #define AWT_WINDOW_DEICONIFIED 204
51 #define AWT_WINDOW_ACTIVATED 205
52 #define AWT_WINDOW_DEACTIVATED 206
53 #define AWT_WINDOW_GAINED_FOCUS 207
54 #define AWT_WINDOW_LOST_FOCUS 208
55 #define AWT_WINDOW_STATE_CHANGED 209
57 #define AWT_FRAME_NORMAL 0
58 #define AWT_FRAME_ICONIFIED 1
59 #define AWT_FRAME_MAXIMIZED_BOTH 6
62 /* This list should be kept in the same order as the VK_ field
63 declarations in KeyEvent.java. */
65 #define VK_BACK_SPACE '\b'
73 #define VK_CAPS_LOCK 20
77 #define VK_PAGE_DOWN 34
98 #define VK_SEMICOLON ';'
126 #define VK_OPEN_BRACKET '['
127 #define VK_BACK_SLASH '\\'
128 #define VK_CLOSE_BRACKET ']'
130 /* #define VK_NUMPAD0 96 */
131 /* #define VK_NUMPAD1 97 */
132 /* #define VK_NUMPAD2 98 */
133 /* #define VK_NUMPAD3 99 */
134 /* #define VK_NUMPAD4 100 */
135 /* #define VK_NUMPAD5 101 */
136 /* #define VK_NUMPAD6 102 */
137 /* #define VK_NUMPAD7 103 */
138 /* #define VK_NUMPAD8 104 */
139 /* #define VK_NUMPAD9 105 */
140 #define VK_MULTIPLY 106
142 #define VK_SEPARATER 108
143 #define VK_SEPARATOR 108
144 #define VK_SUBTRACT 109
146 /* #define VK_DECIMAL 110 */
147 #define VK_DIVIDE 111
148 #define VK_DELETE 127
149 #define VK_NUM_LOCK 144
150 #define VK_SCROLL_LOCK 145
175 #define VK_PRINTSCREEN 154
176 #define VK_INSERT 155
179 #define VK_BACK_QUOTE 192
182 #define VK_KP_DOWN 225
183 #define VK_KP_LEFT 226
184 #define VK_KP_RIGHT 227
185 #define VK_DEAD_GRAVE 128
186 #define VK_DEAD_ACUTE 129
187 #define VK_DEAD_CIRCUMFLEX 130
188 #define VK_DEAD_TILDE 131
189 #define VK_DEAD_MACRON 132
190 #define VK_DEAD_BREVE 133
191 #define VK_DEAD_ABOVEDOT 134
192 #define VK_DEAD_DIAERESIS 135
193 #define VK_DEAD_ABOVERING 136
194 #define VK_DEAD_DOUBLEACUTE 137
195 #define VK_DEAD_CARON 138
196 #define VK_DEAD_CEDILLA 139
197 #define VK_DEAD_OGONEK 140
198 #define VK_DEAD_IOTA 141
199 #define VK_DEAD_VOICED_SOUND 142
200 #define VK_DEAD_SEMIVOICED_SOUND 143
201 #define VK_AMPERSAND 150
202 #define VK_ASTERISK 151
203 #define VK_QUOTEDBL 152
205 #define VK_GREATER 160
206 #define VK_BRACELEFT 161
207 #define VK_BRACERIGHT 162
210 #define VK_CIRCUMFLEX 514
211 #define VK_DOLLAR 515
212 #define VK_EURO_SIGN 516
213 #define VK_EXCLAMATION_MARK 517
214 #define VK_INVERTED_EXCLAMATION_MARK 518
215 #define VK_LEFT_PARENTHESIS 519
216 #define VK_NUMBER_SIGN 520
218 #define VK_RIGHT_PARENTHESIS 522
219 #define VK_UNDERSCORE 523
221 #define VK_CONVERT 28
222 #define VK_NONCONVERT 29
224 #define VK_MODECHANGE 31
227 #define VK_ALPHANUMERIC 240
228 #define VK_KATAKANA 241
229 #define VK_HIRAGANA 242
230 #define VK_FULL_WIDTH 243
231 #define VK_HALF_WIDTH 244
232 #define VK_ROMAN_CHARACTERS 245
233 #define VK_ALL_CANDIDATES 256
234 #define VK_PREVIOUS_CANDIDATE 257
235 #define VK_CODE_INPUT 258
236 #define VK_JAPANESE_KATAKANA 259
237 #define VK_JAPANESE_HIRAGANA 260
238 #define VK_JAPANESE_ROMAN 261
239 #define VK_KANA_LOCK 262
240 #define VK_INPUT_METHOD_ON_OFF 263
242 #define VK_COPY 65485
243 #define VK_PASTE 65487
244 #define VK_UNDO 65483
245 #define VK_AGAIN 65481
246 #define VK_FIND 65488
247 #define VK_PROPS 65482
248 #define VK_STOP 65480
249 #define VK_COMPOSE 65312
250 #define VK_ALT_GRAPH 65406
251 #define VK_UNDEFINED 0
252 #define VK_BEGIN 65368
253 #define VK_CONTEXT_MENU 525
254 #define VK_WINDOWS 524
257 #define AWT_KEY_CHAR_UNDEFINED 0
259 #define AWT_FRAME_STATE_NORMAL 0
260 #define AWT_FRAME_STATE_ICONIFIED 1
261 #define AWT_FRAME_STATE_MAXIMIZED_HORIZ 2
262 #define AWT_FRAME_STATE_MAXIMIZED_VERT 4
263 #define AWT_FRAME_STATE_MAXIMIZED_BOTH 6
265 static jmethodID postKeyEventID
;
266 static jmethodID postWindowEventID
;
267 static jmethodID postConfigureEventID
;
268 static jmethodID postInsetsChangedEventID
;
269 static jmethodID windowGetWidthID
;
270 static jmethodID windowGetHeightID
;
273 cp_gtk_window_init_jni (void)
275 jclass gtkwindowpeer
;
277 gtkwindowpeer
= (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
278 "gnu/java/awt/peer/gtk/GtkWindowPeer");
280 postKeyEventID
= (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer
,
281 "postKeyEvent", "(IJIICI)V");
283 postWindowEventID
= (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer
,
285 "(ILjava/awt/Window;I)V");
287 postConfigureEventID
= (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer
,
288 "postConfigureEvent", "(IIII)V");
290 postInsetsChangedEventID
= (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer
,
291 "postInsetsChangedEvent",
294 windowGetWidthID
= (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer
,
297 windowGetHeightID
= (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer
,
300 gtkwindowpeer
= (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
301 "gnu/java/awt/peer/gtk/GtkWindowPeer");
304 /* Get the first keyval in the keymap for this event's keycode. The
305 first keyval corresponds roughly to Java's notion of a virtual key.
306 Returns the uppercase version of the first keyval or -1 if no
307 keyval was found for the given hardware keycode. */
309 get_first_keyval_from_keymap (GdkEventKey
*event
)
315 if (!gdk_keymap_get_entries_for_keycode (NULL
,
316 event
->hardware_keycode
,
321 /* No keyval found for hardware keycode */
327 return gdk_keyval_to_upper (keyval
);
330 /* Return the AWT key code for the given keysym or -1 if no keyval was
331 found for the given hardware keycode. */
336 keysym_to_awt_keycode (GdkEventKey
*event
)
341 ukeyval
= get_first_keyval_from_keymap (event
);
346 state
= event
->state
;
348 /* VK_A through VK_Z */
349 if (ukeyval
>= GDK_A
&& ukeyval
<= GDK_Z
)
352 /* VK_0 through VK_9 */
353 if (ukeyval
>= GDK_0
&& ukeyval
<= GDK_9
)
362 return VK_BACK_SPACE
;
387 /* For keys on the numeric keypad, the JVM produces one of two
388 virtual keys, depending on the num lock state. */
389 if (state
& GDK_MOD2_MASK
)
395 case GDK_KP_Page_Down
:
396 if (state
& GDK_MOD2_MASK
)
403 if (state
& GDK_MOD2_MASK
)
410 if (state
& GDK_MOD2_MASK
)
417 if (state
& GDK_MOD2_MASK
)
481 case GDK_bracketleft
:
482 return VK_OPEN_BRACKET
;
484 return VK_BACK_SLASH
;
485 case GDK_bracketright
:
486 return VK_CLOSE_BRACKET
;
507 case GDK_KP_Multiply
:
514 case GDK_KP_Separator
:
516 case GDK_KP_Subtract
:
523 if (state
& GDK_MOD2_MASK
)
531 case GDK_Scroll_Lock
:
532 return VK_SCROLL_LOCK
;
582 return VK_PRINTSCREEN
;
584 if (state
& GDK_MOD2_MASK
)
596 return VK_BACK_QUOTE
;
600 if (state
& GDK_MOD2_MASK
)
605 if (state
& GDK_MOD2_MASK
)
610 if (state
& GDK_MOD2_MASK
)
615 if (state
& GDK_MOD2_MASK
)
620 return VK_DEAD_GRAVE
;
622 return VK_DEAD_ACUTE
;
623 case GDK_dead_circumflex
:
624 return VK_DEAD_CIRCUMFLEX
;
626 return VK_DEAD_TILDE
;
627 case GDK_dead_macron
:
628 return VK_DEAD_MACRON
;
630 return VK_DEAD_BREVE
;
631 case GDK_dead_abovedot
:
632 return VK_DEAD_ABOVEDOT
;
633 case GDK_dead_diaeresis
:
634 return VK_DEAD_DIAERESIS
;
635 case GDK_dead_abovering
:
636 return VK_DEAD_ABOVERING
;
637 case GDK_dead_doubleacute
:
638 return VK_DEAD_DOUBLEACUTE
;
640 return VK_DEAD_CARON
;
641 case GDK_dead_cedilla
:
642 return VK_DEAD_CEDILLA
;
643 case GDK_dead_ogonek
:
644 return VK_DEAD_OGONEK
;
647 case GDK_dead_voiced_sound
:
648 return VK_DEAD_VOICED_SOUND
;
649 case GDK_dead_semivoiced_sound
:
650 return VK_DEAD_SEMIVOICED_SOUND
;
664 return VK_BRACERIGHT
;
669 case GDK_asciicircum
:
670 return VK_CIRCUMFLEX
;
676 return VK_EXCLAMATION_MARK
;
678 return VK_INVERTED_EXCLAMATION_MARK
;
680 return VK_LEFT_PARENTHESIS
;
682 return VK_NUMBER_SIGN
;
686 return VK_RIGHT_PARENTHESIS
;
688 return VK_UNDERSCORE
;
692 return VK_NONCONVERT;
695 case GDK_Mode_switch
:
696 return VK_MODECHANGE
;
703 return VK_ALPHANUMERIC;
710 return VK_FULL_WIDTH;
711 return VK_HALF_WIDTH;
712 return VK_ROMAN_CHARACTERS;
713 return VK_ALL_CANDIDATES;
715 case GDK_PreviousCandidate
:
716 return VK_PREVIOUS_CANDIDATE
;
718 return VK_CODE_INPUT
;
720 return VK_JAPANESE_KATAKANA;
721 return VK_JAPANESE_HIRAGANA;
722 return VK_JAPANESE_ROMAN;
727 return VK_INPUT_METHOD_ON_OFF;
742 case GDK_ISO_Level3_Shift
:
748 return VK_CONTEXT_MENU
;
758 /* Return the AWT key location code for the given keysym or -1 if no
759 keyval was found for the given hardware keycode. */
761 keysym_to_awt_keylocation (GdkEventKey
*event
)
765 ukeyval
= get_first_keyval_from_keymap (event
);
770 /* VK_A through VK_Z */
771 if (ukeyval
>= GDK_A
&& ukeyval
<= GDK_Z
)
772 return AWT_KEY_LOCATION_STANDARD
;
774 /* VK_0 through VK_9 */
775 if (ukeyval
>= GDK_0
&& ukeyval
<= GDK_9
)
776 return AWT_KEY_LOCATION_STANDARD
;
784 return AWT_KEY_LOCATION_LEFT
;
790 return AWT_KEY_LOCATION_RIGHT
;
815 case GDK_bracketleft
:
817 case GDK_bracketright
:
819 case GDK_Scroll_Lock
:
851 case GDK_dead_circumflex
:
853 case GDK_dead_macron
:
855 case GDK_dead_abovedot
:
856 case GDK_dead_diaeresis
:
857 case GDK_dead_abovering
:
858 case GDK_dead_doubleacute
:
860 case GDK_dead_cedilla
:
861 case GDK_dead_ogonek
:
863 case GDK_dead_voiced_sound
:
864 case GDK_dead_semivoiced_sound
:
874 case GDK_asciicircum
:
884 case GDK_Mode_switch
:
888 case GDK_PreviousCandidate
:
891 return AWT_KEY_LOCATION_STANDARD
;
895 case GDK_KP_Page_Down
:
909 case GDK_KP_Multiply
:
911 case GDK_KP_Separator
:
912 case GDK_KP_Subtract
:
922 return AWT_KEY_LOCATION_NUMPAD
;
925 return AWT_KEY_LOCATION_UNKNOWN
;
930 keyevent_to_awt_keychar (GdkEventKey
*event
)
932 if (event
->length
> 0)
934 /* Translate GDK carriage return to Java linefeed. */
935 if (event
->string
[0] == 13)
938 return event
->string
[0];
942 switch (event
->keyval
)
945 return VK_BACK_SPACE
;
952 return AWT_KEY_CHAR_UNDEFINED
;
957 /* Modifier key events need special treatment. In Sun's peer
958 implementation, when a modifier key is pressed, the KEY_PRESSED
959 event has that modifier in its modifiers list. The corresponding
960 KEY_RELEASED event's modifier list does not contain the modifier.
961 For example, pressing and releasing the shift key will produce a
962 key press event with modifiers=Shift, and a key release event with
963 no modifiers. GDK's key events behave in the exact opposite way,
964 so this translation code is needed. */
966 keyevent_state_to_awt_mods (GdkEventKey
*event
)
971 if (event
->type
== GDK_KEY_PRESS
)
973 state
= event
->state
;
975 if (event
->keyval
== GDK_Shift_L
976 || event
->keyval
== GDK_Shift_R
)
977 result
|= AWT_SHIFT_DOWN_MASK
| AWT_SHIFT_MASK
;
980 if (state
& GDK_SHIFT_MASK
)
981 result
|= AWT_SHIFT_DOWN_MASK
| AWT_SHIFT_MASK
;
984 if (event
->keyval
== GDK_Control_L
985 || event
->keyval
== GDK_Control_R
)
986 result
|= AWT_CTRL_DOWN_MASK
| AWT_CTRL_MASK
;
989 if (state
& GDK_CONTROL_MASK
)
990 result
|= AWT_CTRL_DOWN_MASK
| AWT_CTRL_MASK
;
993 if (event
->keyval
== GDK_Alt_L
994 || event
->keyval
== GDK_Alt_R
)
995 result
|= AWT_ALT_DOWN_MASK
| AWT_ALT_MASK
;
998 if (state
& GDK_MOD1_MASK
)
999 result
|= AWT_ALT_DOWN_MASK
| AWT_ALT_MASK
;
1002 else if (event
->type
== GDK_KEY_RELEASE
)
1004 state
= event
->state
;
1006 if (event
->keyval
!= GDK_Shift_L
1007 && event
->keyval
!= GDK_Shift_R
)
1009 if (state
& GDK_SHIFT_MASK
)
1010 result
|= AWT_SHIFT_DOWN_MASK
| AWT_SHIFT_MASK
;
1012 if (event
->keyval
!= GDK_Control_L
1013 && event
->keyval
!= GDK_Control_R
)
1015 if (state
& GDK_CONTROL_MASK
)
1016 result
|= AWT_CTRL_DOWN_MASK
| AWT_CTRL_MASK
;
1019 if (event
->keyval
!= GDK_Alt_L
1020 && event
->keyval
!= GDK_Alt_R
)
1022 if (state
& GDK_MOD1_MASK
)
1023 result
|= AWT_ALT_DOWN_MASK
| AWT_ALT_MASK
;
1030 static gboolean
window_configure_cb (GtkWidget
*widget
,
1031 GdkEventConfigure
*event
,
1034 /* FIXME: we're currently seeing the double-activation that occurs
1035 with metacity and GTK. See
1036 http://bugzilla.gnome.org/show_bug.cgi?id=140977 for details. */
1038 static void window_get_frame_extents (GtkWidget
*window
,
1039 int *top
, int *left
,
1040 int *bottom
, int *right
);
1042 static void request_frame_extents (GtkWidget
*window
);
1044 static Bool
property_notify_predicate (Display
*display
,
1048 static gboolean
window_delete_cb (GtkWidget
*widget
, GdkEvent
*event
,
1050 static void window_destroy_cb (GtkWidget
*widget
, GdkEvent
*event
,
1052 static void window_focus_state_change_cb (GtkWidget
*widget
,
1055 static gboolean
window_focus_in_cb (GtkWidget
* widget
,
1056 GdkEventFocus
*event
,
1058 static gboolean
window_focus_out_cb (GtkWidget
* widget
,
1059 GdkEventFocus
*event
,
1061 static gboolean
window_window_state_cb (GtkWidget
*widget
,
1064 static gboolean
window_property_changed_cb (GtkWidget
*widget
,
1065 GdkEventProperty
*event
,
1067 static void realize_cb (GtkWidget
*widget
, jobject peer
);
1070 window_configure_cb (GtkWidget
*widget
__attribute__((unused
)),
1071 GdkEventConfigure
*event
,
1074 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1075 postConfigureEventID
,
1078 (jint
) event
->width
,
1079 (jint
) event
->height
);
1085 key_press_cb (GtkWidget
*widget
__attribute__((unused
)),
1092 keycode
= keysym_to_awt_keycode (event
);
1093 keylocation
= keysym_to_awt_keylocation (event
);
1095 /* Return immediately if an error occurs translating a hardware
1096 keycode to a keyval. */
1097 if (keycode
< 0 || keylocation
< 0)
1100 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1102 (jint
) AWT_KEY_PRESSED
,
1103 (jlong
) event
->time
,
1104 keyevent_state_to_awt_mods (event
),
1106 keyevent_to_awt_keychar (event
),
1109 /* FIXME: generation of key typed events needs to be moved
1110 to GtkComponentPeer.postKeyEvent. If the key in a key
1111 press event is not an "action" key
1112 (KeyEvent.isActionKey) and is not a modifier key, then
1113 it should generate a key typed event. */
1119 key_release_cb (GtkWidget
*widget
__attribute__((unused
)),
1126 keycode
= keysym_to_awt_keycode (event
);
1127 keylocation
= keysym_to_awt_keylocation (event
);
1129 /* Return immediately if an error occurs translating a hardware
1130 keycode to a keyval. */
1131 if (keycode
< 0 || keylocation
< 0)
1134 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1136 (jint
) AWT_KEY_RELEASED
,
1137 (jlong
) event
->time
,
1138 keyevent_state_to_awt_mods (event
),
1140 keyevent_to_awt_keychar (event
),
1146 /* Union used for type punning. */
1149 guchar
**gu_extents
;
1150 unsigned long **extents
;
1153 union atom_list_union
1155 guchar
**gu_extents
;
1159 JNIEXPORT
void JNICALL
1160 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
1161 (JNIEnv
*env
, jobject obj
, jint type
, jboolean decorated
, jobject parent
)
1163 GtkWidget
*window_widget
;
1165 void *window_parent
;
1168 gdk_threads_enter ();
1170 gtkpeer_set_global_ref (env
, obj
);
1172 window_widget
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
1173 window
= GTK_WINDOW (window_widget
);
1175 /* Keep this window in front of its parent, if it has one. */
1178 window_parent
= gtkpeer_get_widget (env
, parent
);
1179 gtk_window_set_transient_for (window
, GTK_WINDOW(window_parent
));
1182 gtk_window_set_decorated (window
, decorated
);
1184 gtk_window_set_type_hint (window
, type
);
1186 gtk_window_group_add_window (cp_gtk_global_window_group
, window
);
1188 fixed
= gtk_fixed_new ();
1190 gtk_container_add (GTK_CONTAINER (window_widget
), fixed
);
1192 gtk_widget_show (fixed
);
1194 gtkpeer_set_widget (env
, obj
, window_widget
);
1196 gdk_threads_leave ();
1199 JNIEXPORT
void JNICALL
1200 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle
1201 (JNIEnv
*env
, jobject obj
, jstring title
)
1203 const char *c_title
;
1206 gdk_threads_enter ();
1208 ptr
= gtkpeer_get_widget (env
, obj
);
1210 c_title
= (*env
)->GetStringUTFChars (env
, title
, NULL
);
1212 gtk_window_set_title (GTK_WINDOW (ptr
), c_title
);
1214 (*env
)->ReleaseStringUTFChars (env
, title
, c_title
);
1216 gdk_threads_leave ();
1219 JNIEXPORT
void JNICALL
1220 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable
1221 (JNIEnv
*env
, jobject obj
, jboolean resizable
)
1225 gdk_threads_enter ();
1227 ptr
= gtkpeer_get_widget (env
, obj
);
1228 gtk_window_set_resizable (GTK_WINDOW (ptr
), resizable
);
1229 g_object_set (G_OBJECT (ptr
), "allow-shrink", resizable
, NULL
);
1231 gdk_threads_leave ();
1234 JNIEXPORT
void JNICALL
1235 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal
1236 (JNIEnv
*env
, jobject obj
, jboolean modal
)
1240 gdk_threads_enter ();
1242 ptr
= gtkpeer_get_widget (env
, obj
);
1244 gtk_window_set_modal (GTK_WINDOW (ptr
), modal
);
1246 gdk_threads_leave ();
1249 JNIEXPORT
void JNICALL
1250 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetAlwaysOnTop
1251 (JNIEnv
*env
, jobject obj
, jboolean alwaysOnTop
)
1255 gdk_threads_enter ();
1257 ptr
= gtkpeer_get_widget (env
, obj
);
1259 gtk_window_set_keep_above (GTK_WINDOW (ptr
), alwaysOnTop
);
1261 gdk_threads_leave ();
1264 JNIEXPORT jboolean JNICALL
1265 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowHasFocus
1266 (JNIEnv
*env
, jobject obj
)
1271 gdk_threads_enter ();
1273 ptr
= gtkpeer_get_widget (env
, obj
);
1275 retval
= gtk_window_has_toplevel_focus (GTK_WINDOW (ptr
));
1277 gdk_threads_leave ();
1281 JNIEXPORT
void JNICALL
1282 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNative
1283 (JNIEnv
*env
, jobject obj
, jboolean visible
)
1285 gdk_threads_enter ();
1287 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNativeUnlocked
1288 (env
, obj
, visible
);
1292 gdk_threads_leave ();
1295 JNIEXPORT
void JNICALL
1296 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNativeUnlocked
1297 (JNIEnv
*env
, jobject obj
, jboolean visible
)
1301 ptr
= gtkpeer_get_widget (env
, obj
);
1304 gtk_widget_show (GTK_WIDGET (ptr
));
1306 gtk_widget_hide (GTK_WIDGET (ptr
));
1309 JNIEXPORT
void JNICALL
1310 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals
1311 (JNIEnv
*env
, jobject obj
)
1316 gdk_threads_enter ();
1318 ptr
= gtkpeer_get_widget (env
, obj
);
1319 gref
= (jobject
) gtkpeer_get_global_ref (env
, obj
);
1321 g_signal_connect (G_OBJECT (ptr
), "delete-event",
1322 G_CALLBACK (window_delete_cb
), gref
);
1324 g_signal_connect (G_OBJECT (ptr
), "destroy-event",
1325 G_CALLBACK (window_destroy_cb
), gref
);
1327 g_signal_connect (G_OBJECT (ptr
), "notify::has-toplevel-focus",
1328 G_CALLBACK (window_focus_state_change_cb
), gref
);
1330 g_signal_connect (G_OBJECT (ptr
), "focus-in-event",
1331 G_CALLBACK (window_focus_in_cb
), gref
);
1333 g_signal_connect (G_OBJECT (ptr
), "focus-out-event",
1334 G_CALLBACK (window_focus_out_cb
), gref
);
1336 g_signal_connect (G_OBJECT (ptr
), "window-state-event",
1337 G_CALLBACK (window_window_state_cb
), gref
);
1339 g_signal_connect (G_OBJECT (ptr
), "property-notify-event",
1340 G_CALLBACK (window_property_changed_cb
), gref
);
1342 g_signal_connect_after (G_OBJECT (ptr
), "realize",
1343 G_CALLBACK (realize_cb
), gref
);
1345 g_signal_connect (G_OBJECT (ptr
), "key-press-event",
1346 G_CALLBACK (key_press_cb
), gref
);
1348 g_signal_connect (G_OBJECT (ptr
), "key-release-event",
1349 G_CALLBACK (key_release_cb
), gref
);
1351 g_signal_connect_after (G_OBJECT (ptr
), "window-state-event",
1352 G_CALLBACK (window_window_state_cb
), gref
);
1354 g_signal_connect (G_OBJECT (ptr
), "configure-event",
1355 G_CALLBACK (window_configure_cb
), gref
);
1357 cp_gtk_component_connect_expose_signals (ptr
, gref
);
1358 cp_gtk_component_connect_mouse_signals (ptr
, gref
);
1360 /* FIXME: override focus signals here to prevent child fixed repaint? */
1362 gdk_threads_leave ();
1365 /* Realize the window here so that its frame extents are known now.
1366 That way Window.pack can operate with the accurate insets returned
1367 by the window manager rather than the default estimates. */
1368 JNIEXPORT
void JNICALL
1369 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_realize (JNIEnv
*env
, jobject obj
)
1373 gdk_threads_enter ();
1375 ptr
= gtkpeer_get_widget (env
, obj
);
1377 gtk_widget_realize (GTK_WIDGET (ptr
));
1379 gdk_threads_leave ();
1382 JNIEXPORT
void JNICALL
1383 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv
*env
,
1388 gdk_threads_enter ();
1390 ptr
= gtkpeer_get_widget (env
, obj
);
1392 gdk_window_lower (GTK_WIDGET (ptr
)->window
);
1395 gdk_threads_leave ();
1398 JNIEXPORT
void JNICALL
1399 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv
*env
,
1404 gdk_threads_enter ();
1406 ptr
= gtkpeer_get_widget (env
, obj
);
1408 gdk_window_raise (GTK_WIDGET (ptr
)->window
);
1411 gdk_threads_leave ();
1414 JNIEXPORT
void JNICALL
1415 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize
1416 (JNIEnv
*env
, jobject obj
, jint width
, jint height
)
1420 gdk_threads_enter ();
1422 ptr
= gtkpeer_get_widget (env
, obj
);
1424 /* Avoid GTK runtime assertion failures. */
1425 width
= (width
< 1) ? 1 : width
;
1426 height
= (height
< 1) ? 1 : height
;
1428 gtk_widget_set_size_request (GTK_WIDGET(ptr
), width
, height
);
1430 gdk_threads_leave ();
1433 JNIEXPORT
void JNICALL
1434 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds
1435 (JNIEnv
*env
, jobject obj
, jint x
, jint y
, jint width
, jint height
)
1437 gdk_threads_enter ();
1439 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBoundsUnlocked
1440 (env
, obj
, x
, y
, width
, height
);
1442 gdk_threads_leave ();
1445 JNIEXPORT
void JNICALL
1446 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocationUnlocked
1447 (JNIEnv
*env
, jobject obj
, jint x
, jint y
)
1451 ptr
= gtkpeer_get_widget (env
, obj
);
1453 gtk_window_move (GTK_WINDOW(ptr
), x
, y
);
1455 if (GTK_WIDGET (ptr
)->window
!= NULL
)
1456 gdk_window_move (GTK_WIDGET (ptr
)->window
, x
, y
);
1459 JNIEXPORT
void JNICALL
1460 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocation
1461 (JNIEnv
*env
, jobject obj
, jint x
, jint y
)
1463 gdk_threads_enter ();
1465 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocationUnlocked
1468 gdk_threads_leave ();
1471 JNIEXPORT
void JNICALL
1472 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBoundsUnlocked
1473 (JNIEnv
*env
, jobject obj
, jint x
, jint y
, jint width
, jint height
)
1477 gint current_height
;
1479 ptr
= gtkpeer_get_widget (env
, obj
);
1481 /* Avoid GTK runtime assertion failures. */
1482 width
= (width
< 1) ? 1 : width
;
1483 height
= (height
< 1) ? 1 : height
;
1485 gtk_window_move (GTK_WINDOW(ptr
), x
, y
);
1486 /* The call to gdk_window_move is needed in addition to the call to
1487 gtk_window_move. If gdk_window_move isn't called, then the
1488 following set of operations doesn't give the expected results:
1491 2. manually move it to another position on the screen
1493 4. reposition the window with Component.setLocation
1496 Instead of being at the position set by setLocation, the window
1497 is reshown at the position to which it was moved manually. */
1498 if (GTK_WIDGET (ptr
)->window
!= NULL
)
1499 gdk_window_move (GTK_WIDGET (ptr
)->window
, x
, y
);
1501 /* Only request resizing if the actual width or height change, otherwise
1502 * we get unnecessary flickers because resizing causes GTK to clear the
1503 * window content, even if the actual size doesn't change. */
1504 gtk_window_get_size(GTK_WINDOW(ptr
), ¤t_width
, ¤t_height
);
1505 if (current_width
!= width
|| current_height
!= height
)
1507 /* Need to change the widget's request size. */
1508 gtk_widget_set_size_request (GTK_WIDGET(ptr
), width
, height
);
1509 /* Also need to call gtk_window_resize. If the resize is requested
1510 by the program and the window's "resizable" property is true then
1511 the size request will not be honoured. */
1512 gtk_window_resize (GTK_WINDOW (ptr
), width
, height
);
1517 window_get_frame_extents (GtkWidget
*window
,
1518 int *top
, int *left
, int *bottom
, int *right
)
1520 unsigned long *extents
= NULL
;
1521 union extents_union gu_ex
;
1523 /* Guess frame extents in case _NET_FRAME_EXTENTS is not
1525 if (!gtk_window_get_decorated (GTK_WINDOW (window
)))
1540 /* Request that the window manager set window's
1541 _NET_FRAME_EXTENTS property. */
1542 request_frame_extents (window
);
1544 /* Attempt to retrieve window's frame extents. */
1545 gu_ex
.extents
= &extents
;
1546 if (gdk_property_get (window
->window
,
1547 gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE
),
1548 gdk_atom_intern ("CARDINAL", FALSE
),
1550 sizeof (unsigned long) * 4,
1557 *left
= extents
[0];
1558 *right
= extents
[1];
1560 *bottom
= extents
[3];
1564 static Atom extents_atom
= 0;
1566 /* Requests that the window manager set window's
1567 _NET_FRAME_EXTENTS property. */
1569 request_frame_extents (GtkWidget
*window
)
1571 const char *request_str
= "_NET_REQUEST_FRAME_EXTENTS";
1572 GdkAtom request_extents
= gdk_atom_intern (request_str
, FALSE
);
1574 /* Check if the current window manager supports
1575 _NET_REQUEST_FRAME_EXTENTS. */
1576 if (gdk_net_wm_supports (request_extents
))
1578 GdkDisplay
*display
= gtk_widget_get_display (window
);
1579 Display
*xdisplay
= GDK_DISPLAY_XDISPLAY (display
);
1581 GdkWindow
*root_window
= gdk_get_default_root_window ();
1582 Window xroot_window
= GDK_WINDOW_XID (root_window
);
1584 Atom extents_request_atom
=
1585 gdk_x11_get_xatom_by_name_for_display (display
, request_str
);
1588 XEvent notify_xevent
;
1590 unsigned long window_id
= GDK_WINDOW_XID (GDK_DRAWABLE(window
->window
));
1594 const char *extents_str
= "_NET_FRAME_EXTENTS";
1596 gdk_x11_get_xatom_by_name_for_display (display
, extents_str
);
1599 xevent
.xclient
.type
= ClientMessage
;
1600 xevent
.xclient
.message_type
= extents_request_atom
;
1601 xevent
.xclient
.display
= xdisplay
;
1602 xevent
.xclient
.window
= window_id
;
1603 xevent
.xclient
.format
= 32;
1604 xevent
.xclient
.data
.l
[0] = 0;
1605 xevent
.xclient
.data
.l
[1] = 0;
1606 xevent
.xclient
.data
.l
[2] = 0;
1607 xevent
.xclient
.data
.l
[3] = 0;
1608 xevent
.xclient
.data
.l
[4] = 0;
1610 XSendEvent (xdisplay
, xroot_window
, False
,
1611 (SubstructureRedirectMask
| SubstructureNotifyMask
),
1614 XIfEvent(xdisplay
, ¬ify_xevent
,
1615 property_notify_predicate
, (XPointer
) &window_id
);
1620 property_notify_predicate (Display
*xdisplay
__attribute__((unused
)),
1624 unsigned long *window
= (unsigned long *) window_id
;
1626 if (event
->xany
.type
== PropertyNotify
1627 && event
->xany
.window
== *window
1628 && event
->xproperty
.atom
== extents_atom
)
1635 window_delete_cb (GtkWidget
*widget
__attribute__((unused
)),
1636 GdkEvent
*event
__attribute__((unused
)),
1639 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1641 (jint
) AWT_WINDOW_CLOSING
,
1642 (jobject
) NULL
, (jint
) 0);
1644 /* Prevents that the Window dissappears ("destroy"
1645 not being signalled). This is necessary because it
1646 should be up to a WindowListener implementation
1647 how the AWT Frame responds to close requests. */
1652 window_destroy_cb (GtkWidget
*widget
__attribute__((unused
)),
1653 GdkEvent
*event
__attribute__((unused
)),
1656 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1658 (jint
) AWT_WINDOW_CLOSED
,
1659 (jobject
) NULL
, (jint
) 0);
1663 window_focus_state_change_cb (GtkWidget
*widget
,
1664 GParamSpec
*pspec
__attribute__((unused
)),
1667 if (GTK_WINDOW (widget
)->has_toplevel_focus
)
1668 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1670 (jint
) AWT_WINDOW_ACTIVATED
,
1671 (jobject
) NULL
, (jint
) 0);
1673 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1675 (jint
) AWT_WINDOW_DEACTIVATED
,
1676 (jobject
) NULL
, (jint
) 0);
1680 window_focus_in_cb (GtkWidget
* widget
__attribute__((unused
)),
1681 GdkEventFocus
*event
__attribute__((unused
)),
1684 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1686 (jint
) AWT_WINDOW_GAINED_FOCUS
,
1687 (jobject
) NULL
, (jint
) 0);
1693 window_focus_out_cb (GtkWidget
* widget
__attribute__((unused
)),
1694 GdkEventFocus
*event
__attribute__((unused
)),
1697 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1699 (jint
) AWT_WINDOW_LOST_FOCUS
,
1700 (jobject
) NULL
, (jint
) 0);
1706 window_window_state_cb (GtkWidget
*widget
__attribute__((unused
)),
1710 jint new_java_state
= 0;
1711 /* Put together the new state and let the java side figure out what
1713 GdkWindowState new_state
= event
->window_state
.new_window_state
;
1714 /* The window can be either iconfified, maximized, iconified + maximized
1716 if ((new_state
& GDK_WINDOW_STATE_ICONIFIED
) != 0)
1717 new_java_state
|= AWT_FRAME_ICONIFIED
;
1718 if ((new_state
& GDK_WINDOW_STATE_MAXIMIZED
) != 0)
1719 new_java_state
|= AWT_FRAME_MAXIMIZED_BOTH
;
1720 if ((new_state
& (GDK_WINDOW_STATE_MAXIMIZED
| GDK_WINDOW_STATE_ICONIFIED
))
1722 new_java_state
= AWT_FRAME_NORMAL
;
1724 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1726 (jint
) AWT_WINDOW_STATE_CHANGED
,
1727 (jobject
) NULL
, new_java_state
);
1733 window_property_changed_cb (GtkWidget
*widget
__attribute__((unused
)),
1734 GdkEventProperty
*event
,
1737 unsigned long *extents
;
1738 union extents_union gu_ex
;
1740 gu_ex
.extents
= &extents
;
1741 if (gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE
) == event
->atom
1742 && gdk_property_get (event
->window
,
1743 gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE
),
1744 gdk_atom_intern ("CARDINAL", FALSE
),
1746 sizeof (unsigned long) * 4,
1753 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1754 postInsetsChangedEventID
,
1755 (jint
) extents
[2], /* top */
1756 (jint
) extents
[0], /* left */
1757 (jint
) extents
[3], /* bottom */
1758 (jint
) extents
[1]); /* right */
1766 realize_cb (GtkWidget
*widget
, jobject peer
)
1775 width
= (*cp_gtk_gdk_env())->CallIntMethod (cp_gtk_gdk_env(), peer
, windowGetWidthID
);
1776 height
= (*cp_gtk_gdk_env())->CallIntMethod (cp_gtk_gdk_env(), peer
, windowGetHeightID
);
1778 window_get_frame_extents (widget
, &top
, &left
, &bottom
, &right
);
1780 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1781 postInsetsChangedEventID
,
1782 top
, left
, bottom
, right
);
1784 gtk_window_set_default_size (GTK_WINDOW (widget
),
1785 MAX (1, width
- left
- right
),
1786 MAX (1, height
- top
- bottom
));
1788 /* set the size like we do in nativeSetBounds */
1789 gtk_widget_set_size_request (widget
,
1790 MAX (1, width
- left
- right
),
1791 MAX (1, height
- top
- bottom
));
1793 gtk_window_resize (GTK_WINDOW (widget
),
1794 MAX (1, width
- left
- right
),
1795 MAX (1, height
- top
- bottom
));
1799 * This method returns a GDK keyval that corresponds to one of the
1800 * keysyms in the X keymap table. The return value is only used to
1801 * determine the keyval's corresponding hardware keycode, and doesn't
1802 * reflect an accurate translation of a Java virtual key value to a
1809 cp_gtk_awt_keycode_to_keysym (jint keyCode
, jint keyLocation
)
1811 /* GDK_A through GDK_Z */
1812 if (keyCode
>= VK_A
&& keyCode
<= VK_Z
)
1813 return gdk_keyval_to_lower (keyCode
);
1815 /* GDK_0 through GDK_9 */
1816 if (keyCode
>= VK_0
&& keyCode
<= VK_9
)
1822 return keyLocation
== AWT_KEY_LOCATION_NUMPAD
? GDK_KP_Enter
: GDK_Return
;
1824 return GDK_BackSpace
;
1832 return keyLocation
== AWT_KEY_LOCATION_LEFT
? GDK_Shift_L
: GDK_Shift_R
;
1834 return keyLocation
== AWT_KEY_LOCATION_LEFT
? GDK_Control_L
: GDK_Control_R
;
1836 return keyLocation
== AWT_KEY_LOCATION_LEFT
? GDK_Alt_L
: GDK_Alt_R
;
1840 return GDK_Caps_Lock
;
1846 return keyLocation
== AWT_KEY_LOCATION_NUMPAD
? GDK_KP_Page_Up
: GDK_Page_Up
;
1848 return keyLocation
== AWT_KEY_LOCATION_NUMPAD
? GDK_KP_Page_Down
: GDK_Page_Down
;
1850 return keyLocation
== AWT_KEY_LOCATION_NUMPAD
? GDK_KP_End
: GDK_End
;
1852 return keyLocation
== AWT_KEY_LOCATION_NUMPAD
? GDK_KP_Home
: GDK_Home
;
1882 return GDK_semicolon
;
1913 case VK_OPEN_BRACKET
:
1914 return GDK_bracketleft
;
1916 return GDK_backslash
;
1917 case VK_CLOSE_BRACKET
:
1918 return GDK_bracketright
;
1940 return GDK_KP_Multiply
;
1947 return GDK_KP_Separator
;
1949 return GDK_KP_Subtract
;
1951 return GDK_KP_Decimal
;
1953 return GDK_KP_Divide
;
1955 return keyLocation
== AWT_KEY_LOCATION_NUMPAD
? GDK_KP_Delete
: GDK_Delete
;
1957 return GDK_Num_Lock
;
1958 case VK_SCROLL_LOCK
:
1959 return GDK_Scroll_Lock
;
2008 case VK_PRINTSCREEN
:
2011 return keyLocation
== AWT_KEY_LOCATION_NUMPAD
? GDK_KP_Insert
: GDK_Insert
;
2015 return keyLocation
== AWT_KEY_LOCATION_LEFT
? GDK_Meta_L
: GDK_Meta_R
;
2019 return GDK_apostrophe
;
2027 return GDK_KP_Right
;
2029 return GDK_dead_grave
;
2031 return GDK_dead_acute
;
2032 case VK_DEAD_CIRCUMFLEX
:
2033 return GDK_dead_circumflex
;
2035 return GDK_dead_tilde
;
2036 case VK_DEAD_MACRON
:
2037 return GDK_dead_macron
;
2039 return GDK_dead_breve
;
2040 case VK_DEAD_ABOVEDOT
:
2041 return GDK_dead_abovedot
;
2042 case VK_DEAD_DIAERESIS
:
2043 return GDK_dead_diaeresis
;
2044 case VK_DEAD_ABOVERING
:
2045 return GDK_dead_abovering
;
2046 case VK_DEAD_DOUBLEACUTE
:
2047 return GDK_dead_doubleacute
;
2049 return GDK_dead_caron
;
2050 case VK_DEAD_CEDILLA
:
2051 return GDK_dead_cedilla
;
2052 case VK_DEAD_OGONEK
:
2053 return GDK_dead_ogonek
;
2055 return GDK_dead_iota
;
2056 case VK_DEAD_VOICED_SOUND
:
2057 return GDK_dead_voiced_sound
;
2058 case VK_DEAD_SEMIVOICED_SOUND
:
2059 return GDK_dead_semivoiced_sound
;
2061 return GDK_ampersand
;
2063 return GDK_asterisk
;
2065 return GDK_quotedbl
;
2071 return GDK_braceleft
;
2073 return GDK_braceright
;
2079 return GDK_asciicircum
;
2083 return GDK_EuroSign
;
2084 case VK_EXCLAMATION_MARK
:
2086 case VK_INVERTED_EXCLAMATION_MARK
:
2087 return GDK_exclamdown
;
2088 case VK_LEFT_PARENTHESIS
:
2089 return GDK_parenleft
;
2090 case VK_NUMBER_SIGN
:
2091 return GDK_numbersign
;
2094 case VK_RIGHT_PARENTHESIS
:
2095 return GDK_parenright
;
2097 return GDK_underscore
;
2105 return GDK_Mode_switch
;
2112 case VK_ALPHANUMERIC:
2115 return GDK_Katakana
;
2117 return GDK_Hiragana
;
2121 case VK_ROMAN_CHARACTERS:
2122 case VK_ALL_CANDIDATES:
2124 case VK_PREVIOUS_CANDIDATE
:
2125 return GDK_PreviousCandidate
;
2127 return GDK_Codeinput
;
2129 case VK_JAPANESE_KATAKANA:
2130 case VK_JAPANESE_HIRAGANA:
2131 case VK_JAPANESE_ROMAN:
2134 return GDK_Kana_Lock
;
2136 case VK_INPUT_METHOD_ON_OFF:
2152 return GDK_ISO_Level3_Shift
;
2156 case VK_CONTEXT_MENU
:
2162 return GDK_VoidSymbol
;