diff options
Diffstat (limited to 'libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c')
| -rw-r--r-- | libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c new file mode 100644 index 00000000000..99ca0934c3d --- /dev/null +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c @@ -0,0 +1,552 @@ +/* gtkevents.c -- GDK/GTK event handlers + Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +#include "gtkpeer.h" +#include <X11/Xlib.h> +#include <gdk/gdkkeysyms.h> +#include <stdarg.h> +#include <assert.h> + +/* A widget can be composed of multipled windows, so we need to hook + events on all of them. */ +struct event_hook_info +{ + jobject *peer_obj; + int nwindows; + GdkWindow ***windows; /* array of pointers to (GdkWindow *) */ +}; + +static jint +button_to_awt_mods (int button) +{ + switch (button) + { + case 1: + return AWT_BUTTON1_MASK; + case 2: + return AWT_BUTTON2_MASK; + case 3: + return AWT_BUTTON3_MASK; + } + + return 0; +} + +static jint +state_to_awt_mods (int mods) +{ + jint result = 0; + + if (mods & (GDK_SHIFT_MASK | GDK_LOCK_MASK)) + result |= AWT_SHIFT_MASK; + if (mods & GDK_CONTROL_MASK) + result |= AWT_CTRL_MASK; + + return result; +} + +#ifdef __GNUC__ +__inline +#endif +static jint +keysym_to_awt_keycode (guint keyval) +{ + guint vk; + + vk = gdk_keyval_to_upper (keyval); + + if (vk <= 0x41 && vk <= 0x5A) /* VK_A through VK_Z */ + return vk; + + if (vk <= 0x30 && vk <= 39) /* VK_0 through VK_9 */ + return vk; + + switch (vk) + { + case GDK_Alt_L: + case GDK_Alt_R: + return VK_ALT; + case GDK_BackSpace: + return VK_BACK_SPACE; + case GDK_Cancel: + return VK_CANCEL; + case GDK_Caps_Lock: + return VK_CAPS_LOCK; + case GDK_Clear: + return VK_CLEAR; + case GDK_bracketright: + return VK_CLOSE_BRACKET; + case GDK_comma: + return VK_COMMA; + case GDK_Control_L: + case GDK_Control_R: + return VK_CONTROL; + case GDK_KP_Decimal: + return VK_DECIMAL; + case GDK_Delete: + return VK_DELETE; + case GDK_KP_Divide: + return VK_DIVIDE; + case GDK_Down: + return VK_DOWN; + case GDK_End: + return VK_END; + case GDK_Return: + return VK_ENTER; + case GDK_Escape: + return VK_ESCAPE; + case GDK_F1: + return VK_F1; + case GDK_F2: + return VK_F2; + case GDK_F3: + return VK_F3; + case GDK_F4: + return VK_F4; + case GDK_F5: + return VK_F5; + case GDK_F6: + return VK_F6; + case GDK_F7: + return VK_F7; + case GDK_F8: + return VK_F8; + case GDK_F9: + return VK_F9; + case GDK_F10: + return VK_F10; + case GDK_F11: + return VK_F11; + case GDK_F12: + return VK_F12; + case GDK_Help: + return VK_HELP; + case GDK_Home: + return VK_HOME; + case GDK_Insert: + return VK_INSERT; + case GDK_Kanji: + return VK_KANJI; + case GDK_Left: + return VK_LEFT; + case GDK_Meta_L: + case GDK_Meta_R: + return VK_META; + case GDK_KP_Multiply: + return VK_MULTIPLY; + case GDK_Num_Lock: + return VK_NUM_LOCK; + case GDK_KP_0: + return VK_NUMPAD0; + case GDK_KP_1: + return VK_NUMPAD1; + case GDK_KP_2: + return VK_NUMPAD2; + case GDK_KP_3: + return VK_NUMPAD3; + case GDK_KP_4: + return VK_NUMPAD4; + case GDK_KP_5: + return VK_NUMPAD5; + case GDK_KP_6: + return VK_NUMPAD6; + case GDK_KP_7: + return VK_NUMPAD7; + case GDK_KP_8: + return VK_NUMPAD8; + case GDK_KP_9: + return VK_NUMPAD9; + case GDK_bracketleft: + return VK_OPEN_BRACKET; + case GDK_Page_Down: + return VK_PAGE_DOWN; + case GDK_Page_Up: + return VK_PAGE_UP; + case GDK_Pause: + return VK_PAUSE; + case GDK_period: + return VK_PERIOD; + case GDK_Print: + return VK_PRINTSCREEN; + case GDK_quoteright: + return VK_QUOTE; + case GDK_Right: + return VK_RIGHT; + case GDK_Scroll_Lock: + return VK_SCROLL_LOCK; + case GDK_semicolon: + return VK_SEMICOLON; + case GDK_KP_Separator: + return VK_SEPARATOR; + case GDK_Shift_L: + case GDK_Shift_R: + return VK_SHIFT; + case GDK_slash: + return VK_SLASH; + case GDK_space: + return VK_SPACE; + case GDK_KP_Subtract: + return VK_SUBTRACT; + case GDK_Tab: + return VK_TAB; + case GDK_Up: + return VK_UP; + + default: + return VK_UNDEFINED; + } +} + +void +awt_event_handler (GdkEvent *event) +{ + jobject *obj_ptr; + static guint32 button_click_time = 0; + static GdkWindow *button_window = NULL; + static guint button_number = -1; + static jint click_count = 1; + + /* keep synthetic AWT events from being processed recursively */ + if (event->type & SYNTHETIC_EVENT_MASK && event->type != GDK_NOTHING) + { + event->type ^= SYNTHETIC_EVENT_MASK; + gtk_main_do_event (event); + return; + } + + /* keep track of clickCount ourselves, since the AWT allows more + than a triple click to occur */ + if (event->type == GDK_BUTTON_PRESS) + { + if ((event->button.time < (button_click_time + MULTI_CLICK_TIME)) + && (event->button.window == button_window) + && (event->button.button == button_number)) + click_count++; + else + click_count = 1; + + button_click_time = event->button.time; + button_window = event->button.window; + button_number = event->button.button; + } + + /* for all input events, which have a window with a jobject attached, + send the input event off to Java before GTK has a chance to process + the event */ + if ((event->type == GDK_BUTTON_PRESS + || event->type == GDK_BUTTON_RELEASE + || event->type == GDK_ENTER_NOTIFY + || event->type == GDK_LEAVE_NOTIFY + || event->type == GDK_CONFIGURE + || event->type == GDK_EXPOSE + || event->type == GDK_KEY_PRESS + || event->type == GDK_FOCUS_CHANGE + || event->type == GDK_MOTION_NOTIFY) + && gdk_property_get (event->any.window, + gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE), + gdk_atom_intern ("CARDINAL", FALSE), + 0, + sizeof (jobject), + FALSE, + NULL, + NULL, + NULL, + (guchar **)&obj_ptr)) + { + switch (event->type) + { + case GDK_BUTTON_PRESS: + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, postMouseEventID, + AWT_MOUSE_PRESSED, + (jlong)event->button.time, + state_to_awt_mods (event->button.state) | + button_to_awt_mods (event->button.button), + (jint)event->button.x, + (jint)event->button.y, + click_count, + (event->button.button == 3) ? JNI_TRUE : + JNI_FALSE); + + /* grab_counter++; + gdk_pointer_grab (event->any.window, + FALSE, + GDK_POINTER_MOTION_MASK | + GDK_BUTTON_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK, + NULL, + NULL, + event->button.time);*/ + break; + case GDK_BUTTON_RELEASE: + { + int width, height; + + /* only ungrab if no other buttons are pressed down */ + /* if (--grab_counter == 0) + gdk_pointer_ungrab (event->button.time); + */ + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, postMouseEventID, + AWT_MOUSE_RELEASED, + (jlong)event->button.time, + state_to_awt_mods (event->button.state) | + button_to_awt_mods (event->button.button), + (jint)event->button.x, + (jint)event->button.y, + click_count, JNI_FALSE); + + /* check to see if the release occured in the window it was pressed + in, and if so, generate an AWT click event */ + gdk_window_get_size (event->any.window, &width, &height); + if (event->button.x >= 0 + && event->button.y >= 0 + && event->button.x <= width + && event->button.y <= height) + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, postMouseEventID, + AWT_MOUSE_CLICKED, + (jlong)event->button.time, + state_to_awt_mods (event->button.state) | + button_to_awt_mods (event->button.button), + (jint)event->button.x, + (jint)event->button.y, + click_count, JNI_FALSE); + + } + break; + case GDK_MOTION_NOTIFY: + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, postMouseEventID, + AWT_MOUSE_MOVED, + (jlong)event->motion.time, + state_to_awt_mods (event->motion.state), + (jint)event->motion.x, + (jint)event->motion.y, + 0, JNI_FALSE); + + if (event->motion.state & (GDK_BUTTON1_MASK + | GDK_BUTTON2_MASK + | GDK_BUTTON3_MASK + | GDK_BUTTON4_MASK + | GDK_BUTTON5_MASK)) + { + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, postMouseEventID, + AWT_MOUSE_DRAGGED, + (jlong)event->motion.time, + state_to_awt_mods (event->motion.state), + (jint)event->motion.x, + (jint)event->motion.y, + 0, JNI_FALSE); + } + break; + case GDK_ENTER_NOTIFY: + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, postMouseEventID, + AWT_MOUSE_ENTERED, + (jlong)event->crossing.time, + state_to_awt_mods (event->crossing.state), + (jint)event->crossing.x, + (jint)event->crossing.y, + 0, JNI_FALSE); + break; + case GDK_LEAVE_NOTIFY: + if (event->crossing.mode == GDK_CROSSING_NORMAL) + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, postMouseEventID, + AWT_MOUSE_EXITED, + (jlong)event->crossing.time, + state_to_awt_mods (event->crossing.state), + (jint)event->crossing.x, + (jint)event->crossing.y, + 0, JNI_FALSE); + break; + case GDK_CONFIGURE: + { + GtkWidget *widget; + + gdk_window_get_user_data (event->any.window, (void **) &widget); + + if (widget && GTK_WIDGET_TOPLEVEL (widget)) + { + gint top, left, right, bottom; + gint x, y, w, h, wb, d; + + /* calculate our insets */ + gdk_window_get_root_geometry (event->any.window, + &x, &y, &w, &h, &wb, &d); + + /* We used to compute these based on the configure + event's fields. However, that gives strange and + apparently incorrect results. */ + top = left = bottom = right = 0; + + /* configure events are not posted to the AWT event queue, + and as such, gdk/gtk will be called back before + postConfigureEvent returns */ + gdk_threads_leave (); + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, + postConfigureEventID, + (jint)event->configure.x, + (jint)event->configure.y, + (jint)event->configure.width, + (jint)event->configure.height, + (jint)top, + (jint)left, + (jint)bottom, + (jint)right); + gdk_threads_enter (); + } + } + break; + case GDK_EXPOSE: + { + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, + postExposeEventID, + (jint)event->expose.area.x, + (jint)event->expose.area.y, + (jint)event->expose.area.width, + (jint)event->expose.area.height); + } + break; + + case GDK_KEY_PRESS: + { + GtkWidget *widget; + GtkWindow *window; + + gdk_window_get_user_data (event->any.window, (void **) &widget); + + window = GTK_WINDOW (gtk_widget_get_ancestor (widget, + GTK_TYPE_WINDOW)); + if (window + && GTK_WIDGET_IS_SENSITIVE (window) + && window->focus_widget + && GTK_WIDGET_IS_SENSITIVE (window->focus_widget) + && window->focus_widget->window) + { + gtk_widget_activate (window->focus_widget); + gdk_property_get (window->focus_widget->window, + gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE), + gdk_atom_intern ("CARDINAL", FALSE), + 0, + sizeof (jobject), + FALSE, + NULL, + NULL, + NULL, + (guchar **)&obj_ptr); + + /* if (grab && GTK_WIDGET_HAS_DEFAULT (widget) ) */ + /* { */ + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, + postKeyEventID, + (jint) AWT_KEY_PRESSED, + (jlong) event->key.time, + state_to_awt_mods (event->key.state), + keysym_to_awt_keycode (event->key.keyval), + (jchar) (event->key.length) ? + event->key.string[0] : + AWT_KEY_CHAR_UNDEFINED); + if (event->key.length) + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, + postKeyEventID, + (jint) AWT_KEY_TYPED, + (jlong) event->key.time, + state_to_awt_mods (event->key.state), + VK_UNDEFINED, + (jchar) event->key.string[0]); + } + } + break; + case GDK_FOCUS_CHANGE: + (*gdk_env)->CallVoidMethod (gdk_env, *obj_ptr, + postFocusEventID, + (jint) (event->focus_change.in) ? + AWT_FOCUS_GAINED : AWT_FOCUS_LOST, + JNI_FALSE); + break; + default: + } + g_free (obj_ptr); + } + + gtk_main_do_event (event); +} + +static void +attach_jobject (GdkWindow *window, jobject *obj) +{ + GdkAtom addr_atom = gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE); + GdkAtom type_atom = gdk_atom_intern ("CARDINAL", FALSE); + + gdk_window_set_events (window, + gdk_window_get_events (window) + | GDK_POINTER_MOTION_MASK + | GDK_BUTTON_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_KEY_PRESS_MASK + | GDK_KEY_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK + | GDK_STRUCTURE_MASK + | GDK_KEY_PRESS_MASK + | GDK_FOCUS_CHANGE_MASK); + + gdk_property_change (window, + addr_atom, + type_atom, + 8, + GDK_PROP_MODE_REPLACE, + (guchar *)obj, + sizeof (jobject)); +} + +void +connect_awt_hook (JNIEnv *env, jobject peer_obj, int nwindows, ...) +{ + int i; + va_list ap; + jobject *obj; + + obj = (jobject *) malloc (sizeof (jobject)); + *obj = (*env)->NewGlobalRef (env, peer_obj); + + va_start (ap, nwindows); + for (i = 0; i < nwindows; i++) + attach_jobject (va_arg (ap, GdkWindow *), obj); + va_end (ap); +} |

