1 /* gtkwindowpeer.c -- Native implementation of GtkWindowPeer
2    Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
3    Free Software Foundation, Inc.
4 
5 This file is part of GNU Classpath.
6 
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.
11 
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.
16 
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.
21 
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.
26 
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. */
38 
39 
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>
46 
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
56 
57 #define AWT_FRAME_NORMAL 0
58 #define AWT_FRAME_ICONIFIED 1
59 #define AWT_FRAME_MAXIMIZED_BOTH 6
60 
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
255 
256 
257 #define AWT_KEY_CHAR_UNDEFINED 0
258 
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
264 
265 static jmethodID postKeyEventID;
266 static jmethodID postWindowEventID;
267 static jmethodID postConfigureEventID;
268 static jmethodID postInsetsChangedEventID;
269 static jmethodID windowGetWidthID;
270 static jmethodID windowGetHeightID;
271 
272 void
cp_gtk_window_init_jni(void)273 cp_gtk_window_init_jni (void)
274 {
275   jclass gtkwindowpeer;
276 
277   gtkwindowpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
278                                            "gnu/java/awt/peer/gtk/GtkWindowPeer");
279 
280   postKeyEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer,
281                                               "postKeyEvent", "(IJIICI)V");
282 
283   postWindowEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer,
284                                                  "postWindowEvent",
285                                                  "(ILjava/awt/Window;I)V");
286 
287   postConfigureEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer,
288                                                     "postConfigureEvent", "(IIII)V");
289 
290   postInsetsChangedEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer,
291                                                         "postInsetsChangedEvent",
292                                                         "(IIII)V");
293 
294   windowGetWidthID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer,
295                                                 "getWidth", "()I");
296 
297   windowGetHeightID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkwindowpeer,
298                                                  "getHeight", "()I");
299 
300   gtkwindowpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
301                                            "gnu/java/awt/peer/gtk/GtkWindowPeer");
302 }
303 
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
get_first_keyval_from_keymap(GdkEventKey * event)309 get_first_keyval_from_keymap (GdkEventKey *event)
310 {
311   guint keyval;
312   guint *keyvals;
313   gint n_entries;
314 
315   if (!gdk_keymap_get_entries_for_keycode (NULL,
316                                            event->hardware_keycode,
317                                            NULL,
318                                            &keyvals,
319                                            &n_entries))
320     {
321       /* No keyval found for hardware keycode */
322       return -1;
323     }
324   keyval = keyvals[0];
325   g_free (keyvals);
326 
327   return gdk_keyval_to_upper (keyval);
328 }
329 
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
keysym_to_awt_keycode(GdkEventKey * event)336 keysym_to_awt_keycode (GdkEventKey *event)
337 {
338   gint ukeyval;
339   guint state;
340 
341   ukeyval = get_first_keyval_from_keymap (event);
342 
343   if (ukeyval < 0)
344     return -1;
345 
346   state = event->state;
347 
348   /* VK_A through VK_Z */
349   if (ukeyval >= GDK_A && ukeyval <= GDK_Z)
350     return ukeyval;
351 
352   /* VK_0 through VK_9 */
353   if (ukeyval >= GDK_0 && ukeyval <= GDK_9)
354     return ukeyval;
355 
356   switch (ukeyval)
357     {
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;
437       /*
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;
448       */
449     case GDK_semicolon:
450       return VK_SEMICOLON;
451     case GDK_equal:
452       return VK_EQUALS;
453       /*
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;
480       */
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;
511       /*
512       return VK_SEPARATER;
513       */
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;
689       /*
690       return VK_FINAL;
691       return VK_CONVERT;
692       return VK_NONCONVERT;
693       return VK_ACCEPT;
694       */
695     case GDK_Mode_switch:
696       return VK_MODECHANGE;
697       /*
698       return VK_KANA;
699       */
700     case GDK_Kanji:
701       return VK_KANJI;
702       /*
703       return VK_ALPHANUMERIC;
704       */
705     case GDK_Katakana:
706       return VK_KATAKANA;
707     case GDK_Hiragana:
708       return VK_HIRAGANA;
709       /*
710       return VK_FULL_WIDTH;
711       return VK_HALF_WIDTH;
712       return VK_ROMAN_CHARACTERS;
713       return VK_ALL_CANDIDATES;
714       */
715     case GDK_PreviousCandidate:
716       return VK_PREVIOUS_CANDIDATE;
717     case GDK_Codeinput:
718       return VK_CODE_INPUT;
719       /*
720       return VK_JAPANESE_KATAKANA;
721       return VK_JAPANESE_HIRAGANA;
722       return VK_JAPANESE_ROMAN;
723       */
724     case GDK_Kana_Lock:
725       return VK_KANA_LOCK;
726       /*
727       return VK_INPUT_METHOD_ON_OFF;
728       return VK_CUT;
729       return VK_COPY;
730       return VK_PASTE;
731       */
732     case GDK_Undo:
733       return VK_UNDO;
734     case GDK_Redo:
735       return VK_AGAIN;
736       /*
737       return VK_FIND;
738       return VK_PROPS;
739       return VK_STOP;
740       return VK_COMPOSE;
741       */
742     case GDK_ISO_Level3_Shift:
743       return VK_ALT_GRAPH;
744       /*
745 	case VK_BEGIN:
746       */
747     case GDK_Menu:
748       return VK_CONTEXT_MENU;
749     case GDK_Super_L:
750     case GDK_Super_R:
751       return VK_WINDOWS;
752 
753     default:
754       return VK_UNDEFINED;
755     }
756 }
757 
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
keysym_to_awt_keylocation(GdkEventKey * event)761 keysym_to_awt_keylocation (GdkEventKey *event)
762 {
763   gint ukeyval;
764 
765   ukeyval = get_first_keyval_from_keymap (event);
766 
767   if (ukeyval < 0)
768     return -1;
769 
770   /* VK_A through VK_Z */
771   if (ukeyval >= GDK_A && ukeyval <= GDK_Z)
772     return AWT_KEY_LOCATION_STANDARD;
773 
774   /* VK_0 through VK_9 */
775   if (ukeyval >= GDK_0 && ukeyval <= GDK_9)
776     return AWT_KEY_LOCATION_STANDARD;
777 
778   switch (ukeyval)
779     {
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;
785 
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;
791 
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;
892 
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;
923 
924     default:
925       return AWT_KEY_LOCATION_UNKNOWN;
926     }
927 }
928 
929 static jchar
keyevent_to_awt_keychar(GdkEventKey * event)930 keyevent_to_awt_keychar (GdkEventKey *event)
931 {
932   if (event->length > 0)
933     {
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];
939     }
940   else
941     {
942       switch (event->keyval)
943         {
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;
953         }
954     }
955 }
956 
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
keyevent_state_to_awt_mods(GdkEventKey * event)966 keyevent_state_to_awt_mods (GdkEventKey *event)
967 {
968   jint result = 0;
969   guint state;
970 
971   if (event->type == GDK_KEY_PRESS)
972     {
973       state = event->state;
974 
975       if (event->keyval == GDK_Shift_L
976           || event->keyval == GDK_Shift_R)
977         result |= AWT_SHIFT_DOWN_MASK | AWT_SHIFT_MASK;
978       else
979         {
980           if (state & GDK_SHIFT_MASK)
981             result |= AWT_SHIFT_DOWN_MASK | AWT_SHIFT_MASK;
982         }
983 
984       if (event->keyval == GDK_Control_L
985           || event->keyval == GDK_Control_R)
986         result |= AWT_CTRL_DOWN_MASK | AWT_CTRL_MASK;
987       else
988         {
989           if (state & GDK_CONTROL_MASK)
990             result |= AWT_CTRL_DOWN_MASK | AWT_CTRL_MASK;
991         }
992 
993       if (event->keyval == GDK_Alt_L
994           || event->keyval == GDK_Alt_R)
995         result |= AWT_ALT_DOWN_MASK | AWT_ALT_MASK;
996       else
997         {
998           if (state & GDK_MOD1_MASK)
999             result |= AWT_ALT_DOWN_MASK | AWT_ALT_MASK;
1000         }
1001     }
1002   else if (event->type == GDK_KEY_RELEASE)
1003     {
1004       state = event->state;
1005 
1006       if (event->keyval != GDK_Shift_L
1007           && event->keyval != GDK_Shift_R)
1008         {
1009           if (state & GDK_SHIFT_MASK)
1010             result |= AWT_SHIFT_DOWN_MASK | AWT_SHIFT_MASK;
1011         }
1012       if (event->keyval != GDK_Control_L
1013           && event->keyval != GDK_Control_R)
1014         {
1015           if (state & GDK_CONTROL_MASK)
1016             result |= AWT_CTRL_DOWN_MASK | AWT_CTRL_MASK;
1017         }
1018 
1019       if (event->keyval != GDK_Alt_L
1020           && event->keyval != GDK_Alt_R)
1021         {
1022           if (state & GDK_MOD1_MASK)
1023             result |= AWT_ALT_DOWN_MASK | AWT_ALT_MASK;
1024         }
1025     }
1026 
1027   return result;
1028 }
1029 
1030 static gboolean window_configure_cb (GtkWidget *widget,
1031                                      GdkEventConfigure *event,
1032                                      jobject peer);
1033 
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. */
1037 
1038 static void window_get_frame_extents (GtkWidget *window,
1039                                       int *top, int *left,
1040                                       int *bottom, int *right);
1041 
1042 static void request_frame_extents (GtkWidget *window);
1043 
1044 static Bool property_notify_predicate (Display *display,
1045                                        XEvent  *xevent,
1046                                        XPointer arg);
1047 
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);
1068 
1069 static gboolean
window_configure_cb(GtkWidget * widget,GdkEventConfigure * event,jobject peer)1070 window_configure_cb (GtkWidget *widget __attribute__((unused)),
1071                      GdkEventConfigure *event,
1072                      jobject peer)
1073 {
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);
1080 
1081   return FALSE;
1082 }
1083 
1084 static gboolean
key_press_cb(GtkWidget * widget,GdkEventKey * event,jobject peer)1085 key_press_cb (GtkWidget *widget __attribute__((unused)),
1086               GdkEventKey *event,
1087               jobject peer)
1088 {
1089   jint keycode;
1090   jint keylocation;
1091 
1092   keycode = keysym_to_awt_keycode (event);
1093   keylocation = keysym_to_awt_keylocation (event);
1094 
1095   /* Return immediately if an error occurs translating a hardware
1096      keycode to a keyval. */
1097   if (keycode < 0 || keylocation < 0)
1098     return TRUE;
1099 
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);
1108 
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;
1115 }
1116 
1117 
1118 static gboolean
key_release_cb(GtkWidget * widget,GdkEventKey * event,jobject peer)1119 key_release_cb (GtkWidget *widget __attribute__((unused)),
1120                 GdkEventKey *event,
1121                 jobject peer)
1122 {
1123   jint keycode;
1124   jint keylocation;
1125 
1126   keycode = keysym_to_awt_keycode (event);
1127   keylocation = keysym_to_awt_keylocation (event);
1128 
1129   /* Return immediately if an error occurs translating a hardware
1130      keycode to a keyval. */
1131   if (keycode < 0 || keylocation < 0)
1132     return TRUE;
1133 
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);
1142 
1143   return TRUE;
1144 }
1145 
1146 /* Union used for type punning. */
1147 union extents_union
1148 {
1149   guchar **gu_extents;
1150   unsigned long **extents;
1151 };
1152 
1153 union atom_list_union
1154 {
1155   guchar **gu_extents;
1156   Atom **atom_list;
1157 };
1158 
1159 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create(JNIEnv * env,jobject obj,jint type,jboolean decorated,jobject parent)1160 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
1161   (JNIEnv *env, jobject obj, jint type, jboolean decorated, jobject parent)
1162 {
1163   GtkWidget *window_widget;
1164   GtkWindow *window;
1165   void *window_parent;
1166   GtkWidget *fixed;
1167 
1168   gdk_threads_enter ();
1169 
1170   gtkpeer_set_global_ref (env, obj);
1171 
1172   window_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1173   window = GTK_WINDOW (window_widget);
1174 
1175   /* Keep this window in front of its parent, if it has one. */
1176   if (parent)
1177     {
1178       window_parent = gtkpeer_get_widget (env, parent);
1179       gtk_window_set_transient_for (window, GTK_WINDOW(window_parent));
1180     }
1181 
1182   gtk_window_set_decorated (window, decorated);
1183 
1184   gtk_window_set_type_hint (window, type);
1185 
1186   gtk_window_group_add_window (cp_gtk_global_window_group, window);
1187 
1188   fixed = gtk_fixed_new ();
1189 
1190   gtk_container_add (GTK_CONTAINER (window_widget), fixed);
1191 
1192   gtk_widget_show (fixed);
1193 
1194   gtkpeer_set_widget (env, obj, window_widget);
1195 
1196   gdk_threads_leave ();
1197 }
1198 
1199 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle(JNIEnv * env,jobject obj,jstring title)1200 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle
1201   (JNIEnv *env, jobject obj, jstring title)
1202 {
1203   const char *c_title;
1204   void *ptr;
1205 
1206   gdk_threads_enter ();
1207 
1208   ptr = gtkpeer_get_widget (env, obj);
1209 
1210   c_title = (*env)->GetStringUTFChars (env, title, NULL);
1211 
1212   gtk_window_set_title (GTK_WINDOW (ptr), c_title);
1213 
1214   (*env)->ReleaseStringUTFChars (env, title, c_title);
1215 
1216   gdk_threads_leave ();
1217 }
1218 
1219 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable(JNIEnv * env,jobject obj,jboolean resizable)1220 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable
1221   (JNIEnv *env, jobject obj, jboolean resizable)
1222 {
1223   void *ptr;
1224 
1225   gdk_threads_enter ();
1226 
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);
1230 
1231   gdk_threads_leave ();
1232 }
1233 
1234 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal(JNIEnv * env,jobject obj,jboolean modal)1235 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal
1236   (JNIEnv *env, jobject obj, jboolean modal)
1237 {
1238   void *ptr;
1239 
1240   gdk_threads_enter ();
1241 
1242   ptr = gtkpeer_get_widget (env, obj);
1243 
1244   gtk_window_set_modal (GTK_WINDOW (ptr), modal);
1245 
1246   gdk_threads_leave ();
1247 }
1248 
1249 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetAlwaysOnTop(JNIEnv * env,jobject obj,jboolean alwaysOnTop)1250 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetAlwaysOnTop
1251   (JNIEnv *env, jobject obj, jboolean alwaysOnTop)
1252 {
1253   void *ptr;
1254 
1255   gdk_threads_enter ();
1256 
1257   ptr = gtkpeer_get_widget (env, obj);
1258 
1259   gtk_window_set_keep_above (GTK_WINDOW (ptr), alwaysOnTop);
1260 
1261   gdk_threads_leave ();
1262 }
1263 
1264 JNIEXPORT jboolean JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowHasFocus(JNIEnv * env,jobject obj)1265 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowHasFocus
1266 (JNIEnv *env, jobject obj)
1267 {
1268   void *ptr;
1269   jboolean retval;
1270 
1271   gdk_threads_enter ();
1272 
1273   ptr = gtkpeer_get_widget (env, obj);
1274 
1275   retval = gtk_window_has_toplevel_focus (GTK_WINDOW (ptr));
1276 
1277   gdk_threads_leave ();
1278   return retval;
1279 }
1280 
1281 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNative(JNIEnv * env,jobject obj,jboolean visible)1282 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNative
1283   (JNIEnv *env, jobject obj, jboolean visible)
1284 {
1285   gdk_threads_enter ();
1286 
1287   Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNativeUnlocked
1288     (env, obj, visible);
1289 
1290   gdk_flush ();
1291 
1292   gdk_threads_leave ();
1293 }
1294 
1295 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNativeUnlocked(JNIEnv * env,jobject obj,jboolean visible)1296 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNativeUnlocked
1297   (JNIEnv *env, jobject obj, jboolean visible)
1298 {
1299   void *ptr;
1300 
1301   ptr = gtkpeer_get_widget (env, obj);
1302 
1303   if (visible)
1304     gtk_widget_show (GTK_WIDGET (ptr));
1305   else
1306     gtk_widget_hide (GTK_WIDGET (ptr));
1307 }
1308 
1309 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals(JNIEnv * env,jobject obj)1310 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_connectSignals
1311   (JNIEnv *env, jobject obj)
1312 {
1313   void *ptr;
1314   jobject gref;
1315 
1316   gdk_threads_enter ();
1317 
1318   ptr = gtkpeer_get_widget (env, obj);
1319   gref = (jobject) gtkpeer_get_global_ref (env, obj);
1320 
1321   g_signal_connect (G_OBJECT (ptr), "delete-event",
1322 		    G_CALLBACK (window_delete_cb), gref);
1323 
1324   g_signal_connect (G_OBJECT (ptr), "destroy-event",
1325 		    G_CALLBACK (window_destroy_cb), gref);
1326 
1327   g_signal_connect (G_OBJECT (ptr), "notify::has-toplevel-focus",
1328   		    G_CALLBACK (window_focus_state_change_cb), gref);
1329 
1330   g_signal_connect (G_OBJECT (ptr), "focus-in-event",
1331                     G_CALLBACK (window_focus_in_cb), gref);
1332 
1333   g_signal_connect (G_OBJECT (ptr), "focus-out-event",
1334                     G_CALLBACK (window_focus_out_cb), gref);
1335 
1336   g_signal_connect (G_OBJECT (ptr), "window-state-event",
1337 		    G_CALLBACK (window_window_state_cb), gref);
1338 
1339   g_signal_connect (G_OBJECT (ptr), "property-notify-event",
1340 		    G_CALLBACK (window_property_changed_cb), gref);
1341 
1342   g_signal_connect_after (G_OBJECT (ptr), "realize",
1343                           G_CALLBACK (realize_cb), gref);
1344 
1345   g_signal_connect (G_OBJECT (ptr), "key-press-event",
1346                     G_CALLBACK (key_press_cb), gref);
1347 
1348   g_signal_connect (G_OBJECT (ptr), "key-release-event",
1349                     G_CALLBACK (key_release_cb), gref);
1350 
1351   g_signal_connect_after (G_OBJECT (ptr), "window-state-event",
1352                           G_CALLBACK (window_window_state_cb), gref);
1353 
1354   g_signal_connect (G_OBJECT (ptr), "configure-event",
1355                     G_CALLBACK (window_configure_cb), gref);
1356 
1357   cp_gtk_component_connect_expose_signals (ptr, gref);
1358   cp_gtk_component_connect_mouse_signals (ptr, gref);
1359 
1360   /* FIXME: override focus signals here to prevent child fixed repaint? */
1361 
1362   gdk_threads_leave ();
1363 }
1364 
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
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_realize(JNIEnv * env,jobject obj)1369 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_realize (JNIEnv *env, jobject obj)
1370 {
1371   void *ptr;
1372 
1373   gdk_threads_enter ();
1374 
1375   ptr = gtkpeer_get_widget (env, obj);
1376 
1377   gtk_widget_realize (GTK_WIDGET (ptr));
1378 
1379   gdk_threads_leave ();
1380 }
1381 
1382 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack(JNIEnv * env,jobject obj)1383 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toBack (JNIEnv *env,
1384     jobject obj)
1385 {
1386   void *ptr;
1387 
1388   gdk_threads_enter ();
1389 
1390   ptr = gtkpeer_get_widget (env, obj);
1391 
1392   gdk_window_lower (GTK_WIDGET (ptr)->window);
1393   gdk_flush ();
1394 
1395   gdk_threads_leave ();
1396 }
1397 
1398 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront(JNIEnv * env,jobject obj)1399 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_toFront (JNIEnv *env,
1400     jobject obj)
1401 {
1402   void *ptr;
1403 
1404   gdk_threads_enter ();
1405 
1406   ptr = gtkpeer_get_widget (env, obj);
1407 
1408   gdk_window_raise (GTK_WIDGET (ptr)->window);
1409   gdk_flush ();
1410 
1411   gdk_threads_leave ();
1412 }
1413 
1414 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize(JNIEnv * env,jobject obj,jint width,jint height)1415 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setSize
1416   (JNIEnv *env, jobject obj, jint width, jint height)
1417 {
1418   void *ptr;
1419 
1420   gdk_threads_enter ();
1421 
1422   ptr = gtkpeer_get_widget (env, obj);
1423 
1424   /* Avoid GTK runtime assertion failures. */
1425   width = (width < 1) ? 1 : width;
1426   height = (height < 1) ? 1 : height;
1427 
1428   gtk_widget_set_size_request (GTK_WIDGET(ptr), width, height);
1429 
1430   gdk_threads_leave ();
1431 }
1432 
1433 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds(JNIEnv * env,jobject obj,jint x,jint y,jint width,jint height)1434 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBounds
1435   (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
1436 {
1437   gdk_threads_enter ();
1438 
1439   Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBoundsUnlocked
1440     (env, obj, x, y, width, height);
1441 
1442   gdk_threads_leave ();
1443 }
1444 
1445 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocationUnlocked(JNIEnv * env,jobject obj,jint x,jint y)1446 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocationUnlocked
1447   (JNIEnv *env, jobject obj, jint x, jint y)
1448 {
1449   void *ptr;
1450 
1451   ptr = gtkpeer_get_widget (env, obj);
1452 
1453   gtk_window_move (GTK_WINDOW(ptr), x, y);
1454 
1455   if (GTK_WIDGET (ptr)->window != NULL)
1456     gdk_window_move (GTK_WIDGET (ptr)->window, x, y);
1457 }
1458 
1459 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocation(JNIEnv * env,jobject obj,jint x,jint y)1460 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocation
1461   (JNIEnv *env, jobject obj, jint x, jint y)
1462 {
1463   gdk_threads_enter ();
1464 
1465   Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetLocationUnlocked
1466     (env, obj, x, y);
1467 
1468   gdk_threads_leave ();
1469 }
1470 
1471 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBoundsUnlocked(JNIEnv * env,jobject obj,jint x,jint y,jint width,jint height)1472 Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetBoundsUnlocked
1473   (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
1474 {
1475   void *ptr;
1476   gint current_width;
1477   gint current_height;
1478 
1479   ptr = gtkpeer_get_widget (env, obj);
1480 
1481   /* Avoid GTK runtime assertion failures. */
1482   width = (width < 1) ? 1 : width;
1483   height = (height < 1) ? 1 : height;
1484 
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:
1489 
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
1495 
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);
1500 
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)
1506     {
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);
1513     }
1514 }
1515 
1516 static void
window_get_frame_extents(GtkWidget * window,int * top,int * left,int * bottom,int * right)1517 window_get_frame_extents (GtkWidget *window,
1518                           int *top, int *left, int *bottom, int *right)
1519 {
1520   unsigned long *extents = NULL;
1521   union extents_union gu_ex;
1522 
1523   /* Guess frame extents in case _NET_FRAME_EXTENTS is not
1524      supported. */
1525   if (!gtk_window_get_decorated (GTK_WINDOW (window)))
1526     {
1527       *top = 0;
1528       *left = 0;
1529       *bottom = 0;
1530       *right = 0;
1531 
1532       return;
1533     }
1534 
1535   *top = 23;
1536   *left = 6;
1537   *bottom = 6;
1538   *right = 6;
1539 
1540   /* Request that the window manager set window's
1541      _NET_FRAME_EXTENTS property. */
1542   request_frame_extents (window);
1543 
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),
1549                         0,
1550                         sizeof (unsigned long) * 4,
1551                         FALSE,
1552                         NULL,
1553                         NULL,
1554                         NULL,
1555                         gu_ex.gu_extents))
1556     {
1557       *left = extents [0];
1558       *right = extents [1];
1559       *top = extents [2];
1560       *bottom = extents [3];
1561     }
1562 }
1563 
1564 static Atom extents_atom = 0;
1565 
1566 /* Requests that the window manager set window's
1567    _NET_FRAME_EXTENTS property. */
1568 static void
request_frame_extents(GtkWidget * window)1569 request_frame_extents (GtkWidget *window)
1570 {
1571   const char *request_str = "_NET_REQUEST_FRAME_EXTENTS";
1572   GdkAtom request_extents = gdk_atom_intern (request_str, FALSE);
1573 
1574   /* Check if the current window manager supports
1575      _NET_REQUEST_FRAME_EXTENTS. */
1576   if (gdk_net_wm_supports (request_extents))
1577     {
1578       GdkDisplay *display = gtk_widget_get_display (window);
1579       Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1580 
1581       GdkWindow *root_window = gdk_get_default_root_window ();
1582       Window xroot_window = GDK_WINDOW_XID (root_window);
1583 
1584       Atom extents_request_atom =
1585 	gdk_x11_get_xatom_by_name_for_display (display, request_str);
1586 
1587       XEvent xevent;
1588       XEvent notify_xevent;
1589 
1590       unsigned long window_id = GDK_WINDOW_XID (GDK_DRAWABLE(window->window));
1591 
1592       if (!extents_atom)
1593 	{
1594 	  const char *extents_str = "_NET_FRAME_EXTENTS";
1595 	  extents_atom =
1596 	    gdk_x11_get_xatom_by_name_for_display (display, extents_str);
1597 	}
1598 
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;
1609 
1610       XSendEvent (xdisplay, xroot_window, False,
1611 		  (SubstructureRedirectMask | SubstructureNotifyMask),
1612                   &xevent);
1613 
1614       XIfEvent(xdisplay, &notify_xevent,
1615 	       property_notify_predicate, (XPointer) &window_id);
1616     }
1617 }
1618 
1619 static Bool
property_notify_predicate(Display * xdisplay,XEvent * event,XPointer window_id)1620 property_notify_predicate (Display *xdisplay __attribute__((unused)),
1621                            XEvent  *event,
1622                            XPointer window_id)
1623 {
1624   unsigned long *window = (unsigned long *) window_id;
1625 
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;
1632 }
1633 
1634 static gboolean
window_delete_cb(GtkWidget * widget,GdkEvent * event,jobject peer)1635 window_delete_cb (GtkWidget *widget __attribute__((unused)),
1636 		  GdkEvent *event __attribute__((unused)),
1637 		  jobject peer)
1638 {
1639   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1640 			      postWindowEventID,
1641 			      (jint) AWT_WINDOW_CLOSING,
1642 			      (jobject) NULL, (jint) 0);
1643 
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;
1649 }
1650 
1651 static void
window_destroy_cb(GtkWidget * widget,GdkEvent * event,jobject peer)1652 window_destroy_cb (GtkWidget *widget __attribute__((unused)),
1653 		   GdkEvent *event __attribute__((unused)),
1654 		   jobject peer)
1655 {
1656   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1657 			      postWindowEventID,
1658 			      (jint) AWT_WINDOW_CLOSED,
1659 			      (jobject) NULL, (jint) 0);
1660 }
1661 
1662 static void
window_focus_state_change_cb(GtkWidget * widget,GParamSpec * pspec,jobject peer)1663 window_focus_state_change_cb (GtkWidget *widget,
1664 			      GParamSpec *pspec __attribute__((unused)),
1665 			      jobject peer)
1666 {
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);
1677 }
1678 
1679 static gboolean
window_focus_in_cb(GtkWidget * widget,GdkEventFocus * event,jobject peer)1680 window_focus_in_cb (GtkWidget * widget  __attribute__((unused)),
1681 		    GdkEventFocus *event  __attribute__((unused)),
1682 		    jobject peer)
1683 {
1684   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1685                               postWindowEventID,
1686                               (jint) AWT_WINDOW_GAINED_FOCUS,
1687                               (jobject) NULL, (jint) 0);
1688 
1689   return FALSE;
1690 }
1691 
1692 static gboolean
window_focus_out_cb(GtkWidget * widget,GdkEventFocus * event,jobject peer)1693 window_focus_out_cb (GtkWidget * widget __attribute__((unused)),
1694 		     GdkEventFocus *event __attribute__((unused)),
1695 		     jobject peer)
1696 {
1697   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1698                               postWindowEventID,
1699                               (jint) AWT_WINDOW_LOST_FOCUS,
1700                               (jobject) NULL, (jint) 0);
1701 
1702   return FALSE;
1703 }
1704 
1705 static gboolean
window_window_state_cb(GtkWidget * widget,GdkEvent * event,jobject peer)1706 window_window_state_cb (GtkWidget *widget __attribute__((unused)),
1707 			GdkEvent *event,
1708 			jobject peer)
1709 {
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;
1723 
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);
1728 
1729   return TRUE;
1730 }
1731 
1732 static gboolean
window_property_changed_cb(GtkWidget * widget,GdkEventProperty * event,jobject peer)1733 window_property_changed_cb (GtkWidget *widget __attribute__((unused)),
1734                             GdkEventProperty *event,
1735                             jobject peer)
1736 {
1737   unsigned long *extents;
1738   union extents_union gu_ex;
1739 
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),
1745                            0,
1746                            sizeof (unsigned long) * 4,
1747                            FALSE,
1748                            NULL,
1749                            NULL,
1750                            NULL,
1751                            gu_ex.gu_extents))
1752     {
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 */
1759     }
1760 
1761 
1762   return FALSE;
1763 }
1764 
1765 static void
realize_cb(GtkWidget * widget,jobject peer)1766 realize_cb (GtkWidget *widget, jobject peer)
1767 {
1768   jint top = 0;
1769   jint left = 0;
1770   jint bottom = 0;
1771   jint right = 0;
1772   jint width = 0;
1773   jint height = 0;
1774 
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);
1777 
1778   window_get_frame_extents (widget, &top, &left, &bottom, &right);
1779 
1780   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1781 				postInsetsChangedEventID,
1782 				top, left, bottom, right);
1783 
1784   gtk_window_set_default_size (GTK_WINDOW (widget),
1785 			       MAX (1, width - left - right),
1786 			       MAX (1, height - top - bottom));
1787 
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));
1792 
1793   gtk_window_resize (GTK_WINDOW (widget),
1794 		     MAX (1, width - left - right),
1795 		     MAX (1, height - top - bottom));
1796 }
1797 
1798 /*
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.
1804  */
1805 #ifdef __GNUC__
1806 __inline
1807 #endif
1808 guint
cp_gtk_awt_keycode_to_keysym(jint keyCode,jint keyLocation)1809 cp_gtk_awt_keycode_to_keysym (jint keyCode, jint keyLocation)
1810 {
1811   /* GDK_A through GDK_Z */
1812   if (keyCode >= VK_A && keyCode <= VK_Z)
1813     return gdk_keyval_to_lower (keyCode);
1814 
1815   /* GDK_0 through GDK_9 */
1816   if (keyCode >= VK_0 && keyCode <= VK_9)
1817     return keyCode;
1818 
1819   switch (keyCode)
1820     {
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;
1869       /*
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:
1880       */
1881     case VK_SEMICOLON:
1882       return GDK_semicolon;
1883     case VK_EQUALS:
1884       return GDK_equal;
1885       /*
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:
1912       */
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;
1943       /*
1944     case VK_SEPARATER:
1945       */
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;
2098       /*
2099     case VK_FINAL:
2100     case VK_CONVERT:
2101     case VK_NONCONVERT:
2102     case VK_ACCEPT:
2103       */
2104     case VK_MODECHANGE:
2105       return GDK_Mode_switch;
2106       /*
2107     case VK_KANA:
2108       */
2109     case VK_KANJI:
2110       return GDK_Kanji;
2111       /*
2112     case VK_ALPHANUMERIC:
2113       */
2114     case VK_KATAKANA:
2115       return GDK_Katakana;
2116     case VK_HIRAGANA:
2117       return GDK_Hiragana;
2118       /*
2119     case VK_FULL_WIDTH:
2120     case VK_HALF_WIDTH:
2121     case VK_ROMAN_CHARACTERS:
2122     case VK_ALL_CANDIDATES:
2123       */
2124     case VK_PREVIOUS_CANDIDATE:
2125       return GDK_PreviousCandidate;
2126     case VK_CODE_INPUT:
2127       return GDK_Codeinput;
2128       /*
2129     case VK_JAPANESE_KATAKANA:
2130     case VK_JAPANESE_HIRAGANA:
2131     case VK_JAPANESE_ROMAN:
2132       */
2133     case VK_KANA_LOCK:
2134       return GDK_Kana_Lock;
2135       /*
2136     case VK_INPUT_METHOD_ON_OFF:
2137     case VK_CUT:
2138     case VK_COPY:
2139     case VK_PASTE:
2140       */
2141     case VK_UNDO:
2142       return GDK_Undo;
2143     case VK_AGAIN:
2144       return GDK_Redo;
2145       /*
2146     case VK_FIND:
2147     case VK_PROPS:
2148     case VK_STOP:
2149     case VK_COMPOSE:
2150       */
2151     case VK_ALT_GRAPH:
2152       return GDK_ISO_Level3_Shift;
2153       /*
2154 	case VK_BEGIN:
2155       */
2156     case VK_CONTEXT_MENU:
2157       return GDK_Menu;
2158     case VK_WINDOWS:
2159       return GDK_Super_R;
2160 
2161     default:
2162       return GDK_VoidSymbol;
2163     }
2164 }
2165