OSDN Git Service

2004-11-30 Thomas Fitzsimmons <fitzsim@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkComponentPeer.c
1 /* gtkcomponentpeer.c -- Native implementation of GtkComponentPeer
2    Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 #include "gtkpeer.h"
40 #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
41 #include <gtk/gtkprivate.h>
42 #include <gdk/gdkkeysyms.h>
43
44 static GtkWidget *find_fg_color_widget (GtkWidget *widget);
45 static GtkWidget *find_bg_color_widget (GtkWidget *widget);
46 static gboolean focus_in_cb (GtkWidget *widget,
47                              GdkEventFocus *event,
48                              jobject peer);
49 static gboolean focus_out_cb (GtkWidget *widget,
50                               GdkEventFocus *event,
51                               jobject peer);
52
53 /*
54  * This method returns a GDK keyval that corresponds to one of the
55  * keysyms in the X keymap table.  The return value is only used to
56  * determine the keyval's corresponding hardware keycode, and doesn't
57  * reflect an accurate translation of a Java virtual key value to a
58  * GDK keyval.
59  */
60 #ifdef __GNUC__
61 __inline
62 #endif
63 static guint
64 awt_keycode_to_keysym (jint keyCode, jint keyLocation)
65 {
66   /* GDK_A through GDK_Z */
67   if (keyCode >= VK_A && keyCode <= VK_Z)
68     return gdk_keyval_to_lower (keyCode);
69
70   /* GDK_0 through GDK_9 */
71   if (keyCode >= VK_0 && keyCode <= VK_9)
72     return keyCode;
73
74   switch (keyCode)
75     {
76     case VK_ENTER:
77       return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Enter : GDK_Return;
78     case VK_BACK_SPACE:
79       return GDK_BackSpace;
80     case VK_TAB:
81       return GDK_Tab;
82     case VK_CANCEL:
83       return GDK_Cancel;
84     case VK_CLEAR:
85       return GDK_Clear;
86     case VK_SHIFT:
87       return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Shift_L : GDK_Shift_R;
88     case VK_CONTROL:
89       return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Control_L : GDK_Control_R;
90     case VK_ALT:
91       return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Alt_L : GDK_Alt_R;
92     case VK_PAUSE:
93       return GDK_Pause;
94     case VK_CAPS_LOCK:
95       return GDK_Caps_Lock;
96     case VK_ESCAPE:
97       return GDK_Escape;
98     case VK_SPACE:
99       return GDK_space;
100     case VK_PAGE_UP:
101       return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Up : GDK_Page_Up;
102     case VK_PAGE_DOWN:
103       return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Page_Down : GDK_Page_Down;
104     case VK_END:
105       return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_End : GDK_End;
106     case VK_HOME:
107       return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Home : GDK_Home;
108     case VK_LEFT:
109       return GDK_Left;
110     case VK_UP:
111       return GDK_Up;
112     case VK_RIGHT:
113       return GDK_Right;
114     case VK_DOWN:
115       return GDK_Down;
116     case VK_COMMA:
117       return GDK_comma;
118     case VK_MINUS:
119       return GDK_minus;
120     case VK_PERIOD:
121       return GDK_period;
122     case VK_SLASH:
123       return GDK_slash;
124       /*
125     case VK_0:
126     case VK_1:
127     case VK_2:
128     case VK_3:
129     case VK_4:
130     case VK_5:
131     case VK_6:
132     case VK_7:
133     case VK_8:
134     case VK_9:
135       */
136     case VK_SEMICOLON:
137       return GDK_semicolon;
138     case VK_EQUALS:
139       return GDK_equal;
140       /*
141     case VK_A:
142     case VK_B:
143     case VK_C:
144     case VK_D:
145     case VK_E:
146     case VK_F:
147     case VK_G:
148     case VK_H:
149     case VK_I:
150     case VK_J:
151     case VK_K:
152     case VK_L:
153     case VK_M:
154     case VK_N:
155     case VK_O:
156     case VK_P:
157     case VK_Q:
158     case VK_R:
159     case VK_S:
160     case VK_T:
161     case VK_U:
162     case VK_V:
163     case VK_W:
164     case VK_X:
165     case VK_Y:
166     case VK_Z:
167       */
168     case VK_OPEN_BRACKET:
169       return GDK_bracketleft;
170     case VK_BACK_SLASH:
171       return GDK_backslash;
172     case VK_CLOSE_BRACKET:
173       return GDK_bracketright;
174     case VK_NUMPAD0:
175       return GDK_KP_0;
176     case VK_NUMPAD1:
177       return GDK_KP_1;
178     case VK_NUMPAD2:
179       return GDK_KP_2;
180     case VK_NUMPAD3:
181       return GDK_KP_3;
182     case VK_NUMPAD4:
183       return GDK_KP_4;
184     case VK_NUMPAD5:
185       return GDK_KP_5;
186     case VK_NUMPAD6:
187       return GDK_KP_6;
188     case VK_NUMPAD7:
189       return GDK_KP_7;
190     case VK_NUMPAD8:
191       return GDK_KP_8;
192     case VK_NUMPAD9:
193       return GDK_KP_9;
194     case VK_MULTIPLY:
195       return GDK_KP_Multiply;
196     case VK_ADD:
197       return GDK_KP_Add;
198       /*
199     case VK_SEPARATER:
200       */
201     case VK_SEPARATOR:
202       return GDK_KP_Separator;
203     case VK_SUBTRACT:
204       return GDK_KP_Subtract;
205     case VK_DECIMAL:
206       return GDK_KP_Decimal;
207     case VK_DIVIDE:
208       return GDK_KP_Divide;
209     case VK_DELETE:
210       return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Delete : GDK_Delete;
211     case VK_NUM_LOCK:
212       return GDK_Num_Lock;
213     case VK_SCROLL_LOCK:
214       return GDK_Scroll_Lock;
215     case VK_F1:
216       return GDK_F1;
217     case VK_F2:
218       return GDK_F2;
219     case VK_F3:
220       return GDK_F3;
221     case VK_F4:
222       return GDK_F4;
223     case VK_F5:
224       return GDK_F5;
225     case VK_F6:
226       return GDK_F6;
227     case VK_F7:
228       return GDK_F7;
229     case VK_F8:
230       return GDK_F8;
231     case VK_F9:
232       return GDK_F9;
233     case VK_F10:
234       return GDK_F10;
235     case VK_F11:
236       return GDK_F11;
237     case VK_F12:
238       return GDK_F12;
239     case VK_F13:
240       return GDK_F13;
241     case VK_F14:
242       return GDK_F14;
243     case VK_F15:
244       return GDK_F15;
245     case VK_F16:
246       return GDK_F16;
247     case VK_F17:
248       return GDK_F17;
249     case VK_F18:
250       return GDK_F18;
251     case VK_F19:
252       return GDK_F19;
253     case VK_F20:
254       return GDK_F20;
255     case VK_F21:
256       return GDK_F21;
257     case VK_F22:
258       return GDK_F22;
259     case VK_F23:
260       return GDK_F23;
261     case VK_F24:
262       return GDK_F24;
263     case VK_PRINTSCREEN:
264       return GDK_Print;
265     case VK_INSERT:
266       return keyLocation == AWT_KEY_LOCATION_NUMPAD ? GDK_KP_Insert : GDK_Insert;
267     case VK_HELP:
268       return GDK_Help;
269     case VK_META:
270       return keyLocation == AWT_KEY_LOCATION_LEFT ? GDK_Meta_L : GDK_Meta_R;
271     case VK_BACK_QUOTE:
272       return GDK_grave;
273     case VK_QUOTE:
274       return GDK_apostrophe;
275     case VK_KP_UP:
276       return GDK_KP_Up;
277     case VK_KP_DOWN:
278       return GDK_KP_Down;
279     case VK_KP_LEFT:
280       return GDK_KP_Left;
281     case VK_KP_RIGHT:
282       return GDK_KP_Right;
283     case VK_DEAD_GRAVE:
284       return GDK_dead_grave;
285     case VK_DEAD_ACUTE:
286       return GDK_dead_acute;
287     case VK_DEAD_CIRCUMFLEX:
288       return GDK_dead_circumflex;
289     case VK_DEAD_TILDE:
290       return GDK_dead_tilde;
291     case VK_DEAD_MACRON:
292       return GDK_dead_macron;
293     case VK_DEAD_BREVE:
294       return GDK_dead_breve;
295     case VK_DEAD_ABOVEDOT:
296       return GDK_dead_abovedot;
297     case VK_DEAD_DIAERESIS:
298       return GDK_dead_diaeresis;
299     case VK_DEAD_ABOVERING:
300       return GDK_dead_abovering;
301     case VK_DEAD_DOUBLEACUTE:
302       return GDK_dead_doubleacute;
303     case VK_DEAD_CARON:
304       return GDK_dead_caron;
305     case VK_DEAD_CEDILLA:
306       return GDK_dead_cedilla;
307     case VK_DEAD_OGONEK:
308       return GDK_dead_ogonek;
309     case VK_DEAD_IOTA:
310       return GDK_dead_iota;
311     case VK_DEAD_VOICED_SOUND:
312       return GDK_dead_voiced_sound;
313     case VK_DEAD_SEMIVOICED_SOUND:
314       return GDK_dead_semivoiced_sound;
315     case VK_AMPERSAND:
316       return GDK_ampersand;
317     case VK_ASTERISK:
318       return GDK_asterisk;
319     case VK_QUOTEDBL:
320       return GDK_quotedbl;
321     case VK_LESS:
322       return GDK_less;
323     case VK_GREATER:
324       return GDK_greater;
325     case VK_BRACELEFT:
326       return GDK_braceleft;
327     case VK_BRACERIGHT:
328       return GDK_braceright;
329     case VK_AT:
330       return GDK_at;
331     case VK_COLON:
332       return GDK_colon;
333     case VK_CIRCUMFLEX:
334       return GDK_asciicircum;
335     case VK_DOLLAR:
336       return GDK_dollar;
337     case VK_EURO_SIGN:
338       return GDK_EuroSign;
339     case VK_EXCLAMATION_MARK:
340       return GDK_exclam;
341     case VK_INVERTED_EXCLAMATION_MARK:
342       return GDK_exclamdown;
343     case VK_LEFT_PARENTHESIS:
344       return GDK_parenleft;
345     case VK_NUMBER_SIGN:
346       return GDK_numbersign;
347     case VK_PLUS:
348       return GDK_plus;
349     case VK_RIGHT_PARENTHESIS:
350       return GDK_parenright;
351     case VK_UNDERSCORE:
352       return GDK_underscore;
353       /*
354     case VK_FINAL:
355     case VK_CONVERT:
356     case VK_NONCONVERT:
357     case VK_ACCEPT:
358       */
359     case VK_MODECHANGE:
360       return GDK_Mode_switch;
361       /*
362     case VK_KANA:
363       */
364     case VK_KANJI:
365       return GDK_Kanji;
366       /*
367     case VK_ALPHANUMERIC:
368       */
369     case VK_KATAKANA:
370       return GDK_Katakana;
371     case VK_HIRAGANA:
372       return GDK_Hiragana;
373       /*
374     case VK_FULL_WIDTH:
375     case VK_HALF_WIDTH:
376     case VK_ROMAN_CHARACTERS:
377     case VK_ALL_CANDIDATES:
378       */
379     case VK_PREVIOUS_CANDIDATE:
380       return GDK_PreviousCandidate;
381     case VK_CODE_INPUT:
382       return GDK_Codeinput;
383       /*
384     case VK_JAPANESE_KATAKANA:
385     case VK_JAPANESE_HIRAGANA:
386     case VK_JAPANESE_ROMAN:
387       */
388     case VK_KANA_LOCK:
389       return GDK_Kana_Lock;
390       /*
391     case VK_INPUT_METHOD_ON_OFF:
392     case VK_CUT:
393     case VK_COPY:
394     case VK_PASTE:
395     case VK_UNDO:
396     case VK_AGAIN:
397     case VK_FIND:
398     case VK_PROPS:
399     case VK_STOP:
400     case VK_COMPOSE:
401     case VK_ALT_GRAPH:
402       */
403     default:
404       return GDK_VoidSymbol;
405     }
406 }
407
408
409 JNIEXPORT void JNICALL 
410 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor 
411   (JNIEnv *env, jobject obj, jint type) 
412 {
413   void *ptr;
414   GtkWidget *widget;
415   GdkCursorType gdk_cursor_type;
416   GdkCursor *gdk_cursor;
417
418   ptr = NSA_GET_PTR (env, obj);
419
420   switch (type)
421     {
422     case AWT_CROSSHAIR_CURSOR:
423       gdk_cursor_type = GDK_CROSSHAIR;
424       break;
425     case AWT_TEXT_CURSOR:
426       gdk_cursor_type = GDK_XTERM;
427       break;
428     case AWT_WAIT_CURSOR:
429       gdk_cursor_type = GDK_WATCH;
430       break;
431     case AWT_SW_RESIZE_CURSOR:
432       gdk_cursor_type = GDK_BOTTOM_LEFT_CORNER;
433       break;
434     case AWT_SE_RESIZE_CURSOR:
435       gdk_cursor_type = GDK_BOTTOM_RIGHT_CORNER;
436       break;
437     case AWT_NW_RESIZE_CURSOR:
438       gdk_cursor_type = GDK_TOP_LEFT_CORNER;
439       break;
440     case AWT_NE_RESIZE_CURSOR:
441       gdk_cursor_type = GDK_TOP_RIGHT_CORNER;
442       break;
443     case AWT_N_RESIZE_CURSOR:
444       gdk_cursor_type = GDK_TOP_SIDE;
445       break;
446     case AWT_S_RESIZE_CURSOR:
447       gdk_cursor_type = GDK_BOTTOM_SIDE;
448       break;
449     case AWT_W_RESIZE_CURSOR:
450       gdk_cursor_type = GDK_LEFT_SIDE;
451       break;
452     case AWT_E_RESIZE_CURSOR:
453       gdk_cursor_type = GDK_RIGHT_SIDE;
454       break;
455     case AWT_HAND_CURSOR:
456       gdk_cursor_type = GDK_HAND2;
457       break;
458     case AWT_MOVE_CURSOR:
459       gdk_cursor_type = GDK_FLEUR;
460       break;
461     default:
462       gdk_cursor_type = GDK_LEFT_PTR;
463     }
464       
465   gdk_threads_enter ();
466
467   widget = GTK_WIDGET(ptr);
468
469   gdk_cursor = gdk_cursor_new (gdk_cursor_type);
470   gdk_window_set_cursor (widget->window, gdk_cursor);
471   gdk_cursor_destroy (gdk_cursor);
472
473   gdk_threads_leave ();
474 }
475
476 JNIEXPORT void JNICALL
477 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent
478   (JNIEnv *env, jobject obj, jobject parent)
479 {
480   void *ptr;
481   void *parent_ptr;
482   GtkWidget *widget;
483   GtkWidget *parent_widget;
484
485   ptr = NSA_GET_PTR (env, obj);
486   parent_ptr = NSA_GET_PTR (env, parent);
487
488   gdk_threads_enter ();
489
490   widget = GTK_WIDGET (ptr);
491   parent_widget = GTK_WIDGET (parent_ptr);
492
493   if (widget->parent == NULL)
494     {
495       if (GTK_IS_WINDOW (parent_widget))
496         {
497           GList *children = gtk_container_children 
498             (GTK_CONTAINER (parent_widget));
499
500           if (GTK_IS_MENU_BAR (children->data))
501             gtk_fixed_put (GTK_FIXED (children->next->data), widget, 0, 0);
502           else
503             gtk_fixed_put (GTK_FIXED (children->data), widget, 0, 0);
504         }
505       else
506         if (GTK_IS_SCROLLED_WINDOW (parent_widget))
507           {
508             gtk_scrolled_window_add_with_viewport 
509               (GTK_SCROLLED_WINDOW (parent_widget), widget);
510             gtk_viewport_set_shadow_type (GTK_VIEWPORT (widget->parent), 
511                                           GTK_SHADOW_NONE);
512
513           }
514         else
515           {
516             if (widget->parent == NULL)
517               gtk_fixed_put (GTK_FIXED (parent_widget), widget, 0, 0);
518           }
519     }
520
521   gdk_threads_leave ();
522 }
523
524 JNIEXPORT void JNICALL
525 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetSensitive
526   (JNIEnv *env, jobject obj, jboolean sensitive)
527 {
528   void *ptr;
529
530   ptr = NSA_GET_PTR (env, obj);
531
532   gdk_threads_enter ();
533
534   gtk_widget_set_sensitive (GTK_WIDGET (ptr), sensitive);
535
536   gdk_threads_leave ();
537 }
538
539 JNIEXPORT void JNICALL
540 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
541   (JNIEnv *env, jobject obj)
542 {
543   void *ptr;
544
545   ptr = NSA_GET_PTR (env, obj);
546   
547   gdk_threads_enter ();
548   gtk_widget_grab_focus (GTK_WIDGET (ptr));
549   gdk_threads_leave ();
550 }
551
552 /*
553  * Translate a Java KeyEvent object into a GdkEventKey event, then
554  * pass it to the GTK main loop for processing.
555  */
556 JNIEXPORT void JNICALL
557 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent
558   (JNIEnv *env, jobject obj, jint id, jlong when, jint mods,
559    jint keyCode, jint keyLocation)
560 {
561   void *ptr;
562   GdkEvent *event = NULL;
563   GdkKeymapKey *keymap_keys = NULL;
564   gint n_keys = 0;
565   guint lookup_keyval = 0;
566
567   ptr = NSA_GET_PTR (env, obj);
568
569   gdk_threads_enter ();
570
571   if (id == AWT_KEY_PRESSED)
572     event = gdk_event_new (GDK_KEY_PRESS);
573   else if (id == AWT_KEY_RELEASED)
574     event = gdk_event_new (GDK_KEY_RELEASE);
575   else
576     {
577       gdk_threads_leave ();
578       /* Don't send AWT KEY_TYPED events to GTK. */
579       return;
580     }
581
582   if (GTK_IS_BUTTON (ptr))
583     event->key.window = GTK_BUTTON (ptr)->event_window;
584   else if (GTK_IS_SCROLLED_WINDOW (ptr))
585     event->key.window = GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child)->window;
586   else
587     event->key.window = GTK_WIDGET (ptr)->window;
588
589   event->key.send_event = 0;
590   event->key.time = (guint32) when;
591
592   if (mods & AWT_SHIFT_DOWN_MASK)
593     event->key.state |= GDK_SHIFT_MASK;
594   if (mods & AWT_CTRL_DOWN_MASK)
595     event->key.state |= GDK_CONTROL_MASK;
596   if (mods & AWT_ALT_DOWN_MASK)
597     event->key.state |= GDK_MOD1_MASK;
598
599   /* This hack is needed because the AWT has no notion of num lock.
600      It infers numlock state from the only Java virtual keys that are
601      affected by it. */
602   if (keyCode == VK_NUMPAD9
603       || keyCode == VK_NUMPAD8
604       || keyCode == VK_NUMPAD7
605       || keyCode == VK_NUMPAD6
606       || keyCode == VK_NUMPAD5
607       || keyCode == VK_NUMPAD4
608       || keyCode == VK_NUMPAD3
609       || keyCode == VK_NUMPAD2
610       || keyCode == VK_NUMPAD1
611       || keyCode == VK_NUMPAD0
612       || keyCode == VK_DECIMAL)
613     event->key.state |= GDK_MOD2_MASK;
614
615   /* These values don't need to be filled in since GTK doesn't use
616      them. */
617   event->key.length = 0;
618   event->key.string = NULL;
619
620   lookup_keyval = awt_keycode_to_keysym (keyCode, keyLocation);
621
622   if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
623                                           lookup_keyval,
624                                           &keymap_keys,
625                                           &n_keys))
626     {
627       /* No matching keymap entry was found. */
628       g_printerr ("No matching keymap entries were found\n");
629       gdk_threads_leave ();
630       return;
631     }
632
633   /* Note: if n_keys > 1 then there are multiple hardware keycodes
634      that translate to lookup_keyval.  We arbitrarily choose the first
635      hardware keycode from the list returned by
636      gdk_keymap_get_entries_for_keyval. */
637
638   event->key.hardware_keycode = keymap_keys[0].keycode;
639   event->key.group =  keymap_keys[0].group;
640
641   g_free (keymap_keys);
642
643   if (!gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
644                                             event->key.hardware_keycode,
645                                             event->key.state,
646                                             event->key.group,
647                                             &event->key.keyval,
648                                             NULL, NULL, NULL))
649     {
650       /* No matching keyval was found. */
651       g_printerr ("No matching keyval was found\n");
652       gdk_threads_leave ();
653       return;
654     }
655
656   /*  keyevent = (GdkEventKey *) event; */
657   /*  g_printerr ("generated event: sent: %d  time: %d  state: %d  keyval: %d  length: %d  string: %s  hardware_keycode: %d  group: %d\n", keyevent->send_event, keyevent->time, keyevent->state, keyevent->keyval, keyevent->length, keyevent->string, keyevent->hardware_keycode, keyevent->group); */
658
659   /* We already received the original key event on the window itself,
660      so we don't want to resend it. */
661   if (!GTK_IS_WINDOW (ptr))
662     {
663       if (GTK_IS_SCROLLED_WINDOW (ptr))
664         gtk_widget_event (GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child), event);
665       else
666         gtk_widget_event (GTK_WIDGET (ptr), event);
667     }
668
669   gdk_threads_leave ();
670 }
671
672 /*
673  * Find the origin of a widget's window.
674  */
675 JNIEXPORT void JNICALL 
676 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetLocationOnScreen
677   (JNIEnv * env, jobject obj, jintArray jpoint)
678 {
679   void *ptr;
680   jint *point;
681
682   ptr = NSA_GET_PTR (env, obj);
683   point = (*env)->GetIntArrayElements (env, jpoint, 0);
684
685   gdk_threads_enter ();
686
687   gdk_window_get_origin (GTK_WIDGET (ptr)->window, point, point+1);
688
689   if (!GTK_IS_CONTAINER (ptr))
690     {
691       *point += GTK_WIDGET(ptr)->allocation.x;
692       *(point+1) += GTK_WIDGET(ptr)->allocation.y;
693     }
694
695   gdk_threads_leave ();
696
697   (*env)->ReleaseIntArrayElements(env, jpoint, point, 0);
698 }
699
700 /*
701  * Find this widget's current size.
702  */
703 JNIEXPORT void JNICALL 
704 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetDimensions
705   (JNIEnv *env, jobject obj, jintArray jdims)
706 {
707   void *ptr;
708   jint *dims;
709   GtkRequisition requisition;
710
711   ptr = NSA_GET_PTR (env, obj);
712
713   dims = (*env)->GetIntArrayElements (env, jdims, 0);  
714   dims[0] = dims[1] = 0;
715
716   gdk_threads_enter ();
717
718   gtk_widget_size_request (GTK_WIDGET (ptr), &requisition);
719
720   dims[0] = requisition.width;
721   dims[1] = requisition.height;
722
723   gdk_threads_leave ();
724
725   (*env)->ReleaseIntArrayElements (env, jdims, dims, 0);
726 }
727
728 /*
729  * Find this widget's preferred size.
730  */
731 JNIEXPORT void JNICALL 
732 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetPreferredDimensions
733   (JNIEnv *env, jobject obj, jintArray jdims)
734 {
735   void *ptr;
736   jint *dims;
737   GtkRequisition current_req;
738   GtkRequisition natural_req;
739
740   ptr = NSA_GET_PTR (env, obj);
741
742   dims = (*env)->GetIntArrayElements (env, jdims, 0);  
743   dims[0] = dims[1] = 0;
744
745   gdk_threads_enter ();
746
747   /* Widgets that extend GtkWindow such as GtkFileChooserDialog may have
748      a default size.  These values seem more useful then the natural
749      requisition values, particularly for GtkFileChooserDialog. */
750   if (GTK_IS_WINDOW (ptr))
751     {
752       gint width, height;
753       gtk_window_get_default_size (GTK_WINDOW (ptr), &width, &height);
754
755       dims[0] = width;
756       dims[1] = height;
757     }
758   else
759     {
760       /* Save the widget's current size request. */
761       gtk_widget_size_request (GTK_WIDGET (ptr), &current_req);
762
763       /* Get the widget's "natural" size request. */
764       gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1);
765       gtk_widget_size_request (GTK_WIDGET (ptr), &natural_req);
766
767       /* Reset the widget's size request. */
768       gtk_widget_set_size_request (GTK_WIDGET (ptr),
769                                    current_req.width, current_req.height);
770
771       dims[0] = natural_req.width;
772       dims[1] = natural_req.height;
773     }
774
775   gdk_threads_leave ();
776
777   (*env)->ReleaseIntArrayElements (env, jdims, dims, 0);
778 }
779
780 JNIEXPORT void JNICALL
781 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeBounds
782   (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
783 {
784   GtkWidget *widget;
785   void *ptr;
786
787   ptr = NSA_GET_PTR (env, obj);
788
789   gdk_threads_enter ();
790
791   widget = GTK_WIDGET (ptr);
792
793   /* We assume that -1 is a width or height and not a request for the
794      widget's natural size. */
795   width = width < 0 ? 0 : width;
796   height = height < 0 ? 0 : height;
797
798   if (GTK_IS_VIEWPORT (widget->parent))
799     gtk_widget_set_size_request (widget, width, height);
800   else
801     {
802       if (!(width == 0 && height == 0))
803         {
804           gtk_widget_set_size_request (widget, width, height);
805           if (widget->parent != NULL)
806             gtk_fixed_move (GTK_FIXED (widget->parent), widget, x, y);
807         }
808     }
809
810   gdk_threads_leave ();
811 }
812
813 JNIEXPORT jintArray JNICALL 
814 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetBackground
815   (JNIEnv *env, jobject obj)
816 {
817   void *ptr;
818   jintArray array;
819   int *rgb;
820   GdkColor bg;
821
822   ptr = NSA_GET_PTR (env, obj);
823
824   gdk_threads_enter ();
825   bg = GTK_WIDGET (ptr)->style->bg[GTK_STATE_NORMAL];
826   gdk_threads_leave ();
827
828   array = (*env)->NewIntArray (env, 3);
829   rgb = (*env)->GetIntArrayElements (env, array, NULL);
830   /* convert color data from 16 bit values down to 8 bit values */
831   rgb[0] = bg.red   >> 8;
832   rgb[1] = bg.green >> 8;
833   rgb[2] = bg.blue  >> 8;
834   (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
835
836   return array;
837 }
838
839 JNIEXPORT jintArray JNICALL 
840 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetForeground
841   (JNIEnv *env, jobject obj)
842 {
843   void *ptr;
844   jintArray array;
845   jint *rgb;
846   GdkColor fg;
847
848   ptr = NSA_GET_PTR (env, obj);
849
850   gdk_threads_enter ();
851   fg = GTK_WIDGET (ptr)->style->fg[GTK_STATE_NORMAL];
852   gdk_threads_leave ();
853
854   array = (*env)->NewIntArray (env, 3);
855   rgb = (*env)->GetIntArrayElements (env, array, NULL);
856   /* convert color data from 16 bit values down to 8 bit values */
857   rgb[0] = fg.red   >> 8;
858   rgb[1] = fg.green >> 8;
859   rgb[2] = fg.blue  >> 8;
860   (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
861
862   return array;
863 }
864
865 JNIEXPORT void JNICALL 
866 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetBackground
867   (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
868 {
869   GdkColor normal_color;
870   GdkColor active_color;
871   GtkWidget *widget;
872   void *ptr;
873
874   ptr = NSA_GET_PTR (env, obj);
875
876   normal_color.red = (red / 255.0) * 65535;
877   normal_color.green = (green / 255.0) * 65535;
878   normal_color.blue = (blue / 255.0) * 65535;
879
880   /* This calculation only approximates the active colors produced by
881      Sun's AWT. */
882   active_color.red = 0.85 * (red / 255.0) * 65535;
883   active_color.green = 0.85 * (green / 255.0) * 65535;
884   active_color.blue = 0.85 * (blue / 255.0) * 65535;
885
886   gdk_threads_enter ();
887
888   widget = find_bg_color_widget (GTK_WIDGET (ptr));
889
890   gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &normal_color);
891   gtk_widget_modify_bg (widget, GTK_STATE_ACTIVE, &active_color);
892   gtk_widget_modify_bg (widget, GTK_STATE_PRELIGHT, &normal_color);
893
894   gdk_threads_leave ();
895 }
896
897 JNIEXPORT void JNICALL 
898 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetForeground
899   (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
900 {
901   GdkColor color;
902   GtkWidget *widget;
903   void *ptr;
904
905   ptr = NSA_GET_PTR (env, obj);
906
907   color.red = (red / 255.0) * 65535;
908   color.green = (green / 255.0) * 65535;
909   color.blue = (blue / 255.0) * 65535;
910
911   gdk_threads_enter ();
912
913   widget = find_fg_color_widget (GTK_WIDGET (ptr));
914
915   gtk_widget_modify_fg (widget, GTK_STATE_NORMAL, &color);
916   gtk_widget_modify_fg (widget, GTK_STATE_ACTIVE, &color);
917   gtk_widget_modify_fg (widget, GTK_STATE_PRELIGHT, &color);
918
919   gdk_threads_leave ();
920 }
921
922 JNIEXPORT void JNICALL
923 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_show
924   (JNIEnv *env, jobject obj)
925 {
926   void *ptr;
927
928   ptr = NSA_GET_PTR (env, obj);
929
930   gdk_threads_enter();
931   gtk_widget_show (GTK_WIDGET (ptr));
932   gdk_threads_leave();
933 }
934
935 JNIEXPORT void JNICALL
936 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_hide
937   (JNIEnv *env, jobject obj)
938 {
939   void *ptr;
940
941   ptr = NSA_GET_PTR (env, obj);
942
943   gdk_threads_enter();
944   gtk_widget_hide (GTK_WIDGET (ptr));
945   gdk_threads_leave();
946 }
947
948 JNIEXPORT jboolean JNICALL 
949 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isEnabled 
950   (JNIEnv *env, jobject obj)
951 {
952   void *ptr;
953   jboolean ret_val;
954   
955   ptr = NSA_GET_PTR (env, obj);
956
957   gdk_threads_enter ();
958   ret_val = GTK_WIDGET_IS_SENSITIVE (GTK_WIDGET (ptr));
959   gdk_threads_leave ();
960
961   return ret_val;
962 }
963
964 JNIEXPORT jboolean JNICALL 
965 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isRealized
966   (JNIEnv *env, jobject obj)
967 {
968   void *ptr;
969   jboolean ret_val;
970
971   ptr = NSA_GET_PTR (env, obj);
972
973   if (ptr == NULL)
974     return FALSE;
975
976   gdk_threads_enter ();
977   ret_val = GTK_WIDGET_REALIZED (GTK_WIDGET (ptr));
978   gdk_threads_leave ();
979
980   return ret_val;
981 }
982
983 JNIEXPORT jboolean JNICALL 
984 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_modalHasGrab
985   (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)))
986 {
987   GtkWidget *widget;
988   jboolean retval;
989
990   gdk_threads_enter ();
991   widget = gtk_grab_get_current ();
992   retval = (widget && GTK_IS_WINDOW (widget) && GTK_WINDOW (widget)->modal);
993   gdk_threads_leave ();
994
995   return retval;
996 }
997
998 JNIEXPORT void JNICALL
999 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals
1000   (JNIEnv *env, jobject obj)
1001 {
1002   void *ptr;
1003   jobject *gref;
1004
1005   ptr = NSA_GET_PTR (env, obj);
1006   gref = NSA_GET_GLOBAL_REF (env, obj);
1007
1008   gdk_threads_enter ();
1009
1010   /* Connect EVENT signal, which happens _before_ any specific signal. */
1011
1012   g_signal_connect (GTK_OBJECT (ptr), "event",
1013                     G_CALLBACK (pre_event_handler), *gref);
1014
1015   g_signal_connect (G_OBJECT (ptr), "focus-in-event",
1016                     G_CALLBACK (focus_in_cb), *gref);
1017
1018   g_signal_connect (G_OBJECT (ptr), "focus-out-event",
1019                     G_CALLBACK (focus_out_cb), *gref);
1020
1021   g_signal_connect_after (G_OBJECT (ptr), "realize",
1022                           G_CALLBACK (connect_awt_hook_cb), *gref);
1023
1024   gdk_threads_leave ();
1025 }
1026
1027 static GtkWidget *
1028 find_fg_color_widget (GtkWidget *widget)
1029 {
1030   GtkWidget *fg_color_widget;
1031
1032   if (GTK_IS_EVENT_BOX (widget)
1033       || (GTK_IS_BUTTON (widget)
1034           && !GTK_IS_OPTION_MENU (widget)))
1035     fg_color_widget = gtk_bin_get_child (GTK_BIN(widget));
1036   else
1037     fg_color_widget = widget;
1038
1039   return fg_color_widget;
1040 }
1041
1042 static GtkWidget *
1043 find_bg_color_widget (GtkWidget *widget)
1044 {
1045   GtkWidget *bg_color_widget;
1046
1047   bg_color_widget = widget;
1048
1049   return bg_color_widget;
1050 }
1051
1052 static gboolean
1053 focus_in_cb (GtkWidget *widget __attribute((unused)),
1054              GdkEventFocus *event __attribute((unused)),
1055              jobject peer)
1056 {
1057   (*gdk_env)->CallVoidMethod (gdk_env, peer,
1058                               postFocusEventID,
1059                               AWT_FOCUS_GAINED,
1060                               JNI_FALSE);
1061   return FALSE;
1062 }
1063
1064 static gboolean
1065 focus_out_cb (GtkWidget *widget __attribute((unused)),
1066               GdkEventFocus *event __attribute((unused)),
1067               jobject peer)
1068 {
1069   (*gdk_env)->CallVoidMethod (gdk_env, peer,
1070                               postFocusEventID,
1071                               AWT_FOCUS_LOST,
1072                               JNI_FALSE);
1073   return FALSE;
1074 }