Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkComponentPeer.c
blob6de7b61b8e9623ba024261cfe89078a8d2e1a3c7
1 /* gtkcomponentpeer.c -- Native implementation of GtkComponentPeer
2 Copyright (C) 1998, 1999, 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
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.
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. */
39 #include "gtkpeer.h"
40 #include "gnu_java_awt_peer_gtk_GtkComponentPeer.h"
42 #include <gtk/gtkprivate.h>
44 #define AWT_DEFAULT_CURSOR 0
45 #define AWT_CROSSHAIR_CURSOR 1
46 #define AWT_TEXT_CURSOR 2
47 #define AWT_WAIT_CURSOR 3
48 #define AWT_SW_RESIZE_CURSOR 4
49 #define AWT_SE_RESIZE_CURSOR 5
50 #define AWT_NW_RESIZE_CURSOR 6
51 #define AWT_NE_RESIZE_CURSOR 7
52 #define AWT_N_RESIZE_CURSOR 8
53 #define AWT_S_RESIZE_CURSOR 9
54 #define AWT_W_RESIZE_CURSOR 10
55 #define AWT_E_RESIZE_CURSOR 11
56 #define AWT_HAND_CURSOR 12
57 #define AWT_MOVE_CURSOR 13
59 /* FIXME: use gtk-double-click-time, gtk-double-click-distance */
60 #define MULTI_CLICK_TIME 250
61 /* as opposed to a MULTI_PASS_TIME :) */
63 #define AWT_MOUSE_CLICKED 500
64 #define AWT_MOUSE_PRESSED 501
65 #define AWT_MOUSE_RELEASED 502
66 #define AWT_MOUSE_MOVED 503
67 #define AWT_MOUSE_ENTERED 504
68 #define AWT_MOUSE_EXITED 505
69 #define AWT_MOUSE_DRAGGED 506
71 #define AWT_FOCUS_GAINED 1004
72 #define AWT_FOCUS_LOST 1005
74 static GtkWidget *find_fg_color_widget (GtkWidget *widget);
75 static GtkWidget *find_bg_color_widget (GtkWidget *widget);
77 static jmethodID postMouseEventID;
78 static jmethodID setCursorID;
79 static jmethodID postExposeEventID;
80 static jmethodID postFocusEventID;
82 void
83 cp_gtk_component_init_jni (void)
85 jclass gtkcomponentpeer;
87 gtkcomponentpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
88 "gnu/java/awt/peer/gtk/GtkComponentPeer");
90 postMouseEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer,
91 "postMouseEvent", "(IJIIIIZ)V");
93 setCursorID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer,
94 "setCursor", "()V");
96 postExposeEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer,
97 "postExposeEvent", "(IIII)V");
99 postFocusEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer,
100 "postFocusEvent", "(IZ)V");
103 static gboolean component_button_press_cb (GtkWidget *widget,
104 GdkEventButton *event,
105 jobject peer);
106 static gboolean component_button_release_cb (GtkWidget *widget,
107 GdkEventButton *event,
108 jobject peer);
109 static gboolean component_motion_notify_cb (GtkWidget *widget,
110 GdkEventMotion *event,
111 jobject peer);
112 static gboolean component_enter_notify_cb (GtkWidget *widget,
113 GdkEventCrossing *event,
114 jobject peer);
115 static gboolean component_leave_notify_cb (GtkWidget *widget,
116 GdkEventCrossing *event,
117 jobject peer);
118 static gboolean component_expose_cb (GtkWidget *widget,
119 GdkEventExpose *event,
120 jobject peer);
121 static gboolean component_focus_in_cb (GtkWidget *widget,
122 GdkEventFocus *event,
123 jobject peer);
124 static gboolean component_focus_out_cb (GtkWidget *widget,
125 GdkEventFocus *event,
126 jobject peer);
128 static jint
129 button_to_awt_mods (int button)
131 switch (button)
133 case 1:
134 return AWT_BUTTON1_DOWN_MASK | AWT_BUTTON1_MASK;
135 case 2:
136 return AWT_BUTTON2_DOWN_MASK | AWT_BUTTON2_MASK;
137 case 3:
138 return AWT_BUTTON3_DOWN_MASK | AWT_BUTTON3_MASK;
141 return 0;
144 jint
145 cp_gtk_state_to_awt_mods (guint state)
147 jint result = 0;
149 if (state & GDK_SHIFT_MASK)
150 result |= (AWT_SHIFT_DOWN_MASK | AWT_SHIFT_MASK);
151 if (state & GDK_CONTROL_MASK)
152 result |= (AWT_CTRL_DOWN_MASK | AWT_CTRL_MASK);
153 if (state & GDK_MOD1_MASK)
154 result |= (AWT_ALT_DOWN_MASK | AWT_ALT_MASK);
156 return result;
159 static jint
160 state_to_awt_mods_with_button_states (guint state)
162 jint result = 0;
164 if (state & GDK_SHIFT_MASK)
165 result |= AWT_SHIFT_DOWN_MASK | AWT_SHIFT_MASK;
166 if (state & GDK_CONTROL_MASK)
167 result |= AWT_CTRL_DOWN_MASK | AWT_CTRL_MASK;
168 if (state & GDK_MOD1_MASK)
169 result |= AWT_ALT_DOWN_MASK | AWT_ALT_MASK;
170 if (state & GDK_BUTTON1_MASK)
171 result |= AWT_BUTTON1_DOWN_MASK | AWT_BUTTON1_MASK;
172 if (state & GDK_BUTTON2_MASK)
173 result |= AWT_BUTTON2_DOWN_MASK;
174 if (state & GDK_BUTTON3_MASK)
175 result |= AWT_BUTTON3_DOWN_MASK;
177 return result;
180 JNIEXPORT void JNICALL
181 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor
182 (JNIEnv *env, jobject obj, jint type)
184 gdk_threads_enter ();
186 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursorUnlocked
187 (env, obj, type);
189 gdk_threads_leave ();
192 JNIEXPORT void JNICALL
193 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursorUnlocked
194 (JNIEnv *env, jobject obj, jint type)
196 void *ptr;
197 GtkWidget *widget;
198 GdkCursorType gdk_cursor_type;
199 GdkCursor *gdk_cursor;
201 ptr = NSA_GET_PTR (env, obj);
203 switch (type)
205 case AWT_CROSSHAIR_CURSOR:
206 gdk_cursor_type = GDK_CROSSHAIR;
207 break;
208 case AWT_TEXT_CURSOR:
209 gdk_cursor_type = GDK_XTERM;
210 break;
211 case AWT_WAIT_CURSOR:
212 gdk_cursor_type = GDK_WATCH;
213 break;
214 case AWT_SW_RESIZE_CURSOR:
215 gdk_cursor_type = GDK_BOTTOM_LEFT_CORNER;
216 break;
217 case AWT_SE_RESIZE_CURSOR:
218 gdk_cursor_type = GDK_BOTTOM_RIGHT_CORNER;
219 break;
220 case AWT_NW_RESIZE_CURSOR:
221 gdk_cursor_type = GDK_TOP_LEFT_CORNER;
222 break;
223 case AWT_NE_RESIZE_CURSOR:
224 gdk_cursor_type = GDK_TOP_RIGHT_CORNER;
225 break;
226 case AWT_N_RESIZE_CURSOR:
227 gdk_cursor_type = GDK_TOP_SIDE;
228 break;
229 case AWT_S_RESIZE_CURSOR:
230 gdk_cursor_type = GDK_BOTTOM_SIDE;
231 break;
232 case AWT_W_RESIZE_CURSOR:
233 gdk_cursor_type = GDK_LEFT_SIDE;
234 break;
235 case AWT_E_RESIZE_CURSOR:
236 gdk_cursor_type = GDK_RIGHT_SIDE;
237 break;
238 case AWT_HAND_CURSOR:
239 gdk_cursor_type = GDK_HAND2;
240 break;
241 case AWT_MOVE_CURSOR:
242 gdk_cursor_type = GDK_FLEUR;
243 break;
244 default:
245 gdk_cursor_type = GDK_LEFT_PTR;
248 widget = GTK_WIDGET(ptr);
250 gdk_cursor = gdk_cursor_new (gdk_cursor_type);
251 gdk_window_set_cursor (widget->window, gdk_cursor);
252 gdk_cursor_unref (gdk_cursor);
255 JNIEXPORT void JNICALL
256 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent
257 (JNIEnv *env, jobject obj, jobject parent)
259 void *ptr;
260 void *parent_ptr;
261 GtkWidget *widget;
262 GtkWidget *parent_widget;
264 gdk_threads_enter ();
266 ptr = NSA_GET_PTR (env, obj);
267 parent_ptr = NSA_GET_PTR (env, parent);
269 widget = GTK_WIDGET (ptr);
270 parent_widget = GTK_WIDGET (parent_ptr);
272 if (widget->parent == NULL)
274 if (GTK_IS_WINDOW (parent_widget))
276 GList *children = gtk_container_get_children
277 (GTK_CONTAINER (parent_widget));
279 if (GTK_IS_MENU_BAR (children->data))
280 gtk_fixed_put (GTK_FIXED (children->next->data), widget, 0, 0);
281 else
282 gtk_fixed_put (GTK_FIXED (children->data), widget, 0, 0);
284 else
285 if (GTK_IS_SCROLLED_WINDOW (parent_widget))
287 gtk_scrolled_window_add_with_viewport
288 (GTK_SCROLLED_WINDOW (parent_widget), widget);
289 gtk_viewport_set_shadow_type (GTK_VIEWPORT (widget->parent),
290 GTK_SHADOW_NONE);
293 else
295 if (widget->parent == NULL)
296 gtk_fixed_put (GTK_FIXED (parent_widget), widget, 0, 0);
300 gdk_threads_leave ();
303 JNIEXPORT void JNICALL
304 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetSensitive
305 (JNIEnv *env, jobject obj, jboolean sensitive)
307 void *ptr;
309 gdk_threads_enter ();
311 ptr = NSA_GET_PTR (env, obj);
313 gtk_widget_set_sensitive (GTK_WIDGET (ptr), sensitive);
315 gdk_threads_leave ();
318 JNIEXPORT void JNICALL
319 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
320 (JNIEnv *env, jobject obj)
322 void *ptr;
324 gdk_threads_enter ();
326 ptr = NSA_GET_PTR (env, obj);
328 gtk_widget_grab_focus (GTK_WIDGET (ptr));
330 gdk_threads_leave ();
334 * Translate a Java KeyEvent object into a GdkEventKey event, then
335 * pass it to the GTK main loop for processing.
337 JNIEXPORT void JNICALL
338 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent
339 (JNIEnv *env, jobject obj, jint id, jlong when, jint mods,
340 jint keyCode, jint keyLocation)
342 void *ptr;
343 GdkEvent *event = NULL;
344 GdkKeymapKey *keymap_keys = NULL;
345 gint n_keys = 0;
346 guint lookup_keyval = 0;
348 gdk_threads_enter ();
350 ptr = NSA_GET_PTR (env, obj);
352 if (id == AWT_KEY_PRESSED)
353 event = gdk_event_new (GDK_KEY_PRESS);
354 else if (id == AWT_KEY_RELEASED)
355 event = gdk_event_new (GDK_KEY_RELEASE);
356 else
358 gdk_threads_leave ();
359 /* Don't send AWT KEY_TYPED events to GTK. */
360 return;
363 if (GTK_IS_BUTTON (ptr))
364 event->key.window = GTK_BUTTON (ptr)->event_window;
365 else if (GTK_IS_SCROLLED_WINDOW (ptr))
366 event->key.window = GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child)->window;
367 else
368 event->key.window = GTK_WIDGET (ptr)->window;
370 event->key.send_event = 0;
371 event->key.time = (guint32) when;
373 if (mods & AWT_SHIFT_DOWN_MASK)
374 event->key.state |= GDK_SHIFT_MASK;
375 if (mods & AWT_CTRL_DOWN_MASK)
376 event->key.state |= GDK_CONTROL_MASK;
377 if (mods & AWT_ALT_DOWN_MASK)
378 event->key.state |= GDK_MOD1_MASK;
380 /* This hack is needed because the AWT has no notion of num lock.
381 It infers numlock state from the only Java virtual keys that are
382 affected by it. */
383 if (keyCode == VK_NUMPAD9
384 || keyCode == VK_NUMPAD8
385 || keyCode == VK_NUMPAD7
386 || keyCode == VK_NUMPAD6
387 || keyCode == VK_NUMPAD5
388 || keyCode == VK_NUMPAD4
389 || keyCode == VK_NUMPAD3
390 || keyCode == VK_NUMPAD2
391 || keyCode == VK_NUMPAD1
392 || keyCode == VK_NUMPAD0
393 || keyCode == VK_DECIMAL)
394 event->key.state |= GDK_MOD2_MASK;
396 /* These values don't need to be filled in since GTK doesn't use
397 them. */
398 event->key.length = 0;
399 event->key.string = NULL;
401 lookup_keyval = cp_gtk_awt_keycode_to_keysym (keyCode, keyLocation);
403 if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
404 lookup_keyval,
405 &keymap_keys,
406 &n_keys))
408 /* No matching keymap entry was found. */
409 g_printerr ("No matching keymap entries were found\n");
410 gdk_threads_leave ();
411 return;
414 /* Note: if n_keys > 1 then there are multiple hardware keycodes
415 that translate to lookup_keyval. We arbitrarily choose the first
416 hardware keycode from the list returned by
417 gdk_keymap_get_entries_for_keyval. */
419 event->key.hardware_keycode = keymap_keys[0].keycode;
420 event->key.group = keymap_keys[0].group;
422 g_free (keymap_keys);
424 if (!gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
425 event->key.hardware_keycode,
426 event->key.state,
427 event->key.group,
428 &event->key.keyval,
429 NULL, NULL, NULL))
431 /* No matching keyval was found. */
432 g_printerr ("No matching keyval was found\n");
433 gdk_threads_leave ();
434 return;
437 /* keyevent = (GdkEventKey *) event; */
438 /* 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); */
440 /* We already received the original key event on the window itself,
441 so we don't want to resend it. */
442 if (!GTK_IS_WINDOW (ptr))
444 if (GTK_IS_SCROLLED_WINDOW (ptr))
445 gtk_widget_event (GTK_WIDGET (GTK_SCROLLED_WINDOW (ptr)->container.child), event);
446 else
447 gtk_widget_event (GTK_WIDGET (ptr), event);
450 gdk_threads_leave ();
454 * Find the origin of a widget's window.
456 JNIEXPORT void JNICALL
457 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWindowGetLocationOnScreen
458 (JNIEnv * env, jobject obj, jintArray jpoint)
460 void *ptr;
461 jint *point;
463 gdk_threads_enter ();
465 ptr = NSA_GET_PTR (env, obj);
466 point = (*env)->GetIntArrayElements (env, jpoint, 0);
468 gdk_window_get_root_origin (GTK_WIDGET (ptr)->window, point, point+1);
470 (*env)->ReleaseIntArrayElements(env, jpoint, point, 0);
472 gdk_threads_leave ();
476 * Find the origin of a widget
478 JNIEXPORT void JNICALL
479 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetLocationOnScreen
480 (JNIEnv * env, jobject obj, jintArray jpoint)
482 void *ptr;
483 jint *point;
484 GtkWidget *widget;
486 gdk_threads_enter ();
488 ptr = NSA_GET_PTR (env, obj);
489 point = (*env)->GetIntArrayElements (env, jpoint, 0);
491 widget = GTK_WIDGET(ptr);
492 while(gtk_widget_get_parent(widget) != NULL)
493 widget = gtk_widget_get_parent(widget);
494 gdk_window_get_position (GTK_WIDGET(widget)->window, point, point+1);
496 *point += GTK_WIDGET(ptr)->allocation.x;
497 *(point+1) += GTK_WIDGET(ptr)->allocation.y;
499 (*env)->ReleaseIntArrayElements(env, jpoint, point, 0);
501 gdk_threads_leave ();
505 * Find this widget's current size.
507 JNIEXPORT void JNICALL
508 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetDimensions
509 (JNIEnv *env, jobject obj, jintArray jdims)
511 void *ptr;
512 jint *dims;
513 GtkRequisition requisition;
515 gdk_threads_enter ();
517 ptr = NSA_GET_PTR (env, obj);
519 dims = (*env)->GetIntArrayElements (env, jdims, 0);
520 dims[0] = dims[1] = 0;
522 gtk_widget_size_request (GTK_WIDGET (ptr), &requisition);
524 dims[0] = requisition.width;
525 dims[1] = requisition.height;
527 (*env)->ReleaseIntArrayElements (env, jdims, dims, 0);
529 gdk_threads_leave ();
533 * Find this widget's preferred size.
535 JNIEXPORT void JNICALL
536 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetPreferredDimensions
537 (JNIEnv *env, jobject obj, jintArray jdims)
539 void *ptr;
540 jint *dims;
541 GtkRequisition current_req;
542 GtkRequisition natural_req;
544 gdk_threads_enter ();
546 ptr = NSA_GET_PTR (env, obj);
548 dims = (*env)->GetIntArrayElements (env, jdims, 0);
549 dims[0] = dims[1] = 0;
551 /* Widgets that extend GtkWindow such as GtkFileChooserDialog may have
552 a default size. These values seem more useful then the natural
553 requisition values, particularly for GtkFileChooserDialog. */
554 if (GTK_IS_WINDOW (ptr))
556 gint width, height;
557 gtk_window_get_default_size (GTK_WINDOW (ptr), &width, &height);
559 dims[0] = width;
560 dims[1] = height;
562 else
564 /* Save the widget's current size request. */
565 gtk_widget_size_request (GTK_WIDGET (ptr), &current_req);
567 /* Get the widget's "natural" size request. */
568 gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1);
569 gtk_widget_size_request (GTK_WIDGET (ptr), &natural_req);
571 /* Reset the widget's size request. */
572 gtk_widget_set_size_request (GTK_WIDGET (ptr),
573 current_req.width, current_req.height);
575 dims[0] = natural_req.width;
576 dims[1] = natural_req.height;
579 (*env)->ReleaseIntArrayElements (env, jdims, dims, 0);
581 gdk_threads_leave ();
584 JNIEXPORT void JNICALL
585 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeBounds
586 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
588 GtkWidget *widget;
589 void *ptr;
591 gdk_threads_enter ();
593 ptr = NSA_GET_PTR (env, obj);
595 widget = GTK_WIDGET (ptr);
597 /* We assume that -1 is a width or height and not a request for the
598 widget's natural size. */
599 width = width < 0 ? 0 : width;
600 height = height < 0 ? 0 : height;
602 if (GTK_IS_VIEWPORT (widget->parent))
603 gtk_widget_set_size_request (widget, width, height);
604 else
606 if (!(width == 0 && height == 0))
608 gtk_widget_set_size_request (widget, width, height);
609 if (widget->parent != NULL)
610 gtk_fixed_move (GTK_FIXED (widget->parent), widget, x, y);
614 gdk_threads_leave ();
617 JNIEXPORT jintArray JNICALL
618 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetBackground
619 (JNIEnv *env, jobject obj)
621 void *ptr;
622 jintArray array;
623 int *rgb;
624 GdkColor bg;
626 gdk_threads_enter ();
628 ptr = NSA_GET_PTR (env, obj);
630 bg = GTK_WIDGET (ptr)->style->bg[GTK_STATE_NORMAL];
632 array = (*env)->NewIntArray (env, 3);
634 rgb = (*env)->GetIntArrayElements (env, array, NULL);
635 /* convert color data from 16 bit values down to 8 bit values */
636 rgb[0] = bg.red >> 8;
637 rgb[1] = bg.green >> 8;
638 rgb[2] = bg.blue >> 8;
639 (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
641 gdk_threads_leave ();
643 return array;
646 JNIEXPORT jintArray JNICALL
647 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetForeground
648 (JNIEnv *env, jobject obj)
650 void *ptr;
651 jintArray array;
652 jint *rgb;
653 GdkColor fg;
655 gdk_threads_enter ();
657 ptr = NSA_GET_PTR (env, obj);
659 fg = GTK_WIDGET (ptr)->style->fg[GTK_STATE_NORMAL];
661 array = (*env)->NewIntArray (env, 3);
663 rgb = (*env)->GetIntArrayElements (env, array, NULL);
664 /* convert color data from 16 bit values down to 8 bit values */
665 rgb[0] = fg.red >> 8;
666 rgb[1] = fg.green >> 8;
667 rgb[2] = fg.blue >> 8;
668 (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
670 gdk_threads_leave ();
672 return array;
675 JNIEXPORT void JNICALL
676 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetBackground
677 (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
679 GdkColor normal_color;
680 GdkColor active_color;
681 GtkWidget *widget;
682 void *ptr;
684 gdk_threads_enter ();
686 ptr = NSA_GET_PTR (env, obj);
688 normal_color.red = (red / 255.0) * 65535;
689 normal_color.green = (green / 255.0) * 65535;
690 normal_color.blue = (blue / 255.0) * 65535;
692 /* This calculation only approximates the active colors produced by
693 Sun's AWT. */
694 active_color.red = 0.85 * (red / 255.0) * 65535;
695 active_color.green = 0.85 * (green / 255.0) * 65535;
696 active_color.blue = 0.85 * (blue / 255.0) * 65535;
698 widget = find_bg_color_widget (GTK_WIDGET (ptr));
700 gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &normal_color);
701 gtk_widget_modify_bg (widget, GTK_STATE_ACTIVE, &active_color);
702 gtk_widget_modify_bg (widget, GTK_STATE_PRELIGHT, &normal_color);
704 gdk_threads_leave ();
707 JNIEXPORT void JNICALL
708 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetForeground
709 (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
711 GdkColor color;
712 GtkWidget *widget;
713 void *ptr;
715 gdk_threads_enter ();
717 ptr = NSA_GET_PTR (env, obj);
719 color.red = (red / 255.0) * 65535;
720 color.green = (green / 255.0) * 65535;
721 color.blue = (blue / 255.0) * 65535;
723 widget = find_fg_color_widget (GTK_WIDGET (ptr));
725 gtk_widget_modify_fg (widget, GTK_STATE_NORMAL, &color);
726 gtk_widget_modify_fg (widget, GTK_STATE_ACTIVE, &color);
727 gtk_widget_modify_fg (widget, GTK_STATE_PRELIGHT, &color);
729 gdk_threads_leave ();
732 JNIEXPORT void JNICALL
733 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNative
734 (JNIEnv *env, jobject obj, jboolean visible)
736 gdk_threads_enter();
738 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
739 (env, obj, visible);
741 gdk_threads_leave();
744 JNIEXPORT void JNICALL
745 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
746 (JNIEnv *env, jobject obj, jboolean visible)
748 void *ptr;
750 ptr = NSA_GET_PTR (env, obj);
752 if (visible)
753 gtk_widget_show (GTK_WIDGET (ptr));
754 else
755 gtk_widget_hide (GTK_WIDGET (ptr));
758 JNIEXPORT jboolean JNICALL
759 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isEnabled
760 (JNIEnv *env, jobject obj)
762 void *ptr;
763 jboolean ret_val;
765 gdk_threads_enter ();
767 ptr = NSA_GET_PTR (env, obj);
769 ret_val = GTK_WIDGET_IS_SENSITIVE (GTK_WIDGET (ptr));
771 gdk_threads_leave ();
773 return ret_val;
776 JNIEXPORT jboolean JNICALL
777 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isRealized
778 (JNIEnv *env, jobject obj)
780 void *ptr;
781 jboolean ret_val;
783 gdk_threads_enter ();
785 ptr = NSA_GET_PTR (env, obj);
787 if (ptr == NULL)
789 gdk_threads_leave ();
790 return FALSE;
793 ret_val = GTK_WIDGET_REALIZED (GTK_WIDGET (ptr));
795 gdk_threads_leave ();
797 return ret_val;
800 JNIEXPORT jboolean JNICALL
801 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_modalHasGrab
802 (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)))
804 GtkWidget *widget;
805 jboolean retval;
807 gdk_threads_enter ();
809 widget = gtk_grab_get_current ();
810 retval = (widget && GTK_IS_WINDOW (widget) && GTK_WINDOW (widget)->modal);
812 gdk_threads_leave ();
814 return retval;
817 JNIEXPORT void JNICALL
818 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals
819 (JNIEnv *env, jobject obj)
821 void *ptr;
822 jobject *gref;
824 gdk_threads_enter ();
826 ptr = NSA_GET_PTR (env, obj);
827 gref = NSA_GET_GLOBAL_REF (env, obj);
829 cp_gtk_component_connect_signals (ptr, gref);
831 gdk_threads_leave ();
834 JNIEXPORT void JNICALL
835 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeEventMask
836 (JNIEnv *env, jobject obj)
838 void *ptr;
840 gdk_threads_enter ();
842 ptr = NSA_GET_PTR (env, obj);
844 gtk_widget_add_events (GTK_WIDGET (ptr),
845 GDK_POINTER_MOTION_MASK
846 | GDK_BUTTON_MOTION_MASK
847 | GDK_BUTTON_PRESS_MASK
848 | GDK_BUTTON_RELEASE_MASK
849 | GDK_KEY_PRESS_MASK
850 | GDK_KEY_RELEASE_MASK
851 | GDK_ENTER_NOTIFY_MASK
852 | GDK_LEAVE_NOTIFY_MASK
853 | GDK_STRUCTURE_MASK
854 | GDK_KEY_PRESS_MASK
855 | GDK_FOCUS_CHANGE_MASK);
857 gdk_threads_leave ();
860 /* FIXME: these functions should be implemented by overridding the
861 appropriate GtkComponentPeer methods. */
862 static GtkWidget *
863 find_fg_color_widget (GtkWidget *widget)
865 GtkWidget *fg_color_widget;
867 if (GTK_IS_EVENT_BOX (widget)
868 || (GTK_IS_BUTTON (widget)
869 && !GTK_IS_COMBO_BOX (widget)))
870 fg_color_widget = gtk_bin_get_child (GTK_BIN(widget));
871 else
872 fg_color_widget = widget;
874 return fg_color_widget;
877 static GtkWidget *
878 find_bg_color_widget (GtkWidget *widget)
880 GtkWidget *bg_color_widget;
882 bg_color_widget = widget;
884 return bg_color_widget;
887 void
888 cp_gtk_component_connect_expose_signals (GObject *ptr, jobject *gref)
890 g_signal_connect (G_OBJECT (ptr), "expose-event",
891 G_CALLBACK (component_expose_cb), *gref);
894 void
895 cp_gtk_component_connect_focus_signals (GObject *ptr, jobject *gref)
897 g_signal_connect (G_OBJECT (ptr), "focus-in-event",
898 G_CALLBACK (component_focus_in_cb), *gref);
900 g_signal_connect (G_OBJECT (ptr), "focus-out-event",
901 G_CALLBACK (component_focus_out_cb), *gref);
904 void
905 cp_gtk_component_connect_mouse_signals (GObject *ptr, jobject *gref)
907 g_signal_connect (G_OBJECT (ptr), "button-press-event",
908 G_CALLBACK (component_button_press_cb), *gref);
910 g_signal_connect (G_OBJECT (ptr), "button-release-event",
911 G_CALLBACK (component_button_release_cb), *gref);
913 g_signal_connect (G_OBJECT (ptr), "enter-notify-event",
914 G_CALLBACK (component_enter_notify_cb), *gref);
916 g_signal_connect (G_OBJECT (ptr), "leave-notify-event",
917 G_CALLBACK (component_leave_notify_cb), *gref);
919 g_signal_connect (G_OBJECT (ptr), "motion-notify-event",
920 G_CALLBACK (component_motion_notify_cb), *gref);
923 void
924 cp_gtk_component_connect_signals (GObject *ptr, jobject *gref)
926 cp_gtk_component_connect_expose_signals (ptr, gref);
927 cp_gtk_component_connect_focus_signals (ptr, gref);
928 cp_gtk_component_connect_mouse_signals (ptr, gref);
931 /* These variables are used to keep track of click counts. The AWT
932 allows more than a triple click to occur but GTK doesn't report
933 more-than-triple clicks. */
934 static jint click_count = 1;
935 static guint32 button_click_time = 0;
936 static GdkWindow *button_window = NULL;
937 static guint button_number = -1;
938 static int hasBeenDragged;
940 static gboolean
941 component_button_press_cb (GtkWidget *widget __attribute__((unused)),
942 GdkEventButton *event,
943 jobject peer)
945 /* Ignore double and triple click events. */
946 if (event->type == GDK_2BUTTON_PRESS
947 || event->type == GDK_3BUTTON_PRESS)
948 return FALSE;
950 if ((event->time < (button_click_time + MULTI_CLICK_TIME))
951 && (event->window == button_window)
952 && (event->button == button_number))
953 click_count++;
954 else
955 click_count = 1;
957 button_click_time = event->time;
958 button_window = event->window;
959 button_number = event->button;
961 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
962 postMouseEventID,
963 AWT_MOUSE_PRESSED,
964 (jlong)event->time,
965 cp_gtk_state_to_awt_mods (event->state)
966 | button_to_awt_mods (event->button),
967 (jint)event->x,
968 (jint)event->y,
969 click_count,
970 (event->button == 3) ? JNI_TRUE :
971 JNI_FALSE);
973 hasBeenDragged = FALSE;
975 return FALSE;
978 static gboolean
979 component_button_release_cb (GtkWidget *widget __attribute__((unused)),
980 GdkEventButton *event,
981 jobject peer)
983 int width, height;
985 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
986 postMouseEventID,
987 AWT_MOUSE_RELEASED,
988 (jlong)event->time,
989 cp_gtk_state_to_awt_mods (event->state)
990 | button_to_awt_mods (event->button),
991 (jint)event->x,
992 (jint)event->y,
993 click_count,
994 JNI_FALSE);
996 /* Generate an AWT click event only if the release occured in the
997 window it was pressed in, and the mouse has not been dragged since
998 the last time it was pressed. */
999 gdk_drawable_get_size (event->window, &width, &height);
1000 if (! hasBeenDragged
1001 && event->x >= 0
1002 && event->y >= 0
1003 && event->x <= width
1004 && event->y <= height)
1006 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1007 postMouseEventID,
1008 AWT_MOUSE_CLICKED,
1009 (jlong)event->time,
1010 cp_gtk_state_to_awt_mods (event->state)
1011 | button_to_awt_mods (event->button),
1012 (jint)event->x,
1013 (jint)event->y,
1014 click_count,
1015 JNI_FALSE);
1017 return FALSE;
1020 static gboolean
1021 component_motion_notify_cb (GtkWidget *widget __attribute__((unused)),
1022 GdkEventMotion *event,
1023 jobject peer)
1025 if (event->state & (GDK_BUTTON1_MASK
1026 | GDK_BUTTON2_MASK
1027 | GDK_BUTTON3_MASK
1028 | GDK_BUTTON4_MASK
1029 | GDK_BUTTON5_MASK))
1031 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1032 postMouseEventID,
1033 AWT_MOUSE_DRAGGED,
1034 (jlong)event->time,
1035 state_to_awt_mods_with_button_states (event->state),
1036 (jint)event->x,
1037 (jint)event->y,
1039 JNI_FALSE);
1041 hasBeenDragged = TRUE;
1043 else
1045 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postMouseEventID,
1046 AWT_MOUSE_MOVED,
1047 (jlong)event->time,
1048 cp_gtk_state_to_awt_mods (event->state),
1049 (jint)event->x,
1050 (jint)event->y,
1052 JNI_FALSE);
1054 return FALSE;
1057 static gboolean
1058 component_enter_notify_cb (GtkWidget *widget __attribute__((unused)),
1059 GdkEventCrossing *event,
1060 jobject peer)
1062 /* We are not interested in enter events that are due to
1063 grab/ungrab and not to actually crossing boundaries */
1064 if (event->mode == GDK_CROSSING_NORMAL)
1066 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postMouseEventID,
1067 AWT_MOUSE_ENTERED,
1068 (jlong)event->time,
1069 state_to_awt_mods_with_button_states (event->state),
1070 (jint)event->x,
1071 (jint)event->y,
1073 JNI_FALSE);
1075 return FALSE;
1078 static gboolean
1079 component_leave_notify_cb (GtkWidget *widget __attribute__((unused)),
1080 GdkEventCrossing *event,
1081 jobject peer)
1083 /* We are not interested in leave events that are due to
1084 grab/ungrab and not to actually crossing boundaries */
1085 if (event->mode == GDK_CROSSING_NORMAL)
1087 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1088 postMouseEventID,
1089 AWT_MOUSE_EXITED,
1090 (jlong)event->time,
1091 state_to_awt_mods_with_button_states (event->state),
1092 (jint)event->x,
1093 (jint)event->y,
1095 JNI_FALSE);
1097 return FALSE;
1100 static gboolean
1101 component_expose_cb (GtkWidget *widget __attribute__((unused)),
1102 GdkEventExpose *event,
1103 jobject peer)
1105 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1106 postExposeEventID,
1107 (jint)event->area.x,
1108 (jint)event->area.y,
1109 (jint)event->area.width,
1110 (jint)event->area.height);
1112 return FALSE;
1115 static gboolean
1116 component_focus_in_cb (GtkWidget *widget __attribute((unused)),
1117 GdkEventFocus *event __attribute((unused)),
1118 jobject peer)
1120 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1121 postFocusEventID,
1122 AWT_FOCUS_GAINED,
1123 JNI_FALSE);
1125 return FALSE;
1128 static gboolean
1129 component_focus_out_cb (GtkWidget *widget __attribute((unused)),
1130 GdkEventFocus *event __attribute((unused)),
1131 jobject peer)
1133 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1134 postFocusEventID,
1135 AWT_FOCUS_LOST,
1136 JNI_FALSE);
1138 return FALSE;