1 /* gtkcomponentpeer.c -- Native implementation of GtkComponentPeer
2 Copyright (C) 1998, 1999, 2002, 2004, 2006 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)
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
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
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. */
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
70 #define AWT_MOUSE_WHEEL 507
72 #define AWT_WHEEL_UNIT_SCROLL 0
74 #define AWT_FOCUS_GAINED 1004
75 #define AWT_FOCUS_LOST 1005
77 static GtkWidget *find_fg_color_widget (GtkWidget *widget);
78 static GtkWidget *find_bg_color_widget (GtkWidget *widget);
79 static GtkWidget *get_widget (GtkWidget *widget);
81 static jmethodID postMouseEventID;
82 static jmethodID postMouseWheelEventID;
83 static jmethodID postExposeEventID;
84 static jmethodID postFocusEventID;
87 cp_gtk_component_init_jni (void)
89 jclass gtkcomponentpeer;
91 gtkcomponentpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
92 "gnu/java/awt/peer/gtk/GtkComponentPeer");
94 postMouseEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer,
95 "postMouseEvent", "(IJIIIIZ)V");
97 postMouseWheelEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
99 "postMouseWheelEvent",
102 postExposeEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer,
103 "postExposeEvent", "(IIII)V");
105 postFocusEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkcomponentpeer,
106 "postFocusEvent", "(IZ)V");
109 static gboolean component_button_press_cb (GtkWidget *widget,
110 GdkEventButton *event,
112 static gboolean component_button_release_cb (GtkWidget *widget,
113 GdkEventButton *event,
115 static gboolean component_motion_notify_cb (GtkWidget *widget,
116 GdkEventMotion *event,
118 static gboolean component_scroll_cb (GtkWidget *widget,
119 GdkEventScroll *event,
121 static gboolean component_enter_notify_cb (GtkWidget *widget,
122 GdkEventCrossing *event,
124 static gboolean component_leave_notify_cb (GtkWidget *widget,
125 GdkEventCrossing *event,
127 static gboolean component_expose_cb (GtkWidget *widget,
128 GdkEventExpose *event,
130 static gboolean component_focus_in_cb (GtkWidget *widget,
131 GdkEventFocus *event,
133 static gboolean component_focus_out_cb (GtkWidget *widget,
134 GdkEventFocus *event,
138 button_to_awt_mods (int button)
143 return AWT_BUTTON1_DOWN_MASK | AWT_BUTTON1_MASK;
145 return AWT_BUTTON2_DOWN_MASK | AWT_BUTTON2_MASK;
147 return AWT_BUTTON3_DOWN_MASK | AWT_BUTTON3_MASK;
154 cp_gtk_state_to_awt_mods (guint state)
158 if (state & GDK_SHIFT_MASK)
159 result |= (AWT_SHIFT_DOWN_MASK | AWT_SHIFT_MASK);
160 if (state & GDK_CONTROL_MASK)
161 result |= (AWT_CTRL_DOWN_MASK | AWT_CTRL_MASK);
162 if (state & GDK_MOD1_MASK)
163 result |= (AWT_ALT_DOWN_MASK | AWT_ALT_MASK);
169 state_to_awt_mods_with_button_states (guint state)
173 if (state & GDK_SHIFT_MASK)
174 result |= AWT_SHIFT_DOWN_MASK | AWT_SHIFT_MASK;
175 if (state & GDK_CONTROL_MASK)
176 result |= AWT_CTRL_DOWN_MASK | AWT_CTRL_MASK;
177 if (state & GDK_MOD1_MASK)
178 result |= AWT_ALT_DOWN_MASK | AWT_ALT_MASK;
179 if (state & GDK_BUTTON1_MASK)
180 result |= AWT_BUTTON1_DOWN_MASK | AWT_BUTTON1_MASK;
181 if (state & GDK_BUTTON2_MASK)
182 result |= AWT_BUTTON2_DOWN_MASK;
183 if (state & GDK_BUTTON3_MASK)
184 result |= AWT_BUTTON3_DOWN_MASK;
189 JNIEXPORT void JNICALL
190 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor
191 (JNIEnv *env, jobject obj, jint type, jobject image, jint x, jint y)
193 gdk_threads_enter ();
195 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursorUnlocked
196 (env, obj, type, image, x, y);
198 gdk_threads_leave ();
201 JNIEXPORT void JNICALL
202 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursorUnlocked
203 (JNIEnv *env, jobject obj, jint type, jobject image, jint x, jint y)
208 GdkCursorType gdk_cursor_type;
209 GdkCursor *gdk_cursor;
211 ptr = NSA_GET_PTR (env, obj);
215 case AWT_CROSSHAIR_CURSOR:
216 gdk_cursor_type = GDK_CROSSHAIR;
218 case AWT_TEXT_CURSOR:
219 gdk_cursor_type = GDK_XTERM;
221 case AWT_WAIT_CURSOR:
222 gdk_cursor_type = GDK_WATCH;
224 case AWT_SW_RESIZE_CURSOR:
225 gdk_cursor_type = GDK_BOTTOM_LEFT_CORNER;
227 case AWT_SE_RESIZE_CURSOR:
228 gdk_cursor_type = GDK_BOTTOM_RIGHT_CORNER;
230 case AWT_NW_RESIZE_CURSOR:
231 gdk_cursor_type = GDK_TOP_LEFT_CORNER;
233 case AWT_NE_RESIZE_CURSOR:
234 gdk_cursor_type = GDK_TOP_RIGHT_CORNER;
236 case AWT_N_RESIZE_CURSOR:
237 gdk_cursor_type = GDK_TOP_SIDE;
239 case AWT_S_RESIZE_CURSOR:
240 gdk_cursor_type = GDK_BOTTOM_SIDE;
242 case AWT_W_RESIZE_CURSOR:
243 gdk_cursor_type = GDK_LEFT_SIDE;
245 case AWT_E_RESIZE_CURSOR:
246 gdk_cursor_type = GDK_RIGHT_SIDE;
248 case AWT_HAND_CURSOR:
249 gdk_cursor_type = GDK_HAND2;
251 case AWT_MOVE_CURSOR:
252 gdk_cursor_type = GDK_FLEUR;
255 gdk_cursor_type = GDK_LEFT_PTR;
258 widget = get_widget(GTK_WIDGET(ptr));
260 win = widget->window;
261 if ((widget->window) == NULL)
262 win = GTK_WIDGET(ptr)->window;
265 gdk_cursor = gdk_cursor_new (gdk_cursor_type);
268 = gdk_cursor_new_from_pixbuf (gdk_drawable_get_display (win),
269 cp_gtk_image_get_pixbuf (env, image),
272 gdk_window_set_cursor (win, gdk_cursor);
273 gdk_cursor_unref (gdk_cursor);
275 /* Make sure the cursor is replaced on screen. */
279 JNIEXPORT void JNICALL
280 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent
281 (JNIEnv *env, jobject obj, jobject parent)
286 GtkWidget *parent_widget;
288 gdk_threads_enter ();
290 ptr = NSA_GET_PTR (env, obj);
291 parent_ptr = NSA_GET_PTR (env, parent);
293 widget = GTK_WIDGET (ptr);
294 parent_widget = get_widget(GTK_WIDGET (parent_ptr));
296 if (widget->parent == NULL)
298 if (GTK_IS_WINDOW (parent_widget))
300 GList *children = gtk_container_get_children
301 (GTK_CONTAINER (parent_widget));
303 if (GTK_IS_MENU_BAR (children->data))
304 gtk_fixed_put (GTK_FIXED (children->next->data), widget, 0, 0);
306 gtk_fixed_put (GTK_FIXED (children->data), widget, 0, 0);
309 if (GTK_IS_SCROLLED_WINDOW (parent_widget))
311 gtk_scrolled_window_add_with_viewport
312 (GTK_SCROLLED_WINDOW (parent_widget), widget);
313 gtk_viewport_set_shadow_type (GTK_VIEWPORT (widget->parent),
319 if (widget->parent == NULL)
320 gtk_fixed_put (GTK_FIXED (parent_widget), widget, 0, 0);
324 gdk_threads_leave ();
327 JNIEXPORT void JNICALL
328 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetSensitive
329 (JNIEnv *env, jobject obj, jboolean sensitive)
333 gdk_threads_enter ();
335 ptr = NSA_GET_PTR (env, obj);
337 gtk_widget_set_sensitive (get_widget(GTK_WIDGET (ptr)), sensitive);
339 gdk_threads_leave ();
342 JNIEXPORT jboolean JNICALL
343 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetHasFocus
344 (JNIEnv *env, jobject obj)
349 gdk_threads_enter ();
351 ptr = NSA_GET_PTR (env, obj);
353 retval = GTK_WIDGET_HAS_FOCUS((GTK_WIDGET (ptr)));
355 gdk_threads_leave ();
360 JNIEXPORT jboolean JNICALL
361 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetCanFocus
362 (JNIEnv *env, jobject obj)
367 gdk_threads_enter ();
369 ptr = NSA_GET_PTR (env, obj);
371 retval = GTK_WIDGET_CAN_FOCUS((GTK_WIDGET (ptr)));
373 gdk_threads_leave ();
378 JNIEXPORT void JNICALL
379 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
380 (JNIEnv *env, jobject obj)
384 gdk_threads_enter ();
386 ptr = NSA_GET_PTR (env, obj);
388 gtk_widget_grab_focus (get_widget(GTK_WIDGET (ptr)));
390 gdk_threads_leave ();
394 * Translate a Java KeyEvent object into a GdkEventKey event, then
395 * pass it to the GTK main loop for processing.
397 JNIEXPORT void JNICALL
398 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent
399 (JNIEnv *env, jobject obj, jint id, jlong when, jint mods,
400 jint keyCode, jint keyLocation)
403 GdkEvent *event = NULL;
404 GdkKeymapKey *keymap_keys = NULL;
406 guint lookup_keyval = 0;
408 gdk_threads_enter ();
410 ptr = NSA_GET_PTR (env, obj);
412 if (id == AWT_KEY_PRESSED)
413 event = gdk_event_new (GDK_KEY_PRESS);
414 else if (id == AWT_KEY_RELEASED)
415 event = gdk_event_new (GDK_KEY_RELEASE);
418 gdk_threads_leave ();
419 /* Don't send AWT KEY_TYPED events to GTK. */
423 if (GTK_IS_BUTTON (ptr))
424 event->key.window = GTK_BUTTON (get_widget(GTK_WIDGET (ptr)))->event_window;
425 else if (GTK_IS_SCROLLED_WINDOW (get_widget(GTK_WIDGET (ptr))))
426 event->key.window = GTK_WIDGET (GTK_SCROLLED_WINDOW (get_widget(GTK_WIDGET (ptr)))->container.child)->window;
428 event->key.window = get_widget(GTK_WIDGET (ptr))->window;
430 event->key.send_event = 0;
431 event->key.time = (guint32) when;
433 if (mods & AWT_SHIFT_DOWN_MASK)
434 event->key.state |= GDK_SHIFT_MASK;
435 if (mods & AWT_CTRL_DOWN_MASK)
436 event->key.state |= GDK_CONTROL_MASK;
437 if (mods & AWT_ALT_DOWN_MASK)
438 event->key.state |= GDK_MOD1_MASK;
440 /* This hack is needed because the AWT has no notion of num lock.
441 It infers numlock state from the only Java virtual keys that are
443 if (keyCode == VK_NUMPAD9
444 || keyCode == VK_NUMPAD8
445 || keyCode == VK_NUMPAD7
446 || keyCode == VK_NUMPAD6
447 || keyCode == VK_NUMPAD5
448 || keyCode == VK_NUMPAD4
449 || keyCode == VK_NUMPAD3
450 || keyCode == VK_NUMPAD2
451 || keyCode == VK_NUMPAD1
452 || keyCode == VK_NUMPAD0
453 || keyCode == VK_DECIMAL)
454 event->key.state |= GDK_MOD2_MASK;
456 /* These values don't need to be filled in since GTK doesn't use
458 event->key.length = 0;
459 event->key.string = NULL;
461 lookup_keyval = cp_gtk_awt_keycode_to_keysym (keyCode, keyLocation);
463 if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
468 /* No matching keymap entry was found. */
469 g_printerr ("No matching keymap entries were found\n");
470 gdk_threads_leave ();
474 /* Note: if n_keys > 1 then there are multiple hardware keycodes
475 that translate to lookup_keyval. We arbitrarily choose the first
476 hardware keycode from the list returned by
477 gdk_keymap_get_entries_for_keyval. */
479 event->key.hardware_keycode = keymap_keys[0].keycode;
480 event->key.group = keymap_keys[0].group;
482 g_free (keymap_keys);
484 if (!gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
485 event->key.hardware_keycode,
491 /* No matching keyval was found. */
492 g_printerr ("No matching keyval was found\n");
493 gdk_threads_leave ();
497 /* keyevent = (GdkEventKey *) event; */
498 /* 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); */
500 /* We already received the original key event on the window itself,
501 so we don't want to resend it. */
502 if (!GTK_IS_WINDOW (ptr))
504 if (GTK_IS_SCROLLED_WINDOW (get_widget(GTK_WIDGET (ptr))))
505 gtk_widget_event (GTK_WIDGET (GTK_SCROLLED_WINDOW (get_widget(GTK_WIDGET (ptr)))->container.child), event);
507 gtk_widget_event (get_widget(GTK_WIDGET (ptr)), event);
510 gdk_threads_leave ();
514 * Find the origin of a widget's window.
516 JNIEXPORT void JNICALL
517 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWindowGetLocationOnScreen
518 (JNIEnv * env, jobject obj, jintArray jpoint)
523 gdk_threads_enter ();
525 ptr = NSA_GET_PTR (env, obj);
526 point = (*env)->GetIntArrayElements (env, jpoint, 0);
528 gdk_window_get_root_origin (get_widget(GTK_WIDGET (ptr))->window, point, point+1);
530 (*env)->ReleaseIntArrayElements(env, jpoint, point, 0);
532 gdk_threads_leave ();
536 * Find the origin of a widget
538 JNIEXPORT void JNICALL
539 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetLocationOnScreen
540 (JNIEnv * env, jobject obj, jintArray jpoint)
546 gdk_threads_enter ();
548 ptr = NSA_GET_PTR (env, obj);
549 point = (*env)->GetIntArrayElements (env, jpoint, 0);
551 widget = get_widget(GTK_WIDGET (ptr));
552 while(gtk_widget_get_parent(widget) != NULL)
553 widget = gtk_widget_get_parent(widget);
554 gdk_window_get_position (GTK_WIDGET(widget)->window, point, point+1);
556 *point += GTK_WIDGET(ptr)->allocation.x;
557 *(point+1) += GTK_WIDGET(ptr)->allocation.y;
559 (*env)->ReleaseIntArrayElements(env, jpoint, point, 0);
561 gdk_threads_leave ();
565 * Find this widget's current size.
567 JNIEXPORT void JNICALL
568 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetDimensions
569 (JNIEnv *env, jobject obj, jintArray jdims)
573 GtkRequisition requisition;
575 gdk_threads_enter ();
577 ptr = NSA_GET_PTR (env, obj);
579 dims = (*env)->GetIntArrayElements (env, jdims, 0);
580 dims[0] = dims[1] = 0;
582 gtk_widget_size_request (get_widget(GTK_WIDGET (ptr)), &requisition);
584 dims[0] = requisition.width;
585 dims[1] = requisition.height;
587 (*env)->ReleaseIntArrayElements (env, jdims, dims, 0);
589 gdk_threads_leave ();
593 * Find this widget's preferred size.
595 JNIEXPORT void JNICALL
596 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetPreferredDimensions
597 (JNIEnv *env, jobject obj, jintArray jdims)
601 GtkRequisition current_req;
602 GtkRequisition natural_req;
604 gdk_threads_enter ();
606 ptr = NSA_GET_PTR (env, obj);
608 dims = (*env)->GetIntArrayElements (env, jdims, 0);
609 dims[0] = dims[1] = 0;
611 /* Widgets that extend GtkWindow such as GtkFileChooserDialog may have
612 a default size. These values seem more useful then the natural
613 requisition values, particularly for GtkFileChooserDialog. */
614 if (GTK_IS_WINDOW (get_widget(GTK_WIDGET (ptr))))
617 gtk_window_get_default_size (GTK_WINDOW (get_widget(GTK_WIDGET (ptr))), &width, &height);
624 /* Save the widget's current size request. */
625 gtk_widget_size_request (get_widget(GTK_WIDGET (ptr)), ¤t_req);
627 /* Get the widget's "natural" size request. */
628 gtk_widget_set_size_request (get_widget(GTK_WIDGET (ptr)), -1, -1);
629 gtk_widget_size_request (get_widget(GTK_WIDGET (ptr)), &natural_req);
631 /* Reset the widget's size request. */
632 gtk_widget_set_size_request (get_widget(GTK_WIDGET (ptr)),
633 current_req.width, current_req.height);
635 dims[0] = natural_req.width;
636 dims[1] = natural_req.height;
639 (*env)->ReleaseIntArrayElements (env, jdims, dims, 0);
641 gdk_threads_leave ();
644 JNIEXPORT void JNICALL
645 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeBounds
646 (JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height)
651 gdk_threads_enter ();
653 ptr = NSA_GET_PTR (env, obj);
655 widget = GTK_WIDGET (ptr);
657 /* We assume that -1 is a width or height and not a request for the
658 widget's natural size. */
659 width = width < 0 ? 0 : width;
660 height = height < 0 ? 0 : height;
662 if (!(width == 0 && height == 0))
664 gtk_widget_set_size_request (widget, width, height);
665 /* The GTK_IS_FIXED check here prevents gtk_fixed_move being
666 called when our parent is a GtkScrolledWindow. In that
667 case though, moving the child widget is invalid since a
668 ScrollPane only has one child and that child is always
669 located at (0, 0) in viewport coordinates. */
670 if (widget->parent != NULL && GTK_IS_FIXED (widget->parent))
671 gtk_fixed_move (GTK_FIXED (widget->parent), widget, x, y);
674 gdk_threads_leave ();
677 JNIEXPORT jintArray JNICALL
678 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetBackground
679 (JNIEnv *env, jobject obj)
686 gdk_threads_enter ();
688 ptr = NSA_GET_PTR (env, obj);
690 bg = GTK_WIDGET (ptr)->style->bg[GTK_STATE_NORMAL];
692 array = (*env)->NewIntArray (env, 3);
694 rgb = (*env)->GetIntArrayElements (env, array, NULL);
695 /* convert color data from 16 bit values down to 8 bit values */
696 rgb[0] = bg.red >> 8;
697 rgb[1] = bg.green >> 8;
698 rgb[2] = bg.blue >> 8;
699 (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
701 gdk_threads_leave ();
706 JNIEXPORT jintArray JNICALL
707 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetForeground
708 (JNIEnv *env, jobject obj)
715 gdk_threads_enter ();
717 ptr = NSA_GET_PTR (env, obj);
719 fg = get_widget(GTK_WIDGET (ptr))->style->fg[GTK_STATE_NORMAL];
721 array = (*env)->NewIntArray (env, 3);
723 rgb = (*env)->GetIntArrayElements (env, array, NULL);
724 /* convert color data from 16 bit values down to 8 bit values */
725 rgb[0] = fg.red >> 8;
726 rgb[1] = fg.green >> 8;
727 rgb[2] = fg.blue >> 8;
728 (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
730 gdk_threads_leave ();
735 JNIEXPORT void JNICALL
736 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetBackground
737 (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
739 GdkColor normal_color;
740 GdkColor active_color;
744 gdk_threads_enter ();
746 ptr = NSA_GET_PTR (env, obj);
748 normal_color.red = (red / 255.0) * 65535;
749 normal_color.green = (green / 255.0) * 65535;
750 normal_color.blue = (blue / 255.0) * 65535;
752 /* This calculation only approximates the active colors produced by
754 active_color.red = 0.85 * (red / 255.0) * 65535;
755 active_color.green = 0.85 * (green / 255.0) * 65535;
756 active_color.blue = 0.85 * (blue / 255.0) * 65535;
758 widget = find_bg_color_widget (GTK_WIDGET (ptr));
760 gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &normal_color);
761 gtk_widget_modify_bg (widget, GTK_STATE_ACTIVE, &active_color);
762 gtk_widget_modify_bg (widget, GTK_STATE_PRELIGHT, &normal_color);
764 gdk_threads_leave ();
767 JNIEXPORT void JNICALL
768 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetForeground
769 (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
775 gdk_threads_enter ();
777 ptr = NSA_GET_PTR (env, obj);
779 color.red = (red / 255.0) * 65535;
780 color.green = (green / 255.0) * 65535;
781 color.blue = (blue / 255.0) * 65535;
783 widget = find_fg_color_widget (GTK_WIDGET (ptr));
785 gtk_widget_modify_fg (widget, GTK_STATE_NORMAL, &color);
786 gtk_widget_modify_fg (widget, GTK_STATE_ACTIVE, &color);
787 gtk_widget_modify_fg (widget, GTK_STATE_PRELIGHT, &color);
789 gdk_threads_leave ();
792 JNIEXPORT void JNICALL
793 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_realize (JNIEnv *env, jobject obj)
797 gdk_threads_enter ();
799 ptr = NSA_GET_PTR (env, obj);
801 gtk_widget_realize (GTK_WIDGET (ptr));
803 gdk_threads_leave ();
806 JNIEXPORT void JNICALL
807 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNative
808 (JNIEnv *env, jobject obj, jboolean visible)
812 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
818 JNIEXPORT void JNICALL
819 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
820 (JNIEnv *env, jobject obj, jboolean visible)
824 ptr = NSA_GET_PTR (env, obj);
827 gtk_widget_show (GTK_WIDGET (ptr));
829 gtk_widget_hide (GTK_WIDGET (ptr));
832 JNIEXPORT jboolean JNICALL
833 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isEnabled
834 (JNIEnv *env, jobject obj)
839 gdk_threads_enter ();
841 ptr = NSA_GET_PTR (env, obj);
843 ret_val = GTK_WIDGET_IS_SENSITIVE (get_widget(GTK_WIDGET (ptr)));
845 gdk_threads_leave ();
850 JNIEXPORT jboolean JNICALL
851 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_modalHasGrab
852 (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)))
857 gdk_threads_enter ();
859 widget = gtk_grab_get_current ();
860 retval = (widget && GTK_IS_WINDOW (widget) && GTK_WINDOW (widget)->modal);
862 gdk_threads_leave ();
867 JNIEXPORT void JNICALL
868 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals
869 (JNIEnv *env, jobject obj)
874 gdk_threads_enter ();
876 ptr = NSA_GET_PTR (env, obj);
877 gref = NSA_GET_GLOBAL_REF (env, obj);
879 cp_gtk_component_connect_signals (ptr, gref);
881 gdk_threads_leave ();
884 JNIEXPORT void JNICALL
885 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeEventMask
886 (JNIEnv *env, jobject obj)
890 gdk_threads_enter ();
892 ptr = NSA_GET_PTR (env, obj);
894 gtk_widget_add_events (get_widget(GTK_WIDGET (ptr)),
895 GDK_POINTER_MOTION_MASK
896 | GDK_BUTTON_MOTION_MASK
897 | GDK_BUTTON_PRESS_MASK
898 | GDK_BUTTON_RELEASE_MASK
900 | GDK_KEY_RELEASE_MASK
901 | GDK_ENTER_NOTIFY_MASK
902 | GDK_LEAVE_NOTIFY_MASK
905 | GDK_FOCUS_CHANGE_MASK);
907 gdk_threads_leave ();
911 get_widget (GtkWidget *widget)
915 if (GTK_IS_EVENT_BOX (widget))
916 w = gtk_bin_get_child (GTK_BIN(widget));
923 /* FIXME: these functions should be implemented by overridding the
924 appropriate GtkComponentPeer methods. */
926 find_fg_color_widget (GtkWidget *widget)
928 GtkWidget *fg_color_widget;
930 if (GTK_IS_EVENT_BOX (widget)
931 || (GTK_IS_BUTTON (widget)
932 && !GTK_IS_COMBO_BOX (widget)))
933 fg_color_widget = gtk_bin_get_child (GTK_BIN(widget));
935 fg_color_widget = widget;
937 return fg_color_widget;
941 find_bg_color_widget (GtkWidget *widget)
943 GtkWidget *bg_color_widget;
945 bg_color_widget = widget;
947 return bg_color_widget;
951 cp_gtk_component_connect_expose_signals (GObject *ptr, jobject *gref)
953 g_signal_connect (G_OBJECT (ptr), "expose-event",
954 G_CALLBACK (component_expose_cb), *gref);
958 cp_gtk_component_connect_focus_signals (GObject *ptr, jobject *gref)
960 g_signal_connect (G_OBJECT (ptr), "focus-in-event",
961 G_CALLBACK (component_focus_in_cb), *gref);
963 g_signal_connect (G_OBJECT (ptr), "focus-out-event",
964 G_CALLBACK (component_focus_out_cb), *gref);
968 cp_gtk_component_connect_mouse_signals (GObject *ptr, jobject *gref)
970 g_signal_connect (G_OBJECT (ptr), "button-press-event",
971 G_CALLBACK (component_button_press_cb), *gref);
973 g_signal_connect (G_OBJECT (ptr), "button-release-event",
974 G_CALLBACK (component_button_release_cb), *gref);
976 g_signal_connect (G_OBJECT (ptr), "enter-notify-event",
977 G_CALLBACK (component_enter_notify_cb), *gref);
979 g_signal_connect (G_OBJECT (ptr), "leave-notify-event",
980 G_CALLBACK (component_leave_notify_cb), *gref);
982 g_signal_connect (G_OBJECT (ptr), "motion-notify-event",
983 G_CALLBACK (component_motion_notify_cb), *gref);
985 g_signal_connect (G_OBJECT (ptr), "scroll-event",
986 G_CALLBACK (component_scroll_cb), *gref);
990 cp_gtk_component_connect_signals (GObject *ptr, jobject *gref)
992 cp_gtk_component_connect_expose_signals (ptr, gref);
993 cp_gtk_component_connect_focus_signals (ptr, gref);
994 cp_gtk_component_connect_mouse_signals (ptr, gref);
997 /* These variables are used to keep track of click counts. The AWT
998 allows more than a triple click to occur but GTK doesn't report
999 more-than-triple clicks. Also used for keeping track of scroll events.*/
1000 static jint click_count = 1;
1001 static guint32 button_click_time = 0;
1002 static GdkWindow *button_window = NULL;
1003 static guint button_number_direction = -1;
1004 static int hasBeenDragged;
1007 component_button_press_cb (GtkWidget *widget __attribute__((unused)),
1008 GdkEventButton *event,
1011 /* Ignore double and triple click events. */
1012 if (event->type == GDK_2BUTTON_PRESS
1013 || event->type == GDK_3BUTTON_PRESS)
1016 if ((event->time < (button_click_time + MULTI_CLICK_TIME))
1017 && (event->window == button_window)
1018 && (event->button == button_number_direction))
1023 button_click_time = event->time;
1024 button_window = event->window;
1025 button_number_direction = event->button;
1027 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1031 cp_gtk_state_to_awt_mods (event->state)
1032 | button_to_awt_mods (event->button),
1036 (event->button == 3) ? JNI_TRUE :
1039 hasBeenDragged = FALSE;
1045 component_button_release_cb (GtkWidget *widget __attribute__((unused)),
1046 GdkEventButton *event,
1051 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1055 cp_gtk_state_to_awt_mods (event->state)
1056 | button_to_awt_mods (event->button),
1062 /* Generate an AWT click event only if the release occured in the
1063 window it was pressed in, and the mouse has not been dragged since
1064 the last time it was pressed. */
1065 gdk_drawable_get_size (event->window, &width, &height);
1066 if (! hasBeenDragged
1069 && event->x <= width
1070 && event->y <= height)
1072 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1076 cp_gtk_state_to_awt_mods (event->state)
1077 | button_to_awt_mods (event->button),
1087 component_motion_notify_cb (GtkWidget *widget __attribute__((unused)),
1088 GdkEventMotion *event,
1091 if (event->state & (GDK_BUTTON1_MASK
1095 | GDK_BUTTON5_MASK))
1097 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1101 state_to_awt_mods_with_button_states (event->state),
1107 hasBeenDragged = TRUE;
1111 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postMouseEventID,
1114 cp_gtk_state_to_awt_mods (event->state),
1124 component_scroll_cb (GtkWidget *widget __attribute__((unused)),
1125 GdkEventScroll *event,
1129 /** Record click count for specific direction. */
1130 if ((event->time < (button_click_time + MULTI_CLICK_TIME))
1131 && (event->window == button_window)
1132 && (event->direction == button_number_direction))
1137 button_click_time = event->time;
1138 button_window = event->window;
1139 button_number_direction = event->direction;
1141 if (event->direction == GDK_SCROLL_UP
1142 || event->direction == GDK_SCROLL_LEFT)
1147 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1148 postMouseWheelEventID,
1151 cp_gtk_state_to_awt_mods (event->state),
1156 AWT_WHEEL_UNIT_SCROLL,
1163 component_enter_notify_cb (GtkWidget *widget __attribute__((unused)),
1164 GdkEventCrossing *event,
1167 /* We are not interested in enter events that are due to
1168 grab/ungrab and not to actually crossing boundaries */
1169 if (event->mode == GDK_CROSSING_NORMAL)
1171 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postMouseEventID,
1174 state_to_awt_mods_with_button_states (event->state),
1184 component_leave_notify_cb (GtkWidget *widget __attribute__((unused)),
1185 GdkEventCrossing *event,
1188 /* We are not interested in leave events that are due to
1189 grab/ungrab and not to actually crossing boundaries */
1190 if (event->mode == GDK_CROSSING_NORMAL)
1192 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1196 state_to_awt_mods_with_button_states (event->state),
1206 component_expose_cb (GtkWidget *widget __attribute__((unused)),
1207 GdkEventExpose *event,
1210 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1212 (jint)event->area.x,
1213 (jint)event->area.y,
1214 (jint)event->area.width,
1215 (jint)event->area.height);
1221 component_focus_in_cb (GtkWidget *widget __attribute((unused)),
1222 GdkEventFocus *event __attribute((unused)),
1225 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1234 component_focus_out_cb (GtkWidget *widget __attribute((unused)),
1235 GdkEventFocus *event __attribute((unused)),
1238 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,