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
)
207 GdkCursorType gdk_cursor_type
;
208 GdkCursor
*gdk_cursor
;
210 ptr
= NSA_GET_PTR (env
, obj
);
214 case AWT_CROSSHAIR_CURSOR
:
215 gdk_cursor_type
= GDK_CROSSHAIR
;
217 case AWT_TEXT_CURSOR
:
218 gdk_cursor_type
= GDK_XTERM
;
220 case AWT_WAIT_CURSOR
:
221 gdk_cursor_type
= GDK_WATCH
;
223 case AWT_SW_RESIZE_CURSOR
:
224 gdk_cursor_type
= GDK_BOTTOM_LEFT_CORNER
;
226 case AWT_SE_RESIZE_CURSOR
:
227 gdk_cursor_type
= GDK_BOTTOM_RIGHT_CORNER
;
229 case AWT_NW_RESIZE_CURSOR
:
230 gdk_cursor_type
= GDK_TOP_LEFT_CORNER
;
232 case AWT_NE_RESIZE_CURSOR
:
233 gdk_cursor_type
= GDK_TOP_RIGHT_CORNER
;
235 case AWT_N_RESIZE_CURSOR
:
236 gdk_cursor_type
= GDK_TOP_SIDE
;
238 case AWT_S_RESIZE_CURSOR
:
239 gdk_cursor_type
= GDK_BOTTOM_SIDE
;
241 case AWT_W_RESIZE_CURSOR
:
242 gdk_cursor_type
= GDK_LEFT_SIDE
;
244 case AWT_E_RESIZE_CURSOR
:
245 gdk_cursor_type
= GDK_RIGHT_SIDE
;
247 case AWT_HAND_CURSOR
:
248 gdk_cursor_type
= GDK_HAND2
;
250 case AWT_MOVE_CURSOR
:
251 gdk_cursor_type
= GDK_FLEUR
;
254 gdk_cursor_type
= GDK_LEFT_PTR
;
257 widget
= get_widget(GTK_WIDGET(ptr
));
260 gdk_cursor
= gdk_cursor_new (gdk_cursor_type
);
263 = gdk_cursor_new_from_pixbuf (gdk_drawable_get_display (widget
->window
),
264 cp_gtk_image_get_pixbuf (env
, image
),
267 gdk_window_set_cursor (widget
->window
, gdk_cursor
);
268 gdk_cursor_unref (gdk_cursor
);
270 /* Make sure the cursor is replaced on screen. */
274 JNIEXPORT
void JNICALL
275 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent
276 (JNIEnv
*env
, jobject obj
, jobject parent
)
281 GtkWidget
*parent_widget
;
283 gdk_threads_enter ();
285 ptr
= NSA_GET_PTR (env
, obj
);
286 parent_ptr
= NSA_GET_PTR (env
, parent
);
288 widget
= GTK_WIDGET (ptr
);
289 parent_widget
= get_widget(GTK_WIDGET (parent_ptr
));
291 if (widget
->parent
== NULL
)
293 if (GTK_IS_WINDOW (parent_widget
))
295 GList
*children
= gtk_container_get_children
296 (GTK_CONTAINER (parent_widget
));
298 if (GTK_IS_MENU_BAR (children
->data
))
299 gtk_fixed_put (GTK_FIXED (children
->next
->data
), widget
, 0, 0);
301 gtk_fixed_put (GTK_FIXED (children
->data
), widget
, 0, 0);
304 if (GTK_IS_SCROLLED_WINDOW (parent_widget
))
306 gtk_scrolled_window_add_with_viewport
307 (GTK_SCROLLED_WINDOW (parent_widget
), widget
);
308 gtk_viewport_set_shadow_type (GTK_VIEWPORT (widget
->parent
),
314 if (widget
->parent
== NULL
)
315 gtk_fixed_put (GTK_FIXED (parent_widget
), widget
, 0, 0);
319 gdk_threads_leave ();
322 JNIEXPORT
void JNICALL
323 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetSensitive
324 (JNIEnv
*env
, jobject obj
, jboolean sensitive
)
328 gdk_threads_enter ();
330 ptr
= NSA_GET_PTR (env
, obj
);
332 gtk_widget_set_sensitive (get_widget(GTK_WIDGET (ptr
)), sensitive
);
334 gdk_threads_leave ();
337 JNIEXPORT
void JNICALL
338 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
339 (JNIEnv
*env
, jobject obj
)
343 gdk_threads_enter ();
345 ptr
= NSA_GET_PTR (env
, obj
);
347 gtk_widget_grab_focus (get_widget(GTK_WIDGET (ptr
)));
349 gdk_threads_leave ();
353 * Translate a Java KeyEvent object into a GdkEventKey event, then
354 * pass it to the GTK main loop for processing.
356 JNIEXPORT
void JNICALL
357 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent
358 (JNIEnv
*env
, jobject obj
, jint id
, jlong when
, jint mods
,
359 jint keyCode
, jint keyLocation
)
362 GdkEvent
*event
= NULL
;
363 GdkKeymapKey
*keymap_keys
= NULL
;
365 guint lookup_keyval
= 0;
367 gdk_threads_enter ();
369 ptr
= NSA_GET_PTR (env
, obj
);
371 if (id
== AWT_KEY_PRESSED
)
372 event
= gdk_event_new (GDK_KEY_PRESS
);
373 else if (id
== AWT_KEY_RELEASED
)
374 event
= gdk_event_new (GDK_KEY_RELEASE
);
377 gdk_threads_leave ();
378 /* Don't send AWT KEY_TYPED events to GTK. */
382 if (GTK_IS_BUTTON (ptr
))
383 event
->key
.window
= GTK_BUTTON (get_widget(GTK_WIDGET (ptr
)))->event_window
;
384 else if (GTK_IS_SCROLLED_WINDOW (get_widget(GTK_WIDGET (ptr
))))
385 event
->key
.window
= GTK_WIDGET (GTK_SCROLLED_WINDOW (get_widget(GTK_WIDGET (ptr
)))->container
.child
)->window
;
387 event
->key
.window
= get_widget(GTK_WIDGET (ptr
))->window
;
389 event
->key
.send_event
= 0;
390 event
->key
.time
= (guint32
) when
;
392 if (mods
& AWT_SHIFT_DOWN_MASK
)
393 event
->key
.state
|= GDK_SHIFT_MASK
;
394 if (mods
& AWT_CTRL_DOWN_MASK
)
395 event
->key
.state
|= GDK_CONTROL_MASK
;
396 if (mods
& AWT_ALT_DOWN_MASK
)
397 event
->key
.state
|= GDK_MOD1_MASK
;
399 /* This hack is needed because the AWT has no notion of num lock.
400 It infers numlock state from the only Java virtual keys that are
402 if (keyCode
== VK_NUMPAD9
403 || keyCode
== VK_NUMPAD8
404 || keyCode
== VK_NUMPAD7
405 || keyCode
== VK_NUMPAD6
406 || keyCode
== VK_NUMPAD5
407 || keyCode
== VK_NUMPAD4
408 || keyCode
== VK_NUMPAD3
409 || keyCode
== VK_NUMPAD2
410 || keyCode
== VK_NUMPAD1
411 || keyCode
== VK_NUMPAD0
412 || keyCode
== VK_DECIMAL
)
413 event
->key
.state
|= GDK_MOD2_MASK
;
415 /* These values don't need to be filled in since GTK doesn't use
417 event
->key
.length
= 0;
418 event
->key
.string
= NULL
;
420 lookup_keyval
= cp_gtk_awt_keycode_to_keysym (keyCode
, keyLocation
);
422 if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
427 /* No matching keymap entry was found. */
428 g_printerr ("No matching keymap entries were found\n");
429 gdk_threads_leave ();
433 /* Note: if n_keys > 1 then there are multiple hardware keycodes
434 that translate to lookup_keyval. We arbitrarily choose the first
435 hardware keycode from the list returned by
436 gdk_keymap_get_entries_for_keyval. */
438 event
->key
.hardware_keycode
= keymap_keys
[0].keycode
;
439 event
->key
.group
= keymap_keys
[0].group
;
441 g_free (keymap_keys
);
443 if (!gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
444 event
->key
.hardware_keycode
,
450 /* No matching keyval was found. */
451 g_printerr ("No matching keyval was found\n");
452 gdk_threads_leave ();
456 /* keyevent = (GdkEventKey *) event; */
457 /* 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); */
459 /* We already received the original key event on the window itself,
460 so we don't want to resend it. */
461 if (!GTK_IS_WINDOW (ptr
))
463 if (GTK_IS_SCROLLED_WINDOW (get_widget(GTK_WIDGET (ptr
))))
464 gtk_widget_event (GTK_WIDGET (GTK_SCROLLED_WINDOW (get_widget(GTK_WIDGET (ptr
)))->container
.child
), event
);
466 gtk_widget_event (get_widget(GTK_WIDGET (ptr
)), event
);
469 gdk_threads_leave ();
473 * Find the origin of a widget's window.
475 JNIEXPORT
void JNICALL
476 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWindowGetLocationOnScreen
477 (JNIEnv
* env
, jobject obj
, jintArray jpoint
)
482 gdk_threads_enter ();
484 ptr
= NSA_GET_PTR (env
, obj
);
485 point
= (*env
)->GetIntArrayElements (env
, jpoint
, 0);
487 gdk_window_get_root_origin (get_widget(GTK_WIDGET (ptr
))->window
, point
, point
+1);
489 (*env
)->ReleaseIntArrayElements(env
, jpoint
, point
, 0);
491 gdk_threads_leave ();
495 * Find the origin of a widget
497 JNIEXPORT
void JNICALL
498 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetLocationOnScreen
499 (JNIEnv
* env
, jobject obj
, jintArray jpoint
)
505 gdk_threads_enter ();
507 ptr
= NSA_GET_PTR (env
, obj
);
508 point
= (*env
)->GetIntArrayElements (env
, jpoint
, 0);
510 widget
= get_widget(GTK_WIDGET (ptr
));
511 while(gtk_widget_get_parent(widget
) != NULL
)
512 widget
= gtk_widget_get_parent(widget
);
513 gdk_window_get_position (GTK_WIDGET(widget
)->window
, point
, point
+1);
515 *point
+= GTK_WIDGET(ptr
)->allocation
.x
;
516 *(point
+1) += GTK_WIDGET(ptr
)->allocation
.y
;
518 (*env
)->ReleaseIntArrayElements(env
, jpoint
, point
, 0);
520 gdk_threads_leave ();
524 * Find this widget's current size.
526 JNIEXPORT
void JNICALL
527 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetDimensions
528 (JNIEnv
*env
, jobject obj
, jintArray jdims
)
532 GtkRequisition requisition
;
534 gdk_threads_enter ();
536 ptr
= NSA_GET_PTR (env
, obj
);
538 dims
= (*env
)->GetIntArrayElements (env
, jdims
, 0);
539 dims
[0] = dims
[1] = 0;
541 gtk_widget_size_request (get_widget(GTK_WIDGET (ptr
)), &requisition
);
543 dims
[0] = requisition
.width
;
544 dims
[1] = requisition
.height
;
546 (*env
)->ReleaseIntArrayElements (env
, jdims
, dims
, 0);
548 gdk_threads_leave ();
552 * Find this widget's preferred size.
554 JNIEXPORT
void JNICALL
555 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetPreferredDimensions
556 (JNIEnv
*env
, jobject obj
, jintArray jdims
)
560 GtkRequisition current_req
;
561 GtkRequisition natural_req
;
563 gdk_threads_enter ();
565 ptr
= NSA_GET_PTR (env
, obj
);
567 dims
= (*env
)->GetIntArrayElements (env
, jdims
, 0);
568 dims
[0] = dims
[1] = 0;
570 /* Widgets that extend GtkWindow such as GtkFileChooserDialog may have
571 a default size. These values seem more useful then the natural
572 requisition values, particularly for GtkFileChooserDialog. */
573 if (GTK_IS_WINDOW (get_widget(GTK_WIDGET (ptr
))))
576 gtk_window_get_default_size (GTK_WINDOW (get_widget(GTK_WIDGET (ptr
))), &width
, &height
);
583 /* Save the widget's current size request. */
584 gtk_widget_size_request (get_widget(GTK_WIDGET (ptr
)), ¤t_req
);
586 /* Get the widget's "natural" size request. */
587 gtk_widget_set_size_request (get_widget(GTK_WIDGET (ptr
)), -1, -1);
588 gtk_widget_size_request (get_widget(GTK_WIDGET (ptr
)), &natural_req
);
590 /* Reset the widget's size request. */
591 gtk_widget_set_size_request (get_widget(GTK_WIDGET (ptr
)),
592 current_req
.width
, current_req
.height
);
594 dims
[0] = natural_req
.width
;
595 dims
[1] = natural_req
.height
;
598 (*env
)->ReleaseIntArrayElements (env
, jdims
, dims
, 0);
600 gdk_threads_leave ();
603 JNIEXPORT
void JNICALL
604 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeBounds
605 (JNIEnv
*env
, jobject obj
, jint x
, jint y
, jint width
, jint height
)
610 gdk_threads_enter ();
612 ptr
= NSA_GET_PTR (env
, obj
);
614 widget
= GTK_WIDGET (ptr
);
616 /* We assume that -1 is a width or height and not a request for the
617 widget's natural size. */
618 width
= width
< 0 ? 0 : width
;
619 height
= height
< 0 ? 0 : height
;
621 if (GTK_IS_VIEWPORT (widget
->parent
))
622 gtk_widget_set_size_request (widget
, width
, height
);
625 if (!(width
== 0 && height
== 0))
627 gtk_widget_set_size_request (widget
, width
, height
);
628 if (widget
->parent
!= NULL
)
629 gtk_fixed_move (GTK_FIXED (widget
->parent
), widget
, x
, y
);
633 gdk_threads_leave ();
636 JNIEXPORT jintArray JNICALL
637 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetBackground
638 (JNIEnv
*env
, jobject obj
)
645 gdk_threads_enter ();
647 ptr
= NSA_GET_PTR (env
, obj
);
649 bg
= GTK_WIDGET (ptr
)->style
->bg
[GTK_STATE_NORMAL
];
651 array
= (*env
)->NewIntArray (env
, 3);
653 rgb
= (*env
)->GetIntArrayElements (env
, array
, NULL
);
654 /* convert color data from 16 bit values down to 8 bit values */
655 rgb
[0] = bg
.red
>> 8;
656 rgb
[1] = bg
.green
>> 8;
657 rgb
[2] = bg
.blue
>> 8;
658 (*env
)->ReleaseIntArrayElements (env
, array
, rgb
, 0);
660 gdk_threads_leave ();
665 JNIEXPORT jintArray JNICALL
666 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetForeground
667 (JNIEnv
*env
, jobject obj
)
674 gdk_threads_enter ();
676 ptr
= NSA_GET_PTR (env
, obj
);
678 fg
= get_widget(GTK_WIDGET (ptr
))->style
->fg
[GTK_STATE_NORMAL
];
680 array
= (*env
)->NewIntArray (env
, 3);
682 rgb
= (*env
)->GetIntArrayElements (env
, array
, NULL
);
683 /* convert color data from 16 bit values down to 8 bit values */
684 rgb
[0] = fg
.red
>> 8;
685 rgb
[1] = fg
.green
>> 8;
686 rgb
[2] = fg
.blue
>> 8;
687 (*env
)->ReleaseIntArrayElements (env
, array
, rgb
, 0);
689 gdk_threads_leave ();
694 JNIEXPORT
void JNICALL
695 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetBackground
696 (JNIEnv
*env
, jobject obj
, jint red
, jint green
, jint blue
)
698 GdkColor normal_color
;
699 GdkColor active_color
;
703 gdk_threads_enter ();
705 ptr
= NSA_GET_PTR (env
, obj
);
707 normal_color
.red
= (red
/ 255.0) * 65535;
708 normal_color
.green
= (green
/ 255.0) * 65535;
709 normal_color
.blue
= (blue
/ 255.0) * 65535;
711 /* This calculation only approximates the active colors produced by
713 active_color
.red
= 0.85 * (red
/ 255.0) * 65535;
714 active_color
.green
= 0.85 * (green
/ 255.0) * 65535;
715 active_color
.blue
= 0.85 * (blue
/ 255.0) * 65535;
717 widget
= find_bg_color_widget (GTK_WIDGET (ptr
));
719 gtk_widget_modify_bg (widget
, GTK_STATE_NORMAL
, &normal_color
);
720 gtk_widget_modify_bg (widget
, GTK_STATE_ACTIVE
, &active_color
);
721 gtk_widget_modify_bg (widget
, GTK_STATE_PRELIGHT
, &normal_color
);
723 gdk_threads_leave ();
726 JNIEXPORT
void JNICALL
727 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetForeground
728 (JNIEnv
*env
, jobject obj
, jint red
, jint green
, jint blue
)
734 gdk_threads_enter ();
736 ptr
= NSA_GET_PTR (env
, obj
);
738 color
.red
= (red
/ 255.0) * 65535;
739 color
.green
= (green
/ 255.0) * 65535;
740 color
.blue
= (blue
/ 255.0) * 65535;
742 widget
= find_fg_color_widget (GTK_WIDGET (ptr
));
744 gtk_widget_modify_fg (widget
, GTK_STATE_NORMAL
, &color
);
745 gtk_widget_modify_fg (widget
, GTK_STATE_ACTIVE
, &color
);
746 gtk_widget_modify_fg (widget
, GTK_STATE_PRELIGHT
, &color
);
748 gdk_threads_leave ();
751 JNIEXPORT
void JNICALL
752 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNative
753 (JNIEnv
*env
, jobject obj
, jboolean visible
)
757 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
763 JNIEXPORT
void JNICALL
764 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
765 (JNIEnv
*env
, jobject obj
, jboolean visible
)
769 ptr
= NSA_GET_PTR (env
, obj
);
772 gtk_widget_show (GTK_WIDGET (ptr
));
774 gtk_widget_hide (GTK_WIDGET (ptr
));
777 JNIEXPORT jboolean JNICALL
778 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isEnabled
779 (JNIEnv
*env
, jobject obj
)
784 gdk_threads_enter ();
786 ptr
= NSA_GET_PTR (env
, obj
);
788 ret_val
= GTK_WIDGET_IS_SENSITIVE (get_widget(GTK_WIDGET (ptr
)));
790 gdk_threads_leave ();
795 JNIEXPORT jboolean JNICALL
796 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isRealized
797 (JNIEnv
*env
, jobject obj
)
802 gdk_threads_enter ();
804 ptr
= NSA_GET_PTR (env
, obj
);
808 gdk_threads_leave ();
812 ret_val
= GTK_WIDGET_REALIZED (get_widget(GTK_WIDGET (ptr
)));
814 gdk_threads_leave ();
819 JNIEXPORT jboolean JNICALL
820 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_modalHasGrab
821 (JNIEnv
*env
__attribute__((unused
)), jclass clazz
__attribute__((unused
)))
826 gdk_threads_enter ();
828 widget
= gtk_grab_get_current ();
829 retval
= (widget
&& GTK_IS_WINDOW (widget
) && GTK_WINDOW (widget
)->modal
);
831 gdk_threads_leave ();
836 JNIEXPORT
void JNICALL
837 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals
838 (JNIEnv
*env
, jobject obj
)
843 gdk_threads_enter ();
845 ptr
= NSA_GET_PTR (env
, obj
);
846 gref
= NSA_GET_GLOBAL_REF (env
, obj
);
848 cp_gtk_component_connect_signals (ptr
, gref
);
850 gdk_threads_leave ();
853 JNIEXPORT
void JNICALL
854 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeEventMask
855 (JNIEnv
*env
, jobject obj
)
859 gdk_threads_enter ();
861 ptr
= NSA_GET_PTR (env
, obj
);
863 gtk_widget_add_events (get_widget(GTK_WIDGET (ptr
)),
864 GDK_POINTER_MOTION_MASK
865 | GDK_BUTTON_MOTION_MASK
866 | GDK_BUTTON_PRESS_MASK
867 | GDK_BUTTON_RELEASE_MASK
869 | GDK_KEY_RELEASE_MASK
870 | GDK_ENTER_NOTIFY_MASK
871 | GDK_LEAVE_NOTIFY_MASK
874 | GDK_FOCUS_CHANGE_MASK
);
876 gdk_threads_leave ();
880 get_widget (GtkWidget
*widget
)
884 if (GTK_IS_EVENT_BOX (widget
))
885 w
= gtk_bin_get_child (GTK_BIN(widget
));
892 /* FIXME: these functions should be implemented by overridding the
893 appropriate GtkComponentPeer methods. */
895 find_fg_color_widget (GtkWidget
*widget
)
897 GtkWidget
*fg_color_widget
;
899 if (GTK_IS_EVENT_BOX (widget
)
900 || (GTK_IS_BUTTON (widget
)
901 && !GTK_IS_COMBO_BOX (widget
)))
902 fg_color_widget
= gtk_bin_get_child (GTK_BIN(widget
));
904 fg_color_widget
= widget
;
906 return fg_color_widget
;
910 find_bg_color_widget (GtkWidget
*widget
)
912 GtkWidget
*bg_color_widget
;
914 bg_color_widget
= widget
;
916 return bg_color_widget
;
920 cp_gtk_component_connect_expose_signals (GObject
*ptr
, jobject
*gref
)
922 g_signal_connect (G_OBJECT (ptr
), "expose-event",
923 G_CALLBACK (component_expose_cb
), *gref
);
927 cp_gtk_component_connect_focus_signals (GObject
*ptr
, jobject
*gref
)
929 g_signal_connect (G_OBJECT (ptr
), "focus-in-event",
930 G_CALLBACK (component_focus_in_cb
), *gref
);
932 g_signal_connect (G_OBJECT (ptr
), "focus-out-event",
933 G_CALLBACK (component_focus_out_cb
), *gref
);
937 cp_gtk_component_connect_mouse_signals (GObject
*ptr
, jobject
*gref
)
939 g_signal_connect (G_OBJECT (ptr
), "button-press-event",
940 G_CALLBACK (component_button_press_cb
), *gref
);
942 g_signal_connect (G_OBJECT (ptr
), "button-release-event",
943 G_CALLBACK (component_button_release_cb
), *gref
);
945 g_signal_connect (G_OBJECT (ptr
), "enter-notify-event",
946 G_CALLBACK (component_enter_notify_cb
), *gref
);
948 g_signal_connect (G_OBJECT (ptr
), "leave-notify-event",
949 G_CALLBACK (component_leave_notify_cb
), *gref
);
951 g_signal_connect (G_OBJECT (ptr
), "motion-notify-event",
952 G_CALLBACK (component_motion_notify_cb
), *gref
);
954 g_signal_connect (G_OBJECT (ptr
), "scroll-event",
955 G_CALLBACK (component_scroll_cb
), *gref
);
959 cp_gtk_component_connect_signals (GObject
*ptr
, jobject
*gref
)
961 cp_gtk_component_connect_expose_signals (ptr
, gref
);
962 cp_gtk_component_connect_focus_signals (ptr
, gref
);
963 cp_gtk_component_connect_mouse_signals (ptr
, gref
);
966 /* These variables are used to keep track of click counts. The AWT
967 allows more than a triple click to occur but GTK doesn't report
968 more-than-triple clicks. Also used for keeping track of scroll events.*/
969 static jint click_count
= 1;
970 static guint32 button_click_time
= 0;
971 static GdkWindow
*button_window
= NULL
;
972 static guint button_number_direction
= -1;
973 static int hasBeenDragged
;
976 component_button_press_cb (GtkWidget
*widget
__attribute__((unused
)),
977 GdkEventButton
*event
,
980 /* Ignore double and triple click events. */
981 if (event
->type
== GDK_2BUTTON_PRESS
982 || event
->type
== GDK_3BUTTON_PRESS
)
985 if ((event
->time
< (button_click_time
+ MULTI_CLICK_TIME
))
986 && (event
->window
== button_window
)
987 && (event
->button
== button_number_direction
))
992 button_click_time
= event
->time
;
993 button_window
= event
->window
;
994 button_number_direction
= event
->button
;
996 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1000 cp_gtk_state_to_awt_mods (event
->state
)
1001 | button_to_awt_mods (event
->button
),
1005 (event
->button
== 3) ? JNI_TRUE
:
1008 hasBeenDragged
= FALSE
;
1014 component_button_release_cb (GtkWidget
*widget
__attribute__((unused
)),
1015 GdkEventButton
*event
,
1020 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1024 cp_gtk_state_to_awt_mods (event
->state
)
1025 | button_to_awt_mods (event
->button
),
1031 /* Generate an AWT click event only if the release occured in the
1032 window it was pressed in, and the mouse has not been dragged since
1033 the last time it was pressed. */
1034 gdk_drawable_get_size (event
->window
, &width
, &height
);
1035 if (! hasBeenDragged
1038 && event
->x
<= width
1039 && event
->y
<= height
)
1041 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1045 cp_gtk_state_to_awt_mods (event
->state
)
1046 | button_to_awt_mods (event
->button
),
1056 component_motion_notify_cb (GtkWidget
*widget
__attribute__((unused
)),
1057 GdkEventMotion
*event
,
1060 if (event
->state
& (GDK_BUTTON1_MASK
1064 | GDK_BUTTON5_MASK
))
1066 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1070 state_to_awt_mods_with_button_states (event
->state
),
1076 hasBeenDragged
= TRUE
;
1080 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
, postMouseEventID
,
1083 cp_gtk_state_to_awt_mods (event
->state
),
1093 component_scroll_cb (GtkWidget
*widget
__attribute__((unused
)),
1094 GdkEventScroll
*event
,
1098 /** Record click count for specific direction. */
1099 if ((event
->time
< (button_click_time
+ MULTI_CLICK_TIME
))
1100 && (event
->window
== button_window
)
1101 && (event
->direction
== button_number_direction
))
1106 button_click_time
= event
->time
;
1107 button_window
= event
->window
;
1108 button_number_direction
= event
->direction
;
1110 if (event
->direction
== GDK_SCROLL_UP
1111 || event
->direction
== GDK_SCROLL_LEFT
)
1116 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1117 postMouseWheelEventID
,
1120 cp_gtk_state_to_awt_mods (event
->state
),
1125 AWT_WHEEL_UNIT_SCROLL
,
1132 component_enter_notify_cb (GtkWidget
*widget
__attribute__((unused
)),
1133 GdkEventCrossing
*event
,
1136 /* We are not interested in enter events that are due to
1137 grab/ungrab and not to actually crossing boundaries */
1138 if (event
->mode
== GDK_CROSSING_NORMAL
)
1140 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
, postMouseEventID
,
1143 state_to_awt_mods_with_button_states (event
->state
),
1153 component_leave_notify_cb (GtkWidget
*widget
__attribute__((unused
)),
1154 GdkEventCrossing
*event
,
1157 /* We are not interested in leave events that are due to
1158 grab/ungrab and not to actually crossing boundaries */
1159 if (event
->mode
== GDK_CROSSING_NORMAL
)
1161 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1165 state_to_awt_mods_with_button_states (event
->state
),
1175 component_expose_cb (GtkWidget
*widget
__attribute__((unused
)),
1176 GdkEventExpose
*event
,
1179 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1181 (jint
)event
->area
.x
,
1182 (jint
)event
->area
.y
,
1183 (jint
)event
->area
.width
,
1184 (jint
)event
->area
.height
);
1190 component_focus_in_cb (GtkWidget
*widget
__attribute((unused
)),
1191 GdkEventFocus
*event
__attribute((unused
)),
1194 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,
1203 component_focus_out_cb (GtkWidget
*widget
__attribute((unused
)),
1204 GdkEventFocus
*event
__attribute((unused
)),
1207 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer
,