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)
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
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
;
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
,
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
,
106 static gboolean
component_button_release_cb (GtkWidget
*widget
,
107 GdkEventButton
*event
,
109 static gboolean
component_motion_notify_cb (GtkWidget
*widget
,
110 GdkEventMotion
*event
,
112 static gboolean
component_enter_notify_cb (GtkWidget
*widget
,
113 GdkEventCrossing
*event
,
115 static gboolean
component_leave_notify_cb (GtkWidget
*widget
,
116 GdkEventCrossing
*event
,
118 static gboolean
component_expose_cb (GtkWidget
*widget
,
119 GdkEventExpose
*event
,
121 static gboolean
component_focus_in_cb (GtkWidget
*widget
,
122 GdkEventFocus
*event
,
124 static gboolean
component_focus_out_cb (GtkWidget
*widget
,
125 GdkEventFocus
*event
,
129 button_to_awt_mods (int button
)
134 return AWT_BUTTON1_DOWN_MASK
| AWT_BUTTON1_MASK
;
136 return AWT_BUTTON2_DOWN_MASK
| AWT_BUTTON2_MASK
;
138 return AWT_BUTTON3_DOWN_MASK
| AWT_BUTTON3_MASK
;
145 cp_gtk_state_to_awt_mods (guint state
)
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
);
160 state_to_awt_mods_with_button_states (guint state
)
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
;
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
189 gdk_threads_leave ();
192 JNIEXPORT
void JNICALL
193 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursorUnlocked
194 (JNIEnv
*env
, jobject obj
, jint type
)
198 GdkCursorType gdk_cursor_type
;
199 GdkCursor
*gdk_cursor
;
201 ptr
= NSA_GET_PTR (env
, obj
);
205 case AWT_CROSSHAIR_CURSOR
:
206 gdk_cursor_type
= GDK_CROSSHAIR
;
208 case AWT_TEXT_CURSOR
:
209 gdk_cursor_type
= GDK_XTERM
;
211 case AWT_WAIT_CURSOR
:
212 gdk_cursor_type
= GDK_WATCH
;
214 case AWT_SW_RESIZE_CURSOR
:
215 gdk_cursor_type
= GDK_BOTTOM_LEFT_CORNER
;
217 case AWT_SE_RESIZE_CURSOR
:
218 gdk_cursor_type
= GDK_BOTTOM_RIGHT_CORNER
;
220 case AWT_NW_RESIZE_CURSOR
:
221 gdk_cursor_type
= GDK_TOP_LEFT_CORNER
;
223 case AWT_NE_RESIZE_CURSOR
:
224 gdk_cursor_type
= GDK_TOP_RIGHT_CORNER
;
226 case AWT_N_RESIZE_CURSOR
:
227 gdk_cursor_type
= GDK_TOP_SIDE
;
229 case AWT_S_RESIZE_CURSOR
:
230 gdk_cursor_type
= GDK_BOTTOM_SIDE
;
232 case AWT_W_RESIZE_CURSOR
:
233 gdk_cursor_type
= GDK_LEFT_SIDE
;
235 case AWT_E_RESIZE_CURSOR
:
236 gdk_cursor_type
= GDK_RIGHT_SIDE
;
238 case AWT_HAND_CURSOR
:
239 gdk_cursor_type
= GDK_HAND2
;
241 case AWT_MOVE_CURSOR
:
242 gdk_cursor_type
= GDK_FLEUR
;
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
)
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);
282 gtk_fixed_put (GTK_FIXED (children
->data
), widget
, 0, 0);
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
),
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
)
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
)
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
)
343 GdkEvent
*event
= NULL
;
344 GdkKeymapKey
*keymap_keys
= NULL
;
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
);
358 gdk_threads_leave ();
359 /* Don't send AWT KEY_TYPED events to GTK. */
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
;
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
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
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 (),
408 /* No matching keymap entry was found. */
409 g_printerr ("No matching keymap entries were found\n");
410 gdk_threads_leave ();
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
,
431 /* No matching keyval was found. */
432 g_printerr ("No matching keyval was found\n");
433 gdk_threads_leave ();
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
);
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
)
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
)
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
)
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
)
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
))
557 gtk_window_get_default_size (GTK_WINDOW (ptr
), &width
, &height
);
564 /* Save the widget's current size request. */
565 gtk_widget_size_request (GTK_WIDGET (ptr
), ¤t_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
)
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
);
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
)
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 ();
646 JNIEXPORT jintArray JNICALL
647 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetForeground
648 (JNIEnv
*env
, jobject obj
)
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 ();
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
;
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
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
)
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
)
738 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
744 JNIEXPORT
void JNICALL
745 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
746 (JNIEnv
*env
, jobject obj
, jboolean visible
)
750 ptr
= NSA_GET_PTR (env
, obj
);
753 gtk_widget_show (GTK_WIDGET (ptr
));
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
)
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 ();
776 JNIEXPORT jboolean JNICALL
777 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isRealized
778 (JNIEnv
*env
, jobject obj
)
783 gdk_threads_enter ();
785 ptr
= NSA_GET_PTR (env
, obj
);
789 gdk_threads_leave ();
793 ret_val
= GTK_WIDGET_REALIZED (GTK_WIDGET (ptr
));
795 gdk_threads_leave ();
800 JNIEXPORT jboolean JNICALL
801 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_modalHasGrab
802 (JNIEnv
*env
__attribute__((unused
)), jclass clazz
__attribute__((unused
)))
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 ();
817 JNIEXPORT
void JNICALL
818 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals
819 (JNIEnv
*env
, jobject obj
)
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
)
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
850 | GDK_KEY_RELEASE_MASK
851 | GDK_ENTER_NOTIFY_MASK
852 | GDK_LEAVE_NOTIFY_MASK
855 | GDK_FOCUS_CHANGE_MASK
);
857 gdk_threads_leave ();
860 /* FIXME: these functions should be implemented by overridding the
861 appropriate GtkComponentPeer methods. */
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
));
872 fg_color_widget
= widget
;
874 return fg_color_widget
;
878 find_bg_color_widget (GtkWidget
*widget
)
880 GtkWidget
*bg_color_widget
;
882 bg_color_widget
= widget
;
884 return bg_color_widget
;
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
);
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
);
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
);
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
;
941 component_button_press_cb (GtkWidget
*widget
__attribute__((unused
)),
942 GdkEventButton
*event
,
945 /* Ignore double and triple click events. */
946 if (event
->type
== GDK_2BUTTON_PRESS
947 || event
->type
== GDK_3BUTTON_PRESS
)
950 if ((event
->time
< (button_click_time
+ MULTI_CLICK_TIME
))
951 && (event
->window
== button_window
)
952 && (event
->button
== button_number
))
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
,
965 cp_gtk_state_to_awt_mods (event
->state
)
966 | button_to_awt_mods (event
->button
),
970 (event
->button
== 3) ? JNI_TRUE
:
973 hasBeenDragged
= FALSE
;
979 component_button_release_cb (GtkWidget
*widget
__attribute__((unused
)),
980 GdkEventButton
*event
,
985 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
989 cp_gtk_state_to_awt_mods (event
->state
)
990 | button_to_awt_mods (event
->button
),
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
1003 && event
->x
<= width
1004 && event
->y
<= height
)
1006 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1010 cp_gtk_state_to_awt_mods (event
->state
)
1011 | button_to_awt_mods (event
->button
),
1021 component_motion_notify_cb (GtkWidget
*widget
__attribute__((unused
)),
1022 GdkEventMotion
*event
,
1025 if (event
->state
& (GDK_BUTTON1_MASK
1029 | GDK_BUTTON5_MASK
))
1031 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1035 state_to_awt_mods_with_button_states (event
->state
),
1041 hasBeenDragged
= TRUE
;
1045 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
, postMouseEventID
,
1048 cp_gtk_state_to_awt_mods (event
->state
),
1058 component_enter_notify_cb (GtkWidget
*widget
__attribute__((unused
)),
1059 GdkEventCrossing
*event
,
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
,
1069 state_to_awt_mods_with_button_states (event
->state
),
1079 component_leave_notify_cb (GtkWidget
*widget
__attribute__((unused
)),
1080 GdkEventCrossing
*event
,
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
,
1091 state_to_awt_mods_with_button_states (event
->state
),
1101 component_expose_cb (GtkWidget
*widget
__attribute__((unused
)),
1102 GdkEventExpose
*event
,
1105 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1107 (jint
)event
->area
.x
,
1108 (jint
)event
->area
.y
,
1109 (jint
)event
->area
.width
,
1110 (jint
)event
->area
.height
);
1116 component_focus_in_cb (GtkWidget
*widget
__attribute((unused
)),
1117 GdkEventFocus
*event
__attribute((unused
)),
1120 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1129 component_focus_out_cb (GtkWidget
*widget
__attribute((unused
)),
1130 GdkEventFocus
*event
__attribute((unused
)),
1133 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,