Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkComponentPeer.c
blobb0d4ab9b01998472f65739cd3dfd5f5acbebd50b
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)
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
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;
86 void
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(),
98 gtkcomponentpeer,
99 "postMouseWheelEvent",
100 "(IJIIIIZIII)V");
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,
111 jobject peer);
112 static gboolean component_button_release_cb (GtkWidget *widget,
113 GdkEventButton *event,
114 jobject peer);
115 static gboolean component_motion_notify_cb (GtkWidget *widget,
116 GdkEventMotion *event,
117 jobject peer);
118 static gboolean component_scroll_cb (GtkWidget *widget,
119 GdkEventScroll *event,
120 jobject peer);
121 static gboolean component_enter_notify_cb (GtkWidget *widget,
122 GdkEventCrossing *event,
123 jobject peer);
124 static gboolean component_leave_notify_cb (GtkWidget *widget,
125 GdkEventCrossing *event,
126 jobject peer);
127 static gboolean component_expose_cb (GtkWidget *widget,
128 GdkEventExpose *event,
129 jobject peer);
130 static gboolean component_focus_in_cb (GtkWidget *widget,
131 GdkEventFocus *event,
132 jobject peer);
133 static gboolean component_focus_out_cb (GtkWidget *widget,
134 GdkEventFocus *event,
135 jobject peer);
137 static jint
138 button_to_awt_mods (int button)
140 switch (button)
142 case 1:
143 return AWT_BUTTON1_DOWN_MASK | AWT_BUTTON1_MASK;
144 case 2:
145 return AWT_BUTTON2_DOWN_MASK | AWT_BUTTON2_MASK;
146 case 3:
147 return AWT_BUTTON3_DOWN_MASK | AWT_BUTTON3_MASK;
150 return 0;
153 jint
154 cp_gtk_state_to_awt_mods (guint state)
156 jint result = 0;
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);
165 return result;
168 static jint
169 state_to_awt_mods_with_button_states (guint state)
171 jint result = 0;
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;
186 return result;
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)
205 void *ptr;
206 GtkWidget *widget;
207 GdkCursorType gdk_cursor_type;
208 GdkCursor *gdk_cursor;
210 ptr = NSA_GET_PTR (env, obj);
212 switch (type)
214 case AWT_CROSSHAIR_CURSOR:
215 gdk_cursor_type = GDK_CROSSHAIR;
216 break;
217 case AWT_TEXT_CURSOR:
218 gdk_cursor_type = GDK_XTERM;
219 break;
220 case AWT_WAIT_CURSOR:
221 gdk_cursor_type = GDK_WATCH;
222 break;
223 case AWT_SW_RESIZE_CURSOR:
224 gdk_cursor_type = GDK_BOTTOM_LEFT_CORNER;
225 break;
226 case AWT_SE_RESIZE_CURSOR:
227 gdk_cursor_type = GDK_BOTTOM_RIGHT_CORNER;
228 break;
229 case AWT_NW_RESIZE_CURSOR:
230 gdk_cursor_type = GDK_TOP_LEFT_CORNER;
231 break;
232 case AWT_NE_RESIZE_CURSOR:
233 gdk_cursor_type = GDK_TOP_RIGHT_CORNER;
234 break;
235 case AWT_N_RESIZE_CURSOR:
236 gdk_cursor_type = GDK_TOP_SIDE;
237 break;
238 case AWT_S_RESIZE_CURSOR:
239 gdk_cursor_type = GDK_BOTTOM_SIDE;
240 break;
241 case AWT_W_RESIZE_CURSOR:
242 gdk_cursor_type = GDK_LEFT_SIDE;
243 break;
244 case AWT_E_RESIZE_CURSOR:
245 gdk_cursor_type = GDK_RIGHT_SIDE;
246 break;
247 case AWT_HAND_CURSOR:
248 gdk_cursor_type = GDK_HAND2;
249 break;
250 case AWT_MOVE_CURSOR:
251 gdk_cursor_type = GDK_FLEUR;
252 break;
253 default:
254 gdk_cursor_type = GDK_LEFT_PTR;
257 widget = get_widget(GTK_WIDGET(ptr));
259 if (image == NULL)
260 gdk_cursor = gdk_cursor_new (gdk_cursor_type);
261 else
262 gdk_cursor
263 = gdk_cursor_new_from_pixbuf (gdk_drawable_get_display (widget->window),
264 cp_gtk_image_get_pixbuf (env, image),
265 x, y);
267 gdk_window_set_cursor (widget->window, gdk_cursor);
268 gdk_cursor_unref (gdk_cursor);
270 /* Make sure the cursor is replaced on screen. */
271 gdk_flush();
274 JNIEXPORT void JNICALL
275 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent
276 (JNIEnv *env, jobject obj, jobject parent)
278 void *ptr;
279 void *parent_ptr;
280 GtkWidget *widget;
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);
300 else
301 gtk_fixed_put (GTK_FIXED (children->data), widget, 0, 0);
303 else
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),
309 GTK_SHADOW_NONE);
312 else
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)
326 void *ptr;
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)
341 void *ptr;
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)
361 void *ptr;
362 GdkEvent *event = NULL;
363 GdkKeymapKey *keymap_keys = NULL;
364 gint n_keys = 0;
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);
375 else
377 gdk_threads_leave ();
378 /* Don't send AWT KEY_TYPED events to GTK. */
379 return;
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;
386 else
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
401 affected by it. */
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
416 them. */
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 (),
423 lookup_keyval,
424 &keymap_keys,
425 &n_keys))
427 /* No matching keymap entry was found. */
428 g_printerr ("No matching keymap entries were found\n");
429 gdk_threads_leave ();
430 return;
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,
445 event->key.state,
446 event->key.group,
447 &event->key.keyval,
448 NULL, NULL, NULL))
450 /* No matching keyval was found. */
451 g_printerr ("No matching keyval was found\n");
452 gdk_threads_leave ();
453 return;
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);
465 else
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)
479 void *ptr;
480 jint *point;
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)
501 void *ptr;
502 jint *point;
503 GtkWidget *widget;
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)
530 void *ptr;
531 jint *dims;
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)
558 void *ptr;
559 jint *dims;
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))))
575 gint width, height;
576 gtk_window_get_default_size (GTK_WINDOW (get_widget(GTK_WIDGET (ptr))), &width, &height);
578 dims[0] = width;
579 dims[1] = height;
581 else
583 /* Save the widget's current size request. */
584 gtk_widget_size_request (get_widget(GTK_WIDGET (ptr)), &current_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)
607 GtkWidget *widget;
608 void *ptr;
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);
623 else
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)
640 void *ptr;
641 jintArray array;
642 int *rgb;
643 GdkColor bg;
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 ();
662 return array;
665 JNIEXPORT jintArray JNICALL
666 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetForeground
667 (JNIEnv *env, jobject obj)
669 void *ptr;
670 jintArray array;
671 jint *rgb;
672 GdkColor fg;
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 ();
691 return array;
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;
700 GtkWidget *widget;
701 void *ptr;
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
712 Sun's AWT. */
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)
730 GdkColor color;
731 GtkWidget *widget;
732 void *ptr;
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)
755 gdk_threads_enter();
757 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
758 (env, obj, visible);
760 gdk_threads_leave();
763 JNIEXPORT void JNICALL
764 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setVisibleNativeUnlocked
765 (JNIEnv *env, jobject obj, jboolean visible)
767 void *ptr;
769 ptr = NSA_GET_PTR (env, obj);
771 if (visible)
772 gtk_widget_show (GTK_WIDGET (ptr));
773 else
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)
781 void *ptr;
782 jboolean ret_val;
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 ();
792 return ret_val;
795 JNIEXPORT jboolean JNICALL
796 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isRealized
797 (JNIEnv *env, jobject obj)
799 void *ptr;
800 jboolean ret_val;
802 gdk_threads_enter ();
804 ptr = NSA_GET_PTR (env, obj);
806 if (ptr == NULL)
808 gdk_threads_leave ();
809 return FALSE;
812 ret_val = GTK_WIDGET_REALIZED (get_widget(GTK_WIDGET (ptr)));
814 gdk_threads_leave ();
816 return ret_val;
819 JNIEXPORT jboolean JNICALL
820 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_modalHasGrab
821 (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)))
823 GtkWidget *widget;
824 jboolean retval;
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 ();
833 return retval;
836 JNIEXPORT void JNICALL
837 Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals
838 (JNIEnv *env, jobject obj)
840 void *ptr;
841 jobject *gref;
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)
857 void *ptr;
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
868 | GDK_KEY_PRESS_MASK
869 | GDK_KEY_RELEASE_MASK
870 | GDK_ENTER_NOTIFY_MASK
871 | GDK_LEAVE_NOTIFY_MASK
872 | GDK_STRUCTURE_MASK
873 | GDK_KEY_PRESS_MASK
874 | GDK_FOCUS_CHANGE_MASK);
876 gdk_threads_leave ();
879 static GtkWidget *
880 get_widget (GtkWidget *widget)
882 GtkWidget *w;
884 if (GTK_IS_EVENT_BOX (widget))
885 w = gtk_bin_get_child (GTK_BIN(widget));
886 else
887 w = widget;
889 return w;
892 /* FIXME: these functions should be implemented by overridding the
893 appropriate GtkComponentPeer methods. */
894 static GtkWidget *
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));
903 else
904 fg_color_widget = widget;
906 return fg_color_widget;
909 static GtkWidget *
910 find_bg_color_widget (GtkWidget *widget)
912 GtkWidget *bg_color_widget;
914 bg_color_widget = widget;
916 return bg_color_widget;
919 void
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);
926 void
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);
936 void
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);
958 void
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;
975 static gboolean
976 component_button_press_cb (GtkWidget *widget __attribute__((unused)),
977 GdkEventButton *event,
978 jobject peer)
980 /* Ignore double and triple click events. */
981 if (event->type == GDK_2BUTTON_PRESS
982 || event->type == GDK_3BUTTON_PRESS)
983 return FALSE;
985 if ((event->time < (button_click_time + MULTI_CLICK_TIME))
986 && (event->window == button_window)
987 && (event->button == button_number_direction))
988 click_count++;
989 else
990 click_count = 1;
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,
997 postMouseEventID,
998 AWT_MOUSE_PRESSED,
999 (jlong)event->time,
1000 cp_gtk_state_to_awt_mods (event->state)
1001 | button_to_awt_mods (event->button),
1002 (jint)event->x,
1003 (jint)event->y,
1004 click_count,
1005 (event->button == 3) ? JNI_TRUE :
1006 JNI_FALSE);
1008 hasBeenDragged = FALSE;
1010 return FALSE;
1013 static gboolean
1014 component_button_release_cb (GtkWidget *widget __attribute__((unused)),
1015 GdkEventButton *event,
1016 jobject peer)
1018 int width, height;
1020 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1021 postMouseEventID,
1022 AWT_MOUSE_RELEASED,
1023 (jlong)event->time,
1024 cp_gtk_state_to_awt_mods (event->state)
1025 | button_to_awt_mods (event->button),
1026 (jint)event->x,
1027 (jint)event->y,
1028 click_count,
1029 JNI_FALSE);
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
1036 && event->x >= 0
1037 && event->y >= 0
1038 && event->x <= width
1039 && event->y <= height)
1041 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1042 postMouseEventID,
1043 AWT_MOUSE_CLICKED,
1044 (jlong)event->time,
1045 cp_gtk_state_to_awt_mods (event->state)
1046 | button_to_awt_mods (event->button),
1047 (jint)event->x,
1048 (jint)event->y,
1049 click_count,
1050 JNI_FALSE);
1052 return FALSE;
1055 static gboolean
1056 component_motion_notify_cb (GtkWidget *widget __attribute__((unused)),
1057 GdkEventMotion *event,
1058 jobject peer)
1060 if (event->state & (GDK_BUTTON1_MASK
1061 | GDK_BUTTON2_MASK
1062 | GDK_BUTTON3_MASK
1063 | GDK_BUTTON4_MASK
1064 | GDK_BUTTON5_MASK))
1066 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1067 postMouseEventID,
1068 AWT_MOUSE_DRAGGED,
1069 (jlong)event->time,
1070 state_to_awt_mods_with_button_states (event->state),
1071 (jint)event->x,
1072 (jint)event->y,
1074 JNI_FALSE);
1076 hasBeenDragged = TRUE;
1078 else
1080 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer, postMouseEventID,
1081 AWT_MOUSE_MOVED,
1082 (jlong)event->time,
1083 cp_gtk_state_to_awt_mods (event->state),
1084 (jint)event->x,
1085 (jint)event->y,
1087 JNI_FALSE);
1089 return FALSE;
1092 static gboolean
1093 component_scroll_cb (GtkWidget *widget __attribute__((unused)),
1094 GdkEventScroll *event,
1095 jobject peer)
1097 int rotation;
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))
1102 click_count++;
1103 else
1104 click_count = 1;
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)
1112 rotation = -1;
1113 else
1114 rotation = 1;
1116 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1117 postMouseWheelEventID,
1118 AWT_MOUSE_WHEEL,
1119 (jlong)event->time,
1120 cp_gtk_state_to_awt_mods (event->state),
1121 (jint)event->x,
1122 (jint)event->y,
1123 click_count,
1124 JNI_FALSE,
1125 AWT_WHEEL_UNIT_SCROLL,
1126 1 /* amount */,
1127 rotation);
1128 return FALSE;
1131 static gboolean
1132 component_enter_notify_cb (GtkWidget *widget __attribute__((unused)),
1133 GdkEventCrossing *event,
1134 jobject peer)
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,
1141 AWT_MOUSE_ENTERED,
1142 (jlong)event->time,
1143 state_to_awt_mods_with_button_states (event->state),
1144 (jint)event->x,
1145 (jint)event->y,
1147 JNI_FALSE);
1149 return FALSE;
1152 static gboolean
1153 component_leave_notify_cb (GtkWidget *widget __attribute__((unused)),
1154 GdkEventCrossing *event,
1155 jobject peer)
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,
1162 postMouseEventID,
1163 AWT_MOUSE_EXITED,
1164 (jlong)event->time,
1165 state_to_awt_mods_with_button_states (event->state),
1166 (jint)event->x,
1167 (jint)event->y,
1169 JNI_FALSE);
1171 return FALSE;
1174 static gboolean
1175 component_expose_cb (GtkWidget *widget __attribute__((unused)),
1176 GdkEventExpose *event,
1177 jobject peer)
1179 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1180 postExposeEventID,
1181 (jint)event->area.x,
1182 (jint)event->area.y,
1183 (jint)event->area.width,
1184 (jint)event->area.height);
1186 return FALSE;
1189 static gboolean
1190 component_focus_in_cb (GtkWidget *widget __attribute((unused)),
1191 GdkEventFocus *event __attribute((unused)),
1192 jobject peer)
1194 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1195 postFocusEventID,
1196 AWT_FOCUS_GAINED,
1197 JNI_FALSE);
1199 return FALSE;
1202 static gboolean
1203 component_focus_out_cb (GtkWidget *widget __attribute((unused)),
1204 GdkEventFocus *event __attribute((unused)),
1205 jobject peer)
1207 (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
1208 postFocusEventID,
1209 AWT_FOCUS_LOST,
1210 JNI_FALSE);
1212 return FALSE;