Merged with mainline at revision 128810.
[official-gcc.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkWindowPeer.c
blob6ba8d4767586573f83b263baffe953912ebae2b3
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)
10 any later version.
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
20 02110-1301 USA.
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
25 combination.
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. */
40 #include "gtkpeer.h"
41 #include "gnu_java_awt_peer_gtk_GtkWindowPeer.h"
42 #include <gdk/gdkprivate.h>
43 #include <gdk/gdkx.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
61 /* Virtual Keys */
62 /* This list should be kept in the same order as the VK_ field
63 declarations in KeyEvent.java. */
64 #define VK_ENTER '\n'
65 #define VK_BACK_SPACE '\b'
66 #define VK_TAB '\t'
67 #define VK_CANCEL 3
68 #define VK_CLEAR 12
69 #define VK_SHIFT 16
70 #define VK_CONTROL 17
71 #define VK_ALT 18
72 #define VK_PAUSE 19
73 #define VK_CAPS_LOCK 20
74 #define VK_ESCAPE 27
75 #define VK_SPACE ' '
76 #define VK_PAGE_UP 33
77 #define VK_PAGE_DOWN 34
78 #define VK_END 35
79 #define VK_HOME 36
80 #define VK_LEFT 37
81 #define VK_UP 38
82 #define VK_RIGHT 39
83 #define VK_DOWN 40
84 #define VK_COMMA ','
85 #define VK_MINUS '-'
86 #define VK_PERIOD '.'
87 #define VK_SLASH '/'
88 #define VK_0 '0'
89 #define VK_1 '1'
90 #define VK_2 '2'
91 #define VK_3 '3'
92 #define VK_4 '4'
93 #define VK_5 '5'
94 #define VK_6 '6'
95 #define VK_7 '7'
96 #define VK_8 '8'
97 #define VK_9 '9'
98 #define VK_SEMICOLON ';'
99 #define VK_EQUALS '='
100 #define VK_A 'A'
101 #define VK_B 'B'
102 #define VK_C 'C'
103 #define VK_D 'D'
104 #define VK_E 'E'
105 #define VK_F 'F'
106 #define VK_G 'G'
107 #define VK_H 'H'
108 #define VK_I 'I'
109 #define VK_J 'J'
110 #define VK_K 'K'
111 #define VK_L 'L'
112 #define VK_M 'M'
113 #define VK_N 'N'
114 #define VK_O 'O'
115 #define VK_P 'P'
116 #define VK_Q 'Q'
117 #define VK_R 'R'
118 #define VK_S 'S'
119 #define VK_T 'T'
120 #define VK_U 'U'
121 #define VK_V 'V'
122 #define VK_W 'W'
123 #define VK_X 'X'
124 #define VK_Y 'Y'
125 #define VK_Z 'Z'
126 #define VK_OPEN_BRACKET '['
127 #define VK_BACK_SLASH '\\'
128 #define VK_CLOSE_BRACKET ']'
129 /* See gtkpeer.h */
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
141 #define VK_ADD 107
142 #define VK_SEPARATER 108
143 #define VK_SEPARATOR 108
144 #define VK_SUBTRACT 109
145 /* See gtkpeer.h */
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
151 #define VK_F1 112
152 #define VK_F2 113
153 #define VK_F3 114
154 #define VK_F4 115
155 #define VK_F5 116
156 #define VK_F6 117
157 #define VK_F7 118
158 #define VK_F8 119
159 #define VK_F9 120
160 #define VK_F10 121
161 #define VK_F11 122
162 #define VK_F12 123
163 #define VK_F13 61440
164 #define VK_F14 61441
165 #define VK_F15 61442
166 #define VK_F16 61443
167 #define VK_F17 61444
168 #define VK_F18 61445
169 #define VK_F19 61446
170 #define VK_F20 61447
171 #define VK_F21 61448
172 #define VK_F22 61449
173 #define VK_F23 61450
174 #define VK_F24 61451
175 #define VK_PRINTSCREEN 154
176 #define VK_INSERT 155
177 #define VK_HELP 156
178 #define VK_META 157
179 #define VK_BACK_QUOTE 192
180 #define VK_QUOTE 222
181 #define VK_KP_UP 224
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
204 #define VK_LESS 153
205 #define VK_GREATER 160
206 #define VK_BRACELEFT 161
207 #define VK_BRACERIGHT 162
208 #define VK_AT 512
209 #define VK_COLON 513
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
217 #define VK_PLUS 521
218 #define VK_RIGHT_PARENTHESIS 522
219 #define VK_UNDERSCORE 523
220 #define VK_FINAL 24
221 #define VK_CONVERT 28
222 #define VK_NONCONVERT 29
223 #define VK_ACCEPT 30
224 #define VK_MODECHANGE 31
225 #define VK_KANA 21
226 #define VK_KANJI 25
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
241 #define VK_CUT 65489
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;
272 void
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,
284 "postWindowEvent",
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",
292 "(IIII)V");
294 windowGetWidthID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer,
295 "getWidth", "()I");
297 windowGetHeightID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer,
298 "getHeight", "()I");
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. */
308 static gint
309 get_first_keyval_from_keymap (GdkEventKey *event)
311 guint keyval;
312 guint *keyvals;
313 gint n_entries;
315 if (!gdk_keymap_get_entries_for_keycode (NULL,
316 event->hardware_keycode,
317 NULL,
318 &keyvals,
319 &n_entries))
321 /* No keyval found for hardware keycode */
322 return -1;
324 keyval = keyvals[0];
325 g_free (keyvals);
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. */
332 #ifdef __GNUC__
333 __inline
334 #endif
335 static jint
336 keysym_to_awt_keycode (GdkEventKey *event)
338 gint ukeyval;
339 guint state;
341 ukeyval = get_first_keyval_from_keymap (event);
343 if (ukeyval < 0)
344 return -1;
346 state = event->state;
348 /* VK_A through VK_Z */
349 if (ukeyval >= GDK_A && ukeyval <= GDK_Z)
350 return ukeyval;
352 /* VK_0 through VK_9 */
353 if (ukeyval >= GDK_0 && ukeyval <= GDK_9)
354 return ukeyval;
356 switch (ukeyval)
358 case GDK_Return:
359 case GDK_KP_Enter:
360 return VK_ENTER;
361 case GDK_BackSpace:
362 return VK_BACK_SPACE;
363 case GDK_Tab:
364 return VK_TAB;
365 case GDK_Cancel:
366 return VK_CANCEL;
367 case GDK_Clear:
368 return VK_CLEAR;
369 case GDK_Shift_L:
370 case GDK_Shift_R:
371 return VK_SHIFT;
372 case GDK_Control_L:
373 case GDK_Control_R:
374 return VK_CONTROL;
375 case GDK_Alt_L:
376 case GDK_Alt_R:
377 return VK_ALT;
378 case GDK_Pause:
379 return VK_PAUSE;
380 case GDK_Caps_Lock:
381 return VK_CAPS_LOCK;
382 case GDK_Escape:
383 return VK_ESCAPE;
384 case GDK_space:
385 return VK_SPACE;
386 case GDK_KP_Page_Up:
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)
390 return VK_NUMPAD9;
391 else
392 return VK_PAGE_UP;
393 case GDK_Page_Up:
394 return VK_PAGE_UP;
395 case GDK_KP_Page_Down:
396 if (state & GDK_MOD2_MASK)
397 return VK_NUMPAD3;
398 else
399 return VK_PAGE_DOWN;
400 case GDK_Page_Down:
401 return VK_PAGE_DOWN;
402 case GDK_KP_End:
403 if (state & GDK_MOD2_MASK)
404 return VK_NUMPAD1;
405 else
406 return VK_END;
407 case GDK_End:
408 return VK_END;
409 case GDK_KP_Home:
410 if (state & GDK_MOD2_MASK)
411 return VK_NUMPAD7;
412 else
413 return VK_HOME;
414 case GDK_Home:
415 return VK_HOME;
416 case GDK_KP_Begin:
417 if (state & GDK_MOD2_MASK)
418 return VK_NUMPAD5;
419 else
420 return VK_UNDEFINED;
421 case GDK_Left:
422 return VK_LEFT;
423 case GDK_Up:
424 return VK_UP;
425 case GDK_Right:
426 return VK_RIGHT;
427 case GDK_Down:
428 return VK_DOWN;
429 case GDK_comma:
430 return VK_COMMA;
431 case GDK_minus:
432 return VK_MINUS;
433 case GDK_period:
434 return VK_PERIOD;
435 case GDK_slash:
436 return VK_SLASH;
438 return VK_0;
439 return VK_1;
440 return VK_2;
441 return VK_3;
442 return VK_4;
443 return VK_5;
444 return VK_6;
445 return VK_7;
446 return VK_8;
447 return VK_9;
449 case GDK_semicolon:
450 return VK_SEMICOLON;
451 case GDK_equal:
452 return VK_EQUALS;
454 return VK_A;
455 return VK_B;
456 return VK_C;
457 return VK_D;
458 return VK_E;
459 return VK_F;
460 return VK_G;
461 return VK_H;
462 return VK_I;
463 return VK_J;
464 return VK_K;
465 return VK_L;
466 return VK_M;
467 return VK_N;
468 return VK_O;
469 return VK_P;
470 return VK_Q;
471 return VK_R;
472 return VK_S;
473 return VK_T;
474 return VK_U;
475 return VK_V;
476 return VK_W;
477 return VK_X;
478 return VK_Y;
479 return VK_Z;
481 case GDK_bracketleft:
482 return VK_OPEN_BRACKET;
483 case GDK_backslash:
484 return VK_BACK_SLASH;
485 case GDK_bracketright:
486 return VK_CLOSE_BRACKET;
487 case GDK_KP_0:
488 return VK_NUMPAD0;
489 case GDK_KP_1:
490 return VK_NUMPAD1;
491 case GDK_KP_2:
492 return VK_NUMPAD2;
493 case GDK_KP_3:
494 return VK_NUMPAD3;
495 case GDK_KP_4:
496 return VK_NUMPAD4;
497 case GDK_KP_5:
498 return VK_NUMPAD5;
499 case GDK_KP_6:
500 return VK_NUMPAD6;
501 case GDK_KP_7:
502 return VK_NUMPAD7;
503 case GDK_KP_8:
504 return VK_NUMPAD8;
505 case GDK_KP_9:
506 return VK_NUMPAD9;
507 case GDK_KP_Multiply:
508 return VK_MULTIPLY;
509 case GDK_KP_Add:
510 return VK_ADD;
512 return VK_SEPARATER;
514 case GDK_KP_Separator:
515 return VK_SEPARATOR;
516 case GDK_KP_Subtract:
517 return VK_SUBTRACT;
518 case GDK_KP_Decimal:
519 return VK_DECIMAL;
520 case GDK_KP_Divide:
521 return VK_DIVIDE;
522 case GDK_KP_Delete:
523 if (state & GDK_MOD2_MASK)
524 return VK_DECIMAL;
525 else
526 return VK_DELETE;
527 case GDK_Delete:
528 return VK_DELETE;
529 case GDK_Num_Lock:
530 return VK_NUM_LOCK;
531 case GDK_Scroll_Lock:
532 return VK_SCROLL_LOCK;
533 case GDK_F1:
534 return VK_F1;
535 case GDK_F2:
536 return VK_F2;
537 case GDK_F3:
538 return VK_F3;
539 case GDK_F4:
540 return VK_F4;
541 case GDK_F5:
542 return VK_F5;
543 case GDK_F6:
544 return VK_F6;
545 case GDK_F7:
546 return VK_F7;
547 case GDK_F8:
548 return VK_F8;
549 case GDK_F9:
550 return VK_F9;
551 case GDK_F10:
552 return VK_F10;
553 case GDK_F11:
554 return VK_F11;
555 case GDK_F12:
556 return VK_F12;
557 case GDK_F13:
558 return VK_F13;
559 case GDK_F14:
560 return VK_F14;
561 case GDK_F15:
562 return VK_F15;
563 case GDK_F16:
564 return VK_F16;
565 case GDK_F17:
566 return VK_F17;
567 case GDK_F18:
568 return VK_F18;
569 case GDK_F19:
570 return VK_F19;
571 case GDK_F20:
572 return VK_F20;
573 case GDK_F21:
574 return VK_F21;
575 case GDK_F22:
576 return VK_F22;
577 case GDK_F23:
578 return VK_F23;
579 case GDK_F24:
580 return VK_F24;
581 case GDK_Print:
582 return VK_PRINTSCREEN;
583 case GDK_KP_Insert:
584 if (state & GDK_MOD2_MASK)
585 return VK_NUMPAD0;
586 else
587 return VK_INSERT;
588 case GDK_Insert:
589 return VK_INSERT;
590 case GDK_Help:
591 return VK_HELP;
592 case GDK_Meta_L:
593 case GDK_Meta_R:
594 return VK_META;
595 case GDK_grave:
596 return VK_BACK_QUOTE;
597 case GDK_apostrophe:
598 return VK_QUOTE;
599 case GDK_KP_Up:
600 if (state & GDK_MOD2_MASK)
601 return VK_NUMPAD8;
602 else
603 return VK_KP_UP;
604 case GDK_KP_Down:
605 if (state & GDK_MOD2_MASK)
606 return VK_NUMPAD2;
607 else
608 return VK_KP_DOWN;
609 case GDK_KP_Left:
610 if (state & GDK_MOD2_MASK)
611 return VK_NUMPAD4;
612 else
613 return VK_KP_LEFT;
614 case GDK_KP_Right:
615 if (state & GDK_MOD2_MASK)
616 return VK_NUMPAD6;
617 else
618 return VK_KP_RIGHT;
619 case GDK_dead_grave:
620 return VK_DEAD_GRAVE;
621 case GDK_dead_acute:
622 return VK_DEAD_ACUTE;
623 case GDK_dead_circumflex:
624 return VK_DEAD_CIRCUMFLEX;
625 case GDK_dead_tilde:
626 return VK_DEAD_TILDE;
627 case GDK_dead_macron:
628 return VK_DEAD_MACRON;
629 case GDK_dead_breve:
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;
639 case GDK_dead_caron:
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;
645 case GDK_dead_iota:
646 return VK_DEAD_IOTA;
647 case GDK_dead_voiced_sound:
648 return VK_DEAD_VOICED_SOUND;
649 case GDK_dead_semivoiced_sound:
650 return VK_DEAD_SEMIVOICED_SOUND;
651 case GDK_ampersand:
652 return VK_AMPERSAND;
653 case GDK_asterisk:
654 return VK_ASTERISK;
655 case GDK_quotedbl:
656 return VK_QUOTEDBL;
657 case GDK_less:
658 return VK_LESS;
659 case GDK_greater:
660 return VK_GREATER;
661 case GDK_braceleft:
662 return VK_BRACELEFT;
663 case GDK_braceright:
664 return VK_BRACERIGHT;
665 case GDK_at:
666 return VK_AT;
667 case GDK_colon:
668 return VK_COLON;
669 case GDK_asciicircum:
670 return VK_CIRCUMFLEX;
671 case GDK_dollar:
672 return VK_DOLLAR;
673 case GDK_EuroSign:
674 return VK_EURO_SIGN;
675 case GDK_exclam:
676 return VK_EXCLAMATION_MARK;
677 case GDK_exclamdown:
678 return VK_INVERTED_EXCLAMATION_MARK;
679 case GDK_parenleft:
680 return VK_LEFT_PARENTHESIS;
681 case GDK_numbersign:
682 return VK_NUMBER_SIGN;
683 case GDK_plus:
684 return VK_PLUS;
685 case GDK_parenright:
686 return VK_RIGHT_PARENTHESIS;
687 case GDK_underscore:
688 return VK_UNDERSCORE;
690 return VK_FINAL;
691 return VK_CONVERT;
692 return VK_NONCONVERT;
693 return VK_ACCEPT;
695 case GDK_Mode_switch:
696 return VK_MODECHANGE;
698 return VK_KANA;
700 case GDK_Kanji:
701 return VK_KANJI;
703 return VK_ALPHANUMERIC;
705 case GDK_Katakana:
706 return VK_KATAKANA;
707 case GDK_Hiragana:
708 return VK_HIRAGANA;
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;
717 case GDK_Codeinput:
718 return VK_CODE_INPUT;
720 return VK_JAPANESE_KATAKANA;
721 return VK_JAPANESE_HIRAGANA;
722 return VK_JAPANESE_ROMAN;
724 case GDK_Kana_Lock:
725 return VK_KANA_LOCK;
727 return VK_INPUT_METHOD_ON_OFF;
728 return VK_CUT;
729 return VK_COPY;
730 return VK_PASTE;
732 case GDK_Undo:
733 return VK_UNDO;
734 case GDK_Redo:
735 return VK_AGAIN;
737 return VK_FIND;
738 return VK_PROPS;
739 return VK_STOP;
740 return VK_COMPOSE;
742 case GDK_ISO_Level3_Shift:
743 return VK_ALT_GRAPH;
745 case VK_BEGIN:
747 case GDK_Menu:
748 return VK_CONTEXT_MENU;
749 case GDK_Super_L:
750 case GDK_Super_R:
751 return VK_WINDOWS;
753 default:
754 return VK_UNDEFINED;
758 /* Return the AWT key location code for the given keysym or -1 if no
759 keyval was found for the given hardware keycode. */
760 static jint
761 keysym_to_awt_keylocation (GdkEventKey *event)
763 gint ukeyval;
765 ukeyval = get_first_keyval_from_keymap (event);
767 if (ukeyval < 0)
768 return -1;
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;
778 switch (ukeyval)
780 case GDK_Shift_L:
781 case GDK_Control_L:
782 case GDK_Alt_L:
783 case GDK_Meta_L:
784 return AWT_KEY_LOCATION_LEFT;
786 case GDK_Shift_R:
787 case GDK_Control_R:
788 case GDK_Alt_R:
789 case GDK_Meta_R:
790 return AWT_KEY_LOCATION_RIGHT;
792 case GDK_Return:
793 case GDK_BackSpace:
794 case GDK_Tab:
795 case GDK_Cancel:
796 case GDK_Clear:
797 case GDK_Pause:
798 case GDK_Caps_Lock:
799 case GDK_Escape:
800 case GDK_space:
801 case GDK_Page_Up:
802 case GDK_Page_Down:
803 case GDK_End:
804 case GDK_Home:
805 case GDK_Left:
806 case GDK_Up:
807 case GDK_Right:
808 case GDK_Down:
809 case GDK_comma:
810 case GDK_minus:
811 case GDK_period:
812 case GDK_slash:
813 case GDK_semicolon:
814 case GDK_equal:
815 case GDK_bracketleft:
816 case GDK_backslash:
817 case GDK_bracketright:
818 case GDK_Delete:
819 case GDK_Scroll_Lock:
820 case GDK_F1:
821 case GDK_F2:
822 case GDK_F3:
823 case GDK_F4:
824 case GDK_F5:
825 case GDK_F6:
826 case GDK_F7:
827 case GDK_F8:
828 case GDK_F9:
829 case GDK_F10:
830 case GDK_F11:
831 case GDK_F12:
832 case GDK_F13:
833 case GDK_F14:
834 case GDK_F15:
835 case GDK_F16:
836 case GDK_F17:
837 case GDK_F18:
838 case GDK_F19:
839 case GDK_F20:
840 case GDK_F21:
841 case GDK_F22:
842 case GDK_F23:
843 case GDK_F24:
844 case GDK_Print:
845 case GDK_Insert:
846 case GDK_Help:
847 case GDK_grave:
848 case GDK_apostrophe:
849 case GDK_dead_grave:
850 case GDK_dead_acute:
851 case GDK_dead_circumflex:
852 case GDK_dead_tilde:
853 case GDK_dead_macron:
854 case GDK_dead_breve:
855 case GDK_dead_abovedot:
856 case GDK_dead_diaeresis:
857 case GDK_dead_abovering:
858 case GDK_dead_doubleacute:
859 case GDK_dead_caron:
860 case GDK_dead_cedilla:
861 case GDK_dead_ogonek:
862 case GDK_dead_iota:
863 case GDK_dead_voiced_sound:
864 case GDK_dead_semivoiced_sound:
865 case GDK_ampersand:
866 case GDK_asterisk:
867 case GDK_quotedbl:
868 case GDK_less:
869 case GDK_greater:
870 case GDK_braceleft:
871 case GDK_braceright:
872 case GDK_at:
873 case GDK_colon:
874 case GDK_asciicircum:
875 case GDK_dollar:
876 case GDK_EuroSign:
877 case GDK_exclam:
878 case GDK_exclamdown:
879 case GDK_parenleft:
880 case GDK_numbersign:
881 case GDK_plus:
882 case GDK_parenright:
883 case GDK_underscore:
884 case GDK_Mode_switch:
885 case GDK_Kanji:
886 case GDK_Katakana:
887 case GDK_Hiragana:
888 case GDK_PreviousCandidate:
889 case GDK_Codeinput:
890 case GDK_Kana_Lock:
891 return AWT_KEY_LOCATION_STANDARD;
893 case GDK_KP_Enter:
894 case GDK_KP_Page_Up:
895 case GDK_KP_Page_Down:
896 case GDK_KP_End:
897 case GDK_KP_Home:
898 case GDK_KP_Begin:
899 case GDK_KP_0:
900 case GDK_KP_1:
901 case GDK_KP_2:
902 case GDK_KP_3:
903 case GDK_KP_4:
904 case GDK_KP_5:
905 case GDK_KP_6:
906 case GDK_KP_7:
907 case GDK_KP_8:
908 case GDK_KP_9:
909 case GDK_KP_Multiply:
910 case GDK_KP_Add:
911 case GDK_KP_Separator:
912 case GDK_KP_Subtract:
913 case GDK_KP_Decimal:
914 case GDK_KP_Divide:
915 case GDK_KP_Delete:
916 case GDK_Num_Lock:
917 case GDK_KP_Insert:
918 case GDK_KP_Up:
919 case GDK_KP_Down:
920 case GDK_KP_Left:
921 case GDK_KP_Right:
922 return AWT_KEY_LOCATION_NUMPAD;
924 default:
925 return AWT_KEY_LOCATION_UNKNOWN;
929 static jchar
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)
936 return VK_ENTER;
937 else
938 return event->string[0];
940 else
942 switch (event->keyval)
944 case GDK_BackSpace:
945 return VK_BACK_SPACE;
946 case GDK_Tab:
947 return VK_TAB;
948 case GDK_Delete:
949 case GDK_KP_Delete:
950 return VK_DELETE;
951 default:
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. */
965 static jint
966 keyevent_state_to_awt_mods (GdkEventKey *event)
968 jint result = 0;
969 guint state;
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;
978 else
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;
987 else
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;
996 else
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;
1027 return result;
1030 static gboolean window_configure_cb (GtkWidget *widget,
1031 GdkEventConfigure *event,
1032 jobject peer);
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,
1045 XEvent *xevent,
1046 XPointer arg);
1048 static gboolean window_delete_cb (GtkWidget *widget, GdkEvent *event,
1049 jobject peer);
1050 static void window_destroy_cb (GtkWidget *widget, GdkEvent *event,
1051 jobject peer);
1052 static void window_focus_state_change_cb (GtkWidget *widget,
1053 GParamSpec *pspec,
1054 jobject peer);
1055 static gboolean window_focus_in_cb (GtkWidget * widget,
1056 GdkEventFocus *event,
1057 jobject peer);
1058 static gboolean window_focus_out_cb (GtkWidget * widget,
1059 GdkEventFocus *event,
1060 jobject peer);
1061 static gboolean window_window_state_cb (GtkWidget *widget,
1062 GdkEvent *event,
1063 jobject peer);
1064 static gboolean window_property_changed_cb (GtkWidget *widget,
1065 GdkEventProperty *event,
1066 jobject peer);
1067 static void realize_cb (GtkWidget *widget, jobject peer);
1069 static gboolean
1070 window_configure_cb (GtkWidget *widget __attribute__((unused)),
1071 GdkEventConfigure *event,
1072 jobject peer)
1074 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1075 postConfigureEventID,
1076 (jint) event->x,
1077 (jint) event->y,
1078 (jint) event->width,
1079 (jint) event->height);
1081 return FALSE;
1084 static gboolean
1085 key_press_cb (GtkWidget *widget __attribute__((unused)),
1086 GdkEventKey *event,
1087 jobject peer)
1089 jint keycode;
1090 jint keylocation;
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)
1098 return TRUE;
1100 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1101 postKeyEventID,
1102 (jint) AWT_KEY_PRESSED,
1103 (jlong) event->time,
1104 keyevent_state_to_awt_mods (event),
1105 keycode,
1106 keyevent_to_awt_keychar (event),
1107 keylocation);
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. */
1114 return TRUE;
1118 static gboolean
1119 key_release_cb (GtkWidget *widget __attribute__((unused)),
1120 GdkEventKey *event,
1121 jobject peer)
1123 jint keycode;
1124 jint keylocation;
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)
1132 return TRUE;
1134 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1135 postKeyEventID,
1136 (jint) AWT_KEY_RELEASED,
1137 (jlong) event->time,
1138 keyevent_state_to_awt_mods (event),
1139 keycode,
1140 keyevent_to_awt_keychar (event),
1141 keylocation);
1143 return TRUE;
1146 /* Union used for type punning. */
1147 union extents_union
1149 guchar **gu_extents;
1150 unsigned long **extents;
1153 union atom_list_union
1155 guchar **gu_extents;
1156 Atom **atom_list;
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;
1164 GtkWindow *window;
1165 void *window_parent;
1166 GtkWidget *fixed;
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. */
1176 if (parent)
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;
1204 void *ptr;
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)
1223 void *ptr;
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)
1238 void *ptr;
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)
1253 void *ptr;
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)
1268 void *ptr;
1269 jboolean retval;
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 ();
1278 return retval;
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);
1290 gdk_flush ();
1292 gdk_threads_leave ();
1295 JNIEXPORT void JNICALL
1296 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNativeUnlocked
1297 (JNIEnv *env, jobject obj, jboolean visible)
1299 void *ptr;
1301 ptr = gtkpeer_get_widget (env, obj);
1303 if (visible)
1304 gtk_widget_show (GTK_WIDGET (ptr));
1305 else
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)
1313 void *ptr;
1314 jobject gref;
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)
1371 void *ptr;
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,
1384 jobject obj)
1386 void *ptr;
1388 gdk_threads_enter ();
1390 ptr = gtkpeer_get_widget (env, obj);
1392 gdk_window_lower (GTK_WIDGET (ptr)->window);
1393 gdk_flush ();
1395 gdk_threads_leave ();
1398 JNIEXPORT void JNICALL
1399 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env,
1400 jobject obj)
1402 void *ptr;
1404 gdk_threads_enter ();
1406 ptr = gtkpeer_get_widget (env, obj);
1408 gdk_window_raise (GTK_WIDGET (ptr)->window);
1409 gdk_flush ();
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)
1418 void *ptr;
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)
1449 void *ptr;
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
1466 (env, obj, x, y);
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)
1475 void *ptr;
1476 gint current_width;
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:
1490 1. show a window
1491 2. manually move it to another position on the screen
1492 3. hide the window
1493 4. reposition the window with Component.setLocation
1494 5. show the window
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), &current_width, &current_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);
1516 static void
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
1524 supported. */
1525 if (!gtk_window_get_decorated (GTK_WINDOW (window)))
1527 *top = 0;
1528 *left = 0;
1529 *bottom = 0;
1530 *right = 0;
1532 return;
1535 *top = 23;
1536 *left = 6;
1537 *bottom = 6;
1538 *right = 6;
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,
1551 FALSE,
1552 NULL,
1553 NULL,
1554 NULL,
1555 gu_ex.gu_extents))
1557 *left = extents [0];
1558 *right = extents [1];
1559 *top = extents [2];
1560 *bottom = extents [3];
1564 static Atom extents_atom = 0;
1566 /* Requests that the window manager set window's
1567 _NET_FRAME_EXTENTS property. */
1568 static void
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);
1587 XEvent xevent;
1588 XEvent notify_xevent;
1590 unsigned long window_id = GDK_WINDOW_XID (GDK_DRAWABLE(window->window));
1592 if (!extents_atom)
1594 const char *extents_str = "_NET_FRAME_EXTENTS";
1595 extents_atom =
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),
1612 &xevent);
1614 XIfEvent(xdisplay, &notify_xevent,
1615 property_notify_predicate, (XPointer) &window_id);
1619 static Bool
1620 property_notify_predicate (Display *xdisplay __attribute__((unused)),
1621 XEvent *event,
1622 XPointer window_id)
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)
1629 return True;
1630 else
1631 return False;
1634 static gboolean
1635 window_delete_cb (GtkWidget *widget __attribute__((unused)),
1636 GdkEvent *event __attribute__((unused)),
1637 jobject peer)
1639 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1640 postWindowEventID,
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. */
1648 return TRUE;
1651 static void
1652 window_destroy_cb (GtkWidget *widget __attribute__((unused)),
1653 GdkEvent *event __attribute__((unused)),
1654 jobject peer)
1656 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1657 postWindowEventID,
1658 (jint) AWT_WINDOW_CLOSED,
1659 (jobject) NULL, (jint) 0);
1662 static void
1663 window_focus_state_change_cb (GtkWidget *widget,
1664 GParamSpec *pspec __attribute__((unused)),
1665 jobject peer)
1667 if (GTK_WINDOW (widget)->has_toplevel_focus)
1668 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1669 postWindowEventID,
1670 (jint) AWT_WINDOW_ACTIVATED,
1671 (jobject) NULL, (jint) 0);
1672 else
1673 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1674 postWindowEventID,
1675 (jint) AWT_WINDOW_DEACTIVATED,
1676 (jobject) NULL, (jint) 0);
1679 static gboolean
1680 window_focus_in_cb (GtkWidget * widget __attribute__((unused)),
1681 GdkEventFocus *event __attribute__((unused)),
1682 jobject peer)
1684 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1685 postWindowEventID,
1686 (jint) AWT_WINDOW_GAINED_FOCUS,
1687 (jobject) NULL, (jint) 0);
1689 return FALSE;
1692 static gboolean
1693 window_focus_out_cb (GtkWidget * widget __attribute__((unused)),
1694 GdkEventFocus *event __attribute__((unused)),
1695 jobject peer)
1697 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1698 postWindowEventID,
1699 (jint) AWT_WINDOW_LOST_FOCUS,
1700 (jobject) NULL, (jint) 0);
1702 return FALSE;
1705 static gboolean
1706 window_window_state_cb (GtkWidget *widget __attribute__((unused)),
1707 GdkEvent *event,
1708 jobject peer)
1710 jint new_java_state = 0;
1711 /* Put together the new state and let the java side figure out what
1712 * to post */
1713 GdkWindowState new_state = event->window_state.new_window_state;
1714 /* The window can be either iconfified, maximized, iconified + maximized
1715 * or normal. */
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))
1721 == 0)
1722 new_java_state = AWT_FRAME_NORMAL;
1724 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1725 postWindowEventID,
1726 (jint) AWT_WINDOW_STATE_CHANGED,
1727 (jobject) NULL, new_java_state);
1729 return TRUE;
1732 static gboolean
1733 window_property_changed_cb (GtkWidget *widget __attribute__((unused)),
1734 GdkEventProperty *event,
1735 jobject peer)
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,
1747 FALSE,
1748 NULL,
1749 NULL,
1750 NULL,
1751 gu_ex.gu_extents))
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 */
1762 return FALSE;
1765 static void
1766 realize_cb (GtkWidget *widget, jobject peer)
1768 jint top = 0;
1769 jint left = 0;
1770 jint bottom = 0;
1771 jint right = 0;
1772 jint width = 0;
1773 jint height = 0;
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
1803 * GDK keyval.
1805 #ifdef __GNUC__
1806 __inline
1807 #endif
1808 guint
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)
1817 return keyCode;
1819 switch (keyCode)
1821 case VK_ENTER:
1822 return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Enter : GDK_Return;
1823 case VK_BACK_SPACE:
1824 return GDK_BackSpace;
1825 case VK_TAB:
1826 return GDK_Tab;
1827 case VK_CANCEL:
1828 return GDK_Cancel;
1829 case VK_CLEAR:
1830 return GDK_Clear;
1831 case VK_SHIFT:
1832 return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Shift_L : GDK_Shift_R;
1833 case VK_CONTROL:
1834 return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Control_L : GDK_Control_R;
1835 case VK_ALT:
1836 return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Alt_L : GDK_Alt_R;
1837 case VK_PAUSE:
1838 return GDK_Pause;
1839 case VK_CAPS_LOCK:
1840 return GDK_Caps_Lock;
1841 case VK_ESCAPE:
1842 return GDK_Escape;
1843 case VK_SPACE:
1844 return GDK_space;
1845 case VK_PAGE_UP:
1846 return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Up : GDK_Page_Up;
1847 case VK_PAGE_DOWN:
1848 return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Down : GDK_Page_Down;
1849 case VK_END:
1850 return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_End : GDK_End;
1851 case VK_HOME:
1852 return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Home : GDK_Home;
1853 case VK_LEFT:
1854 return GDK_Left;
1855 case VK_UP:
1856 return GDK_Up;
1857 case VK_RIGHT:
1858 return GDK_Right;
1859 case VK_DOWN:
1860 return GDK_Down;
1861 case VK_COMMA:
1862 return GDK_comma;
1863 case VK_MINUS:
1864 return GDK_minus;
1865 case VK_PERIOD:
1866 return GDK_period;
1867 case VK_SLASH:
1868 return GDK_slash;
1870 case VK_0:
1871 case VK_1:
1872 case VK_2:
1873 case VK_3:
1874 case VK_4:
1875 case VK_5:
1876 case VK_6:
1877 case VK_7:
1878 case VK_8:
1879 case VK_9:
1881 case VK_SEMICOLON:
1882 return GDK_semicolon;
1883 case VK_EQUALS:
1884 return GDK_equal;
1886 case VK_A:
1887 case VK_B:
1888 case VK_C:
1889 case VK_D:
1890 case VK_E:
1891 case VK_F:
1892 case VK_G:
1893 case VK_H:
1894 case VK_I:
1895 case VK_J:
1896 case VK_K:
1897 case VK_L:
1898 case VK_M:
1899 case VK_N:
1900 case VK_O:
1901 case VK_P:
1902 case VK_Q:
1903 case VK_R:
1904 case VK_S:
1905 case VK_T:
1906 case VK_U:
1907 case VK_V:
1908 case VK_W:
1909 case VK_X:
1910 case VK_Y:
1911 case VK_Z:
1913 case VK_OPEN_BRACKET:
1914 return GDK_bracketleft;
1915 case VK_BACK_SLASH:
1916 return GDK_backslash;
1917 case VK_CLOSE_BRACKET:
1918 return GDK_bracketright;
1919 case VK_NUMPAD0:
1920 return GDK_KP_0;
1921 case VK_NUMPAD1:
1922 return GDK_KP_1;
1923 case VK_NUMPAD2:
1924 return GDK_KP_2;
1925 case VK_NUMPAD3:
1926 return GDK_KP_3;
1927 case VK_NUMPAD4:
1928 return GDK_KP_4;
1929 case VK_NUMPAD5:
1930 return GDK_KP_5;
1931 case VK_NUMPAD6:
1932 return GDK_KP_6;
1933 case VK_NUMPAD7:
1934 return GDK_KP_7;
1935 case VK_NUMPAD8:
1936 return GDK_KP_8;
1937 case VK_NUMPAD9:
1938 return GDK_KP_9;
1939 case VK_MULTIPLY:
1940 return GDK_KP_Multiply;
1941 case VK_ADD:
1942 return GDK_KP_Add;
1944 case VK_SEPARATER:
1946 case VK_SEPARATOR:
1947 return GDK_KP_Separator;
1948 case VK_SUBTRACT:
1949 return GDK_KP_Subtract;
1950 case VK_DECIMAL:
1951 return GDK_KP_Decimal;
1952 case VK_DIVIDE:
1953 return GDK_KP_Divide;
1954 case VK_DELETE:
1955 return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Delete : GDK_Delete;
1956 case VK_NUM_LOCK:
1957 return GDK_Num_Lock;
1958 case VK_SCROLL_LOCK:
1959 return GDK_Scroll_Lock;
1960 case VK_F1:
1961 return GDK_F1;
1962 case VK_F2:
1963 return GDK_F2;
1964 case VK_F3:
1965 return GDK_F3;
1966 case VK_F4:
1967 return GDK_F4;
1968 case VK_F5:
1969 return GDK_F5;
1970 case VK_F6:
1971 return GDK_F6;
1972 case VK_F7:
1973 return GDK_F7;
1974 case VK_F8:
1975 return GDK_F8;
1976 case VK_F9:
1977 return GDK_F9;
1978 case VK_F10:
1979 return GDK_F10;
1980 case VK_F11:
1981 return GDK_F11;
1982 case VK_F12:
1983 return GDK_F12;
1984 case VK_F13:
1985 return GDK_F13;
1986 case VK_F14:
1987 return GDK_F14;
1988 case VK_F15:
1989 return GDK_F15;
1990 case VK_F16:
1991 return GDK_F16;
1992 case VK_F17:
1993 return GDK_F17;
1994 case VK_F18:
1995 return GDK_F18;
1996 case VK_F19:
1997 return GDK_F19;
1998 case VK_F20:
1999 return GDK_F20;
2000 case VK_F21:
2001 return GDK_F21;
2002 case VK_F22:
2003 return GDK_F22;
2004 case VK_F23:
2005 return GDK_F23;
2006 case VK_F24:
2007 return GDK_F24;
2008 case VK_PRINTSCREEN:
2009 return GDK_Print;
2010 case VK_INSERT:
2011 return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Insert : GDK_Insert;
2012 case VK_HELP:
2013 return GDK_Help;
2014 case VK_META:
2015 return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Meta_L : GDK_Meta_R;
2016 case VK_BACK_QUOTE:
2017 return GDK_grave;
2018 case VK_QUOTE:
2019 return GDK_apostrophe;
2020 case VK_KP_UP:
2021 return GDK_KP_Up;
2022 case VK_KP_DOWN:
2023 return GDK_KP_Down;
2024 case VK_KP_LEFT:
2025 return GDK_KP_Left;
2026 case VK_KP_RIGHT:
2027 return GDK_KP_Right;
2028 case VK_DEAD_GRAVE:
2029 return GDK_dead_grave;
2030 case VK_DEAD_ACUTE:
2031 return GDK_dead_acute;
2032 case VK_DEAD_CIRCUMFLEX:
2033 return GDK_dead_circumflex;
2034 case VK_DEAD_TILDE:
2035 return GDK_dead_tilde;
2036 case VK_DEAD_MACRON:
2037 return GDK_dead_macron;
2038 case VK_DEAD_BREVE:
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;
2048 case VK_DEAD_CARON:
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;
2054 case VK_DEAD_IOTA:
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;
2060 case VK_AMPERSAND:
2061 return GDK_ampersand;
2062 case VK_ASTERISK:
2063 return GDK_asterisk;
2064 case VK_QUOTEDBL:
2065 return GDK_quotedbl;
2066 case VK_LESS:
2067 return GDK_less;
2068 case VK_GREATER:
2069 return GDK_greater;
2070 case VK_BRACELEFT:
2071 return GDK_braceleft;
2072 case VK_BRACERIGHT:
2073 return GDK_braceright;
2074 case VK_AT:
2075 return GDK_at;
2076 case VK_COLON:
2077 return GDK_colon;
2078 case VK_CIRCUMFLEX:
2079 return GDK_asciicircum;
2080 case VK_DOLLAR:
2081 return GDK_dollar;
2082 case VK_EURO_SIGN:
2083 return GDK_EuroSign;
2084 case VK_EXCLAMATION_MARK:
2085 return GDK_exclam;
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;
2092 case VK_PLUS:
2093 return GDK_plus;
2094 case VK_RIGHT_PARENTHESIS:
2095 return GDK_parenright;
2096 case VK_UNDERSCORE:
2097 return GDK_underscore;
2099 case VK_FINAL:
2100 case VK_CONVERT:
2101 case VK_NONCONVERT:
2102 case VK_ACCEPT:
2104 case VK_MODECHANGE:
2105 return GDK_Mode_switch;
2107 case VK_KANA:
2109 case VK_KANJI:
2110 return GDK_Kanji;
2112 case VK_ALPHANUMERIC:
2114 case VK_KATAKANA:
2115 return GDK_Katakana;
2116 case VK_HIRAGANA:
2117 return GDK_Hiragana;
2119 case VK_FULL_WIDTH:
2120 case VK_HALF_WIDTH:
2121 case VK_ROMAN_CHARACTERS:
2122 case VK_ALL_CANDIDATES:
2124 case VK_PREVIOUS_CANDIDATE:
2125 return GDK_PreviousCandidate;
2126 case VK_CODE_INPUT:
2127 return GDK_Codeinput;
2129 case VK_JAPANESE_KATAKANA:
2130 case VK_JAPANESE_HIRAGANA:
2131 case VK_JAPANESE_ROMAN:
2133 case VK_KANA_LOCK:
2134 return GDK_Kana_Lock;
2136 case VK_INPUT_METHOD_ON_OFF:
2137 case VK_CUT:
2138 case VK_COPY:
2139 case VK_PASTE:
2141 case VK_UNDO:
2142 return GDK_Undo;
2143 case VK_AGAIN:
2144 return GDK_Redo;
2146 case VK_FIND:
2147 case VK_PROPS:
2148 case VK_STOP:
2149 case VK_COMPOSE:
2151 case VK_ALT_GRAPH:
2152 return GDK_ISO_Level3_Shift;
2154 case VK_BEGIN:
2156 case VK_CONTEXT_MENU:
2157 return GDK_Menu;
2158 case VK_WINDOWS:
2159 return GDK_Super_R;
2161 default:
2162 return GDK_VoidSymbol;