1 /* gtkevents.c -- GDK/GTK event handlers
2 Copyright (C) 1998, 1999, 2002 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., 59 Temple Place, Suite 330, 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. */
41 #include <gdk/gdkkeysyms.h>
45 /* A widget can be composed of multipled windows, so we need to hook
46 events on all of them. */
47 struct event_hook_info
51 GdkWindow
***windows
; /* array of pointers to (GdkWindow *) */
55 button_to_awt_mods (int button
)
60 return AWT_BUTTON1_MASK
;
62 return AWT_BUTTON2_MASK
;
64 return AWT_BUTTON3_MASK
;
71 state_to_awt_mods (int mods
)
75 if (mods
& (GDK_SHIFT_MASK
| GDK_LOCK_MASK
))
76 result
|= AWT_SHIFT_MASK
;
77 if (mods
& GDK_CONTROL_MASK
)
78 result
|= AWT_CTRL_MASK
;
87 keysym_to_awt_keycode (guint keyval
)
91 vk
= gdk_keyval_to_upper (keyval
);
93 if (vk
<= 0x41 && vk
<= 0x5A) /* VK_A through VK_Z */
96 if (vk
<= 0x30 && vk
<= 39) /* VK_0 through VK_9 */
105 return VK_BACK_SPACE
;
112 case GDK_bracketright
:
113 return VK_CLOSE_BRACKET
;
170 case GDK_KP_Multiply
:
194 case GDK_bracketleft
:
195 return VK_OPEN_BRACKET
;
205 return VK_PRINTSCREEN
;
210 case GDK_Scroll_Lock
:
211 return VK_SCROLL_LOCK
;
214 case GDK_KP_Separator
:
223 case GDK_KP_Subtract
:
236 awt_event_handler (GdkEvent
*event
)
239 static guint32 button_click_time
= 0;
240 static GdkWindow
*button_window
= NULL
;
241 static guint button_number
= -1;
242 static jint click_count
= 1;
244 /* keep synthetic AWT events from being processed recursively */
245 if (event
->type
& SYNTHETIC_EVENT_MASK
&& event
->type
!= GDK_NOTHING
)
247 event
->type
^= SYNTHETIC_EVENT_MASK
;
248 gtk_main_do_event (event
);
252 /* keep track of clickCount ourselves, since the AWT allows more
253 than a triple click to occur */
254 if (event
->type
== GDK_BUTTON_PRESS
)
256 if ((event
->button
.time
< (button_click_time
+ MULTI_CLICK_TIME
))
257 && (event
->button
.window
== button_window
)
258 && (event
->button
.button
== button_number
))
263 button_click_time
= event
->button
.time
;
264 button_window
= event
->button
.window
;
265 button_number
= event
->button
.button
;
268 /* for all input events, which have a window with a jobject attached,
269 send the input event off to Java before GTK has a chance to process
271 if ((event
->type
== GDK_BUTTON_PRESS
272 || event
->type
== GDK_BUTTON_RELEASE
273 || event
->type
== GDK_ENTER_NOTIFY
274 || event
->type
== GDK_LEAVE_NOTIFY
275 || event
->type
== GDK_CONFIGURE
276 || event
->type
== GDK_EXPOSE
277 || event
->type
== GDK_KEY_PRESS
278 || event
->type
== GDK_FOCUS_CHANGE
279 || event
->type
== GDK_MOTION_NOTIFY
)
280 && gdk_property_get (event
->any
.window
,
281 gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE
),
282 gdk_atom_intern ("CARDINAL", FALSE
),
289 (guchar
**)&obj_ptr
))
293 case GDK_BUTTON_PRESS
:
294 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
, postMouseEventID
,
296 (jlong
)event
->button
.time
,
297 state_to_awt_mods (event
->button
.state
) |
298 button_to_awt_mods (event
->button
.button
),
299 (jint
)event
->button
.x
,
300 (jint
)event
->button
.y
,
302 (event
->button
.button
== 3) ? JNI_TRUE
:
306 gdk_pointer_grab (event->any.window,
308 GDK_POINTER_MOTION_MASK |
309 GDK_BUTTON_MOTION_MASK |
310 GDK_BUTTON_PRESS_MASK |
311 GDK_BUTTON_RELEASE_MASK |
312 GDK_ENTER_NOTIFY_MASK |
313 GDK_LEAVE_NOTIFY_MASK,
316 event->button.time);*/
318 case GDK_BUTTON_RELEASE
:
322 /* only ungrab if no other buttons are pressed down */
323 /* if (--grab_counter == 0)
324 gdk_pointer_ungrab (event->button.time);
326 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
, postMouseEventID
,
328 (jlong
)event
->button
.time
,
329 state_to_awt_mods (event
->button
.state
) |
330 button_to_awt_mods (event
->button
.button
),
331 (jint
)event
->button
.x
,
332 (jint
)event
->button
.y
,
333 click_count
, JNI_FALSE
);
335 /* check to see if the release occured in the window it was pressed
336 in, and if so, generate an AWT click event */
337 gdk_window_get_size (event
->any
.window
, &width
, &height
);
338 if (event
->button
.x
>= 0
339 && event
->button
.y
>= 0
340 && event
->button
.x
<= width
341 && event
->button
.y
<= height
)
342 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
, postMouseEventID
,
344 (jlong
)event
->button
.time
,
345 state_to_awt_mods (event
->button
.state
) |
346 button_to_awt_mods (event
->button
.button
),
347 (jint
)event
->button
.x
,
348 (jint
)event
->button
.y
,
349 click_count
, JNI_FALSE
);
353 case GDK_MOTION_NOTIFY
:
354 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
, postMouseEventID
,
356 (jlong
)event
->motion
.time
,
357 state_to_awt_mods (event
->motion
.state
),
358 (jint
)event
->motion
.x
,
359 (jint
)event
->motion
.y
,
362 if (event
->motion
.state
& (GDK_BUTTON1_MASK
368 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
, postMouseEventID
,
370 (jlong
)event
->motion
.time
,
371 state_to_awt_mods (event
->motion
.state
),
372 (jint
)event
->motion
.x
,
373 (jint
)event
->motion
.y
,
377 case GDK_ENTER_NOTIFY
:
378 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
, postMouseEventID
,
380 (jlong
)event
->crossing
.time
,
381 state_to_awt_mods (event
->crossing
.state
),
382 (jint
)event
->crossing
.x
,
383 (jint
)event
->crossing
.y
,
386 case GDK_LEAVE_NOTIFY
:
387 if (event
->crossing
.mode
== GDK_CROSSING_NORMAL
)
388 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
, postMouseEventID
,
390 (jlong
)event
->crossing
.time
,
391 state_to_awt_mods (event
->crossing
.state
),
392 (jint
)event
->crossing
.x
,
393 (jint
)event
->crossing
.y
,
400 gdk_window_get_user_data (event
->any
.window
, (void **) &widget
);
402 if (widget
&& GTK_WIDGET_TOPLEVEL (widget
))
404 gint top
, left
, right
, bottom
;
405 gint x
, y
, w
, h
, wb
, d
;
407 /* calculate our insets */
408 gdk_window_get_root_geometry (event
->any
.window
,
409 &x
, &y
, &w
, &h
, &wb
, &d
);
411 /* We used to compute these based on the configure
412 event's fields. However, that gives strange and
413 apparently incorrect results. */
414 top
= left
= bottom
= right
= 0;
416 /* configure events are not posted to the AWT event queue,
417 and as such, gdk/gtk will be called back before
418 postConfigureEvent returns */
419 gdk_threads_leave ();
420 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
,
421 postConfigureEventID
,
422 (jint
)event
->configure
.x
,
423 (jint
)event
->configure
.y
,
424 (jint
)event
->configure
.width
,
425 (jint
)event
->configure
.height
,
430 gdk_threads_enter ();
436 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
,
438 (jint
)event
->expose
.area
.x
,
439 (jint
)event
->expose
.area
.y
,
440 (jint
)event
->expose
.area
.width
,
441 (jint
)event
->expose
.area
.height
);
450 gdk_window_get_user_data (event
->any
.window
, (void **) &widget
);
452 window
= GTK_WINDOW (gtk_widget_get_ancestor (widget
,
455 && GTK_WIDGET_IS_SENSITIVE (window
)
456 && window
->focus_widget
457 && GTK_WIDGET_IS_SENSITIVE (window
->focus_widget
)
458 && window
->focus_widget
->window
)
460 gtk_widget_activate (window
->focus_widget
);
461 gdk_property_get (window
->focus_widget
->window
,
462 gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE
),
463 gdk_atom_intern ("CARDINAL", FALSE
),
470 (guchar
**)&obj_ptr
);
472 /* if (grab && GTK_WIDGET_HAS_DEFAULT (widget) ) */
474 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
,
476 (jint
) AWT_KEY_PRESSED
,
477 (jlong
) event
->key
.time
,
478 state_to_awt_mods (event
->key
.state
),
479 keysym_to_awt_keycode (event
->key
.keyval
),
480 (jchar
) (event
->key
.length
) ?
481 event
->key
.string
[0] :
482 AWT_KEY_CHAR_UNDEFINED
);
483 if (event
->key
.length
)
484 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
,
486 (jint
) AWT_KEY_TYPED
,
487 (jlong
) event
->key
.time
,
488 state_to_awt_mods (event
->key
.state
),
490 (jchar
) event
->key
.string
[0]);
494 case GDK_FOCUS_CHANGE
:
495 (*gdk_env
)->CallVoidMethod (gdk_env
, *obj_ptr
,
497 (jint
) (event
->focus_change
.in
) ?
498 AWT_FOCUS_GAINED
: AWT_FOCUS_LOST
,
506 gtk_main_do_event (event
);
510 attach_jobject (GdkWindow
*window
, jobject
*obj
)
512 GdkAtom addr_atom
= gdk_atom_intern ("_GNU_GTKAWT_ADDR", FALSE
);
513 GdkAtom type_atom
= gdk_atom_intern ("CARDINAL", FALSE
);
515 gdk_window_set_events (window
,
516 gdk_window_get_events (window
)
517 | GDK_POINTER_MOTION_MASK
518 | GDK_BUTTON_MOTION_MASK
519 | GDK_BUTTON_PRESS_MASK
520 | GDK_BUTTON_RELEASE_MASK
522 | GDK_KEY_RELEASE_MASK
523 | GDK_ENTER_NOTIFY_MASK
524 | GDK_LEAVE_NOTIFY_MASK
527 | GDK_FOCUS_CHANGE_MASK
);
529 gdk_property_change (window
,
533 GDK_PROP_MODE_REPLACE
,
539 connect_awt_hook (JNIEnv
*env
, jobject peer_obj
, int nwindows
, ...)
545 obj
= (jobject
*) malloc (sizeof (jobject
));
546 *obj
= (*env
)->NewGlobalRef (env
, peer_obj
);
548 va_start (ap
, nwindows
);
549 for (i
= 0; i
< nwindows
; i
++)
550 attach_jobject (va_arg (ap
, GdkWindow
*), obj
);